From 40bf1ff36bc54b766dd8c4f04f3c67277e29042f Mon Sep 17 00:00:00 2001 From: Xiong Date: Tue, 31 May 2022 17:50:31 -0600 Subject: [PATCH 1/5] Draft notebook and example output xml First commit. Necessary next steps: 1. Update descriptions and guiding paragraph in between cells for level 2 audit (based on level 1) 2. Update values in fields based on OS simulation (most fields are currently filled with arbitrary number such as 123) 3. Update declaration setting in first cell to set xml attribute declaration heading correctly (now it has to be manually corrected) --- .../bsync_examples/Small-Office-Level-2.md | 2170 ++++++++++++++++ .../bsync_examples/example-level2.xml | 2245 +++++++++++++++++ .../bsync_examples/img/valid_level2.png | Bin 0 -> 31423 bytes 3 files changed, 4415 insertions(+) create mode 100644 docs/notebooks/bsync_examples/Small-Office-Level-2.md create mode 100644 docs/notebooks/bsync_examples/example-level2.xml create mode 100644 docs/notebooks/bsync_examples/img/valid_level2.png diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-2.md b/docs/notebooks/bsync_examples/Small-Office-Level-2.md new file mode 100644 index 00000000..efa92d82 --- /dev/null +++ b/docs/notebooks/bsync_examples/Small-Office-Level-2.md @@ -0,0 +1,2170 @@ +# Energy Auditing with BuildingSync + +Follow the instructions in the [README.md](../README.md) file to run in Jupyter Lab/Notebook. + +## Introduction +So you've been tasked with performing an energy audit that requires submission of a BuildingSync document? What does that even mean? This notebook is intended to provide an interactive and informational introduction to what BuildingSync is and how it relates to buildings, building systems, and energy audit reporting. This will be done by performing an example energy audit on the DOE Small Office Prototype building. + +## Who This is For +While this notebook is setup in Python, this introduction is not reserved only for software developers. The code is more of a supplement, but doesn't need to be run. Energy auditors, mechanical engineers, AHJ's procuring audits, and software developers all have something to gain from walking through this notebook. + +## Learning Objectives +By the end of this notebook, you should: +- Have a practical understanding of some XML features, namely: elements, attributes, and xpaths +- Know the main elements of the BuildingSync schema: Buildings, Systems, Reports, Scenarios, TimeSeriesData +- Be able to relate these concepts back to an ASHRAE Standard 211 energy audit +- Create a minimum viable Level 1 BuildingSync document and verify it validates using the [BuildingSync Use Case Validator](https://buildingsync.net/validator) + +## For Reference: Core Concepts and Notation Used +- We will be using BuildingSync version 2.3.0. [Documentation](https://buildingsync.net/documentation/2.3.0). [Github release](https://github.com/BuildingSync/schema/releases/tag/v2.3.0). +- BuildingSync is an XML Schema Document (XSD). It defines intended structure. Referring to something as a BuildingSync document typically means the document is intended to conform to the BuildingSync schema. +- An XSD defines a hierarchical or tree-based schema, where elements are 'nested' within other elements. An XML document then looks like nested elements within one another. Similar to HTML, it uses angle brackets `<` and `>` to open and close an element tag. The example below provides a very simple example of an XML document: +```xml + + This child element captures information in a string (text), whereas the second-child captures a numeric datatype. + 2 + +``` +- `auc:` is often used as the namespace prefix for elements in a BuildingSync document. If a document declares the BuildingSync namespace prefix to be `auc:`, an element would look like `auc:Facility`. The same element in a BuildingSync document without a namespace prefix would look like `Facility`. Going forward, we will not prefix elements with `auc` - the remaining XML content should only refer to things defined by the BuildingSync schema. +- XPath: xpath is basically a syntax for 'walking' an xml tree, mainly used for 'querying' information out of an XML document. In the simple example xml document above, to get the `` element, we would notate this in XPath as `/a-root-node/first-child`. XPath will be used throughout this document to concisely convey where elements can be found in a BuildingSync document. + +## Caveats +- These cells are meant to be run 1x through sequentially. Running a single cell multiple times may give you bad results + + +```python +# Import the main bsync module +from bsyncpy import bsync +from lxml import etree +from datetime import datetime, date +import eeweather + +def pretty_print(element): + """Simple printing of an xml element from the bsync library""" + print(etree.tostring(element.toxml(), pretty_print=True).decode('utf-8')) + +def bsync_dump(root_element, file="example1.xml"): + """Write the element to the specified file""" + doctype = '' + as_etree = root_element.toxml() + as_etree.set("xmlns", "http://buildingsync.net/schemas/bedes-auc/2019") + #as_etree.set("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + #as_etree.set("xsi:schemaLocation", "http://buildingsync.net/schemas/bedes-auc/2019 https://raw.githubusercontent.com/BuildingSync/schema/v2.4.0/BuildingSync.xsd") + # Have to manually set the version right now. Align release of bsyncpy to this version. + as_etree.set("version", "2.4.0") + output = etree.tostring(as_etree, doctype=doctype, pretty_print=True) + with open(file, 'wb+') as f: + f.write(output) + return True +``` + +# Starting the Audit + +## Small Office Prototype Building +The small office prototype is a single story rectangular building. We will show some love to Missoula and assume this building is located at 4055 Brooks St. Missoula, MT 59804. +![](./img/b1-bldg.png) + +We can summarize the high level features as: +- Total Floor Area: 5500sf +- WWR: Southern Wall ~25%, Other Walls ~20% +- Climate Zone 6B +- Assume built year: 2006 +- Let's assume this is on the 90.1-2004 code cycle + +## "I have a building...where do I start" +Relevant Standard 211 Sections: +- 6.1.1 Facility Description + +Let's start by defining a building. In this exercise, we will learn about some BuildingSync design patterns that will continue to propagate. In xpath terms, buildings live here: `/BuildingSync/Facilities/Facility/Sites/Site/Buildings/Building`. A few things to notice: +- The root node of a BuildingSync document is the `BuildingSync` element +- Plurals (Facilities, Sites, Buildings) are often used to indicate parents that can contain 1 <= n < infinite child elements having a non-pluralized name (Facility, Site, Building). For example: +```xml + + + + ...children stuff here... + + + ...children stuff here... + + + +``` +- While the above can be done, it is __most common__ to find a single Facility, Site, and Building in a BuildingSync document. In general: + - Facility refers to a grouping of Sites, but a Facility is still geographically proximate. Its boundary might include not building specific things (streets, sidewalks, etc.) + - A Site is everything in and around a group of Buildings. This might be two Buildings that are connected via a tunnel, etc. + - ** Most common is just to have a single Building + +### Primary BuildingSync Structural Elements +We start by creating the primary structure of a BuildingSync document. We introduced `Facilities`, `Sites`, and `Buildings`, but there are a few additional: +- `Sections` are subportions of a `Building`. Think of a mixed-use commercial building with retail and office space, each of these would become a section. For those familiar with the ASHRAE 211 Normative Spreadsheet, a `Section` is analagous to a column in the `All - Space Functions` sheet. +- `Systems` are defined under a `Facility` and capture the energy consuming / producing assets. Each can be linked back to an individual `Facility`, `Site`, `Building`, or `Section`. +- `Reports` are defined under a `Facility` and each `Report` would contain information about reporting type requirements. Most importantly, a `Report` contains a set of `Scenario` elements, where each `Scenario` would convey building performance for one of: current / historical data, target performance, benchmark performance, baseline modeled performance, or expected performance with measure(s) implemented. + + +```python +# just take this for what it is at the moment. the bsync package makes +# it easier to work with xml content. All of this is mainly syntactic +# sugar around the lxml package, with some type checking, attribute +# assignment, etc. +root = bsync.BuildingSync() +facs = bsync.Facilities() +f1 = bsync.Facilities.Facility(ID="Facility-1") +sites = bsync.Sites() +s1 = bsync.Sites.Site(ID="Site-1") +bldgs = bsync.Buildings() +b1 = bsync.Buildings.Building(ID="Building-Small-Office-Prototype") +sections = bsync.Sections() +systems = bsync.Systems() +contacts = bsync.Contacts() +reports = bsync.Reports() +measures = bsync.Measures() +schedules = bsync.Schedules() +utilities = bsync.Utilities() + +# We link the entire report to the building +r1 = bsync.Report( + bsync.LinkedPremisesOrSystem( + bsync.LinkedPremisesOrSystem.Building( + bsync.LinkedBuildingID(IDref=b1["ID"]) + ) + ), + ID='Report-L2-Audit') +scenarios = bsync.Scenarios() + +# We now combine these and pretty print the result for easy viewing of what we just made +root += facs +facs += f1 + +# Direct children of a facility +f1 += sites +f1 += systems +f1 += schedules +f1 += measures +f1 += reports +f1 += contacts + +# Specific to a site +sites += s1 +s1 += bldgs +bldgs += b1 + +# Direct children of a building +b1 += sections + +# Specific to a report +reports += r1 +r1 += scenarios +r1 += utilities + +pretty_print(root) +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#### 6.2.1.1 Building information + +This section of Standard 211 asks for lots of detail. We walk through the components of this that get added _as child elements of the building_, and then discuss other information. + + +```python +# 6.2.1.1.a - name +b1 += bsync.PremisesName('Small Office Prototype') + +# 6.1.1.1.m +b1 += bsync.PremisesNotes("Here we record general problems / issues identified in a walkthrough survey.") + +# 6.1.1.1.d - address +b1 += bsync.Address( + bsync.StreetAddressDetail( + bsync.Simplified( + bsync.StreetAddress("4055 Brooks Street") + ) + ), + bsync.Address.State("MT"), + bsync.City("Missoula"), + bsync.PostalCode("59804") +) + +# 6.2.1.1.b - gross and conditioned floor area +b1 += bsync.FloorAreas( + bsync.FloorArea( + bsync.FloorAreaType("Gross"), + bsync.FloorAreaValue(5500.0), + bsync.ExcludedSectionIDs( + bsync.ExcludedSectionID(IDref="Section-excluded") + ) + ), + bsync.FloorArea( + bsync.FloorAreaType("Conditioned"), + bsync.FloorAreaValue(5500.0), + bsync.ExcludedSectionIDs( + bsync.ExcludedSectionID(IDref="Section-excluded") + ) + ) +) + +# 6.2.1.2.b - gross wall area +b1 += bsync.TotalExteriorAboveGradeWallArea(6500.) +b1 += bsync.TotalExteriorBelowGradeWallArea(0.) + +# 6.2.1.2.c - fenestration-wall ratio +b1 += bsync.OverallWindowToWallRatio(0.2133) +b1 += bsync.OverallDoorToWallRatio(0.05) + +# 6.1.1.1.f - classification of the uses +b1 += bsync.BuildingClassification("Commercial") +b1 += bsync.OccupancyClassification("Office") +b1 += bsync.BuildingAutomationSystem(True) +b1 += bsync.HistoricalLandmark(False) + +# 6.1.1.1.h - for completeness, we spell this out explicitly +b1 += bsync.FloorsAboveGrade(1) +b1 += bsync.FloorsBelowGrade(0) +b1 += bsync.ConditionedFloorsAboveGrade(1) +b1 += bsync.ConditionedFloorsBelowGrade(0) + +# 6.1.1.1.i - again, to be explicit, we define the latest remodel / retrofit year +# to be the same as the original build year to indicate nothing has happened since original construction +b1 += bsync.YearOfConstruction(2000) +b1 += bsync.YearOccupied(2000) +b1 += bsync.RetrocommissioningDate(date(2020,3,1)) +b1 += bsync.YearOfLastMajorRemodel(2000) +b1 += bsync.YearOfLastEnergyAudit(2010) + +#pretty_print(root) +``` + +Continuing with the information required by 6.1.1.1, we define additional content that doesn't sit as direct child elements of the Building. This includes: +- Contacts. Key contacts (1 auditor and 1 owner) __must be linked__ back to the building, even though they are not in the Building subtree: + - Contacts live: /BuildingSync/Facilities/Facility/Contacts/Contact + - An auditor is linked to a building at a Report level (i.e. who performed the audit) + - Reports live: /BuildingSync/Facilities/Facility/Reports/Report + - An audit report, with the correct links to a Building, Measures, etc. should be sufficient to meet the Standard 211 requirements spelled out in Section 6. More on this later. +- Space function breakdown by space type +- Occupied hours and number of occupants + +#### Contacts + + +```python +# 6.1.1.1.b - Owner and auditor contact info +c1 = bsync.Contact( + bsync.ContactName('The dude'), + bsync.ContactCompany("Some big company"), + bsync.ContactRoles( + bsync.ContactRole('Owner') + ), + bsync.ContactTelephoneNumbers( + bsync.ContactTelephoneNumber( + bsync.TelephoneNumber("123-456-7890") + ) + ), + bsync.ContactEmailAddresses( + bsync.ContactEmailAddress( + bsync.EmailAddress("the.dude@somebigco.net") + ) + ), + ID='Contact-Owner' +) +c2 = bsync.Contact( + bsync.ContactName('The lady'), + bsync.ContactCompany("Auditeers"), + bsync.ContactRoles( + bsync.ContactRole('Energy Auditor') + ), + bsync.ContactTelephoneNumbers( + bsync.ContactTelephoneNumber( + bsync.TelephoneNumber("123-456-7890") + ) + ), + bsync.ContactEmailAddresses( + bsync.ContactEmailAddress( + bsync.EmailAddress("the.lady@the-three-auditeers.com") + ) + ), + ID='Contact-Auditor' +) +# We add the two contacts to the correct parent +contacts += c1 +contacts += c2 + +# We 'assign' (link) the owner as the primary contact for the building, though this +# could be an owners rep or some other contact type. +b1 += bsync.PrimaryContactID(IDref=c1['ID']) + +# We link the auditor contact to the report +r1 += bsync.AuditorContactID(IDref=c2['ID']) +``` + +### Space Function Analysis +Relevant Standard 211 Sections: +- 5.3.4 Space Function Analysis + +Space functions are used to define sections of a building used for different purposes. The classic example of this is a mixed use commercial real estate, with retail space on the bottom floor and offices in the remainder of the building. We do this in BuildingSync via the following: +- Each space functions gets its own `Section` element +- Each `Section` element should specify the `Section/SectionType` as "Space function" + +The Small Office, as its name suggests, is just an office space, and therefore we will only create one section for it. + + +```python +# create a new section +section = bsync.Sections.Section( + bsync.SectionType("Space function"), + bsync.OccupancyClassification("Office"), + bsync.OriginalOccupancyClassification("Office"), + bsync.ThermalZoneLayout("Single zone"), + ID=f"Section-office" +) +section_wb = bsync.Sections.Section(ID="Section-Whole-building") +section_wb += bsync.SectionType("Whole building") +section_ex = bsync.Sections.Section(ID="Section-excluded") +sections += section +sections += section_wb +sections += section_ex +``` + +Section 5.3.4 lays out specific requirements to convey for each space function. These include: +- floor area requirements +- typical occupant usages +- systems information (plugs, lighting, hvac) + + +```python +# 5.3.4.a Gross floor area for the section (we also add conditioned for 5.3.4.f) +section_fa = bsync.FloorAreas( + bsync.FloorArea( + bsync.FloorAreaType("Gross"), + bsync.FloorAreaValue(5500.0) + ), + bsync.FloorArea( + bsync.FloorAreaType("Conditioned"), + bsync.FloorAreaValue(5500.0) + ) +) + +# 5.3.4.b and 5.3.4.c are asking for typical operating hours for the section +tous = bsync.TypicalOccupantUsages() +tou_hpw = bsync.TypicalOccupantUsage( + bsync.TypicalOccupantUsageUnits("Hours per week"), + bsync.TypicalOccupantUsageValue(40.0) +) +tou_wpy = bsync.TypicalOccupantUsage( + bsync.TypicalOccupantUsageUnits("Weeks per year"), + bsync.TypicalOccupantUsageValue(50.) +) +tous += tou_hpw +tous += tou_wpy + +# 5.3.4.d looks for normal / design or peak occupancy. +occ_levels = bsync.OccupancyLevels() +occ_design = bsync.OccupancyLevel( + bsync.OccupantQuantityType("Peak total occupants"), + bsync.OccupantQuantity(31.) +) +occ_levels += occ_design + +``` + + +```python +# finally, we add these to the actual section element +section += section_fa +section += tous +section += occ_levels +#pretty_print(sections) +``` + +6.2.1.1.e Schedules + + +```python +schedule_occ = bsync.Schedule(ID="Schedule-Occupancy") +schedule_light = bsync.Schedule(ID="Schedule-Lighting") +schedule_pl = bsync.Schedule(ID="Schedule-PlugLoad") +schedule_hvac = bsync.Schedule(ID="Schedule-HVAC") +schedule_hvac_new = bsync.Schedule(ID="Schedule-HVAC-new") + +# occupancy schedule +schedule_occ += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(11.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(21.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(53.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(32.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(11.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(5.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekend"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), + bsync.ScheduleDetail( + bsync.DayType("Holiday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ) +) +schedule_occ += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ), + bsync.LinkedPremises.Section( + bsync.LinkedSectionID(IDref=section['ID']) + ) +) +# lighting schedule +schedule_light += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(18.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(23.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(42.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(90.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(61.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(42.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(32.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(23.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(18.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekend"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(18.) + ), + bsync.ScheduleDetail( + bsync.DayType("Holiday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(18.) + ) +) +schedule_light += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) +) +# plug load schedule +schedule_pl += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(50.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(94.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(50.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(20.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekend"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(20.) + ), + bsync.ScheduleDetail( + bsync.DayType("Holiday"), + bsync.ScheduleCategory("Miscellaneous equipment"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(20.) + ) +) +schedule_pl += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) +) +# HVAC schedule +schedule_hvac += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekend"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Holiday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ) +) +schedule_hvac += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) +) +# upgraded HVAC schedule (for EEM) +schedule_hvac_new += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(60.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(80.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(100.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(60.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekend"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(30.) + ), + bsync.ScheduleDetail( + bsync.DayType("Holiday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(20.) + ) +) +schedule_hvac_new += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) +) + +schedules += schedule_occ +schedules += schedule_light +schedules += schedule_pl +schedules += schedule_hvac +schedules += schedule_hvac_new +#pretty_print(schedules) +``` + +#### 6.2.1.2 Envelope + +Level 2 energy audits require information about the building envelop, including roof, wall, floor and fenestration. BuildingSync defines these components (construction, thermal properties, etc.) under the `Systems` element, and links corresponding elements back to the envelope specified under the `Section` elements. A few other information (e.g. gross areas) are added under the `Building` element above. +In addition, 6.2.1.2.e requires information of the building overall tightness, and this is covered under the `AirInfiltrationSystems` element. + + + +```python +# 6.2.1.2.a roof +roofsys = bsync.RoofSystems() +roof = bsync.RoofSystem( + bsync.RoofConstruction("Wood frame"), + bsync.RoofRValue(1.), + ID=f"Roof-1" +) +roofsys += roof + +# 6.2.1.2.b wall +wallsys = bsync.WallSystems() +wall = bsync.WallSystem( + bsync.ExteriorWallConstruction("Wood frame"), + bsync.WallRValue(1.), + ID=f"Wall-1" +) +wallsys += wall + +# 6.2.1.2.c fenestration +fenestsys = bsync.FenestrationSystems() +win1_orig = bsync.FenestrationSystem( + bsync.FenestrationType( + bsync.Window() + ), + bsync.FenestrationFrameMaterial("Vinyl"), + bsync.GlassType("Clear uncoated"), + bsync.FenestrationGlassLayers("Single pane"), + bsync.FenestrationUFactor(1.25), + bsync.SolarHeatGainCoefficient(0.5), + bsync.VisibleTransmittance(0.8), + ID=f"Window-1-Original" +) +win1 = bsync.FenestrationSystem( + bsync.FenestrationType( + bsync.Window() + ), + bsync.FenestrationFrameMaterial("Vinyl"), + bsync.GlassType("Low e"), + bsync.FenestrationGlassLayers("Triple pane"), + bsync.FenestrationUFactor(0.25), + bsync.SolarHeatGainCoefficient(0.5), + bsync.VisibleTransmittance(0.7), + ID=f"Window-1" +) +door = bsync.FenestrationSystem( + bsync.FenestrationType( + bsync.Door( + bsync.ExteriorDoorType("Insulated metal"), + bsync.DoorGlazedAreaFraction(0.5) + ) + ), + bsync.FenestrationFrameMaterial("Steel"), + bsync.FenestrationRValue(0.5), + ID=f"Door-1" +) +fenestsys += win1_orig +fenestsys += win1 +fenestsys += door + +# 6.2.1.2.d floor +foundsys = bsync.FoundationSystems() +found = bsync.FoundationSystem( + bsync.GroundCouplings( + bsync.GroundCoupling( + bsync.SlabOnGrade( + bsync.SlabUFactor(0.5) + ) + ) + ), + bsync.FloorConstructionType("Concrete poured"), + ID=f"Foundation-1" +) +foundsys += found + +# 6.2.1.2.e tightness +infiltsys = bsync.AirInfiltrationSystems() +infilt = bsync.AirInfiltrationSystem( + bsync.AirInfiltrationNotes("Notes on test"), + bsync.AirInfiltrationSystem.Tightness("Very Tight"), + bsync.AirInfiltrationValue(123.), + bsync.AirInfiltrationValueUnits("CFM25"), + bsync.AirInfiltrationTest("Blower door"), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID(IDref=section_wb["ID"]) + ) + ), + ID=f"Infiltration-1" +) +infiltsys += infilt + +waterinfiltsys = bsync.WaterInfiltrationSystems() +waterinfilt = bsync.WaterInfiltrationSystem( + bsync.WaterInfiltrationNotes("Notes on test"), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID(IDref=section_wb["ID"]) + ) + ) +) +waterinfiltsys += waterinfilt +``` + + +```python +# now we add these components to System element +systems += roofsys +systems += wallsys +systems += fenestsys +systems += foundsys +systems += infiltsys +systems += waterinfiltsys +#pretty_print(systems) +``` + + +```python +# then we link these components to the envelope elements under Section/Sides +section_wb += bsync.FootprintShape("Rectangular") + +section_sides = bsync.Sides() +for sidenumber in ["A1", "B1", "C1", "D1"]: + section_sides += bsync.Side( + bsync.SideNumber(sidenumber), + bsync.WallIDs( + bsync.WallID( + bsync.WallArea(123.), + IDref=wall["ID"] + ) + ), + bsync.WindowIDs( + bsync.WindowID( + bsync.FenestrationArea(123.), + IDref=win1_orig["ID"] + ) + ), + bsync.DoorIDs( + bsync.DoorID( + bsync.FenestrationArea(123.), + IDref=door["ID"] + ) + ) + ) + +section_roofs = bsync.Roofs( + bsync.Roof( + bsync.RoofID( + bsync.RoofArea(123.), + bsync.RoofCondition("Good"), + IDref=roof["ID"] + ) + ) +) +section_founds = bsync.Foundations( + bsync.Foundation( + bsync.FoundationID( + bsync.FoundationArea(123.), + IDref=found["ID"] + ) + ) +) + +section_wb += section_sides +section_wb += section_roofs +section_wb += section_founds +#pretty_print(sections) +``` + +#### HVAC, SHW/DHW, Lighting, Plugs + +Level 2 energy audits require information about the primary systems serving a specific section, with details such as types, capacities and conditions + + +```python +# 6.2.1.3 HVAC +# Here we specify HVAC system details +# and link them back to the Section of interest. +# According to prototype small office spec in ASHRAE901_OfficeSmall_STD2004 +# the heating source is Air-source heat pump with gas furnace as back up +# and cooling source is Air-source heat pump +# and air distribution unit is Single zone, constant air volume air distribution, one unit per occupied thermal zone + +hvac_systems = bsync.HVACSystems() +hvac_system = bsync.HVACSystem(ID="HVACSystem-1") +hvac_systems += hvac_system +# link hvac to section +hvac_system += bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID( + bsync.LinkedScheduleIDs( + bsync.LinkedScheduleID(IDref=schedule_hvac['ID']) + ), + IDref=section["ID"] + ) + ) +) + +# heating and cooling system +hc_systems = bsync.HeatingAndCoolingSystems() +hc_systems += bsync.ZoningSystemType("Single zone") +# cooling system +css = bsync.CoolingSources() +cs = bsync.CoolingSource( + bsync.CoolingSourceType( + bsync.DX( + bsync.DXSystemType("Packaged/unitary heat pump"), + bsync.CompressorType("Reciprocating"), + bsync.CompressorStaging("Single stage") + ) + ), + bsync.AnnualCoolingEfficiencyValue(123.), + bsync.AnnualCoolingEfficiencyUnits('COP'), + bsync.Capacity(123.), + bsync.CapacityUnits('gpm'), + bsync.CoolingSourceCondition('Good'), + bsync.CoolingSource.Controls( + bsync.CoolingSource.Controls.Control( + bsync.CoolingSource.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) + ) + ) + ), + bsync.YearInstalled(2020), + ID=f"CoolingSource-1" +) +css += cs +hc_systems += css +# heating system +hss = bsync.HeatingSources() +hs1 = bsync.HeatingSource( + bsync.HeatingSourceType( + bsync.HeatingSourceType.HeatPump( + bsync.HeatPumpType("Packaged Unitary"), + bsync.HeatPumpBackupSystemFuel("Natural gas"), + bsync.HeatPumpBackupAFUE(0.123), + bsync.CoolingSourceID(IDref=cs['ID']) + ) + ), + bsync.AnnualHeatingEfficiencyValue(123.), + bsync.AnnualHeatingEfficiencyUnits('COP'), + bsync.InputCapacity(123.), + bsync.HeatingSource.Capacity(123.), + bsync.CapacityUnits('gpm'), + bsync.HeatingSourceCondition('Good'), + bsync.HeatingSource.Controls( + bsync.HeatingSource.Controls.Control( + bsync.HeatingSource.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) + ) + ) + ), + bsync.YearInstalled(2020), + ID=f"HeatingSource-1" +) +hs2 = bsync.HeatingSource( + bsync.HeatingSourceType( + bsync.Furnace( + bsync.FurnaceType('Warm air') + ) + ), + bsync.AnnualHeatingEfficiencyValue(123.), + bsync.AnnualHeatingEfficiencyUnits('COP'), + bsync.InputCapacity(123.), + bsync.HeatingSource.Capacity(123.), + bsync.CapacityUnits('gpm'), + bsync.HeatingSourceCondition('Good'), + bsync.HeatingSource.Controls( + bsync.HeatingSource.Controls.Control( + bsync.HeatingSource.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) + ) + ) + ), + bsync.YearInstalled(2020), + ID=f"HeatingSource-2" +) +hss += hs1 +hss += hs2 +hc_systems += hss +# delivery system +delivers = bsync.Deliveries() +deliver = bsync.Delivery( + bsync.DeliveryType( + bsync.CentralAirDistribution( + bsync.AirDeliveryType("Central fan"), + bsync.TerminalUnit("CAV terminal box no reheat"), + bsync.ReheatSource("None"), + bsync.FanBased( + bsync.AirSideEconomizer( + bsync.AirSideEconomizerType("None"), + bsync.EconomizerControl("Fixed"), + ID=f"AirSideEconomizer-1" + ) + ) + ) + ), + bsync.HeatingSourceID(IDref=hs1["ID"]), + bsync.CoolingSourceID(IDref=cs["ID"]), + bsync.Delivery.Controls( + bsync.Delivery.Controls.Control( + bsync.Delivery.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) + ) + ) + ), + bsync.YearInstalled(2020), + bsync.Quantity(5), + bsync.DeliveryCondition("Good"), + ID=f"Delivery-1" +) +delivers += deliver +hc_systems += delivers +# duct +duct_systems = bsync.DuctSystems() +duct = bsync.DuctSystem( + bsync.DuctConfiguration("Single"), + bsync.DuctInsulationCondition("Good"), + bsync.HeatingDeliveryID(IDref=deliver['ID']), + bsync.CoolingDeliveryID(IDref=deliver['ID']), + ID=f"DuctSystem-1" +) +duct_systems += duct +# HVAC control +hvacctl = bsync.HVACControlSystemTypes( + bsync.HVACControlSystemType("Digital") +) + +hvac_system += hc_systems +hvac_system += duct_systems +hvac_system += hvacctl +#pretty_print(hvac_systems) + +# fan +fan_systems = bsync.FanSystems() +fan = bsync.FanSystem( + bsync.FanEfficiency(123.), + bsync.FanSize(123.), + bsync.InstalledFlowRate(123.), + bsync.FanControlType("Constant Volume"), + bsync.LinkedSystemIDs( + bsync.LinkedSystemID(IDref=deliver['ID']) + ), + ID=f"FanSystem-1" +) +fan_new = bsync.FanSystem( + bsync.FanEfficiency(123.), + bsync.FanSize(123.), + bsync.InstalledFlowRate(123.), + bsync.FanControlType("Variable Volume"), + bsync.LinkedSystemIDs( + bsync.LinkedSystemID(IDref=deliver['ID']) + ), + ID=f"FanSystem-new" +) +fan_systems += fan +fan_systems += fan_new +``` + + +```python +# 6.2.1.4 SHW/DHW +# Required information are types, ratings, operating and general conditions, +# According to prototype small office spec in ASHRAE901_OfficeSmall_STD2004 +# SHW type is electric Storage tank + +shw_systems = bsync.DomesticHotWaterSystems() +shw = bsync.DomesticHotWaterSystem( + bsync.DomesticHotWaterType( + bsync.StorageTank( + bsync.TankHeatingType( + bsync.Direct( + bsync.DirectTankHeatingSource( + bsync.ElectricResistance() + ) + ) + ), + bsync.TankVolume(40.), + bsync.StorageTankInsulationRValue(123.) + ) + ), + bsync.DomesticHotWaterSystemNotes("Notes"), + bsync.PrimaryFuel("Electricity"), + bsync.Recirculation( + bsync.RecirculationLoopCount(1), + bsync.RecirculationFlowRate(123.), + bsync.RecirculationControlType("Continuous"), + bsync.PipeInsulationThickness(123.), + bsync.RecirculationEnergyLossRate(123.) + ), + bsync.HotWaterDistributionType("Looped"), + bsync.HotWaterSetpointTemperature(140.), + bsync.WaterHeaterEfficiency(123.), + bsync.WaterHeaterEfficiencyType("COP"), + bsync.DailyHotWaterDraw(123.), + bsync.ParasiticFuelConsumptionRate(123.), + bsync.Capacity(123.), + bsync.CapacityUnits("gpm"), + bsync.YearInstalled(2020), + bsync.DomesticHotWaterSystemCondition("Good"), + bsync.DomesticHotWaterSystem.Controls( + bsync.DomesticHotWaterSystem.Controls.Control( + bsync.DomesticHotWaterSystem.Controls.Control.Manual( + bsync.ControlSystemType( + bsync.ControlSystemType.Other() + ) + ) + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ), + bsync.LinkedPremises.Section( + bsync.LinkedSectionID(IDref=section["ID"]) + ) + ), + bsync.Quantity(1), + ID=f"SHW-1" +) +shw_systems += shw +``` + + +```python +# 6.2.1.5 +# For the lighting systems, this is a bit different. When +# performing an audit, it is atypical to know the LPD of a space / zone +# as you would in 'Energy Modeling' world / design world. +# Assuming drawings are unavailable and we go in to check, +# based on the vintage it's likely we will find T8 linear +# fluorescents (thanks Jay Wratten!). So we add that information +light_systems = bsync.LightingSystems() +ls1 = bsync.LightingSystem( + bsync.OutsideLighting(False), + bsync.LampType( + bsync.LinearFluorescent( + bsync.LinearFluorescent.LampLabel("T8") + ) + ), + bsync.BallastType("Standard Electronic"), + bsync.DimmingCapability( + bsync.MinimumDimmingLightFraction(0.2) + ), + bsync.InstalledPower(123.), + bsync.LampPower(123.), + bsync.NumberOfLampsPerBallast(1), + bsync.NumberOfBallastsPerLuminaire(1.), + bsync.NumberOfLuminaires(10), + bsync.PercentPremisesServed(100.), + bsync.LightingAutomationSystem(False), + bsync.LightingSystem.Controls( + bsync.LightingSystem.Controls.Control( + bsync.LightingSystem.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ), + bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy("Programmable") + ) + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID( + bsync.LinkedScheduleIDs( + bsync.LinkedScheduleID(IDref=schedule_light['ID']) + ), + IDref=section["ID"]) + ) + ), + ID="LightingSystem-1" +) +# there is no specific information related to exterior lighting (but it exists) +ls2 = bsync.LightingSystem( + bsync.OutsideLighting(True), + bsync.LampType( + bsync.LinearFluorescent( + bsync.LinearFluorescent.LampLabel("T12") + ) + ), + bsync.BallastType("Standard Electronic"), + bsync.InstalledPower(123.), + bsync.LampPower(123.), + bsync.NumberOfLampsPerBallast(1), + bsync.NumberOfBallastsPerLuminaire(1.), + bsync.NumberOfLuminaires(1), + bsync.PercentPremisesServed(100.), + bsync.LightingAutomationSystem(False), + bsync.LightingSystem.Controls( + bsync.LightingSystem.Controls.Control( + bsync.LightingSystem.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ), + bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy("Programmable") + ) + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID( + bsync.LinkedScheduleIDs( + bsync.LinkedScheduleID(IDref=schedule_light['ID']) + ), + IDref=section_wb["ID"]) + ) + ), + ID="LightingSystem-2" +) +# new lighting system for measure +ls_new = bsync.LightingSystem( + bsync.OutsideLighting(False), + bsync.LampType( + bsync.SolidStateLighting( + bsync.SolidStateLighting.LampLabel("LED") + ) + ), + bsync.BallastType("Standard Electronic"), + bsync.DimmingCapability( + bsync.MinimumDimmingLightFraction(0.1) + ), + bsync.InstalledPower(123.), + bsync.LampPower(123.), + bsync.NumberOfLampsPerBallast(1), + bsync.NumberOfBallastsPerLuminaire(1.), + bsync.NumberOfLuminaires(10), + bsync.PercentPremisesServed(100.), + bsync.LightingAutomationSystem(False), + bsync.LightingSystem.Controls( + bsync.LightingSystem.Controls.Control( + bsync.Daylighting( + bsync.ControlSystemType( + bsync.Digital() + ), + bsync.Daylighting.ControlSensor("Photocell"), + bsync.Daylighting.ControlStrategy("Continuous") + ) + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID( + bsync.LinkedScheduleIDs( + bsync.LinkedScheduleID(IDref=schedule_light['ID']) + ), + IDref=section["ID"]) + ) + ), + ID="LightingSystem-new" +) + +light_systems += ls1 +light_systems += ls2 +light_systems += ls_new +``` + + +```python +# 6.2.1.6 Process, plug and conveyance loads +# There are no process and conveyance loads identified for prototype small office +# The plug loads are pretty straightforwad +# Based on the Small Office 90.1-2004 prototype model, +# each zone has an EPD of 0.63 W/ft2 +# Since all zones are part of the same section, we can +# just assign this EPD to the Section as a whole +plug_systems = bsync.PlugLoads() +psys = bsync.PlugLoad( + bsync.PlugLoadType("Miscellaneous Electric Load"), + bsync.WeightedAverageLoad(0.63), + bsync.LinkedPremises( + bsync.LinkedPremises.Section( + bsync.LinkedSectionID( + bsync.LinkedScheduleIDs( + bsync.LinkedScheduleID(IDref=schedule_pl['ID']) + ), + IDref=section["ID"]) + ) + ), + ID="PlugLoad-1" +) +plug_systems += psys +``` + + +```python +systems += hvac_systems +systems += fan_systems +systems += shw_systems +systems += light_systems +systems += plug_systems +#pretty_print(systems) +``` + +### Current Building Measured Scenario +Relevant Standard 211 Sections: +- 6.1.2 + +Now that we have a quick sense of the building, let's start off by looking at the requirements for an ASHRAE 211 Level 1 audit. This leads us to the concept of a [Scenario](https://buildingsync.net/schema/v2.3.0/documentation/BuildingSync_xsd.html#ScenarioType). A Scenario in BuildingSync is used to refer to energy and timeseries data associated with a particular, well, scenario. Specifically, there are 5 primary Scenarios used in BuildingSync, all which relate back to Standard 211: + +![Scenario Types](./img/b1-sc-docs.png) + +We will repeatedly come back to the concept of a Scenario, as they are core to organizing information in a BuildingSync document. + +The current building measured scenario is intended to capture true measured historical data. Typically this refers to utility bill data, but AMI type data can also be captured (later). We start off by creating a new scenario element and defining its type as follows: +- `Scenario[ScenarioType/CurrentBuilding/CalculationMethod/Measured]`. This is an XPath expression that can be interpreted as "A Scenario that has the child elements ScenarioType/CurrentBuilding/CalculationMethod/Measured". The XML for this would look like: +```xml + + + + + + + + + +``` + +We build this scenario up programatically as follows: + + +```python +# define the current building measured scenario (cbms) +cbms = bsync.Scenario( + bsync.Scenario.ScenarioType( + bsync.CurrentBuilding( + bsync.CalculationMethod( + bsync.Measured() + ) + ) + ) +) +cbms['ID'] = 'Scenario-measured' + +# add the scenario to the audit report and scenarios parent grouping +scenarios += cbms +``` + +#### Utilities +Relevant Standard 211 Sections: 6.1.2 +In the next section, we will create resource use elements to define energy data. First, we need to get add utility information. Utility information gets added at the report level. Specific information required includes: +- Rate schedules (you can get very expressive in BuildingSync with Rate Schedules - we keep it pretty minimal here) +- Utility account numbers + + +```python +elec_ut = bsync.Utility( + bsync.RateSchedules( + bsync.RateSchedule( + bsync.TypeOfRateStructure( + bsync.FlatRate( + bsync.FlatRate.RatePeriods( + bsync.FlatRate.RatePeriods.RatePeriod( + bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), + bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), + bsync.EnergyCostRate(0.0725), # $0.0725/kWh + bsync.ApplicableStartDateForDemandRate(date(2019,1,1)), + bsync.ApplicableEndDateForDemandRate(date(2020,1,1)), + bsync.ElectricDemandRate(0.0) # no demand charge per https://missoulaelectric.com/member-care/billing-payment/rates/ + ) + ) + ) + ), + bsync.ReferenceForRateStructure("https://missoulaelectric.com/member-care/billing-payment/rates/"), + bsync.FixedMonthlyCharge(28.), + ID="RateSchedule-Electricity" + ) + ), + bsync.UtilityMeterNumbers( + bsync.UtilityMeterNumber("Some-meter-ID") + ), + bsync.EIAUtilityID(12692), + bsync.UtilityName("Missoula Electric Cooperative"), + bsync.UtilityAccountNumber("some-account-number"), + bsync.UtilityBillpayer("Building Owner"), + ID="Utility-Electric" +) +ng_ut = bsync.Utility( + bsync.RateSchedules( + bsync.RateSchedule( + bsync.TypeOfRateStructure( + bsync.FlatRate( + bsync.FlatRate.RatePeriods( + bsync.FlatRate.RatePeriods.RatePeriod( + bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), + bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), + bsync.EnergyCostRate(5.5) # $/MMBtu + ) + ) + ) + ), + bsync.ReferenceForRateStructure("https://naturalgaslocal.com/states/montana/missoula/"), + ID="RateSchedule-Natural-Gas" + ) + ), + bsync.UtilityMeterNumbers( + bsync.UtilityMeterNumber("Some-meter-ID") + ), + bsync.UtilityName("NorthWestern Energy"), + bsync.UtilityAccountNumber("some-other-account-number"), + bsync.UtilityBillpayer("Building Owner"), + ID="Utility-Natural-Gas" +) +``` + + +```python +utilities += elec_ut +utilities += ng_ut +``` + +#### ResourceUses and TimeSeries Data +Now that we have a current building measured scenario, we want to declare energy and monthly billing data. Per Std 211 6.1.2.1, a minimum of 12 months (preferably up to 3 years) of energy use data is required. The mechanical system of the small office prototype is a heatpump air handler with natural gas backup. We know that Missoula is cold, so likely it will use natural gas backup at some point during its operation. We run an example simulation to get estimates for this, which come out as follows: + +| Resource Type | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| Electricity (kWh) | 6792.89 | 5841.75 | 6025.19 | 4985.3 | 5184.04 | 5358.55 | 5755.67 | 5981.78 | 5401.94 | 5225.84 | 5672.15 | 6291.63 | +| Natural Gas (MMBtu) | 5.7 | 4.01 | 0.58 | 0.4 | 0.02 | 0 | 0 | 0 | 0 | 0.01 | 0.36 | 6.08 | 17.16 | +| GHG Emissions (MtCO2e) | 250.0 | 240.0 | 260.0 | 250.0 | 260.0 | 230.0 | 280.0 | 270.0 | 260.0 | 250.0 | 240.0 | 250.0 | + +In BuildingSync land, we need to declare an resource use for each resource type. Standard, allowable enumerations exist for this already. We do this as follows: + + +```python +all_ru = bsync.ResourceUses() + +# create a resource use for electricity, units of kWh, all end uses +# we also add info about the 'peak' units +# we also connect it up to a utility +elec_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUseNotes("This is required for L1 to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found."), + bsync.ResourceUnits('kWh'), + bsync.PeakResourceUnits('kW'), + bsync.EndUse('All end uses'), + bsync.UtilityIDs( + bsync.UtilityID(IDref=elec_ut['ID']) + ), + ID=f"ResourceUse-Electricity" +) +# given the above, we add the annual totals +elec_ru += bsync.AnnualFuelUseNativeUnits(68516.73) +elec_ru += bsync.AnnualFuelUseConsistentUnits(234.) #convert to MMBTU +elec_ru += bsync.AnnualPeakNativeUnits(21.12) # kW as specified above +elec_ru += bsync.AnnualPeakConsistentUnits(21.12) # already in kW, same as above +elec_ru += bsync.AnnualFuelCost(5304.) # $28 monthly + $0.0725/kwh per https://missoulaelectric.com/member-care/billing-payment/rates/ + +# create a resource use for natural gas, units of MMBtu, all end uses +# additional connect it up to the utility +ng_ru = bsync.ResourceUse( + bsync.EnergyResource('Natural gas'), + bsync.ResourceUseNotes("No irregularities in monthly energy consumption found."), + bsync.ResourceUnits('MMBtu'), + bsync.EndUse('All end uses'), + bsync.UtilityIDs( + bsync.UtilityID(IDref=ng_ut['ID']) + ), + ID=f"ResourceUse-Natural-gas" +) +# given the above, we add the annual totals +ng_ru += bsync.AnnualFuelUseNativeUnits(17.16) +ng_ru += bsync.AnnualFuelUseConsistentUnits(17.16) # already in MMBTU +ng_ru += bsync.AnnualFuelCost(91.63) # ~ $5.50/1000ft3 NG per https://naturalgaslocal.com/states/montana/missoula/ +251.16 +# create resource uses for submetering of lighting, heating and cooling +lighting_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), + bsync.EndUse('Total lighting'), + bsync.AnnualFuelUseNativeUnits(18384.912), + bsync.AnnualFuelUseConsistentUnits(62.79), + bsync.PercentEndUse(25.), + bsync.ParentResourceUseID(IDref=elec_ru['ID']), + ID=f"ResourceUse-Electricity-Lighting-Submeter" +) +heating_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), + bsync.EndUse('Heating'), + bsync.AnnualFuelUseNativeUnits(22061.8944), + bsync.AnnualFuelUseConsistentUnits(75.348), + bsync.PercentEndUse(30.), + bsync.ParentResourceUseID(IDref=elec_ru['ID']), + ID=f"ResourceUse-Electricity-Heating-Submeter" +) +cooling_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), + bsync.EndUse('Cooling'), + bsync.AnnualFuelUseNativeUnits(18384.912), + bsync.AnnualFuelUseConsistentUnits(62.79), + bsync.PercentEndUse(25.), + bsync.ParentResourceUseID(IDref=elec_ru['ID']), + ID=f"ResourceUse-Electricity-Cooling-Submeter" +) +shw_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), + bsync.EndUse('Domestic hot water'), + bsync.AnnualFuelUseNativeUnits(7353.9648), + bsync.AnnualFuelUseConsistentUnits(25.116), + bsync.PercentEndUse(10.), + bsync.ParentResourceUseID(IDref=elec_ru['ID']), + ID=f"ResourceUse-Electricity-SHW-Submeter" +) +pl_ru = bsync.ResourceUse( + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), + bsync.EndUse('Plug load'), + bsync.AnnualFuelUseNativeUnits(3676.9824), + bsync.AnnualFuelUseConsistentUnits(12.558), + bsync.PercentEndUse(5.), + bsync.ParentResourceUseID(IDref=elec_ru['ID']), + ID=f"ResourceUse-Electricity-Plugload-Submeter" +) + +# add these to the ResourceUses parent element +all_ru += elec_ru +all_ru += ng_ru +all_ru += lighting_ru +all_ru += heating_ru +all_ru += cooling_ru +all_ru += shw_ru +all_ru += pl_ru +# ResourceUses are child elements of a specific scenario: +cbms += all_ru +``` + +#### All TimeSeries Data +The following cell simply performs the following: +1. Create a simple function to generate monthly timeseries elements for each resource use +1. Add it to a `TimeSeriesData` parent element +1. Add this back to the previously defined current building measured scenario (i.e. Scenario-1) + + +```python +full_ts_data = bsync.TimeSeriesData() + +# usage and peak data +monthly_elec = [6792.89, 5841.75, 6025.19, 4985.3, 5184.04, 5358.55, 5755.67, 5981.78, 5401.94, 5225.84, 5672.15, 6291.63] +monthly_ng = [5.7, 4.01, 0.58, 0.4, 0.02, 0, 0, 0, 0, 0.01, 0.36, 6.08] +monthly_elec_peak = [15.42, 15.5, 16.25, 16.65, 18.56, 20.01, 20.82, 21.12, 20.42, 20.08, 17.4, 16.3] +monthly_elec_lf = [0.373, 0.394, 0.390, 0.358, 0.374, 0.386, 0.369, 0.372, 0.373, 0.354, 0.380, 0.362] + +# costs data +monthly_elec_cost = [520.48, 451.53, 464.83, 389.43, 403.84, 416.49, 445.29, 461.68, 419.64, 406.87, 439.23, 484.14] +monthly_ng_cost = [30.44, 21.41, 3.10, 2.14, 0.11, 0.00, 0.00, 0.00, 0.00, 0.05, 1.92, 32.47] + +elec_ids = [] +ng_ids = [] +daysinmonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] +def create_monthly(values, resource_use_id, start_year, tsrq='Energy', rt='Total'): + """ + tsrq: One of Energy, Power, Cost + rt: One of Total, Peak, Cost, Load factor + """ + monthly = [] + end_year = start_year + for i, val in enumerate(values, start=1): + if i % 12 == 0: + start_month = 12 + end_month = 1 + end_year += 1 + else: + start_month = i % 12 + end_month = start_month + 1 + start_dt = datetime(start_year, start_month, 1) + end_dt = datetime(end_year, end_month, 1) + + if rt == 'Load factor': + my_id = f"TS-{resource_use_id}-Loadfactor-{start_month}" + else: + my_id = f"TS-{resource_use_id}-{rt}-{start_month}" + + if rt == 'Peak': + ts = bsync.TimeSeries( + bsync.ReadingType(rt), + bsync.PeakType("On-peak"), + bsync.TimeSeriesReadingQuantity(tsrq), + bsync.StartTimestamp(start_dt), + bsync.EndTimestamp(end_dt), + bsync.IntervalDuration(daysinmonth[i-1]), + bsync.IntervalDurationUnits("Day"), + bsync.IntervalFrequency("Month"), + bsync.IntervalReading(float(val)), + bsync.ResourceUseID(IDref=resource_use_id), + ID=my_id + ) + else: + ts = bsync.TimeSeries( + bsync.ReadingType(rt), + bsync.TimeSeriesReadingQuantity(tsrq), + bsync.StartTimestamp(start_dt), + bsync.EndTimestamp(end_dt), + bsync.IntervalDuration(daysinmonth[i-1]), + bsync.IntervalDurationUnits("Day"), + bsync.IntervalFrequency("Month"), + bsync.IntervalReading(float(val)), + bsync.ResourceUseID(IDref=resource_use_id), + ID=my_id + ) + + monthly.append(ts) + + if tsrq == 'Energy': + if 'Electricity' in resource_use_id: + elec_ids.append(my_id) + else: + ng_ids.append(my_id) + return monthly + +elec_ts = create_monthly(monthly_elec, elec_ru['ID'], 2019) +ng_ts = create_monthly(monthly_ng, ng_ru['ID'], 2019) +elec_peak_ts = create_monthly(monthly_elec_peak, elec_ru['ID'], 2019, 'Power', 'Peak') +elec_lf_ts = create_monthly(monthly_elec_lf, elec_ru['ID'], 2019, 'Power', 'Load factor') + +elec_cost_ts = create_monthly(monthly_elec_cost, elec_ru['ID'], 2019, 'Cost', 'Cost') +ng_cost_ts = create_monthly(monthly_ng_cost, ng_ru['ID'], 2019, 'Cost', 'Cost') + +def add_to_full(months, full): + for month in months: + full += month + +add_to_full(elec_ts, full_ts_data) +add_to_full(ng_ts, full_ts_data) +add_to_full(elec_peak_ts, full_ts_data) +add_to_full(elec_lf_ts, full_ts_data) +add_to_full(elec_cost_ts, full_ts_data) +add_to_full(ng_cost_ts, full_ts_data) + +cbms += full_ts_data +``` + +#### Linked TimeSeriesIDs +Due to the fact that annual data reporting is dependent on which months / utility bill periods were used to calculate the annual total, the `AnnualFuelUseLinkedTimeSeriesIDs` element was introduced. It is required to specify exactly which months for each resource use were used in the calculation of the `AnnualFuelUseNativeUnits` and `AnnualFuelUseConsistentUnits` elements. We add this element below. + + +```python +elec_linked_ids = bsync.AnnualFuelUseLinkedTimeSeriesIDs() +for each_id in elec_ids: + elec_linked_ids += bsync.LinkedTimeSeriesID(IDref=each_id) + + +ng_linked_ids = bsync.AnnualFuelUseLinkedTimeSeriesIDs() +for each_id in ng_ids: + ng_linked_ids += bsync.LinkedTimeSeriesID(IDref=each_id) + +elec_ru += elec_linked_ids +ng_ru += ng_linked_ids +``` + +#### All Resource Totals + +We have defined monthly electricity (energy, power, cost) and natural gas (energy, cost) usage as timeseries elements. Now we basically just need to summarize these into site and source energy use totals. We use the `Scenario/AllResourceTotals/AllResourceTotal` element to achieve this. The Level 1 use case requires annual energy reporting to follow Standard 105s methodology including: + +- `SiteEnergyUse`: Corresponds to $E_{site}$ +- `BuildingEnergyUse`: Corresponds to $E_{bld}$ +- `ImportedEnergyConsistentUnits`: Corresponds to $E_{imp}$ +- `OnsiteEnergyProductionConsistentUnits`: Corresponds to $E_{g}$ +- `ExportedEnergyConsistentUnits`: Corresponds to $E_{exp}$ +- `NetIncreaseInStoredEnergyConsistentUnits`: Corresponds to $E_{s}$ + + +```python +art = bsync.AllResourceTotals( + bsync.AllResourceTotal( + bsync.AllResourceTotal.SiteEnergyUse(250953.5), # reported in kBtu + bsync.SiteEnergyUseIntensity(45.6), # reported in kbtu/ft2 + + # Since there is no energy generated onsite, there is no difference btw site and building energy usage / intensity + bsync.BuildingEnergyUse(250953.5), + bsync.BuildingEnergyUseIntensity(45.6), + + bsync.ImportedEnergyConsistentUnits(250.9535), # in this case, same as building and site energy, but in MMBTU + bsync.OnsiteEnergyProductionConsistentUnits(0.), # no energy produced onsite, MMBtu + bsync.ExportedEnergyConsistentUnits(0.), # no energy exported, MMBtu + bsync.NetIncreaseInStoredEnergyConsistentUnits(0.), # no energy stored, MMBtu + + bsync.AllResourceTotal.SourceEnergyUse(759011.9), # reported in kBtu. Assume site -> source: elec = 3.167, ng = 1.084 + bsync.SourceEnergyUseIntensity(138.0), # kbtu/ft2 + bsync.EnergyCost(5395.), + bsync.EnergyCostIndex(0.98), # $/ft2 + ID="AllResourceTotal-1" + ) +) +``` + + +```python +cbms += art +cbms += bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) +) +``` + +### Benchmark Scenario +Relevant Standard 211 Sections: +- 6.1.3 + +We inserted the above information (electricity, natural gas, square footage, etc.) into the Energy Star Portfolio Manager and got a score of 56. We can add this information into BuildingSync with our benchmark scenario. +TODO: Figure this out: +1. Entered info into ESPM. Got the following: + +![ESPM](./img/ESPM-Target.png) + +1. So, the ES score for the _current building measured_ should be 56? And then 50 is used as the benchmark value here...? And 274,825 kBtu as the SiteEnergyUse...? Confused. + + +```python +# define the benchmark scenario +bench_sc = bsync.Scenario( + bsync.AllResourceTotals( + bsync.AllResourceTotal( + bsync.AllResourceTotal.SiteEnergyUse(274825.), + bsync.SiteEnergyUseIntensity(50.), + ID="AllResourceTotal-Benchmark" + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) + ), + ID="Scenario-Benchmark" +) +bench_st = bsync.Scenario.ScenarioType() +bench = bsync.Benchmark( + bsync.BenchmarkType( + bsync.PortfolioManager( + bsync.PMBenchmarkDate(date(2021, 3, 24)) + ) + ), + bsync.BenchmarkTool("Portfolio Manager"), + bsync.BenchmarkYear(2019), + bsync.BenchmarkValue(56.) +) + +# +scenarios += bench_sc +bench_sc += bench_st +bench_st += bench +``` + +### Target Scenario +Relevant Standard 211 Sections: +- 6.1.4 + +Since we used a PM score in the baseline, we will also use that for our target. Let's say we are shooting for a target score of 70. + + +```python +# define the target scenario in reference to the benchmark scenario +target_sc = bsync.Scenario( + bsync.AllResourceTotals( + bsync.AllResourceTotal( + bsync.AllResourceTotal.SiteEnergyUse(207643.5), + bsync.SiteEnergyUseIntensity(37.8), + bsync.EnergyCost(4451.51), + bsync.EnergyCostIndex(0.81), + ID="AllResourceTotal-Target" + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) + ), + ID="Scenario-Target" +) +target_st = bsync.Scenario.ScenarioType() +target = bsync.Target( + bsync.ReferenceCase(IDref=bench_sc["ID"]), + bsync.AnnualSavingsSiteEnergy(67181.5), + bsync.AnnualSavingsCost(931), + bsync.ENERGYSTARScore(70.), +) + +# +scenarios += target_sc +target_sc += target_st +target_st += target +``` + +### Current Building Modeled Scenario +Relevant Standard 211 Sections: +- 6.1.5 & 6.1.6 + +Although not explicitly called out in Standard 211, the current building modeled scenario is mostly implied as part of a Level 2 energy audit when doing more detailed savings estimates / calculations for potential measure(s) implementation. This is because when an energy / cost savings claim is made for a package of measures scenario, it needs to be _in reference_ to something, i.e. a current building modeled scenario (also often referred to as a baseline modeled scenario). The baseline modeled scenario should be interpreted as the expected performance of your building on an average or typical year. This is assuming the baseline modeled scenario is performed with TMY3 data, although they are likely first calibrated with AMY data. + +Since we are already using an energy model for this example and providing details for implementing a Standard 211 Level 1 energy audit, we will not go into this too much at this point. It should be addressed in future examples. + +### Package of Measures Scenario +Relevant Standard 211 Sections: +- 6.1.5 & 6.1.6 + +Standard 211 breaks out recommendations into low / no-cost (6.1.5) or capital (6.1.6). On the BuildingSync side, we don't change the data modeling between these two situations significantly, we simply change the value of the `Scenario/ScenarioType/PackageOfMeasures/CostCategory` element, while the majority of other features remain the same. +- Low / no-cost scenario: `CostCategory>Low-Cost or No-Cost` +- Capital scenario: `CostCategory>Capital` + +For Level 1 audits, since the reporting only requires estimated costs, savings, and ROI, we don't specifically need a current building modeled scenario to be our reference case. + +#### Measures + +Packages of measures first require measures to be instantiated inside the BuildingSync document in order to correctly 'incorporate' them into the scenario. BuildingSync provides a significant number of already enumerated measures that can easily be used. We will first add some of these to our doc. + +The scope of an individual measure is primarily conveyed by a few elements: +- `SystemCategoryAffected`: select one of an enumerated set of strings representing the general scope of system, i.e. Refrigeration, Fan, Lighting, etc. +- `TechnologyCategories/TechnologyCategory/*/MeasureName`: Select a very specific measure to implement + + +```python +# A measure to modify HVAC schedules (low-cost EEM) +hvac_schedule_measure = bsync.Measure( + bsync.TypeOfMeasure( + bsync.ModificationRetrocommissions( + bsync.ModificationRetrocommissioning( + bsync.ExistingScheduleAffected(IDref=schedule_hvac['ID']), + bsync.ModifiedSchedule(IDref=schedule_hvac_new['ID']) + ) + ) + ), + bsync.SystemCategoryAffected("Air Distribution"), + bsync.TechnologyCategories( + bsync.TechnologyCategory( + bsync.OtherHVAC( + bsync.OtherHVAC.MeasureName("Other distribution") + ) + ) + ), + bsync.CustomMeasureName("Update HVAC schedule"), + bsync.LongDescription("The current HVAC schedule is set to be at 100'%' fan operation during weekday from 7am - 8pm. This measure would implement a modified schedule to enable pre-cooling/pre-heating from 6am - 7am, and reduce output to 80'%' during peak time 12pm - 1pm. "), + bsync.MeasureScaleOfApplication("Individual system"), + bsync.UsefulLife(1.), + bsync.MeasureInstallationCost(0.), + bsync.MeasureMaterialCost(0.), + bsync.StartDate(date(2021,1,1)), + bsync.EndDate(date(2021,12,30)), + bsync.Recommended(True), + ID="Measure-HVAC-schedule-lowcost" +) + +# A measure to upgrade the lighting system to LEDs +led_measure = bsync.Measure( + bsync.TypeOfMeasure( + bsync.Replacements( + bsync.Replacement( + bsync.ExistingSystemReplaced(IDref=ls1['ID']), + bsync.AlternativeSystemReplacement(IDref=ls_new['ID']) + ) + ) + ), + bsync.SystemCategoryAffected("Lighting"), + bsync.TechnologyCategories( + bsync.TechnologyCategory( + bsync.LightingImprovements( + bsync.LightingImprovements.MeasureName("Retrofit with light emitting diode technologies") + ) + ) + ), + bsync.LongDescription("This measure is designed to replace all fluorescent bulbs with LEDs"), + bsync.MeasureScaleOfApplication("Individual system"), + bsync.UsefulLife(1.), + bsync.MeasureInstallationCost(123.), + bsync.MeasureMaterialCost(123.), + bsync.StartDate(date(2021,1,1)), + bsync.EndDate(date(2021,12,30)), + bsync.Recommended(True), + ID="Measure-LEDs" +) + +# A measure to upgrade the fans in the RTUs to use VFDs +# instead of simple on/off fans. +# The CFMs for each of the RTUs are around ~ 700-800cfm, +# so there is no obvious choice of fans to upgrade to vfds. +# Here, we just recommend upgrading all of them. +vsd_measure = bsync.Measure( + bsync.TypeOfMeasure( + bsync.ModificationRetrocommissions( + bsync.ModificationRetrocommissioning( + bsync.ExistingSystemAffected(IDref=fan['ID']), + bsync.ModifiedSystem(IDref=fan_new['ID']) + ) + ) + ), + # could have also used Air Distribution or Motor, this seemed ok too. + bsync.SystemCategoryAffected("Fan"), + bsync.TechnologyCategories( + bsync.TechnologyCategory( + bsync.OtherElectricMotorsAndDrives( + bsync.OtherElectricMotorsAndDrives.MeasureName("Add VSD motor controller") + ) + ) + ), + bsync.LongDescription("This measure is designed to retrofit all RTU fans with a VSD"), + bsync.MeasureScaleOfApplication("Individual system"), + bsync.UsefulLife(1.), + bsync.MeasureInstallationCost(123.), + bsync.MeasureMaterialCost(123.), + bsync.StartDate(date(2021,1,1)), + bsync.EndDate(date(2021,12,30)), + bsync.Recommended(True), + ID="Measure-VSDs" +) +``` + + +```python +measures += hvac_schedule_measure +measures += led_measure +measures += vsd_measure +``` + +#### POM Scenarios +Now that the measures have been added, we create three potential POM scenarios, and add the necessary attributes per Standard 211 6.1.5 and 6.1.6 +1. LEDs only +1. VSDs only +1. HVAC schedule only + + +```python +pom_sc_1 = bsync.Scenario( + bsync.Scenario.ScenarioType( + bsync.PackageOfMeasures( + bsync.ReferenceCase(IDref=cbms['ID']), + bsync.MeasureIDs( + bsync.MeasureID(IDref=led_measure['ID']) + ), + bsync.CostCategory("Capital"), + bsync.AnnualSavingsSiteEnergy(123.), + bsync.AnnualSavingsCost(123), + bsync.AnnualSavingsByFuels( + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Electricity"), + bsync.ResourceUnits("kWh"), + bsync.AnnualSavingsNativeUnits(123.) + ), + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Natural gas"), + bsync.ResourceUnits("MMBtu"), + bsync.AnnualSavingsNativeUnits(0.) + ) + ), + bsync.AnnualPeakElectricityReduction(123.), + bsync.AnnualDemandSavingsCost(123), + bsync.AnnualWaterSavings(0.), + bsync.AnnualWaterCostSavings(0.), + bsync.ImplementationPeriod(1), + bsync.ImplementationPeriodCostSavings(0.), + bsync.PackageFirstCost(0.), + bsync.MVCost(0.), + bsync.OMCostAnnualSavings(123.), + bsync.EquipmentDisposalAndSalvageCosts(0.), + bsync.ProjectMarkup(123.), + bsync.FundingFromIncentives(123.), + bsync.FundingFromTaxCredits(123.), + bsync.OtherFinancialIncentives(123), + bsync.RecurringIncentives(123), + bsync.InternalRateOfReturn(1.), + bsync.SimplePayback(123.), + ID="POM-LEDs" + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) + ), + ID="Scenario-POM-LEDs" +) + +pom_sc_2 = bsync.Scenario( + bsync.Scenario.ScenarioType( + bsync.PackageOfMeasures( + bsync.ReferenceCase(IDref=cbms['ID']), + bsync.MeasureIDs( + bsync.MeasureID(IDref=vsd_measure['ID']) + ), + bsync.CostCategory("Capital"), + bsync.AnnualSavingsSiteEnergy(123.), + bsync.AnnualSavingsCost(123), + bsync.AnnualSavingsByFuels( + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Electricity"), + bsync.ResourceUnits("kWh"), + bsync.AnnualSavingsNativeUnits(123.) + ), + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Natural gas"), + bsync.ResourceUnits("MMBtu"), + bsync.AnnualSavingsNativeUnits(12.) + ) + ), + bsync.AnnualPeakElectricityReduction(123.), + bsync.AnnualDemandSavingsCost(123), + bsync.AnnualWaterSavings(0.), + bsync.AnnualWaterCostSavings(0.), + bsync.ImplementationPeriod(1), + bsync.ImplementationPeriodCostSavings(0.), + bsync.PackageFirstCost(0.), + bsync.MVCost(0.), + bsync.OMCostAnnualSavings(123.), + bsync.EquipmentDisposalAndSalvageCosts(0.), + bsync.ProjectMarkup(123.), + bsync.FundingFromIncentives(123.), + bsync.FundingFromTaxCredits(123.), + bsync.OtherFinancialIncentives(123), + bsync.RecurringIncentives(123), + bsync.InternalRateOfReturn(1.), + bsync.SimplePayback(123.), + ID="POM-VSDs" + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) + ), + ID="Scenario-POM-VSDs" +) + +pom_sc_3 = bsync.Scenario( + bsync.Scenario.ScenarioType( + bsync.PackageOfMeasures( + bsync.ReferenceCase(IDref=cbms['ID']), + bsync.MeasureIDs( + bsync.MeasureID(IDref=hvac_schedule_measure['ID']), + ), + bsync.CostCategory("Low-Cost or No-Cost"), + bsync.AnnualSavingsSiteEnergy(123.), + bsync.AnnualSavingsCost(123), + bsync.AnnualSavingsByFuels( + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Electricity"), + bsync.ResourceUnits("kWh"), + bsync.AnnualSavingsNativeUnits(123.) + ), + bsync.AnnualSavingsByFuel( + bsync.EnergyResource("Natural gas"), + bsync.ResourceUnits("MMBtu"), + bsync.AnnualSavingsNativeUnits(0.) + ) + ), + bsync.AnnualPeakElectricityReduction(123.), + bsync.AnnualDemandSavingsCost(123), + bsync.AnnualWaterSavings(0.), + bsync.AnnualWaterCostSavings(0.), + bsync.ImplementationPeriod(1), + bsync.ImplementationPeriodCostSavings(0.), + bsync.PackageFirstCost(0.), + bsync.MVCost(0.), + bsync.OMCostAnnualSavings(123.), + bsync.EquipmentDisposalAndSalvageCosts(0.), + bsync.ProjectMarkup(123.), + bsync.FundingFromIncentives(123.), + bsync.FundingFromTaxCredits(123.), + bsync.OtherFinancialIncentives(123), + bsync.RecurringIncentives(123), + bsync.InternalRateOfReturn(1.), + bsync.SimplePayback(123.), + ID="POM-HVAC-Schedule" + ) + ), + bsync.LinkedPremises( + bsync.LinkedPremises.Building( + bsync.LinkedBuildingID(IDref=b1['ID']) + ) + ), + ID="Scenario-POM-HVAC-Schedule" +) +``` + + +```python +scenarios += pom_sc_1 +scenarios += pom_sc_2 +scenarios += pom_sc_3 +``` + +# Validation + +So did what we just went through actually work? Do we have the required information for a Level 1 Audit? Head over to the [use case validator](https://buildingsync.net/validator) to find out! + +![Selection Tool](./img/UC-Selection.png) + +Use the line below to write the file to disk + + +```python +bsync_dump(root, file="example-level2.xml") +``` + + + + + True + + + + True + + + +You should see a green check mark for the L100 AUDIT use case! + +![Valid](./img/valid_level2.png) + + +```python + +``` diff --git a/docs/notebooks/bsync_examples/example-level2.xml b/docs/notebooks/bsync_examples/example-level2.xml new file mode 100644 index 00000000..db71f740 --- /dev/null +++ b/docs/notebooks/bsync_examples/example-level2.xml @@ -0,0 +1,2245 @@ + + + + + + + + + Small Office Prototype + Here we record general problems / issues identified in a walkthrough survey. +
+ + + 4055 Brooks Street + + + Missoula + MT + 59804 +
+ Commercial + Office + + 1 + 0 + 1 + 0 + true + false + + + Gross + 5500.000000 + + + + + + Conditioned + 5500.000000 + + + + + + 6500.000000 + 0.000000 + 0.213300 + 0.050000 + 2000 + 2000 + 2010 + 2020-03-01 + 2000 + +
+ Space function + Office + Office + + + Peak total occupants + 31.000000 + + + + + 40.000000 + Hours per week + + + 50.000000 + Weeks per year + + + + + Gross + 5500.000000 + + + Conditioned + 5500.000000 + + + Single zone +
+
+ Whole building + Rectangular + + + A1 + + + 123.000000 + + + + + 123.000000 + + + + + 123.000000 + + + + + B1 + + + 123.000000 + + + + + 123.000000 + + + + + 123.000000 + + + + + C1 + + + 123.000000 + + + + + 123.000000 + + + + + 123.000000 + + + + + D1 + + + 123.000000 + + + + + 123.000000 + + + + + 123.000000 + + + + + + + + 123.000000 + Good + + + + + + + 123.000000 + + + +
+
+ + + + + + + + + + Single zone + + + + + Packaged Unitary + Natural gas + 0.123000 + + + + 123.000000 + COP + 123.000000 + 123.000000 + gpm + Good + + + + + + + + + + 2020 + + + + + Warm air + + + 123.000000 + COP + 123.000000 + 123.000000 + gpm + Good + + + + + + + + + + 2020 + + + + + + + Packaged/unitary heat pump + Reciprocating + Single stage + + + 123.000000 + COP + 123.000000 + gpm + Good + + + + + + + + + + 2020 + + + + + + + Central fan + CAV terminal box no reheat + None + + + None + Fixed + + + + + + + + + + + + + + + + 2020 + 5 + Good + + + + + + Single + Good + + + + + + Digital + + +
+ + + + + +
+
+
+
+ + + + + T8 + + + Standard Electronic + + 0.200000 + + 100.000000 + 123.000000 + 123.000000 + 1 + 1.000000 + 10 + false + + + + + + + Programmable + + + + false + +
+ + + + + +
+
+
+ + + + T12 + + + Standard Electronic + 100.000000 + 123.000000 + 123.000000 + 1 + 1.000000 + 1 + true + + + + + + + Programmable + + + + false + +
+ + + + + +
+
+
+ + + + LED + + + Standard Electronic + + 0.100000 + + 100.000000 + 123.000000 + 123.000000 + 1 + 1.000000 + 10 + false + + + + + + + Photocell + Continuous + + + + false + +
+ + + + + +
+
+
+
+ + + + + + + + + + + + 40.000000 + 123.000000 + + + Notes + + 1 + 123.000000 + Continuous + 123.000000 + 123.000000 + + Looped + COP + 123.000000 + 123.000000 + 140.000000 + 123.000000 + 123.000000 + gpm + + + + + + + + + + 2020 + Electricity + Good + + + + +
+ +
+
+ 1 +
+
+ + + 123.000000 + 123.000000 + 123.000000 + Constant Volume + + + + + + 123.000000 + 123.000000 + 123.000000 + Variable Volume + + + + + + + + Wood frame + 1.000000 + + + + + Wood frame + 1.000000 + + + + + + + + Vinyl + Clear uncoated + Single pane + 1.250000 + 0.500000 + 0.800000 + + + + + + Vinyl + Low e + Triple pane + 0.250000 + 0.500000 + 0.700000 + + + + + Insulated metal + 0.500000 + + + Steel + 0.500000 + + + + + + + + 0.500000 + + + + Concrete poured + + + + + Miscellaneous Electric Load + 0.630000 + +
+ + + + + +
+
+
+
+ + + Notes on test + Very Tight + 123.000000 + CFM25 + Blower door + +
+ +
+
+
+
+ + + Notes on test + +
+ +
+
+
+
+
+ + + + + Weekday + Occupied + 06:00:00 + 07:00:00 + 11.000000 + + + Weekday + Occupied + 07:00:00 + 08:00:00 + 21.000000 + + + Weekday + Occupied + 08:00:00 + 12:00:00 + 100.000000 + + + Weekday + Occupied + 12:00:00 + 13:00:00 + 53.000000 + + + Weekday + Occupied + 13:00:00 + 17:00:00 + 100.000000 + + + Weekday + Occupied + 17:00:00 + 18:00:00 + 32.000000 + + + Weekday + Occupied + 18:00:00 + 22:00:00 + 11.000000 + + + Weekday + Occupied + 22:00:00 + 23:00:00 + 5.000000 + + + Weekend + Occupied + 00:00:00 + 23:59:59 + 0.000000 + + + Holiday + Occupied + 00:00:00 + 23:59:59 + 0.000000 + + + + + + +
+ +
+
+
+ + + + Weekday + Lighting + 00:00:00 + 05:00:00 + 18.000000 + + + Weekday + Lighting + 05:00:00 + 07:00:00 + 23.000000 + + + Weekday + Lighting + 07:00:00 + 08:00:00 + 42.000000 + + + Weekday + Lighting + 08:00:00 + 17:00:00 + 90.000000 + + + Weekday + Lighting + 17:00:00 + 18:00:00 + 61.000000 + + + Weekday + Lighting + 18:00:00 + 20:00:00 + 42.000000 + + + Weekday + Lighting + 20:00:00 + 22:00:00 + 32.000000 + + + Weekday + Lighting + 22:00:00 + 23:00:00 + 23.000000 + + + Weekday + Lighting + 23:00:00 + 23:59:59 + 18.000000 + + + Weekend + Lighting + 00:00:00 + 23:59:59 + 18.000000 + + + Holiday + Lighting + 00:00:00 + 23:59:59 + 18.000000 + + + + + + + + + + + + Weekday + Miscellaneous equipment + 00:00:00 + 05:00:00 + 50.000000 + + + Weekday + Miscellaneous equipment + 05:00:00 + 12:00:00 + 100.000000 + + + Weekday + Miscellaneous equipment + 12:00:00 + 13:00:00 + 94.000000 + + + Weekday + Miscellaneous equipment + 13:00:00 + 17:00:00 + 100.000000 + + + Weekday + Miscellaneous equipment + 17:00:00 + 18:00:00 + 50.000000 + + + Weekday + Miscellaneous equipment + 18:00:00 + 23:59:59 + 20.000000 + + + Weekend + Miscellaneous equipment + 00:00:00 + 23:59:59 + 20.000000 + + + Holiday + Miscellaneous equipment + 00:00:00 + 23:59:59 + 20.000000 + + + + + + + + + + + + Weekday + HVAC equipment + 07:00:00 + 20:00:00 + 100.000000 + + + Weekend + HVAC equipment + 07:00:00 + 20:00:00 + 100.000000 + + + Holiday + HVAC equipment + 07:00:00 + 20:00:00 + 100.000000 + + + + + + + + + + + + Weekday + HVAC equipment + 06:00:00 + 07:00:00 + 60.000000 + + + Weekday + HVAC equipment + 07:00:00 + 12:00:00 + 100.000000 + + + Weekday + HVAC equipment + 12:00:00 + 13:00:00 + 80.000000 + + + Weekday + HVAC equipment + 13:00:00 + 18:00:00 + 100.000000 + + + Weekday + HVAC equipment + 18:00:00 + 20:00:00 + 60.000000 + + + Weekend + HVAC equipment + 07:00:00 + 20:00:00 + 30.000000 + + + Holiday + HVAC equipment + 07:00:00 + 20:00:00 + 20.000000 + + + + + + + + +
+ + + + + + + + + + + Air Distribution + + + + Other distribution + + + + Individual system + Update HVAC schedule + The current HVAC schedule is set to be at 100'%' fan operation during weekday from 7am - 8pm. This measure would implement a modified schedule to enable pre-cooling/pre-heating from 6am - 7am, and reduce output to 80'%' during peak time 12pm - 1pm. + 1.000000 + 0.000000 + 0.000000 + true + 2021-01-01 + 2021-12-30 + + + + + + + + + + + Lighting + + + + Retrofit with light emitting diode technologies + + + + Individual system + This measure is designed to replace all fluorescent bulbs with LEDs + 1.000000 + 123.000000 + 123.000000 + true + 2021-01-01 + 2021-12-30 + + + + + + + + + + + Fan + + + + Add VSD motor controller + + + + Individual system + This measure is designed to retrofit all RTU fans with a VSD + 1.000000 + 123.000000 + 123.000000 + true + 2021-01-01 + 2021-12-30 + + + + + + + + + + + + + + + + Electricity + This is required for L1 to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found. + kWh + All end uses + 68516.730000 + 234.000000 + + + + + + + + + + + + + + + kW + 21.120000 + 21.120000 + 5304.000000 + + + + + + Natural gas + No irregularities in monthly energy consumption found. + MMBtu + All end uses + 17.160000 + 17.160000 + + + + + + + + + + + + + + + 91.630000 + + + + + + Electricity + kWh + Total lighting + 25.000000 + 18384.912000 + 62.790000 + + + + Electricity + kWh + Heating + 30.000000 + 22061.894400 + 75.348000 + + + + Electricity + kWh + Cooling + 25.000000 + 18384.912000 + 62.790000 + + + + Electricity + kWh + Domestic hot water + 10.000000 + 7353.964800 + 25.116000 + + + + Electricity + kWh + Plug load + 5.000000 + 3676.982400 + 12.558000 + + + + + + Total + Energy + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 6792.890000 + + + + Total + Energy + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 5841.750000 + + + + Total + Energy + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 6025.190000 + + + + Total + Energy + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 4985.300000 + + + + Total + Energy + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 5184.040000 + + + + Total + Energy + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 5358.550000 + + + + Total + Energy + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 5755.670000 + + + + Total + Energy + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 5981.780000 + + + + Total + Energy + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 5401.940000 + + + + Total + Energy + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 5225.840000 + + + + Total + Energy + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 5672.150000 + + + + Total + Energy + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 6291.630000 + + + + Total + Energy + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 5.700000 + + + + Total + Energy + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 4.010000 + + + + Total + Energy + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 0.580000 + + + + Total + Energy + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 0.400000 + + + + Total + Energy + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 0.020000 + + + + Total + Energy + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 0.000000 + + + + Total + Energy + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 0.000000 + + + + Total + Energy + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 0.000000 + + + + Total + Energy + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 0.000000 + + + + Total + Energy + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 0.010000 + + + + Total + Energy + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 0.360000 + + + + Total + Energy + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 6.080000 + + + + Peak + On-peak + Power + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 15.420000 + + + + Peak + On-peak + Power + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 15.500000 + + + + Peak + On-peak + Power + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 16.250000 + + + + Peak + On-peak + Power + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 16.650000 + + + + Peak + On-peak + Power + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 18.560000 + + + + Peak + On-peak + Power + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 20.010000 + + + + Peak + On-peak + Power + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 20.820000 + + + + Peak + On-peak + Power + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 21.120000 + + + + Peak + On-peak + Power + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 20.420000 + + + + Peak + On-peak + Power + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 20.080000 + + + + Peak + On-peak + Power + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 17.400000 + + + + Peak + On-peak + Power + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 16.300000 + + + + Load factor + Power + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 0.373000 + + + + Load factor + Power + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 0.394000 + + + + Load factor + Power + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 0.390000 + + + + Load factor + Power + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 0.358000 + + + + Load factor + Power + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 0.374000 + + + + Load factor + Power + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 0.386000 + + + + Load factor + Power + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 0.369000 + + + + Load factor + Power + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 0.372000 + + + + Load factor + Power + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 0.373000 + + + + Load factor + Power + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 0.354000 + + + + Load factor + Power + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 0.380000 + + + + Load factor + Power + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 0.362000 + + + + Cost + Cost + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 520.480000 + + + + Cost + Cost + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 451.530000 + + + + Cost + Cost + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 464.830000 + + + + Cost + Cost + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 389.430000 + + + + Cost + Cost + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 403.840000 + + + + Cost + Cost + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 416.490000 + + + + Cost + Cost + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 445.290000 + + + + Cost + Cost + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 461.680000 + + + + Cost + Cost + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 419.640000 + + + + Cost + Cost + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 406.870000 + + + + Cost + Cost + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 439.230000 + + + + Cost + Cost + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 484.140000 + + + + Cost + Cost + 2019-01-01T00:00:00 + 2019-02-01T00:00:00 + 31 + Day + Month + 30.440000 + + + + Cost + Cost + 2019-02-01T00:00:00 + 2019-03-01T00:00:00 + 28 + Day + Month + 21.410000 + + + + Cost + Cost + 2019-03-01T00:00:00 + 2019-04-01T00:00:00 + 31 + Day + Month + 3.100000 + + + + Cost + Cost + 2019-04-01T00:00:00 + 2019-05-01T00:00:00 + 30 + Day + Month + 2.140000 + + + + Cost + Cost + 2019-05-01T00:00:00 + 2019-06-01T00:00:00 + 31 + Day + Month + 0.110000 + + + + Cost + Cost + 2019-06-01T00:00:00 + 2019-07-01T00:00:00 + 30 + Day + Month + 0.000000 + + + + Cost + Cost + 2019-07-01T00:00:00 + 2019-08-01T00:00:00 + 31 + Day + Month + 0.000000 + + + + Cost + Cost + 2019-08-01T00:00:00 + 2019-09-01T00:00:00 + 31 + Day + Month + 0.000000 + + + + Cost + Cost + 2019-09-01T00:00:00 + 2019-10-01T00:00:00 + 30 + Day + Month + 0.000000 + + + + Cost + Cost + 2019-10-01T00:00:00 + 2019-11-01T00:00:00 + 31 + Day + Month + 0.050000 + + + + Cost + Cost + 2019-11-01T00:00:00 + 2019-12-01T00:00:00 + 30 + Day + Month + 1.920000 + + + + Cost + Cost + 2019-12-01T00:00:00 + 2020-01-01T00:00:00 + 31 + Day + Month + 32.470000 + + + + + + 250953.500000 + 45.600000 + 759011.900000 + 138.000000 + 250953.500000 + 45.600000 + 250.953500 + 0.000000 + 0.000000 + 0.000000 + 5395.000000 + 0.980000 + + + + + + + + + + + + + + 2021-03-24 + + + Portfolio Manager + 2019 + 56.000000 + + + + + 274825.000000 + 50.000000 + + + + + + + + + + + + + 67181.500000 + 931 + 70.000000 + + + + + 207643.500000 + 37.800000 + 4451.510000 + 0.810000 + + + + + + + + + + + + + + + + Capital + 123.000000 + 123 + + + Electricity + kWh + 123.000000 + + + Natural gas + MMBtu + 0.000000 + + + 123.000000 + 123 + 0.000000 + 0.000000 + 1 + 0.000000 + 0.000000 + 123.000000 + 0.000000 + 0.000000 + 123.000000 + 123.000000 + 123.000000 + 123 + 123 + 123.000000 + 1.000000 + + + + + + + + + + + + + + + + Capital + 123.000000 + 123 + + + Electricity + kWh + 123.000000 + + + Natural gas + MMBtu + 12.000000 + + + 123.000000 + 123 + 0.000000 + 0.000000 + 1 + 0.000000 + 0.000000 + 123.000000 + 0.000000 + 0.000000 + 123.000000 + 123.000000 + 123.000000 + 123 + 123 + 123.000000 + 1.000000 + + + + + + + + + + + + + + + + Low-Cost or No-Cost + 123.000000 + 123 + + + Electricity + kWh + 123.000000 + + + Natural gas + MMBtu + 0.000000 + + + 123.000000 + 123 + 0.000000 + 0.000000 + 1 + 0.000000 + 0.000000 + 123.000000 + 0.000000 + 0.000000 + 123.000000 + 123.000000 + 123.000000 + 123 + 123 + 123.000000 + 1.000000 + + + + + + + + + + + + + + + + + + --01-01 + --01-01 + --01-01 + --01-01 + 0.072500 + 0.000000 + + + + + https://missoulaelectric.com/member-care/billing-payment/rates/ + 28.000000 + + + 12692 + Missoula Electric Cooperative + + Some-meter-ID + + some-account-number + Building Owner + + + + + + + + + --01-01 + --01-01 + 5.500000 + + + + + https://naturalgaslocal.com/states/montana/missoula/ + + + NorthWestern Energy + + Some-meter-ID + + some-other-account-number + Building Owner + + + + + + + + + + + + + + Owner + + The dude + Some big company + + + 123-456-7890 + + + + + the.dude@somebigco.net + + + + + + Energy Auditor + + The lady + Auditeers + + + 123-456-7890 + + + + + the.lady@the-three-auditeers.com + + + + + + + diff --git a/docs/notebooks/bsync_examples/img/valid_level2.png b/docs/notebooks/bsync_examples/img/valid_level2.png new file mode 100644 index 0000000000000000000000000000000000000000..b80fe67888ca7c9819073da87b2cbf0bd2376727 GIT binary patch literal 31423 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

M4=b55+$)L7UmiAP_H|a~6)^-!*E*^maPt*; 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 &Qi8Dhg8!6E?7?(A(kV&#npT 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 Date: Fri, 10 Jun 2022 11:11:54 -0600 Subject: [PATCH 2/5] Update notebook with OS simulation Map inputs with OS simulation of prototype small office Change location to Denver --- .../bsync_examples/Small-Office-Level-2.md | 625 +++++++++--------- docs/notebooks/bsync_examples/img/ESPM.png | Bin 0 -> 29708 bytes 2 files changed, 317 insertions(+), 308 deletions(-) create mode 100644 docs/notebooks/bsync_examples/img/ESPM.png diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-2.md b/docs/notebooks/bsync_examples/Small-Office-Level-2.md index efa92d82..5cbace7a 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-2.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-2.md @@ -61,14 +61,13 @@ def bsync_dump(root_element, file="example1.xml"): # Starting the Audit ## Small Office Prototype Building -The small office prototype is a single story rectangular building. We will show some love to Missoula and assume this building is located at 4055 Brooks St. Missoula, MT 59804. -![](./img/b1-bldg.png) +The small office prototype is a single story rectangular building. We will use Denver as the location. We can summarize the high level features as: - Total Floor Area: 5500sf - WWR: Southern Wall ~25%, Other Walls ~20% -- Climate Zone 6B -- Assume built year: 2006 +- Climate Zone 5B +- Assume built year: 2000 - Let's assume this is on the 90.1-2004 code cycle ## "I have a building...where do I start" @@ -160,39 +159,6 @@ r1 += utilities pretty_print(root) ``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #### 6.2.1.1 Building information This section of Standard 211 asks for lots of detail. We walk through the components of this that get added _as child elements of the building_, and then discuss other information. @@ -200,7 +166,7 @@ This section of Standard 211 asks for lots of detail. We walk through the compon ```python # 6.2.1.1.a - name -b1 += bsync.PremisesName('Small Office Prototype') +b1 += bsync.PremisesName('Small Office Prototype in Denver') # 6.1.1.1.m b1 += bsync.PremisesNotes("Here we record general problems / issues identified in a walkthrough survey.") @@ -209,12 +175,12 @@ b1 += bsync.PremisesNotes("Here we record general problems / issues identified i b1 += bsync.Address( bsync.StreetAddressDetail( bsync.Simplified( - bsync.StreetAddress("4055 Brooks Street") + bsync.StreetAddress("Some address") ) ), - bsync.Address.State("MT"), - bsync.City("Missoula"), - bsync.PostalCode("59804") + bsync.Address.State("CO"), + bsync.City("Denver"), + bsync.PostalCode("80401") ) # 6.2.1.1.b - gross and conditioned floor area @@ -419,6 +385,13 @@ schedule_hvac_new = bsync.Schedule(ID="Schedule-HVAC-new") # occupancy schedule schedule_occ += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), bsync.ScheduleDetail( bsync.DayType("Weekday"), bsync.ScheduleCategory("Occupied"), @@ -475,6 +448,13 @@ schedule_occ += bsync.ScheduleDetails( bsync.DayEndTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(5.) ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Occupied"), + bsync.DayStartTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), bsync.ScheduleDetail( bsync.DayType("Weekend"), bsync.ScheduleCategory("Occupied"), @@ -525,6 +505,20 @@ schedule_light += bsync.ScheduleDetails( bsync.DayType("Weekday"), bsync.ScheduleCategory("Lighting"), bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(90.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(80.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("Lighting"), + bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(90.) ), @@ -589,13 +583,13 @@ schedule_pl += bsync.ScheduleDetails( bsync.DayType("Weekday"), bsync.ScheduleCategory("Miscellaneous equipment"), bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(50.) ), bsync.ScheduleDetail( bsync.DayType("Weekday"), bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(100.) ), @@ -652,23 +646,37 @@ schedule_hvac += bsync.ScheduleDetails( bsync.ScheduleDetail( bsync.DayType("Weekday"), bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("19:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(100.) ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("19:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), bsync.ScheduleDetail( bsync.DayType("Weekend"), bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.PartialOperationPercentage(100.) + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( bsync.DayType("Holiday"), bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.PartialOperationPercentage(100.) + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) ) ) schedule_hvac += bsync.LinkedPremises( @@ -678,6 +686,13 @@ schedule_hvac += bsync.LinkedPremises( ) # upgraded HVAC schedule (for EEM) schedule_hvac_new += bsync.ScheduleDetails( + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), bsync.ScheduleDetail( bsync.DayType("Weekday"), bsync.ScheduleCategory("HVAC equipment"), @@ -713,19 +728,26 @@ schedule_hvac_new += bsync.ScheduleDetails( bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), bsync.PartialOperationPercentage(60.) ), + bsync.ScheduleDetail( + bsync.DayType("Weekday"), + bsync.ScheduleCategory("HVAC equipment"), + bsync.DayStartTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) + ), bsync.ScheduleDetail( bsync.DayType("Weekend"), bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.PartialOperationPercentage(30.) + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( bsync.DayType("Holiday"), bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.PartialOperationPercentage(20.) + bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), + bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.PartialOperationPercentage(0.) ) ) schedule_hvac_new += bsync.LinkedPremises( @@ -754,7 +776,7 @@ In addition, 6.2.1.2.e requires information of the building overall tightness, a roofsys = bsync.RoofSystems() roof = bsync.RoofSystem( bsync.RoofConstruction("Wood frame"), - bsync.RoofRValue(1.), + bsync.RoofUFactor(4.706), ID=f"Roof-1" ) roofsys += roof @@ -763,7 +785,7 @@ roofsys += roof wallsys = bsync.WallSystems() wall = bsync.WallSystem( bsync.ExteriorWallConstruction("Wood frame"), - bsync.WallRValue(1.), + bsync.WallUFactor(0.547), ID=f"Wall-1" ) wallsys += wall @@ -777,9 +799,9 @@ win1_orig = bsync.FenestrationSystem( bsync.FenestrationFrameMaterial("Vinyl"), bsync.GlassType("Clear uncoated"), bsync.FenestrationGlassLayers("Single pane"), - bsync.FenestrationUFactor(1.25), - bsync.SolarHeatGainCoefficient(0.5), - bsync.VisibleTransmittance(0.8), + bsync.FenestrationUFactor(3.241), + bsync.SolarHeatGainCoefficient(0.391), + bsync.VisibleTransmittance(0.391), ID=f"Window-1-Original" ) win1 = bsync.FenestrationSystem( @@ -789,9 +811,9 @@ win1 = bsync.FenestrationSystem( bsync.FenestrationFrameMaterial("Vinyl"), bsync.GlassType("Low e"), bsync.FenestrationGlassLayers("Triple pane"), - bsync.FenestrationUFactor(0.25), - bsync.SolarHeatGainCoefficient(0.5), - bsync.VisibleTransmittance(0.7), + bsync.FenestrationUFactor(0.3), + bsync.SolarHeatGainCoefficient(0.391), + bsync.VisibleTransmittance(0.391), ID=f"Window-1" ) door = bsync.FenestrationSystem( @@ -802,7 +824,7 @@ door = bsync.FenestrationSystem( ) ), bsync.FenestrationFrameMaterial("Steel"), - bsync.FenestrationRValue(0.5), + bsync.FenestrationUFactor(2.839), ID=f"Door-1" ) fenestsys += win1_orig @@ -815,7 +837,7 @@ found = bsync.FoundationSystem( bsync.GroundCouplings( bsync.GroundCoupling( bsync.SlabOnGrade( - bsync.SlabUFactor(0.5) + bsync.SlabUFactor(0.345) ) ) ), @@ -828,9 +850,9 @@ foundsys += found infiltsys = bsync.AirInfiltrationSystems() infilt = bsync.AirInfiltrationSystem( bsync.AirInfiltrationNotes("Notes on test"), - bsync.AirInfiltrationSystem.Tightness("Very Tight"), - bsync.AirInfiltrationValue(123.), - bsync.AirInfiltrationValueUnits("CFM25"), + bsync.AirInfiltrationSystem.Tightness("Tight"), + bsync.AirInfiltrationValue(0.151), + bsync.AirInfiltrationValueUnits("ACHnatural"), bsync.AirInfiltrationTest("Blower door"), bsync.LinkedPremises( bsync.LinkedPremises.Section( @@ -869,6 +891,9 @@ systems += waterinfiltsys ```python # then we link these components to the envelope elements under Section/Sides section_wb += bsync.FootprintShape("Rectangular") +wallarea = {"A1":909.01223, "B1":606.0082, "C1":909.01223, "D1":606.0082} +windowarea = {"A1":180.18786, "B1":120.12524, "C1":180.18786, "D1":120.12524} +doorarea = {"A1":42.08689, "B1":0.0, "C1":0.0, "D1":0.0} section_sides = bsync.Sides() for sidenumber in ["A1", "B1", "C1", "D1"]: @@ -876,19 +901,19 @@ for sidenumber in ["A1", "B1", "C1", "D1"]: bsync.SideNumber(sidenumber), bsync.WallIDs( bsync.WallID( - bsync.WallArea(123.), + bsync.WallArea(wallarea[sidenumber]), IDref=wall["ID"] ) ), bsync.WindowIDs( bsync.WindowID( - bsync.FenestrationArea(123.), + bsync.FenestrationArea(windowarea[sidenumber]), IDref=win1_orig["ID"] ) ), bsync.DoorIDs( bsync.DoorID( - bsync.FenestrationArea(123.), + bsync.FenestrationArea(doorarea[sidenumber]), IDref=door["ID"] ) ) @@ -897,7 +922,7 @@ for sidenumber in ["A1", "B1", "C1", "D1"]: section_roofs = bsync.Roofs( bsync.Roof( bsync.RoofID( - bsync.RoofArea(123.), + bsync.RoofArea(6444.999), bsync.RoofCondition("Good"), IDref=roof["ID"] ) @@ -906,7 +931,7 @@ section_roofs = bsync.Roofs( section_founds = bsync.Foundations( bsync.Foundation( bsync.FoundationID( - bsync.FoundationArea(123.), + bsync.FoundationArea(3891.1536), IDref=found["ID"] ) ) @@ -950,136 +975,125 @@ hvac_system += bsync.LinkedPremises( # heating and cooling system hc_systems = bsync.HeatingAndCoolingSystems() hc_systems += bsync.ZoningSystemType("Single zone") + # cooling system css = bsync.CoolingSources() -cs = bsync.CoolingSource( - bsync.CoolingSourceType( - bsync.DX( - bsync.DXSystemType("Packaged/unitary heat pump"), - bsync.CompressorType("Reciprocating"), - bsync.CompressorStaging("Single stage") - ) - ), - bsync.AnnualCoolingEfficiencyValue(123.), - bsync.AnnualCoolingEfficiencyUnits('COP'), - bsync.Capacity(123.), - bsync.CapacityUnits('gpm'), - bsync.CoolingSourceCondition('Good'), - bsync.CoolingSource.Controls( - bsync.CoolingSource.Controls.Control( - bsync.CoolingSource.Controls.Control.OtherControlTechnology( - bsync.ControlSystemType( - bsync.Digital() +coolingcapacity = [6862.6, 6344.4, 4688.8, 5836.3, 5989.0] +for each in range(1,6): + cs = bsync.CoolingSource( + bsync.CoolingSourceType( + bsync.DX( + bsync.DXSystemType("Packaged/unitary heat pump"), + bsync.CompressorType("Reciprocating"), + bsync.CompressorStaging("Single stage") + ) + ), + bsync.AnnualCoolingEfficiencyValue(2.61), + bsync.AnnualCoolingEfficiencyUnits('COP'), + bsync.Capacity(coolingcapacity[each-1]), + bsync.CapacityUnits('W'), + bsync.CoolingSourceCondition('Good'), + bsync.CoolingSource.Controls( + bsync.CoolingSource.Controls.Control( + bsync.CoolingSource.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) ) ) - ) - ), - bsync.YearInstalled(2020), - ID=f"CoolingSource-1" -) -css += cs + ), + bsync.YearInstalled(2000), + ID=f"CoolingSource-{each}" + ) + css += cs + hc_systems += css + # heating system hss = bsync.HeatingSources() -hs1 = bsync.HeatingSource( - bsync.HeatingSourceType( - bsync.HeatingSourceType.HeatPump( - bsync.HeatPumpType("Packaged Unitary"), - bsync.HeatPumpBackupSystemFuel("Natural gas"), - bsync.HeatPumpBackupAFUE(0.123), - bsync.CoolingSourceID(IDref=cs['ID']) - ) - ), - bsync.AnnualHeatingEfficiencyValue(123.), - bsync.AnnualHeatingEfficiencyUnits('COP'), - bsync.InputCapacity(123.), - bsync.HeatingSource.Capacity(123.), - bsync.CapacityUnits('gpm'), - bsync.HeatingSourceCondition('Good'), - bsync.HeatingSource.Controls( - bsync.HeatingSource.Controls.Control( - bsync.HeatingSource.Controls.Control.OtherControlTechnology( - bsync.ControlSystemType( - bsync.Digital() - ) +heatingcapacity = [7203.66, 6659.65, 4921.86, 6126.30, 6286.66] +for each in range(1,6): + hs = bsync.HeatingSource( + bsync.HeatingSourceType( + bsync.HeatingSourceType.HeatPump( + bsync.HeatPumpType("Packaged Unitary"), + bsync.HeatPumpBackupSystemFuel("Natural gas"), + bsync.HeatPumpBackupAFUE(0.0), + bsync.CoolingSourceID(IDref=cs['ID']) ) - ) - ), - bsync.YearInstalled(2020), - ID=f"HeatingSource-1" -) -hs2 = bsync.HeatingSource( - bsync.HeatingSourceType( - bsync.Furnace( - bsync.FurnaceType('Warm air') - ) - ), - bsync.AnnualHeatingEfficiencyValue(123.), - bsync.AnnualHeatingEfficiencyUnits('COP'), - bsync.InputCapacity(123.), - bsync.HeatingSource.Capacity(123.), - bsync.CapacityUnits('gpm'), - bsync.HeatingSourceCondition('Good'), - bsync.HeatingSource.Controls( - bsync.HeatingSource.Controls.Control( - bsync.HeatingSource.Controls.Control.OtherControlTechnology( - bsync.ControlSystemType( - bsync.Digital() + ), + bsync.AnnualHeatingEfficiencyValue(3.01), + bsync.AnnualHeatingEfficiencyUnits('COP'), + bsync.InputCapacity(heatingcapacity[each-1]), + bsync.HeatingSource.Capacity(heatingcapacity[each-1]), + bsync.CapacityUnits('W'), + bsync.HeatingSourceCondition('Good'), + bsync.HeatingSource.Controls( + bsync.HeatingSource.Controls.Control( + bsync.HeatingSource.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) ) ) - ) - ), - bsync.YearInstalled(2020), - ID=f"HeatingSource-2" -) -hss += hs1 -hss += hs2 + ), + bsync.YearInstalled(2000), + ID=f"HeatingSource-{each}" + ) + hss += hs + hc_systems += hss + # delivery system delivers = bsync.Deliveries() -deliver = bsync.Delivery( - bsync.DeliveryType( - bsync.CentralAirDistribution( - bsync.AirDeliveryType("Central fan"), - bsync.TerminalUnit("CAV terminal box no reheat"), - bsync.ReheatSource("None"), - bsync.FanBased( - bsync.AirSideEconomizer( - bsync.AirSideEconomizerType("None"), - bsync.EconomizerControl("Fixed"), - ID=f"AirSideEconomizer-1" +for each in range(1,6): + deliver = bsync.Delivery( + bsync.DeliveryType( + bsync.CentralAirDistribution( + bsync.AirDeliveryType("Central fan"), + bsync.TerminalUnit("CAV terminal box no reheat"), + bsync.ReheatSource("None"), + bsync.FanBased( + bsync.AirSideEconomizer( + bsync.AirSideEconomizerType("None"), + bsync.EconomizerControl("Fixed"), + ID=f"AirSideEconomizer-{each}" + ) ) ) - ) - ), - bsync.HeatingSourceID(IDref=hs1["ID"]), - bsync.CoolingSourceID(IDref=cs["ID"]), - bsync.Delivery.Controls( - bsync.Delivery.Controls.Control( - bsync.Delivery.Controls.Control.OtherControlTechnology( - bsync.ControlSystemType( - bsync.Digital() + ), + bsync.HeatingSourceID(IDref=f"HeatingSource-{each}"), + bsync.CoolingSourceID(IDref=f"CoolingSource-{each}"), + bsync.Delivery.Controls( + bsync.Delivery.Controls.Control( + bsync.Delivery.Controls.Control.OtherControlTechnology( + bsync.ControlSystemType( + bsync.Digital() + ) ) ) - ) - ), - bsync.YearInstalled(2020), - bsync.Quantity(5), - bsync.DeliveryCondition("Good"), - ID=f"Delivery-1" -) -delivers += deliver + ), + bsync.YearInstalled(2000), + bsync.Quantity(1), + bsync.DeliveryCondition("Good"), + ID=f"Delivery-{each}" + ) + delivers += deliver + hc_systems += delivers + # duct duct_systems = bsync.DuctSystems() -duct = bsync.DuctSystem( - bsync.DuctConfiguration("Single"), - bsync.DuctInsulationCondition("Good"), - bsync.HeatingDeliveryID(IDref=deliver['ID']), - bsync.CoolingDeliveryID(IDref=deliver['ID']), - ID=f"DuctSystem-1" -) -duct_systems += duct +for each in range(1,6): + duct = bsync.DuctSystem( + bsync.DuctConfiguration("Single"), + bsync.DuctInsulationCondition("Good"), + bsync.HeatingDeliveryID(IDref=f"Delivery-{each}"), + bsync.CoolingDeliveryID(IDref=f"Delivery-{each}"), + ID=f"DuctSystem-{each}" + ) + duct_systems += duct + # HVAC control hvacctl = bsync.HVACControlSystemTypes( bsync.HVACControlSystemType("Digital") @@ -1092,28 +1106,31 @@ hvac_system += hvacctl # fan fan_systems = bsync.FanSystems() -fan = bsync.FanSystem( - bsync.FanEfficiency(123.), - bsync.FanSize(123.), - bsync.InstalledFlowRate(123.), - bsync.FanControlType("Constant Volume"), - bsync.LinkedSystemIDs( - bsync.LinkedSystemID(IDref=deliver['ID']) - ), - ID=f"FanSystem-1" -) -fan_new = bsync.FanSystem( - bsync.FanEfficiency(123.), - bsync.FanSize(123.), - bsync.InstalledFlowRate(123.), - bsync.FanControlType("Variable Volume"), - bsync.LinkedSystemIDs( - bsync.LinkedSystemID(IDref=deliver['ID']) - ), - ID=f"FanSystem-new" -) -fan_systems += fan -fan_systems += fan_new +fanflowrate = [0.44, 0.40, 0.30, 0.37, 0.38] +fanflowrate = [x*2118.88 for x in fanflowrate] +for each in range(1,6): + fan = bsync.FanSystem( + bsync.FanEfficiency(0.54), + bsync.FanSize(1000.), + bsync.FanInstalledFlowRate(fanflowrate[each-1]), + bsync.FanControlType("Constant Volume"), + bsync.LinkedSystemIDs( + bsync.LinkedSystemID(IDref=f"Delivery-{each}") + ), + ID=f"FanSystem-{each}" + ) + fan_new = bsync.FanSystem( + bsync.FanEfficiency(0.54), + bsync.FanSize(1000.), + bsync.InstalledFlowRate(fanflowrate[each-1]), + bsync.FanControlType("Variable Volume"), + bsync.LinkedSystemIDs( + bsync.LinkedSystemID(IDref=f"Delivery-{each}") + ), + ID=f"FanSystem-{each}-new" + ) + fan_systems += fan + fan_systems += fan_new ``` @@ -1127,35 +1144,36 @@ shw_systems = bsync.DomesticHotWaterSystems() shw = bsync.DomesticHotWaterSystem( bsync.DomesticHotWaterType( bsync.StorageTank( - bsync.TankHeatingType( - bsync.Direct( - bsync.DirectTankHeatingSource( - bsync.ElectricResistance() - ) - ) - ), + #bsync.TankHeatingType( + # bsync.Direct( + # bsync.DirectTankHeatingSource( + # bsync.ElectricResistance(123.) + # ) + # ) + #), + bsync.TankHeatingType(bsync.Unknown()), bsync.TankVolume(40.), - bsync.StorageTankInsulationRValue(123.) + bsync.StorageTankInsulationRValue(123.) # arbitrary value, actually not required ) ), bsync.DomesticHotWaterSystemNotes("Notes"), bsync.PrimaryFuel("Electricity"), bsync.Recirculation( bsync.RecirculationLoopCount(1), - bsync.RecirculationFlowRate(123.), + bsync.RecirculationFlowRate(3.84972648), # 4.048e-06 m3/s to gal/hr bsync.RecirculationControlType("Continuous"), - bsync.PipeInsulationThickness(123.), - bsync.RecirculationEnergyLossRate(123.) + bsync.PipeInsulationThickness(123.), # arbitrary value, actually not required + bsync.RecirculationEnergyLossRate(1.870180469) ), bsync.HotWaterDistributionType("Looped"), bsync.HotWaterSetpointTemperature(140.), - bsync.WaterHeaterEfficiency(123.), + bsync.WaterHeaterEfficiency(1.), bsync.WaterHeaterEfficiencyType("COP"), - bsync.DailyHotWaterDraw(123.), - bsync.ParasiticFuelConsumptionRate(123.), - bsync.Capacity(123.), - bsync.CapacityUnits("gpm"), - bsync.YearInstalled(2020), + bsync.DailyHotWaterDraw(40.), # arbitrary value, actually not required + bsync.ParasiticFuelConsumptionRate(1950.52), # 572 W to Btu/hr + bsync.Capacity(11722.84), + bsync.CapacityUnits("W"), + bsync.YearInstalled(2000), bsync.DomesticHotWaterSystemCondition("Good"), bsync.DomesticHotWaterSystem.Controls( bsync.DomesticHotWaterSystem.Controls.Control( @@ -1201,8 +1219,8 @@ ls1 = bsync.LightingSystem( bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.2) ), - bsync.InstalledPower(123.), - bsync.LampPower(123.), + bsync.InstalledPower(5.50205), + bsync.LampPower(550.205), bsync.NumberOfLampsPerBallast(1), bsync.NumberOfBallastsPerLuminaire(1.), bsync.NumberOfLuminaires(10), @@ -1238,11 +1256,11 @@ ls2 = bsync.LightingSystem( ) ), bsync.BallastType("Standard Electronic"), - bsync.InstalledPower(123.), - bsync.LampPower(123.), + bsync.InstalledPower(1.58258), + bsync.LampPower(316.516), bsync.NumberOfLampsPerBallast(1), bsync.NumberOfBallastsPerLuminaire(1.), - bsync.NumberOfLuminaires(1), + bsync.NumberOfLuminaires(5), bsync.PercentPremisesServed(100.), bsync.LightingAutomationSystem(False), bsync.LightingSystem.Controls( @@ -1278,8 +1296,8 @@ ls_new = bsync.LightingSystem( bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.1) ), - bsync.InstalledPower(123.), - bsync.LampPower(123.), + bsync.InstalledPower(0.64), + bsync.LampPower(64.), bsync.NumberOfLampsPerBallast(1), bsync.NumberOfBallastsPerLuminaire(1.), bsync.NumberOfLuminaires(10), @@ -1411,24 +1429,24 @@ elec_ut = bsync.Utility( bsync.FlatRate.RatePeriods.RatePeriod( bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), - bsync.EnergyCostRate(0.0725), # $0.0725/kWh + bsync.EnergyCostRate(0.00458), # $0.00458/kWh bsync.ApplicableStartDateForDemandRate(date(2019,1,1)), bsync.ApplicableEndDateForDemandRate(date(2020,1,1)), - bsync.ElectricDemandRate(0.0) # no demand charge per https://missoulaelectric.com/member-care/billing-payment/rates/ + bsync.ElectricDemandRate(3.86) # $3.86/kW ) ) ) ), - bsync.ReferenceForRateStructure("https://missoulaelectric.com/member-care/billing-payment/rates/"), - bsync.FixedMonthlyCharge(28.), + bsync.ReferenceForRateStructure("https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/Regulatory'/%'20Filings/CO%20Recent'/%'20Filings/PSCo_Electric_Entire_Tariff.pdf"), + bsync.FixedMonthlyCharge(346.29), ID="RateSchedule-Electricity" ) ), bsync.UtilityMeterNumbers( bsync.UtilityMeterNumber("Some-meter-ID") ), - bsync.EIAUtilityID(12692), - bsync.UtilityName("Missoula Electric Cooperative"), + bsync.EIAUtilityID(12345), + bsync.UtilityName("Xcel Energy"), bsync.UtilityAccountNumber("some-account-number"), bsync.UtilityBillpayer("Building Owner"), ID="Utility-Electric" @@ -1442,19 +1460,20 @@ ng_ut = bsync.Utility( bsync.FlatRate.RatePeriods.RatePeriod( bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), - bsync.EnergyCostRate(5.5) # $/MMBtu + bsync.EnergyCostRate(0.16360) # $/therm ) ) ) ), - bsync.ReferenceForRateStructure("https://naturalgaslocal.com/states/montana/missoula/"), + bsync.ReferenceForRateStructure("https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/psco_gas_entire_tariff.pdf"), + bsync.FixedMonthlyCharge(43.88), ID="RateSchedule-Natural-Gas" ) ), bsync.UtilityMeterNumbers( bsync.UtilityMeterNumber("Some-meter-ID") ), - bsync.UtilityName("NorthWestern Energy"), + bsync.UtilityName("Xcel Energy"), bsync.UtilityAccountNumber("some-other-account-number"), bsync.UtilityBillpayer("Building Owner"), ID="Utility-Natural-Gas" @@ -1472,9 +1491,9 @@ Now that we have a current building measured scenario, we want to declare energy | Resource Type | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| Electricity (kWh) | 6792.89 | 5841.75 | 6025.19 | 4985.3 | 5184.04 | 5358.55 | 5755.67 | 5981.78 | 5401.94 | 5225.84 | 5672.15 | 6291.63 | -| Natural Gas (MMBtu) | 5.7 | 4.01 | 0.58 | 0.4 | 0.02 | 0 | 0 | 0 | 0 | 0.01 | 0.36 | 6.08 | 17.16 | -| GHG Emissions (MtCO2e) | 250.0 | 240.0 | 260.0 | 250.0 | 260.0 | 230.0 | 280.0 | 270.0 | 260.0 | 250.0 | 240.0 | 250.0 | +| Electricity (kWh) | 5663.92 | 5099.31 | 5290.08 | 4868.67 | 5121.08 | 6018.81 | 5776.42 | 6407.08 | 5702.81 | 5139.72 | 5080.94 | 5204.11 | +| Natural Gas (MMBtu) | 1.83 | 2.32 | 0.45 | 0.62 | 0.04 | 0 | 0 | 0 | 0 | 0.0 | 0.47 | 0.63 | +| Electricity peak (kW) | 19.68 | 19.11 | 17.02 | 19.53 | 16.04 | 19.94 | 18.65 | 18.57 | 18.48 | 16.81 | 17.36 | 18.68 | In BuildingSync land, we need to declare an resource use for each resource type. Standard, allowable enumerations exist for this already. We do this as follows: @@ -1487,7 +1506,7 @@ all_ru = bsync.ResourceUses() # we also connect it up to a utility elec_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), - bsync.ResourceUseNotes("This is required for L1 to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found."), + bsync.ResourceUseNotes("This is required to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found."), bsync.ResourceUnits('kWh'), bsync.PeakResourceUnits('kW'), bsync.EndUse('All end uses'), @@ -1497,11 +1516,11 @@ elec_ru = bsync.ResourceUse( ID=f"ResourceUse-Electricity" ) # given the above, we add the annual totals -elec_ru += bsync.AnnualFuelUseNativeUnits(68516.73) -elec_ru += bsync.AnnualFuelUseConsistentUnits(234.) #convert to MMBTU -elec_ru += bsync.AnnualPeakNativeUnits(21.12) # kW as specified above -elec_ru += bsync.AnnualPeakConsistentUnits(21.12) # already in kW, same as above -elec_ru += bsync.AnnualFuelCost(5304.) # $28 monthly + $0.0725/kwh per https://missoulaelectric.com/member-care/billing-payment/rates/ +elec_ru += bsync.AnnualFuelUseNativeUnits(65372.2222) +elec_ru += bsync.AnnualFuelUseConsistentUnits(223.05928) #convert to MMBTU +elec_ru += bsync.AnnualPeakNativeUnits(19.93565) # kW as specified above +elec_ru += bsync.AnnualPeakConsistentUnits(19.93565) # already in kW, same as above +elec_ru += bsync.AnnualFuelCost(5303.57) # # create a resource use for natural gas, units of MMBtu, all end uses # additional connect it up to the utility @@ -1516,18 +1535,18 @@ ng_ru = bsync.ResourceUse( ID=f"ResourceUse-Natural-gas" ) # given the above, we add the annual totals -ng_ru += bsync.AnnualFuelUseNativeUnits(17.16) -ng_ru += bsync.AnnualFuelUseConsistentUnits(17.16) # already in MMBTU -ng_ru += bsync.AnnualFuelCost(91.63) # ~ $5.50/1000ft3 NG per https://naturalgaslocal.com/states/montana/missoula/ -251.16 +ng_ru += bsync.AnnualFuelUseNativeUnits(6.35985) +ng_ru += bsync.AnnualFuelUseConsistentUnits(6.35985) # already in MMBTU +ng_ru += bsync.AnnualFuelCost(536.97) # + # create resource uses for submetering of lighting, heating and cooling lighting_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), - bsync.EndUse('Total lighting'), - bsync.AnnualFuelUseNativeUnits(18384.912), - bsync.AnnualFuelUseConsistentUnits(62.79), - bsync.PercentEndUse(25.), + bsync.EndUse('Interior lighting'), + bsync.AnnualFuelUseNativeUnits(19711.1111), + bsync.AnnualFuelUseConsistentUnits(67.2571), + bsync.PercentEndUse(29.32), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Lighting-Submeter" ) @@ -1535,9 +1554,9 @@ heating_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Heating'), - bsync.AnnualFuelUseNativeUnits(22061.8944), - bsync.AnnualFuelUseConsistentUnits(75.348), - bsync.PercentEndUse(30.), + bsync.AnnualFuelUseNativeUnits(4141.66667), + bsync.AnnualFuelUseConsistentUnits(14.13195), + bsync.PercentEndUse(6.16), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Heating-Submeter" ) @@ -1545,9 +1564,9 @@ cooling_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Cooling'), - bsync.AnnualFuelUseNativeUnits(18384.912), - bsync.AnnualFuelUseConsistentUnits(62.79), - bsync.PercentEndUse(25.), + bsync.AnnualFuelUseNativeUnits(7136.11111), + bsync.AnnualFuelUseConsistentUnits(24.3494), + bsync.PercentEndUse(10.61), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Cooling-Submeter" ) @@ -1555,9 +1574,9 @@ shw_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Domestic hot water'), - bsync.AnnualFuelUseNativeUnits(7353.9648), - bsync.AnnualFuelUseConsistentUnits(25.116), - bsync.PercentEndUse(10.), + bsync.AnnualFuelUseNativeUnits(5011.11111), + bsync.AnnualFuelUseConsistentUnits(17.0986), + bsync.PercentEndUse(7.45), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-SHW-Submeter" ) @@ -1565,9 +1584,9 @@ pl_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Plug load'), - bsync.AnnualFuelUseNativeUnits(3676.9824), - bsync.AnnualFuelUseConsistentUnits(12.558), - bsync.PercentEndUse(5.), + bsync.AnnualFuelUseNativeUnits(14666.6667), + bsync.AnnualFuelUseConsistentUnits(50.0447), + bsync.PercentEndUse(21.81), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Plugload-Submeter" ) @@ -1595,14 +1614,14 @@ The following cell simply performs the following: full_ts_data = bsync.TimeSeriesData() # usage and peak data -monthly_elec = [6792.89, 5841.75, 6025.19, 4985.3, 5184.04, 5358.55, 5755.67, 5981.78, 5401.94, 5225.84, 5672.15, 6291.63] -monthly_ng = [5.7, 4.01, 0.58, 0.4, 0.02, 0, 0, 0, 0, 0.01, 0.36, 6.08] -monthly_elec_peak = [15.42, 15.5, 16.25, 16.65, 18.56, 20.01, 20.82, 21.12, 20.42, 20.08, 17.4, 16.3] +monthly_elec = [5663.92, 5099.31, 5290.08, 4868.67, 5121.08, 6018.81, 5776.42, 6407.08, 5702.81, 5139.72, 5080.94, 5204.11] +monthly_ng = [1.83, 2.32, 0.45, 0.62, 0.04, 0.0, 0.0, 0.0, 0.0, 0.0, 0.47, 0.63] +monthly_elec_peak = [19.68, 19.11, 17.02, 19.53, 16.04, 19.94, 18.65, 18.57, 18.48, 16.81, 17.36, 18.68] monthly_elec_lf = [0.373, 0.394, 0.390, 0.358, 0.374, 0.386, 0.369, 0.372, 0.373, 0.354, 0.380, 0.362] # costs data -monthly_elec_cost = [520.48, 451.53, 464.83, 389.43, 403.84, 416.49, 445.29, 461.68, 419.64, 406.87, 439.23, 484.14] -monthly_ng_cost = [30.44, 21.41, 3.10, 2.14, 0.11, 0.00, 0.00, 0.00, 0.00, 0.05, 1.92, 32.47] +monthly_elec_cost = [448.20, 443.41, 436.22, 443.97, 431.66, 450.82, 444.74, 447.31, 443.74, 434.72, 436.57, 442.23] +monthly_ng_cost = [46.87, 47.68, 44.62, 44.89, 43.95, 43.88, 43.88, 43.88, 43.88, 43.88, 44.65, 44.91] elec_ids = [] ng_ids = [] @@ -1722,22 +1741,22 @@ We have defined monthly electricity (energy, power, cost) and natural gas (energ ```python art = bsync.AllResourceTotals( bsync.AllResourceTotal( - bsync.AllResourceTotal.SiteEnergyUse(250953.5), # reported in kBtu - bsync.SiteEnergyUseIntensity(45.6), # reported in kbtu/ft2 + bsync.AllResourceTotal.SiteEnergyUse(229419.13), # reported in kBtu + bsync.SiteEnergyUseIntensity(41.71), # reported in kbtu/ft2 # Since there is no energy generated onsite, there is no difference btw site and building energy usage / intensity - bsync.BuildingEnergyUse(250953.5), - bsync.BuildingEnergyUseIntensity(45.6), + bsync.BuildingEnergyUse(229419.13), + bsync.BuildingEnergyUseIntensity(41.71), - bsync.ImportedEnergyConsistentUnits(250.9535), # in this case, same as building and site energy, but in MMBTU + bsync.ImportedEnergyConsistentUnits(229.41913), # in this case, same as building and site energy, but in MMBTU bsync.OnsiteEnergyProductionConsistentUnits(0.), # no energy produced onsite, MMBtu bsync.ExportedEnergyConsistentUnits(0.), # no energy exported, MMBtu bsync.NetIncreaseInStoredEnergyConsistentUnits(0.), # no energy stored, MMBtu - bsync.AllResourceTotal.SourceEnergyUse(759011.9), # reported in kBtu. Assume site -> source: elec = 3.167, ng = 1.084 - bsync.SourceEnergyUseIntensity(138.0), # kbtu/ft2 - bsync.EnergyCost(5395.), - bsync.EnergyCostIndex(0.98), # $/ft2 + bsync.AllResourceTotal.SourceEnergyUse(713327.16), # reported in kBtu. Assume site -> source: elec = 3.167, ng = 1.084 + bsync.SourceEnergyUseIntensity(129.7), # kbtu/ft2 + bsync.EnergyCost(5840.54), + bsync.EnergyCostIndex(1.06), # $/ft2 ID="AllResourceTotal-1" ) ) @@ -1757,13 +1776,9 @@ cbms += bsync.LinkedPremises( Relevant Standard 211 Sections: - 6.1.3 -We inserted the above information (electricity, natural gas, square footage, etc.) into the Energy Star Portfolio Manager and got a score of 56. We can add this information into BuildingSync with our benchmark scenario. -TODO: Figure this out: -1. Entered info into ESPM. Got the following: - -![ESPM](./img/ESPM-Target.png) +We inserted the above information (electricity, natural gas, square footage, etc.) into the Energy Star Portfolio Manager and got a score of 82. We can add this information into BuildingSync with our benchmark scenario. -1. So, the ES score for the _current building measured_ should be 56? And then 50 is used as the benchmark value here...? And 274,825 kBtu as the SiteEnergyUse...? Confused. +![ESPM](./img/ESPM.png) ```python @@ -1771,8 +1786,9 @@ TODO: Figure this out: bench_sc = bsync.Scenario( bsync.AllResourceTotals( bsync.AllResourceTotal( - bsync.AllResourceTotal.SiteEnergyUse(274825.), - bsync.SiteEnergyUseIntensity(50.), + bsync.AllResourceTotal.SiteEnergyUse(229419.13), + bsync.SiteEnergyUseIntensity(41.71), + bsync.EnergyCost(5840.54), ID="AllResourceTotal-Benchmark" ) ), @@ -1787,12 +1803,12 @@ bench_st = bsync.Scenario.ScenarioType() bench = bsync.Benchmark( bsync.BenchmarkType( bsync.PortfolioManager( - bsync.PMBenchmarkDate(date(2021, 3, 24)) + bsync.PMBenchmarkDate(date(2022, 6, 1)) ) ), bsync.BenchmarkTool("Portfolio Manager"), bsync.BenchmarkYear(2019), - bsync.BenchmarkValue(56.) + bsync.BenchmarkValue(82.) ) # @@ -1813,10 +1829,10 @@ Since we used a PM score in the baseline, we will also use that for our target. target_sc = bsync.Scenario( bsync.AllResourceTotals( bsync.AllResourceTotal( - bsync.AllResourceTotal.SiteEnergyUse(207643.5), - bsync.SiteEnergyUseIntensity(37.8), - bsync.EnergyCost(4451.51), - bsync.EnergyCostIndex(0.81), + bsync.AllResourceTotal.SiteEnergyUse(190348.6), + bsync.SiteEnergyUseIntensity(34.6), + bsync.EnergyCost(4846.04), + bsync.EnergyCostIndex(0.881), ID="AllResourceTotal-Target" ) ), @@ -1830,9 +1846,9 @@ target_sc = bsync.Scenario( target_st = bsync.Scenario.ScenarioType() target = bsync.Target( bsync.ReferenceCase(IDref=bench_sc["ID"]), - bsync.AnnualSavingsSiteEnergy(67181.5), - bsync.AnnualSavingsCost(931), - bsync.ENERGYSTARScore(70.), + bsync.AnnualSavingsSiteEnergy(39070.53), + bsync.AnnualSavingsCost(995), + bsync.ENERGYSTARScore(89.), ) # @@ -2149,13 +2165,6 @@ Use the line below to write the file to disk bsync_dump(root, file="example-level2.xml") ``` - - - - True - - - True diff --git a/docs/notebooks/bsync_examples/img/ESPM.png b/docs/notebooks/bsync_examples/img/ESPM.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba60f8298777eef3592e88b3377da4ab72750cc GIT binary patch literal 29708 zcmb@t1yCGM+xEMJ;O-VYSO}2dwm1a$K!Pk5++7w69-QFr9^7Sdx5eGv-Sv?F^PTg) zr|PM%-sd}KsHZ>k8+nss%LfKLp5j|Ds zf?!513a9QaeAKvil8FHEQk8C5Bo*&X5-sdm+0wvOIuhlmwi7Cg(4D3B=DrqA$zV}Q zM2Y9$&;@fZhm+%pr5%+L`9wk_8zxHhrOv;S zLa0LCu>Z=W#$5eZUKiq9?ti5|zkxyjCnXg6cEo4=`WWl!e}#y|keeAEO~=iA^LU?# z=Y|G|L^*j!9OD%gFI3oGi_!$wjef{380mS|ZhAzpiYN^8PZ$abinf2Hg0K*6{&f!h zw{QM-F96_8_!EHePwGD^ru&Z7<@at~I_+M11nr(qL~1TZczQ05@yI>|fQwMB@=576 zY=)o9OFv5CcBS`LKkzx}OvgZL2Uwb$PYVP4c=mhsqvwq3nyAu;q^DlGX-Lw&tN`GSAPn|%=(*(muGdHO33tVnDWBGcv=TI$j z5lRk#w*!&O?LYL(jv-*nC2M<6@byN`%;;sLOrw1mOK`uuaOTk(;Zalx?AL9t112fyF9zSsmTKW?%=-E9)N?M$#$ zAIuWXdmL5^n1!zG@N4))A06G(&X=esF0G{J`a8g17j<`f-9I})jyvAmw^~dx{>Hy& zQEG*~CYF|(WuQlFdcZhP@Nr(wFuv^dQECV!d%9)Y_sFY0Cwi?jO&_oCAD3aKSf&I4<6gj}pE=jds4!@sQ z1XHtA^8F%t?2`s0CRwH2$x!eg*E6mx(8sCA@%>zC4w>gc5VD$ro^3j7>*)0btqUE` z3Nb6MZ8_T#hwBd){@A-H_{Ap;sAGJ5-(pxYzbq@Yil;XDKj%YbN)hYSt=$p~Ii6By z9|tjKe%seL4WaYgV>(Q=wF`|=`>e|nd0H|=reX3nCSIFdt|!OAOcqi z=AkggACth{jhAjOZ7iklxqkgCL-cg_w~^R^R{wyq^fHC%0R2M>m@_(*4hlbC3#g(kd4QZ5@X3(dTf< z)?VjbsE>@*w|yL^QWs4ZU&%V9)f+kqla>5@)0tJI`#J@Maq>U~CFS5G6^HK43HF0U zHuj4}{oQ$%eCwBN?3T+`^ufztwd$p^Y$psvyEl0kG;G^_ttdsMeM2BeUz;f=HxAh6 zCrP1fv+6^R_b++uhak&L;~z=38j+Hs2Yid)Uh+NM#BH92i?GNkVvZY3(;hYHrF-Rt zpFd`T)fU23wbMUZ<$)~%Ws_JFNOGO-PKWfyN=f&?lg6;cZvbnxKj>B{&^kXaZ)U0bg+G-Jy`FlC_i%RHrzIZ@bk+9$;#5jHjaPgJS?L0gS8i%2J&&Y?U1UZpqm_MH6(sD{>1B8?wor_; zVRK`S;U=ljzp@1FZI)b#+p}mMm5$7>QMVf6tv$|9VSdnjX6!n>8t9Qt2+j{#!qhAK z$ozPnG!8(oP@nKWaU1*U_S#JsEsy5>S5!;_)20O^1dply>(2E<*=2)iOws68CowDF zbVeG}dz%wme+HwAqIoh z0tx;|@JlHeq35^&IcR}eSY;4Kva*6JkDt*2@)jrj8h=Ddakm_vnBsPNPh6QO(o=b5 zPTrB^c|EP9E3J&~IGn!^Ny1^j8FQ^7Yv*GG`jnWL#wPAn93*K_He&BQ zKEjS1)`#ACm9lbS)@Z=y%jonqkr5ve9J|i#Jyxl14^reY%&#nU9nev&>4|f;BvhnL=zP^=o`7zfltB@`y4gHu}v_Bg(-l!ys#v8tO2~AKQT>n6W z`@=;B|82LopqqJ1CYgY6Gz~4Pzd^)TXV0}xg>Vnsr0eHr?xWooYSPC|`};wHPBD?m z6#H#lZPyW^Bxfa`=T3FniLHse(fB<1%)*_t>{gy0?pQMi7m4F*vyc<$F0;1nj&&L6 zWImhg7Z`V;5^wJ3=haN0cp^4-V=RM)->gWX;u;-|d42|9cR5zQPN@mCb1+X`Jf z3vA)882R1}xi35Dk-rT>NRuNM+`&qvFuMH&YV1`K@{Kb;)wX^XX~o z1|E6jCVg`0XBL2?qO7@((421id%6rpPXEWr4nNa`3yGCLYN|KQS;C)J6T{7%`KO-k z#bPuIP3wc6fritl7Z14psDeDM+aI5jF**3WZV>K=GYuT{T@pspc!dp((Y0!+vn8!x13_R0w0Bdx) zdigzAn6+Jkd;xw}vH7U_9x<6=xI}rOhCb&S4n&6mH;GTeDt>wE^NkD`!C`MS8kV%p z`M=NUHd~m|kKK{M5Po&}^edL`v7#uH1Yz*=irZ@LPe{a1?bV)SObN4hTq`npYvl2Z z_f;_`0Z!e?+z=6rm^IdJR0lS{yg=cc%q!As3HafpH8p;J6hR)R$M;WyUtT0%&aKJE zS}`7@(HnNILE z0i%_Frd)pEDMy!7zu7b{<1d)CPk-d=*v}fPoXL13Ng{)PUYd5k<$Ccoqi`wL*SkOy zBqDI)RV%-(U51#={sC3;B{6)PKx+QF{7ig6Nj z6s{*XQQ?y}h}Jr|WT5mjw8f25zZfta-AAl1I<@aKMZ{Qr0rYq~qoWP95^d2$Vii4p z+Ug-(kKs9nBvcNoJSS9sk}fc8uYf9yg2}z4TY;Bgx0?;YF=IM;oYv|l+1*$of>ec> zI2}oy*2h7I?s#ZEOR97D@ksjbngYEA|D|n(vDso3x+c9Ji!w|H>MGVUvf3#t!1&VC zq*EHc#St`9)_T+JycuAz<}T4Rr^ZRbrQxyb6@~V-f;&2+wg+!NPrd?_+c0$b*aLL; z)18bwW%}44)M^s&jaN#?WKlpNMO5<~#K zp(=svY>0w>m+ZqXMhIqXE-BYRGcGOkG&-tEideug;MsCD;&K5)Ft4ube9qX*R^POh zl}Bnu+wJwjpNll^GfwQvsQ4G~1U6mJb!Kx1;D$kxxWSB}vcE*rzl=BMe(F7qJ~PQr z9A+r#t`oX`hp4R|D8*lO8(1yl6?dB&^9G#(d4kDnJ94@Ez2B{{M!kXBK5lWwdj>_s zfnnYN1-XS>_`IOtUD{>iprnJTW95zMG^np-OZ2+19l~$!_J_uU%-Kd_002&?w=&%I zd7F76rom*++^9L=kZ6MHON>tO`QG~vk3bu3>-s84WNZO!r5TPRgY;0?f{_r&>hdlxJHSsdpQ zS>PJy7}hFN@&iYpPxOu#FqPquu#h-}!yy7P5|r>1l{T$arny6~*iiZKF0c7T6`pVJ zK0#huy%hNF1u`%M?|~lA@vVK|<}2CqcY|3{MQ3z8KWo3#l#Lq_$f+#d@y0n}cR6Dz zid~!aD0~k&*d4!NsN2DJV_iOCcat}5+8LapF^jBdBYIohcew#p(%<~UUUiH?ju zQaj%K*dFo*(003ZI9KIx87(-ryh57mj82xP@N#J^jjUupGRLOMV~PBv-QBIqBsM%G z!<-W`l3t{5TJyygyNfI6*O^8BJKjMmo;04^3-Aqqo(Y)?CHTT@?Woe6#t<~gZV%ZG zc=&MOgoD#v@pUn)i`^gKjlDCOh;{!Wa1VsMG*PoZ-t9PCZC^(@ea| zRyTn@GS{c=P%pk=qrWGqbRlOd7g1#OylLwZ*9V)9JfV%N2*FrMxTAJG~&EXcGcF0op9m$ zIByzmFO8y2MVAIKVgM`72vHX z4JNZ;Yqdnw`i`p$I*=Sv)y{Tg0{RykFCSB7Up2&=o|=S#ItUUOQ3uhhdY(f)$bCw^f>vzY2bJ%WPpq>C&-((ixiGi^x+z(C zaE=DJR}PtFR@u(7b@V9TBM`c-SHFpK4wZ3@W%;;nX%e2T6=(xbhCA%@p zF);e>EJTz`v9UCnw{D{)EbOhllpeO#P;OwcU7H<_&O#;JMrI4kDGjQiKvN4Ha%&4! zmfHN`yYO=L8^Q-(iJ<};gb}(As_l>!{lBg4aw*2d_8hsN!(Y96?hY&q9|gjj*@dk> zQlD+%Da={KUbWWlBed@DHXkF_9}7NyG2R9e5j#K)E<=J&AS}jcypky5&kIjaqL)`n zLD0ZgPP5tet}zsanwj2%rQ`P-5rRBnmI@c63dY|JfGanKZs#ggl)0xT+CdcRt^vWM zlZ7k^>JMUdm@~e)hdplz2@0H*Y=W|nEI+=E4Gl<`%A4-ldTz4thS^AJj;hMnnhMhf{`X-QxR|b0kA0J31Dkr(HJ8kyvxF^&_*ooi!bi;<=EzY`{vPC8ykd&h$t zTUwkWd{i)JUuG-Wi2yE5A~bV;IE!*@a8>^Uu;?&M_p}h!nwq$xwF;; zr2mpbs?%QYrZWBIt6KWqly8vE>V%tzFV_ck;*D%?=&gUXYA!=}TT)Q;joek_z z(s`l28O`Yl=8diW1v3oOtOe&S`w8vGfw*`I*Nc?DmkVg!Bn*1D8Jqug`Eh}9_xGD= zQhAmm{VDJPMkp4YtS~_7Ee=s3SXDupu?SskSnEZEOgd`V03R+`tI{mh&*C2 z=ncGUUULIM4Ce^{KE@ej0>L;A7?>^8`5z zz3ua{U~$@b%&8D%0RcFL+Uhn7=`(}aQf6r}$xfPL`E7>+;VbkJimSh%*ReZ*R*x!` z-zWqWNJ7PVJRXSHu98u}IbjIA_gh+b`WO~$>=S}~zL^2Lsiay3y_&l|+`0=@qUorM z+E#NjSH-~Vx>W)`l|v4LamZ^;gjurLe23%4uTHak&qNeKYwi8dKZ~ed_}BZ>@1{uQ z-!&kxjef_xV2^Ua!T@B8nYIQQQ)T2c{D@+=GN$hfJ3FOHv;CP^I_#Q>QvNe_`^#8f zdc{M+!1m2mOhBRU7Ze0g*DF(oCp`f}1%=#w*TuprzKKLU8V6YeBoLg{;_AU7l&{^3 zgUz#JEmAz(Q2(UG3mdhqz8mzzhdKD9hMvj0V~doch1;@N+z5fsG_ce_)))*`4#Wpn4p8*rPTx9_6* zNATX5IA*27pf^t12|!KJ{C;B-pJ*bM4p>GI9uj@wf2XnNtY{j%U_ zz)i=EEB-?YE84TrRTT=@prRFp~>36i6= zQ-U_qB9@iL8@_*Z4koE4_0c!5k@4uWS1FfkcsP64PH124yH5(1WeU_S+lcrxP_V!! zUHcqP@DWGpSgLp%)-OF@PJjM^|NEvwXB7 z7&gDh{?)Ck5_|N*wCHBGiB2gSvsU_}j*vNdiiji34d?B=l!m&1Km2i{kadOb&!=6Y zqPml>DfuVgnQ{hMvgCJ?)|a~=;Nv--e9XC4;>_s=!^xTrFU z9jVB(5Y<#g87pKxgrQ@XKTi&t|)RYDSvaWVrFY>WUw<5ZWO%{R?6KEWqi>sZ@(D?I7*gToLsmENlSUsgOT2kmtQ1-Sj34oUOw zKHt-B+I7ds{BY0h^MgWNVWviC>Xaf8e9JsUE)eoYy{{867VYA;`6wAhJ_))d6_J+R zs}?QWYF)vX-+EsES%9SkBR5mIFNIfCOM6Cu-+yyYr?4C02%ATcf9p4H@{J<;tEAL^ zta?U+T3J5zqsv!BHKkaP@rRD`j6KgOY>K%pIMTj6%0D6M?HH+$gnzA;pP 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ݛ+Tk}Ak5$34$>cEa)|xLo(%s=; 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 literal 0 HcmV?d00001 From 808778a339a1c046147615f76a7425b04353e60b Mon Sep 17 00:00:00 2001 From: Xiong Date: Tue, 28 Jun 2022 06:09:01 -0600 Subject: [PATCH 3/5] Update example Update some text, fix some tweaks. Still need to make quotes consistent for strings. --- docs/notebooks/README.md | 4 +- .../bsync_examples/Small-Office-Level-1.md | 2 +- .../bsync_examples/Small-Office-Level-2.md | 445 +++---- .../bsync_examples/example-level2.xml | 1027 ++++++++++++----- docs/notebooks/bsync_examples/img/ESPM.png | Bin 29708 -> 31032 bytes 5 files changed, 985 insertions(+), 493 deletions(-) diff --git a/docs/notebooks/README.md b/docs/notebooks/README.md index 9a5e7b12..2075c889 100644 --- a/docs/notebooks/README.md +++ b/docs/notebooks/README.md @@ -1,4 +1,4 @@ -Here you can find Jupyter Notebooks which serve as guides for using BuildingSync. Currently there is only one notebook for a small office building with a Level 1 energy audit. +Here you can find Jupyter Notebooks which serve as guides for using BuildingSync. Currently there are several notebooks for prototype small office and primary school buildings with ASHRAE Level 1 and 2 energy audit. # Setup @@ -6,4 +6,4 @@ Here you can find Jupyter Notebooks which serve as guides for using BuildingSync - `poetry install` - `poetry run jupyter lab` -Navigate to the `bsync_examples/Small-Office-Level-1.md`, right click on the file and select `Open With -> Jupytext Notebook`, then walk through the example. +Navigate to the notebook examples (e.g. `bsync_examples/Small-Office-Level-1.md`), right click on the file and select `Open With -> Jupytext Notebook`, then walk through the example. diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-1.md b/docs/notebooks/bsync_examples/Small-Office-Level-1.md index 05fad67b..d9e375b7 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-1.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-1.md @@ -16,7 +16,7 @@ By the end of this notebook, you should: - Create a minimum viable Level 1 BuildingSync document and verify it validates using the [BuildingSync Use Case Validator](https://buildingsync.net/validator) ## For Reference: Core Concepts and Notation Used -- We will be using BuildingSync version 2.3.0. [Documentation](https://buildingsync.net/documentation/2.3.0). [Github release](https://github.com/BuildingSync/schema/releases/tag/v2.3.0). +- We will be using BuildingSync version 2.4.0. [Documentation](https://buildingsync.net/documentation/2.4.0). [Github release](https://github.com/BuildingSync/schema/releases/tag/v2.4.0). - BuildingSync is an XML Schema Document (XSD). It defines intended structure. Referring to something as a BuildingSync document typically means the document is intended to conform to the BuildingSync schema. - An XSD defines a hierarchical or tree-based schema, where elements are 'nested' within other elements. An XML document then looks like nested elements within one another. Similar to HTML, it uses angle brackets `<` and `>` to open and close an element tag. The example below provides a very simple example of an XML document: ```xml diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-2.md b/docs/notebooks/bsync_examples/Small-Office-Level-2.md index 5cbace7a..3348cce5 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-2.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-2.md @@ -11,12 +11,12 @@ While this notebook is setup in Python, this introduction is not reserved only f ## Learning Objectives By the end of this notebook, you should: - Have a practical understanding of some XML features, namely: elements, attributes, and xpaths -- Know the main elements of the BuildingSync schema: Buildings, Systems, Reports, Scenarios, TimeSeriesData -- Be able to relate these concepts back to an ASHRAE Standard 211 energy audit -- Create a minimum viable Level 1 BuildingSync document and verify it validates using the [BuildingSync Use Case Validator](https://buildingsync.net/validator) +- Know the main elements of the BuildingSync schema: Buildings, Systems, Reports, Scenarios, TimeSeriesData, Measures +- Be able to relate these concepts back to an ASHRAE Standard 211 energy audit, and have an understanding of the additional detail needed in a Level 2 audit (compared to a Level 1 audit) +- Create a minimum viable Level 2 BuildingSync document and verify it validates using the [BuildingSync Use Case Validator](https://buildingsync.net/validator) ## For Reference: Core Concepts and Notation Used -- We will be using BuildingSync version 2.3.0. [Documentation](https://buildingsync.net/documentation/2.3.0). [Github release](https://github.com/BuildingSync/schema/releases/tag/v2.3.0). +- We will be using BuildingSync version 2.4.0. [Documentation](https://buildingsync.net/documentation/2.4.0). [Github release](https://github.com/BuildingSync/schema/releases/tag/v2.4.0). - BuildingSync is an XML Schema Document (XSD). It defines intended structure. Referring to something as a BuildingSync document typically means the document is intended to conform to the BuildingSync schema. - An XSD defines a hierarchical or tree-based schema, where elements are 'nested' within other elements. An XML document then looks like nested elements within one another. Similar to HTML, it uses angle brackets `<` and `>` to open and close an element tag. The example below provides a very simple example of an XML document: ```xml @@ -43,15 +43,15 @@ def pretty_print(element): """Simple printing of an xml element from the bsync library""" print(etree.tostring(element.toxml(), pretty_print=True).decode('utf-8')) -def bsync_dump(root_element, file="example1.xml"): +def bsync_dump(root_element, file='example1.xml'): """Write the element to the specified file""" doctype = '' as_etree = root_element.toxml() - as_etree.set("xmlns", "http://buildingsync.net/schemas/bedes-auc/2019") - #as_etree.set("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") - #as_etree.set("xsi:schemaLocation", "http://buildingsync.net/schemas/bedes-auc/2019 https://raw.githubusercontent.com/BuildingSync/schema/v2.4.0/BuildingSync.xsd") + as_etree.set('xmlns', 'http://buildingsync.net/schemas/bedes-auc/2019') + #as_etree.set('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') + #as_etree.set('xsi:schemaLocation', 'http://buildingsync.net/schemas/bedes-auc/2019 https://raw.githubusercontent.com/BuildingSync/schema/v2.4.0/BuildingSync.xsd') # Have to manually set the version right now. Align release of bsyncpy to this version. - as_etree.set("version", "2.4.0") + as_etree.set('version', '2.4.0') output = etree.tostring(as_etree, doctype=doctype, pretty_print=True) with open(file, 'wb+') as f: f.write(output) @@ -66,9 +66,10 @@ The small office prototype is a single story rectangular building. We will use D We can summarize the high level features as: - Total Floor Area: 5500sf - WWR: Southern Wall ~25%, Other Walls ~20% -- Climate Zone 5B +- ASHRAE Climate Zone 5B - Assume built year: 2000 - Let's assume this is on the 90.1-2004 code cycle +- Audit year: 2020 ## "I have a building...where do I start" Relevant Standard 211 Sections: @@ -80,10 +81,10 @@ Let's start by defining a building. In this exercise, we will learn about some B ```xml - + ...children stuff here... - + ...children stuff here... @@ -108,11 +109,11 @@ We start by creating the primary structure of a BuildingSync document. We introd # assignment, etc. root = bsync.BuildingSync() facs = bsync.Facilities() -f1 = bsync.Facilities.Facility(ID="Facility-1") +f1 = bsync.Facilities.Facility(ID='Facility-1') sites = bsync.Sites() -s1 = bsync.Sites.Site(ID="Site-1") +s1 = bsync.Sites.Site(ID='Site-1') bldgs = bsync.Buildings() -b1 = bsync.Buildings.Building(ID="Building-Small-Office-Prototype") +b1 = bsync.Buildings.Building(ID='Building-Small-Office-Prototype') sections = bsync.Sections() systems = bsync.Systems() contacts = bsync.Contacts() @@ -123,9 +124,10 @@ utilities = bsync.Utilities() # We link the entire report to the building r1 = bsync.Report( + bsync.ASHRAEAuditLevel('Level 2: Energy Survey and Analysis'), bsync.LinkedPremisesOrSystem( bsync.LinkedPremisesOrSystem.Building( - bsync.LinkedBuildingID(IDref=b1["ID"]) + bsync.LinkedBuildingID(IDref=b1['ID']) ) ), ID='Report-L2-Audit') @@ -159,6 +161,40 @@ r1 += utilities pretty_print(root) ``` + + + + + + + + + + + + + + + + + + + Level 2: Energy Survey and Analysis + + + + + + + + + + + + + + + #### 6.2.1.1 Building information This section of Standard 211 asks for lots of detail. We walk through the components of this that get added _as child elements of the building_, and then discuss other information. @@ -169,34 +205,34 @@ This section of Standard 211 asks for lots of detail. We walk through the compon b1 += bsync.PremisesName('Small Office Prototype in Denver') # 6.1.1.1.m -b1 += bsync.PremisesNotes("Here we record general problems / issues identified in a walkthrough survey.") +b1 += bsync.PremisesNotes('Here we record general problems / issues identified in a walkthrough survey.') # 6.1.1.1.d - address b1 += bsync.Address( bsync.StreetAddressDetail( bsync.Simplified( - bsync.StreetAddress("Some address") + bsync.StreetAddress('Some address') ) ), - bsync.Address.State("CO"), - bsync.City("Denver"), - bsync.PostalCode("80401") + bsync.Address.State('CO'), + bsync.City('Denver'), + bsync.PostalCode('80014') ) # 6.2.1.1.b - gross and conditioned floor area b1 += bsync.FloorAreas( bsync.FloorArea( - bsync.FloorAreaType("Gross"), + bsync.FloorAreaType('Gross'), bsync.FloorAreaValue(5500.0), bsync.ExcludedSectionIDs( - bsync.ExcludedSectionID(IDref="Section-excluded") + bsync.ExcludedSectionID(IDref='Section-excluded') ) ), bsync.FloorArea( - bsync.FloorAreaType("Conditioned"), + bsync.FloorAreaType('Conditioned'), bsync.FloorAreaValue(5500.0), bsync.ExcludedSectionIDs( - bsync.ExcludedSectionID(IDref="Section-excluded") + bsync.ExcludedSectionID(IDref='Section-excluded') ) ) ) @@ -210,8 +246,8 @@ b1 += bsync.OverallWindowToWallRatio(0.2133) b1 += bsync.OverallDoorToWallRatio(0.05) # 6.1.1.1.f - classification of the uses -b1 += bsync.BuildingClassification("Commercial") -b1 += bsync.OccupancyClassification("Office") +b1 += bsync.BuildingClassification('Commercial') +b1 += bsync.OccupancyClassification('Office') b1 += bsync.BuildingAutomationSystem(True) b1 += bsync.HistoricalLandmark(False) @@ -248,36 +284,36 @@ Continuing with the information required by 6.1.1.1, we define additional conten # 6.1.1.1.b - Owner and auditor contact info c1 = bsync.Contact( bsync.ContactName('The dude'), - bsync.ContactCompany("Some big company"), + bsync.ContactCompany('Some big company'), bsync.ContactRoles( bsync.ContactRole('Owner') ), bsync.ContactTelephoneNumbers( bsync.ContactTelephoneNumber( - bsync.TelephoneNumber("123-456-7890") + bsync.TelephoneNumber('123-456-7890') ) ), bsync.ContactEmailAddresses( bsync.ContactEmailAddress( - bsync.EmailAddress("the.dude@somebigco.net") + bsync.EmailAddress('the.dude@somebigco.net') ) ), ID='Contact-Owner' ) c2 = bsync.Contact( bsync.ContactName('The lady'), - bsync.ContactCompany("Auditeers"), + bsync.ContactCompany('Auditeers'), bsync.ContactRoles( bsync.ContactRole('Energy Auditor') ), bsync.ContactTelephoneNumbers( bsync.ContactTelephoneNumber( - bsync.TelephoneNumber("123-456-7890") + bsync.TelephoneNumber('123-456-7890') ) ), bsync.ContactEmailAddresses( bsync.ContactEmailAddress( - bsync.EmailAddress("the.lady@the-three-auditeers.com") + bsync.EmailAddress('the.lady@the-three-auditeers.com') ) ), ID='Contact-Auditor' @@ -308,15 +344,15 @@ The Small Office, as its name suggests, is just an office space, and therefore w ```python # create a new section section = bsync.Sections.Section( - bsync.SectionType("Space function"), - bsync.OccupancyClassification("Office"), - bsync.OriginalOccupancyClassification("Office"), - bsync.ThermalZoneLayout("Single zone"), - ID=f"Section-office" + bsync.SectionType('Space function'), + bsync.OccupancyClassification('Office'), + bsync.OriginalOccupancyClassification('Office'), + bsync.ThermalZoneLayout('Single zone'), + ID=f'Section-office' ) -section_wb = bsync.Sections.Section(ID="Section-Whole-building") -section_wb += bsync.SectionType("Whole building") -section_ex = bsync.Sections.Section(ID="Section-excluded") +section_wb = bsync.Sections.Section(ID='Section-Whole-building') +section_wb += bsync.SectionType('Whole building') +section_ex = bsync.Sections.Section(ID='Section-excluded') sections += section sections += section_wb sections += section_ex @@ -332,11 +368,11 @@ Section 5.3.4 lays out specific requirements to convey for each space function. # 5.3.4.a Gross floor area for the section (we also add conditioned for 5.3.4.f) section_fa = bsync.FloorAreas( bsync.FloorArea( - bsync.FloorAreaType("Gross"), + bsync.FloorAreaType('Gross'), bsync.FloorAreaValue(5500.0) ), bsync.FloorArea( - bsync.FloorAreaType("Conditioned"), + bsync.FloorAreaType('Conditioned'), bsync.FloorAreaValue(5500.0) ) ) @@ -344,11 +380,11 @@ section_fa = bsync.FloorAreas( # 5.3.4.b and 5.3.4.c are asking for typical operating hours for the section tous = bsync.TypicalOccupantUsages() tou_hpw = bsync.TypicalOccupantUsage( - bsync.TypicalOccupantUsageUnits("Hours per week"), + bsync.TypicalOccupantUsageUnits('Hours per week'), bsync.TypicalOccupantUsageValue(40.0) ) tou_wpy = bsync.TypicalOccupantUsage( - bsync.TypicalOccupantUsageUnits("Weeks per year"), + bsync.TypicalOccupantUsageUnits('Weeks per year'), bsync.TypicalOccupantUsageValue(50.) ) tous += tou_hpw @@ -357,7 +393,7 @@ tous += tou_wpy # 5.3.4.d looks for normal / design or peak occupancy. occ_levels = bsync.OccupancyLevels() occ_design = bsync.OccupancyLevel( - bsync.OccupantQuantityType("Peak total occupants"), + bsync.OccupantQuantityType('Peak total occupants'), bsync.OccupantQuantity(31.) ) occ_levels += occ_design @@ -373,7 +409,9 @@ section += occ_levels #pretty_print(sections) ``` -6.2.1.1.e Schedules +### 6.2.1.1.e Schedules +Schedules of occupancy, lighting, process and plug loads, and HVAC shall be provided for typical days (weekdays, weekends, holidays). +In BuildingSync, schedules are defined individually and referred (linked) in different sections. For example, lighting schedule is linked when lighting system is defined. ```python @@ -761,7 +799,6 @@ schedules += schedule_light schedules += schedule_pl schedules += schedule_hvac schedules += schedule_hvac_new -#pretty_print(schedules) ``` #### 6.2.1.2 Envelope @@ -781,7 +818,7 @@ roof = bsync.RoofSystem( ) roofsys += roof -# 6.2.1.2.b wall +# 6.2.1.2.b Opaque walls (above ground) wallsys = bsync.WallSystems() wall = bsync.WallSystem( bsync.ExteriorWallConstruction("Wood frame"), @@ -978,8 +1015,8 @@ hc_systems += bsync.ZoningSystemType("Single zone") # cooling system css = bsync.CoolingSources() -coolingcapacity = [6862.6, 6344.4, 4688.8, 5836.3, 5989.0] -for each in range(1,6): +coolingcapacities = [10198.9, 9847.2, 7737.1, 9143.8, 9847.2] +for index, coolingcapacity in enumerate(coolingcapacities): cs = bsync.CoolingSource( bsync.CoolingSourceType( bsync.DX( @@ -990,7 +1027,7 @@ for each in range(1,6): ), bsync.AnnualCoolingEfficiencyValue(2.61), bsync.AnnualCoolingEfficiencyUnits('COP'), - bsync.Capacity(coolingcapacity[each-1]), + bsync.Capacity(coolingcapacity), bsync.CapacityUnits('W'), bsync.CoolingSourceCondition('Good'), bsync.CoolingSource.Controls( @@ -1003,7 +1040,7 @@ for each in range(1,6): ) ), bsync.YearInstalled(2000), - ID=f"CoolingSource-{each}" + ID=f"CoolingSource-{index+1}" ) css += cs @@ -1011,8 +1048,8 @@ hc_systems += css # heating system hss = bsync.HeatingSources() -heatingcapacity = [7203.66, 6659.65, 4921.86, 6126.30, 6286.66] -for each in range(1,6): +heatingcapacities = [10311.1, 9801.3, 7858.1, 9067.8, 9855.4] +for index, heatingcapacity in enumerate(heatingcapacities): hs = bsync.HeatingSource( bsync.HeatingSourceType( bsync.HeatingSourceType.HeatPump( @@ -1024,8 +1061,8 @@ for each in range(1,6): ), bsync.AnnualHeatingEfficiencyValue(3.01), bsync.AnnualHeatingEfficiencyUnits('COP'), - bsync.InputCapacity(heatingcapacity[each-1]), - bsync.HeatingSource.Capacity(heatingcapacity[each-1]), + bsync.InputCapacity(heatingcapacity), + bsync.HeatingSource.Capacity(heatingcapacity), bsync.CapacityUnits('W'), bsync.HeatingSourceCondition('Good'), bsync.HeatingSource.Controls( @@ -1038,7 +1075,7 @@ for each in range(1,6): ) ), bsync.YearInstalled(2000), - ID=f"HeatingSource-{each}" + ID=f"HeatingSource-{index+1}" ) hss += hs @@ -1102,16 +1139,15 @@ hvacctl = bsync.HVACControlSystemTypes( hvac_system += hc_systems hvac_system += duct_systems hvac_system += hvacctl -#pretty_print(hvac_systems) # fan fan_systems = bsync.FanSystems() -fanflowrate = [0.44, 0.40, 0.30, 0.37, 0.38] -fanflowrate = [x*2118.88 for x in fanflowrate] +fanflowrate = [880., 836., 671., 774., 841.] +fanflowrate_new = [872., 830., 664., 766., 833.] for each in range(1,6): fan = bsync.FanSystem( - bsync.FanEfficiency(0.54), - bsync.FanSize(1000.), + bsync.FanEfficiency(0.536), + bsync.FanSize(fanflowrate[each-1]), bsync.FanInstalledFlowRate(fanflowrate[each-1]), bsync.FanControlType("Constant Volume"), bsync.LinkedSystemIDs( @@ -1120,9 +1156,9 @@ for each in range(1,6): ID=f"FanSystem-{each}" ) fan_new = bsync.FanSystem( - bsync.FanEfficiency(0.54), - bsync.FanSize(1000.), - bsync.InstalledFlowRate(fanflowrate[each-1]), + bsync.FanEfficiency(0.536), + bsync.FanSize(fanflowrate_new[each-1]), + bsync.InstalledFlowRate(fanflowrate_new[each-1]), bsync.FanControlType("Variable Volume"), bsync.LinkedSystemIDs( bsync.LinkedSystemID(IDref=f"Delivery-{each}") @@ -1160,7 +1196,7 @@ shw = bsync.DomesticHotWaterSystem( bsync.PrimaryFuel("Electricity"), bsync.Recirculation( bsync.RecirculationLoopCount(1), - bsync.RecirculationFlowRate(3.84972648), # 4.048e-06 m3/s to gal/hr + bsync.RecirculationFlowRate(3.6), bsync.RecirculationControlType("Continuous"), bsync.PipeInsulationThickness(123.), # arbitrary value, actually not required bsync.RecirculationEnergyLossRate(1.870180469) @@ -1168,7 +1204,7 @@ shw = bsync.DomesticHotWaterSystem( bsync.HotWaterDistributionType("Looped"), bsync.HotWaterSetpointTemperature(140.), bsync.WaterHeaterEfficiency(1.), - bsync.WaterHeaterEfficiencyType("COP"), + bsync.WaterHeaterEfficiencyType("Thermal Efficiency"), bsync.DailyHotWaterDraw(40.), # arbitrary value, actually not required bsync.ParasiticFuelConsumptionRate(1950.52), # 572 W to Btu/hr bsync.Capacity(11722.84), @@ -1219,11 +1255,11 @@ ls1 = bsync.LightingSystem( bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.2) ), - bsync.InstalledPower(5.50205), - bsync.LampPower(550.205), - bsync.NumberOfLampsPerBallast(1), + bsync.InstalledPower(5.500), + bsync.LampPower(32.0), + bsync.NumberOfLampsPerBallast(4), bsync.NumberOfBallastsPerLuminaire(1.), - bsync.NumberOfLuminaires(10), + bsync.NumberOfLuminaires(43), bsync.PercentPremisesServed(100.), bsync.LightingAutomationSystem(False), bsync.LightingSystem.Controls( @@ -1256,7 +1292,7 @@ ls2 = bsync.LightingSystem( ) ), bsync.BallastType("Standard Electronic"), - bsync.InstalledPower(1.58258), + bsync.InstalledPower(1.582575), bsync.LampPower(316.516), bsync.NumberOfLampsPerBallast(1), bsync.NumberOfBallastsPerLuminaire(1.), @@ -1284,7 +1320,7 @@ ls2 = bsync.LightingSystem( ), ID="LightingSystem-2" ) -# new lighting system for measure +# new led lighting system for measure ls_new = bsync.LightingSystem( bsync.OutsideLighting(False), bsync.LampType( @@ -1296,11 +1332,11 @@ ls_new = bsync.LightingSystem( bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.1) ), - bsync.InstalledPower(0.64), - bsync.LampPower(64.), - bsync.NumberOfLampsPerBallast(1), + bsync.InstalledPower(2.752), + bsync.LampPower(16.), + bsync.NumberOfLampsPerBallast(4), bsync.NumberOfBallastsPerLuminaire(1.), - bsync.NumberOfLuminaires(10), + bsync.NumberOfLuminaires(43), bsync.PercentPremisesServed(100.), bsync.LightingAutomationSystem(False), bsync.LightingSystem.Controls( @@ -1426,19 +1462,35 @@ elec_ut = bsync.Utility( bsync.TypeOfRateStructure( bsync.FlatRate( bsync.FlatRate.RatePeriods( + bsync.FlatRate.RatePeriods.RatePeriod( + bsync.ApplicableStartDateForEnergyRate(date(2019,6,1)), + bsync.ApplicableEndDateForEnergyRate(date(2019,9,30)), + bsync.EnergyCostRate(0.08852), # $0.08852/kWh + bsync.ApplicableStartDateForDemandRate(date(2019,6,1)), + bsync.ApplicableEndDateForDemandRate(date(2019,9,30)), + bsync.ElectricDemandRate(0.) # no demand cost + ), bsync.FlatRate.RatePeriods.RatePeriod( bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), - bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), - bsync.EnergyCostRate(0.00458), # $0.00458/kWh + bsync.ApplicableEndDateForEnergyRate(date(2019,5,31)), + bsync.EnergyCostRate(0.05314), # $0.05314/kWh bsync.ApplicableStartDateForDemandRate(date(2019,1,1)), - bsync.ApplicableEndDateForDemandRate(date(2020,1,1)), - bsync.ElectricDemandRate(3.86) # $3.86/kW + bsync.ApplicableEndDateForDemandRate(date(2019,5,31)), + bsync.ElectricDemandRate(0.) # no demand cost + ), + bsync.FlatRate.RatePeriods.RatePeriod( + bsync.ApplicableStartDateForEnergyRate(date(2019,10,1)), + bsync.ApplicableEndDateForEnergyRate(date(2019,12,31)), + bsync.EnergyCostRate(0.05314), # $0.05314/kWh + bsync.ApplicableStartDateForDemandRate(date(2019,10,1)), + bsync.ApplicableEndDateForDemandRate(date(2019,12,31)), + bsync.ElectricDemandRate(0.) # no demand cost ) ) ) ), bsync.ReferenceForRateStructure("https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/Regulatory'/%'20Filings/CO%20Recent'/%'20Filings/PSCo_Electric_Entire_Tariff.pdf"), - bsync.FixedMonthlyCharge(346.29), + bsync.FixedMonthlyCharge(16.88), ID="RateSchedule-Electricity" ) ), @@ -1459,7 +1511,7 @@ ng_ut = bsync.Utility( bsync.FlatRate.RatePeriods( bsync.FlatRate.RatePeriods.RatePeriod( bsync.ApplicableStartDateForEnergyRate(date(2019,1,1)), - bsync.ApplicableEndDateForEnergyRate(date(2020,1,1)), + bsync.ApplicableEndDateForEnergyRate(date(2019,12,31)), bsync.EnergyCostRate(0.16360) # $/therm ) ) @@ -1491,9 +1543,9 @@ Now that we have a current building measured scenario, we want to declare energy | Resource Type | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| Electricity (kWh) | 5663.92 | 5099.31 | 5290.08 | 4868.67 | 5121.08 | 6018.81 | 5776.42 | 6407.08 | 5702.81 | 5139.72 | 5080.94 | 5204.11 | -| Natural Gas (MMBtu) | 1.83 | 2.32 | 0.45 | 0.62 | 0.04 | 0 | 0 | 0 | 0 | 0.0 | 0.47 | 0.63 | -| Electricity peak (kW) | 19.68 | 19.11 | 17.02 | 19.53 | 16.04 | 19.94 | 18.65 | 18.57 | 18.48 | 16.81 | 17.36 | 18.68 | +| Electricity (kWh) | 5933.1 | 5446.1 | 5736.49 | 4980.5 | 5187.21 | 5842.95 | 5801.73 | 6220.16 | 5682.87 | 5571.93 | 5525.15 | 5405.94 | +| Natural Gas (MMBtu) | 1.72 | 1.25 | 0.41 | 0.43 | 0.01 | 0.0 | 0.0 | 0.0 | 0.0 | 0.2 | 0.4 | 4.3 | +| Electricity peak (kW) | 23.58 | 25.38 | 26.04 | 24.45 | 17.03 | 22.71 | 22.01 | 21.81 | 20.63 | 21.87 | 21.63 | 21.78 | In BuildingSync land, we need to declare an resource use for each resource type. Standard, allowable enumerations exist for this already. We do this as follows: @@ -1516,11 +1568,11 @@ elec_ru = bsync.ResourceUse( ID=f"ResourceUse-Electricity" ) # given the above, we add the annual totals -elec_ru += bsync.AnnualFuelUseNativeUnits(65372.2222) -elec_ru += bsync.AnnualFuelUseConsistentUnits(223.05928) #convert to MMBTU -elec_ru += bsync.AnnualPeakNativeUnits(19.93565) # kW as specified above -elec_ru += bsync.AnnualPeakConsistentUnits(19.93565) # already in kW, same as above -elec_ru += bsync.AnnualFuelCost(5303.57) # +elec_ru += bsync.AnnualFuelUseNativeUnits(67334.15) +elec_ru += bsync.AnnualFuelUseConsistentUnits(229.75365655) #convert to MMBTU +elec_ru += bsync.AnnualPeakNativeUnits(26.04) # kW as specified above +elec_ru += bsync.AnnualPeakConsistentUnits(26.04) # already in kW, same as above +elec_ru += bsync.AnnualFuelCost(4613.82) # # create a resource use for natural gas, units of MMBtu, all end uses # additional connect it up to the utility @@ -1535,18 +1587,18 @@ ng_ru = bsync.ResourceUse( ID=f"ResourceUse-Natural-gas" ) # given the above, we add the annual totals -ng_ru += bsync.AnnualFuelUseNativeUnits(6.35985) -ng_ru += bsync.AnnualFuelUseConsistentUnits(6.35985) # already in MMBTU -ng_ru += bsync.AnnualFuelCost(536.97) # +ng_ru += bsync.AnnualFuelUseNativeUnits(8.72) +ng_ru += bsync.AnnualFuelUseConsistentUnits(8.72) # already in MMBTU +ng_ru += bsync.AnnualFuelCost(540.83) # # create resource uses for submetering of lighting, heating and cooling lighting_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Interior lighting'), - bsync.AnnualFuelUseNativeUnits(19711.1111), - bsync.AnnualFuelUseConsistentUnits(67.2571), - bsync.PercentEndUse(29.32), + bsync.AnnualFuelUseNativeUnits(20062.69), + bsync.AnnualFuelUseConsistentUnits(68.45389828), + bsync.PercentEndUse(28.705), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Lighting-Submeter" ) @@ -1554,9 +1606,9 @@ heating_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Heating'), - bsync.AnnualFuelUseNativeUnits(4141.66667), - bsync.AnnualFuelUseConsistentUnits(14.13195), - bsync.PercentEndUse(6.16), + bsync.AnnualFuelUseNativeUnits(4698.23), + bsync.AnnualFuelUseConsistentUnits(16.03036076), + bsync.PercentEndUse(6.722), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Heating-Submeter" ) @@ -1564,9 +1616,9 @@ cooling_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Cooling'), - bsync.AnnualFuelUseNativeUnits(7136.11111), - bsync.AnnualFuelUseConsistentUnits(24.3494), - bsync.PercentEndUse(10.61), + bsync.AnnualFuelUseNativeUnits(6128.87), + bsync.AnnualFuelUseConsistentUnits(20.91170444), + bsync.PercentEndUse(8.769), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Cooling-Submeter" ) @@ -1574,9 +1626,9 @@ shw_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Domestic hot water'), - bsync.AnnualFuelUseNativeUnits(5011.11111), - bsync.AnnualFuelUseConsistentUnits(17.0986), - bsync.PercentEndUse(7.45), + bsync.AnnualFuelUseNativeUnits(7185.37), + bsync.AnnualFuelUseConsistentUnits(24.51648244), + bsync.PercentEndUse(10.281), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-SHW-Submeter" ) @@ -1584,9 +1636,9 @@ pl_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), bsync.ResourceUnits('kWh'), bsync.EndUse('Plug load'), - bsync.AnnualFuelUseNativeUnits(14666.6667), - bsync.AnnualFuelUseConsistentUnits(50.0447), - bsync.PercentEndUse(21.81), + bsync.AnnualFuelUseNativeUnits(14942.15), + bsync.AnnualFuelUseConsistentUnits(50.9826158), + bsync.PercentEndUse(21.379), bsync.ParentResourceUseID(IDref=elec_ru['ID']), ID=f"ResourceUse-Electricity-Plugload-Submeter" ) @@ -1614,14 +1666,14 @@ The following cell simply performs the following: full_ts_data = bsync.TimeSeriesData() # usage and peak data -monthly_elec = [5663.92, 5099.31, 5290.08, 4868.67, 5121.08, 6018.81, 5776.42, 6407.08, 5702.81, 5139.72, 5080.94, 5204.11] -monthly_ng = [1.83, 2.32, 0.45, 0.62, 0.04, 0.0, 0.0, 0.0, 0.0, 0.0, 0.47, 0.63] -monthly_elec_peak = [19.68, 19.11, 17.02, 19.53, 16.04, 19.94, 18.65, 18.57, 18.48, 16.81, 17.36, 18.68] +monthly_elec = [5933.1, 5446.1, 5736.49, 4980.5, 5187.21, 5842.95, 5801.73, 6220.16, 5682.87, 5571.93, 5525.15, 5405.94] +monthly_ng = [1.72, 1.25, 0.41, 0.43, 0.01, 0.0, 0.0, 0.0, 0.0, 0.2, 0.4, 4.3] +monthly_elec_peak = [23.58, 25.38, 26.04, 24.45, 17.03, 22.71, 22.01, 21.81, 20.63, 21.87, 21.63, 21.78] monthly_elec_lf = [0.373, 0.394, 0.390, 0.358, 0.374, 0.386, 0.369, 0.372, 0.373, 0.354, 0.380, 0.362] # costs data -monthly_elec_cost = [448.20, 443.41, 436.22, 443.97, 431.66, 450.82, 444.74, 447.31, 443.74, 434.72, 436.57, 442.23] -monthly_ng_cost = [46.87, 47.68, 44.62, 44.89, 43.95, 43.88, 43.88, 43.88, 43.88, 43.88, 44.65, 44.91] +monthly_elec_cost = [332.16, 306.29, 321.72, 281.54, 292.53, 534.10, 530.45, 567.49, 519.93, 312.97, 310.49, 304.15] +monthly_ng_cost = [46.69, 45.93, 44.55, 44.58, 43.90, 43.88, 43.88, 43.88, 43.88, 44.21, 44.53, 50.92] elec_ids = [] ng_ids = [] @@ -1741,22 +1793,22 @@ We have defined monthly electricity (energy, power, cost) and natural gas (energ ```python art = bsync.AllResourceTotals( bsync.AllResourceTotal( - bsync.AllResourceTotal.SiteEnergyUse(229419.13), # reported in kBtu - bsync.SiteEnergyUseIntensity(41.71), # reported in kbtu/ft2 + bsync.AllResourceTotal.SiteEnergyUse(238473.65655), # reported in kBtu + bsync.SiteEnergyUseIntensity(43.3588), # reported in kbtu/ft2 # Since there is no energy generated onsite, there is no difference btw site and building energy usage / intensity - bsync.BuildingEnergyUse(229419.13), - bsync.BuildingEnergyUseIntensity(41.71), + bsync.BuildingEnergyUse(238473.65655), + bsync.BuildingEnergyUseIntensity(43.3588), - bsync.ImportedEnergyConsistentUnits(229.41913), # in this case, same as building and site energy, but in MMBTU + bsync.ImportedEnergyConsistentUnits(238.47365655), # in this case, same as building and site energy, but in MMBTU bsync.OnsiteEnergyProductionConsistentUnits(0.), # no energy produced onsite, MMBtu bsync.ExportedEnergyConsistentUnits(0.), # no energy exported, MMBtu bsync.NetIncreaseInStoredEnergyConsistentUnits(0.), # no energy stored, MMBtu - bsync.AllResourceTotal.SourceEnergyUse(713327.16), # reported in kBtu. Assume site -> source: elec = 3.167, ng = 1.084 - bsync.SourceEnergyUseIntensity(129.7), # kbtu/ft2 - bsync.EnergyCost(5840.54), - bsync.EnergyCostIndex(1.06), # $/ft2 + bsync.AllResourceTotal.SourceEnergyUse(737088.9), # reported in kBtu. Assume site -> source: elec = 3.167, ng = 1.084 + bsync.SourceEnergyUseIntensity(134.0), # kbtu/ft2 + bsync.EnergyCost(4952.48), + bsync.EnergyCostIndex(0.90), # $/ft2 ID="AllResourceTotal-1" ) ) @@ -1786,9 +1838,9 @@ We inserted the above information (electricity, natural gas, square footage, etc bench_sc = bsync.Scenario( bsync.AllResourceTotals( bsync.AllResourceTotal( - bsync.AllResourceTotal.SiteEnergyUse(229419.13), - bsync.SiteEnergyUseIntensity(41.71), - bsync.EnergyCost(5840.54), + bsync.AllResourceTotal.SiteEnergyUse(238473.65655), + bsync.SiteEnergyUseIntensity(43.3588), + bsync.EnergyCost(4952.48), ID="AllResourceTotal-Benchmark" ) ), @@ -1808,7 +1860,7 @@ bench = bsync.Benchmark( ), bsync.BenchmarkTool("Portfolio Manager"), bsync.BenchmarkYear(2019), - bsync.BenchmarkValue(82.) + bsync.BenchmarkValue(80.) ) # @@ -1861,7 +1913,7 @@ target_st += target Relevant Standard 211 Sections: - 6.1.5 & 6.1.6 -Although not explicitly called out in Standard 211, the current building modeled scenario is mostly implied as part of a Level 2 energy audit when doing more detailed savings estimates / calculations for potential measure(s) implementation. This is because when an energy / cost savings claim is made for a package of measures scenario, it needs to be _in reference_ to something, i.e. a current building modeled scenario (also often referred to as a baseline modeled scenario). The baseline modeled scenario should be interpreted as the expected performance of your building on an average or typical year. This is assuming the baseline modeled scenario is performed with TMY3 data, although they are likely first calibrated with AMY data. +Although not explicitly called out in Standard 211, the current building modeled scenario is implied as part of a Level 2 energy audit when doing detailed savings estimates and calculations for potential energy conservation measures. This is because when an energy and cost savings claim is made for a package of measures scenario, it needs to be _in reference_ to something, i.e., a current building modeled scenario (also often referred to as a baseline modeled scenario). The baseline modeled scenario should be interpreted as the expected performance of your building on an average or typical year. This is assuming the baseline modeled scenario is performed with TMY data, although they are likely first calibrated with AMY data. Since we are already using an energy model for this example and providing details for implementing a Standard 211 Level 1 energy audit, we will not go into this too much at this point. It should be addressed in future examples. @@ -1870,22 +1922,20 @@ Relevant Standard 211 Sections: - 6.1.5 & 6.1.6 Standard 211 breaks out recommendations into low / no-cost (6.1.5) or capital (6.1.6). On the BuildingSync side, we don't change the data modeling between these two situations significantly, we simply change the value of the `Scenario/ScenarioType/PackageOfMeasures/CostCategory` element, while the majority of other features remain the same. -- Low / no-cost scenario: `CostCategory>Low-Cost or No-Cost` -- Capital scenario: `CostCategory>Capital` - -For Level 1 audits, since the reporting only requires estimated costs, savings, and ROI, we don't specifically need a current building modeled scenario to be our reference case. +- Low / no-cost scenario: `Low-Cost or No-Cost` +- Capital scenario: `Capital` #### Measures -Packages of measures first require measures to be instantiated inside the BuildingSync document in order to correctly 'incorporate' them into the scenario. BuildingSync provides a significant number of already enumerated measures that can easily be used. We will first add some of these to our doc. +Packages of measures first require measures to be instantiated inside the BuildingSync document in order to correctly incorporate them into the scenario. BuildingSync provides a significant number of already enumerated measures that can be used. We will first add some of these to our BuildingSync file. The scope of an individual measure is primarily conveyed by a few elements: -- `SystemCategoryAffected`: select one of an enumerated set of strings representing the general scope of system, i.e. Refrigeration, Fan, Lighting, etc. +- `SystemCategoryAffected`: select one of an enumerated set of strings representing the general scope of system, e.g.. Refrigeration, Fan, Lighting, etc. - `TechnologyCategories/TechnologyCategory/*/MeasureName`: Select a very specific measure to implement ```python -# A measure to modify HVAC schedules (low-cost EEM) +# A measure to modify HVAC schedules (no-cost EEM) hvac_schedule_measure = bsync.Measure( bsync.TypeOfMeasure( bsync.ModificationRetrocommissions( @@ -1912,10 +1962,10 @@ hvac_schedule_measure = bsync.Measure( bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), - ID="Measure-HVAC-schedule-lowcost" + ID="Measure-HVAC-schedule-nocost" ) -# A measure to upgrade the lighting system to LEDs +# A measure to upgrade the lighting system to LEDs (low-cost EEM) led_measure = bsync.Measure( bsync.TypeOfMeasure( bsync.Replacements( @@ -1936,8 +1986,8 @@ led_measure = bsync.Measure( bsync.LongDescription("This measure is designed to replace all fluorescent bulbs with LEDs"), bsync.MeasureScaleOfApplication("Individual system"), bsync.UsefulLife(1.), - bsync.MeasureInstallationCost(123.), - bsync.MeasureMaterialCost(123.), + bsync.MeasureInstallationCost(50.), + bsync.MeasureMaterialCost(774.), bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), @@ -1947,7 +1997,7 @@ led_measure = bsync.Measure( # A measure to upgrade the fans in the RTUs to use VFDs # instead of simple on/off fans. # The CFMs for each of the RTUs are around ~ 700-800cfm, -# so there is no obvious choice of fans to upgrade to vfds. +# so there is no obvious choice of fans to upgrade to vsds. # Here, we just recommend upgrading all of them. vsd_measure = bsync.Measure( bsync.TypeOfMeasure( @@ -1970,8 +2020,8 @@ vsd_measure = bsync.Measure( bsync.LongDescription("This measure is designed to retrofit all RTU fans with a VSD"), bsync.MeasureScaleOfApplication("Individual system"), bsync.UsefulLife(1.), - bsync.MeasureInstallationCost(123.), - bsync.MeasureMaterialCost(123.), + bsync.MeasureInstallationCost(750.), + bsync.MeasureMaterialCost(1250.), # assume $200~300 per fan bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), @@ -1981,7 +2031,6 @@ vsd_measure = bsync.Measure( ```python -measures += hvac_schedule_measure measures += led_measure measures += vsd_measure ``` @@ -1989,8 +2038,10 @@ measures += vsd_measure #### POM Scenarios Now that the measures have been added, we create three potential POM scenarios, and add the necessary attributes per Standard 211 6.1.5 and 6.1.6 1. LEDs only -1. VSDs only -1. HVAC schedule only +2. VSDs only +3. LEDs+VSDs + +The no-cost HVAC schedule measure is not taken into account in this example. ```python @@ -2002,13 +2053,13 @@ pom_sc_1 = bsync.Scenario( bsync.MeasureID(IDref=led_measure['ID']) ), bsync.CostCategory("Capital"), - bsync.AnnualSavingsSiteEnergy(123.), - bsync.AnnualSavingsCost(123), + bsync.AnnualSavingsSiteEnergy(35.713), + bsync.AnnualSavingsCost(772), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( bsync.EnergyResource("Electricity"), bsync.ResourceUnits("kWh"), - bsync.AnnualSavingsNativeUnits(123.) + bsync.AnnualSavingsNativeUnits(11524.54) ), bsync.AnnualSavingsByFuel( bsync.EnergyResource("Natural gas"), @@ -2016,23 +2067,23 @@ pom_sc_1 = bsync.Scenario( bsync.AnnualSavingsNativeUnits(0.) ) ), - bsync.AnnualPeakElectricityReduction(123.), - bsync.AnnualDemandSavingsCost(123), + bsync.AnnualPeakElectricityReduction(3.22), + bsync.AnnualDemandSavingsCost(0), bsync.AnnualWaterSavings(0.), bsync.AnnualWaterCostSavings(0.), bsync.ImplementationPeriod(1), bsync.ImplementationPeriodCostSavings(0.), - bsync.PackageFirstCost(0.), + bsync.PackageFirstCost(824.), bsync.MVCost(0.), - bsync.OMCostAnnualSavings(123.), + bsync.OMCostAnnualSavings(0.), bsync.EquipmentDisposalAndSalvageCosts(0.), - bsync.ProjectMarkup(123.), - bsync.FundingFromIncentives(123.), - bsync.FundingFromTaxCredits(123.), - bsync.OtherFinancialIncentives(123), - bsync.RecurringIncentives(123), - bsync.InternalRateOfReturn(1.), - bsync.SimplePayback(123.), + bsync.ProjectMarkup(0.), + bsync.FundingFromIncentives(0.), + bsync.FundingFromTaxCredits(0.), + bsync.OtherFinancialIncentives(0), # there might be incentives from utility for upgrading lighting to led + bsync.RecurringIncentives(0), + bsync.InternalRateOfReturn(0.), # for the first year the IRR is nagative (payback>1 yr) + bsync.SimplePayback(1.07), ID="POM-LEDs" ) ), @@ -2052,37 +2103,37 @@ pom_sc_2 = bsync.Scenario( bsync.MeasureID(IDref=vsd_measure['ID']) ), bsync.CostCategory("Capital"), - bsync.AnnualSavingsSiteEnergy(123.), - bsync.AnnualSavingsCost(123), + bsync.AnnualSavingsSiteEnergy(5.175), + bsync.AnnualSavingsCost(9), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( bsync.EnergyResource("Electricity"), bsync.ResourceUnits("kWh"), - bsync.AnnualSavingsNativeUnits(123.) + bsync.AnnualSavingsNativeUnits(207.24) ), bsync.AnnualSavingsByFuel( bsync.EnergyResource("Natural gas"), bsync.ResourceUnits("MMBtu"), - bsync.AnnualSavingsNativeUnits(12.) + bsync.AnnualSavingsNativeUnits(4.46) ) ), - bsync.AnnualPeakElectricityReduction(123.), - bsync.AnnualDemandSavingsCost(123), + bsync.AnnualPeakElectricityReduction(0.42), + bsync.AnnualDemandSavingsCost(0), bsync.AnnualWaterSavings(0.), bsync.AnnualWaterCostSavings(0.), bsync.ImplementationPeriod(1), bsync.ImplementationPeriodCostSavings(0.), - bsync.PackageFirstCost(0.), + bsync.PackageFirstCost(2000.), bsync.MVCost(0.), - bsync.OMCostAnnualSavings(123.), + bsync.OMCostAnnualSavings(0.), bsync.EquipmentDisposalAndSalvageCosts(0.), - bsync.ProjectMarkup(123.), - bsync.FundingFromIncentives(123.), - bsync.FundingFromTaxCredits(123.), - bsync.OtherFinancialIncentives(123), - bsync.RecurringIncentives(123), - bsync.InternalRateOfReturn(1.), - bsync.SimplePayback(123.), + bsync.ProjectMarkup(0.), + bsync.FundingFromIncentives(0.), + bsync.FundingFromTaxCredits(0.), + bsync.OtherFinancialIncentives(0), + bsync.RecurringIncentives(0), + bsync.InternalRateOfReturn(0.), + bsync.SimplePayback(230.15), ID="POM-VSDs" ) ), @@ -2099,41 +2150,42 @@ pom_sc_3 = bsync.Scenario( bsync.PackageOfMeasures( bsync.ReferenceCase(IDref=cbms['ID']), bsync.MeasureIDs( - bsync.MeasureID(IDref=hvac_schedule_measure['ID']), + bsync.MeasureID(IDref=led_measure['ID']), + bsync.MeasureID(IDref=vsd_measure['ID']), ), - bsync.CostCategory("Low-Cost or No-Cost"), - bsync.AnnualSavingsSiteEnergy(123.), - bsync.AnnualSavingsCost(123), + bsync.CostCategory("Capital"), + bsync.AnnualSavingsSiteEnergy(41.827), + bsync.AnnualSavingsCost(781), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( bsync.EnergyResource("Electricity"), bsync.ResourceUnits("kWh"), - bsync.AnnualSavingsNativeUnits(123.) + bsync.AnnualSavingsNativeUnits(11701.62) ), bsync.AnnualSavingsByFuel( bsync.EnergyResource("Natural gas"), bsync.ResourceUnits("MMBtu"), - bsync.AnnualSavingsNativeUnits(0.) + bsync.AnnualSavingsNativeUnits(1.89) ) ), - bsync.AnnualPeakElectricityReduction(123.), - bsync.AnnualDemandSavingsCost(123), + bsync.AnnualPeakElectricityReduction(4.7), + bsync.AnnualDemandSavingsCost(0), bsync.AnnualWaterSavings(0.), bsync.AnnualWaterCostSavings(0.), bsync.ImplementationPeriod(1), bsync.ImplementationPeriodCostSavings(0.), - bsync.PackageFirstCost(0.), + bsync.PackageFirstCost(2824.), bsync.MVCost(0.), - bsync.OMCostAnnualSavings(123.), + bsync.OMCostAnnualSavings(0.), bsync.EquipmentDisposalAndSalvageCosts(0.), - bsync.ProjectMarkup(123.), - bsync.FundingFromIncentives(123.), - bsync.FundingFromTaxCredits(123.), - bsync.OtherFinancialIncentives(123), - bsync.RecurringIncentives(123), - bsync.InternalRateOfReturn(1.), - bsync.SimplePayback(123.), - ID="POM-HVAC-Schedule" + bsync.ProjectMarkup(0.), + bsync.FundingFromIncentives(0.), + bsync.FundingFromTaxCredits(0.), + bsync.OtherFinancialIncentives(0), + bsync.RecurringIncentives(0), + bsync.InternalRateOfReturn(0.), + bsync.SimplePayback(3.62), + ID="POM-LEDs-VSDs" ) ), bsync.LinkedPremises( @@ -2141,7 +2193,7 @@ pom_sc_3 = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-POM-HVAC-Schedule" + ID="Scenario-POM-LEDs-VSDs" ) ``` @@ -2165,11 +2217,14 @@ Use the line below to write the file to disk bsync_dump(root, file="example-level2.xml") ``` + + + True -You should see a green check mark for the L100 AUDIT use case! +You should see a green check mark for the L200 AUDIT use case! ![Valid](./img/valid_level2.png) diff --git a/docs/notebooks/bsync_examples/example-level2.xml b/docs/notebooks/bsync_examples/example-level2.xml index db71f740..89def166 100644 --- a/docs/notebooks/bsync_examples/example-level2.xml +++ b/docs/notebooks/bsync_examples/example-level2.xml @@ -1,22 +1,25 @@ - + - Small Office Prototype + Small Office Prototype in Denver Here we record general problems / issues identified in a walkthrough survey.

- 4055 Brooks Street + Some address - Missoula - MT - 59804 + Denver + CO + 80014
Commercial Office @@ -93,17 +96,17 @@ A1 - 123.000000 + 909.012230 - 123.000000 + 180.187860 - 123.000000 + 42.086890 @@ -111,17 +114,17 @@ B1 - 123.000000 + 606.008200 - 123.000000 + 120.125240 - 123.000000 + 0.000000 @@ -129,17 +132,17 @@ C1 - 123.000000 + 909.012230 - 123.000000 + 180.187860 - 123.000000 + 0.000000 @@ -147,17 +150,17 @@ D1 - 123.000000 + 606.008200 - 123.000000 + 120.125240 - 123.000000 + 0.000000 @@ -165,7 +168,7 @@ - 123.000000 + 6444.999000 Good @@ -173,7 +176,7 @@ - 123.000000 + 3891.153600 @@ -195,15 +198,15 @@ Packaged Unitary Natural gas - 0.123000 - + 0.000000 + - 123.000000 + 3.010000 COP - 123.000000 - 123.000000 - gpm + 10311.100000 + 10311.100000 + W Good @@ -214,19 +217,22 @@ - 2020 + 2000 - - Warm air - + + Packaged Unitary + Natural gas + 0.000000 + + - 123.000000 + 3.010000 COP - 123.000000 - 123.000000 - gpm + 9801.300000 + 9801.300000 + W Good @@ -237,7 +243,85 @@ - 2020 + 2000 + + + + + Packaged Unitary + Natural gas + 0.000000 + + + + 3.010000 + COP + 7858.100000 + 7858.100000 + W + Good + + + + + + + + + + 2000 + + + + + Packaged Unitary + Natural gas + 0.000000 + + + + 3.010000 + COP + 9067.800000 + 9067.800000 + W + Good + + + + + + + + + + 2000 + + + + + Packaged Unitary + Natural gas + 0.000000 + + + + 3.010000 + COP + 9855.400000 + 9855.400000 + W + Good + + + + + + + + + + 2000 @@ -249,10 +333,82 @@ Single stage - 123.000000 + 2.610000 + COP + 10198.900000 + W + Good + + + + + + + + + + 2000 + + + + + Packaged/unitary heat pump + Reciprocating + Single stage + + + 2.610000 + COP + 9847.200000 + W + Good + + + + + + + + + + 2000 + + + + + Packaged/unitary heat pump + Reciprocating + Single stage + + + 2.610000 + COP + 7737.100000 + W + Good + + + + + + + + + + 2000 + + + + + Packaged/unitary heat pump + Reciprocating + Single stage + + + 2.610000 COP - 123.000000 - gpm + 9143.800000 + W Good @@ -263,7 +419,31 @@ - 2020 + 2000 + + + + + Packaged/unitary heat pump + Reciprocating + Single stage + + + 2.610000 + COP + 9847.200000 + W + Good + + + + + + + + + + 2000 @@ -292,8 +472,124 @@ - 2020 - 5 + 2000 + 1 + Good + + + + + Central fan + CAV terminal box no reheat + None + + + None + Fixed + + + + + + + + + + + + + + + + 2000 + 1 + Good + + + + + Central fan + CAV terminal box no reheat + None + + + None + Fixed + + + + + + + + + + + + + + + + 2000 + 1 + Good + + + + + Central fan + CAV terminal box no reheat + None + + + None + Fixed + + + + + + + + + + + + + + + + 2000 + 1 + Good + + + + + Central fan + CAV terminal box no reheat + None + + + None + Fixed + + + + + + + + + + + + + + + + 2000 + 1 Good @@ -305,6 +601,30 @@ + + Single + Good + + + + + Single + Good + + + + + Single + Good + + + + + Single + Good + + + Digital @@ -332,11 +652,11 @@ 0.200000 100.000000 - 123.000000 - 123.000000 - 1 + 5.500000 + 32.000000 + 4 1.000000 - 10 + 43 false @@ -367,11 +687,11 @@ Standard Electronic 100.000000 - 123.000000 - 123.000000 + 1.582575 + 316.516000 1 1.000000 - 1 + 5 true @@ -405,11 +725,11 @@ 0.100000 100.000000 - 123.000000 - 123.000000 - 1 + 2.752000 + 16.000000 + 4 1.000000 - 10 + 43 false @@ -439,11 +759,7 @@ - - - - - + 40.000000 123.000000 @@ -452,19 +768,19 @@ Notes 1 - 123.000000 + 3.600000 Continuous 123.000000 - 123.000000 + 1.870180 Looped - COP - 123.000000 - 123.000000 + Thermal Efficiency + 1.000000 + 40.000000 140.000000 - 123.000000 - 123.000000 - gpm + 1950.520000 + 11722.840000 + W @@ -474,7 +790,7 @@ - 2020 + 2000 Electricity Good @@ -490,34 +806,106 @@ - 123.000000 - 123.000000 - 123.000000 + 0.536000 + 880.000000 + 880.000000 Constant Volume - - 123.000000 - 123.000000 - 123.000000 + + 0.536000 + 872.000000 + 872.000000 Variable Volume + + 0.536000 + 836.000000 + 836.000000 + Constant Volume + + + + + + 0.536000 + 830.000000 + 830.000000 + Variable Volume + + + + + + 0.536000 + 671.000000 + 671.000000 + Constant Volume + + + + + + 0.536000 + 664.000000 + 664.000000 + Variable Volume + + + + + + 0.536000 + 774.000000 + 774.000000 + Constant Volume + + + + + + 0.536000 + 766.000000 + 766.000000 + Variable Volume + + + + + + 0.536000 + 841.000000 + 841.000000 + Constant Volume + + + + + + 0.536000 + 833.000000 + 833.000000 + Variable Volume + + + + Wood frame - 1.000000 + 0.547000 Wood frame - 1.000000 + 4.706000 @@ -528,9 +916,9 @@ Vinyl Clear uncoated Single pane - 1.250000 - 0.500000 - 0.800000 + 3.241000 + 0.391000 + 0.391000 @@ -539,9 +927,9 @@ Vinyl Low e Triple pane - 0.250000 - 0.500000 - 0.700000 + 0.300000 + 0.391000 + 0.391000 @@ -551,7 +939,7 @@ Steel - 0.500000 + 2.839000 @@ -559,7 +947,7 @@ - 0.500000 + 0.345000 @@ -584,9 +972,9 @@ Notes on test - Very Tight - 123.000000 - CFM25 + Tight + 0.151000 + ACHnatural Blower door
@@ -609,6 +997,13 @@ + + Weekday + Occupied + 00:00:00 + 06:00:00 + 0.000000 + Weekday Occupied @@ -665,6 +1060,13 @@ 23:00:00 5.000000 + + Weekday + Occupied + 23:00:00 + 23:59:59 + 0.000000 + Weekend Occupied @@ -716,6 +1118,20 @@ Weekday Lighting 08:00:00 + 12:00:00 + 90.000000 + + + Weekday + Lighting + 12:00:00 + 13:00:00 + 80.000000 + + + Weekday + Lighting + 13:00:00 17:00:00 90.000000 @@ -781,13 +1197,13 @@ Weekday Miscellaneous equipment 00:00:00 - 05:00:00 + 08:00:00 50.000000 Weekday Miscellaneous equipment - 05:00:00 + 08:00:00 12:00:00 100.000000 @@ -845,23 +1261,37 @@ Weekday HVAC equipment - 07:00:00 - 20:00:00 + 00:00:00 + 06:00:00 + 0.000000 + + + Weekday + HVAC equipment + 06:00:00 + 19:00:00 100.000000 + + Weekday + HVAC equipment + 19:00:00 + 23:59:59 + 0.000000 + Weekend HVAC equipment - 07:00:00 - 20:00:00 - 100.000000 + 00:00:00 + 23:59:59 + 0.000000 Holiday HVAC equipment - 07:00:00 - 20:00:00 - 100.000000 + 00:00:00 + 23:59:59 + 0.000000 @@ -872,6 +1302,13 @@ + + Weekday + HVAC equipment + 00:00:00 + 06:00:00 + 0.000000 + Weekday HVAC equipment @@ -907,19 +1344,26 @@ 20:00:00 60.000000 + + Weekday + HVAC equipment + 20:00:00 + 23:59:59 + 0.000000 + Weekend HVAC equipment - 07:00:00 - 20:00:00 - 30.000000 + 00:00:00 + 23:59:59 + 0.000000 Holiday HVAC equipment - 07:00:00 - 20:00:00 - 20.000000 + 00:00:00 + 23:59:59 + 0.000000 @@ -930,33 +1374,6 @@ - - - - - - - - - - Air Distribution - - - - Other distribution - - - - Individual system - Update HVAC schedule - The current HVAC schedule is set to be at 100'%' fan operation during weekday from 7am - 8pm. This measure would implement a modified schedule to enable pre-cooling/pre-heating from 6am - 7am, and reduce output to 80'%' during peak time 12pm - 1pm. - 1.000000 - 0.000000 - 0.000000 - true - 2021-01-01 - 2021-12-30 - @@ -977,8 +1394,8 @@ Individual system This measure is designed to replace all fluorescent bulbs with LEDs 1.000000 - 123.000000 - 123.000000 + 50.000000 + 774.000000 true 2021-01-01 2021-12-30 @@ -987,8 +1404,8 @@ - - + + @@ -1003,8 +1420,8 @@ Individual system This measure is designed to retrofit all RTU fans with a VSD 1.000000 - 123.000000 - 123.000000 + 750.000000 + 1250.000000 true 2021-01-01 2021-12-30 @@ -1024,11 +1441,11 @@ Electricity - This is required for L1 to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found. + This is required to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found. kWh All end uses - 68516.730000 - 234.000000 + 67334.150000 + 229.753657 @@ -1044,9 +1461,9 @@ kW - 21.120000 - 21.120000 - 5304.000000 + 26.040000 + 26.040000 + 4613.820000 @@ -1056,8 +1473,8 @@ No irregularities in monthly energy consumption found. MMBtu All end uses - 17.160000 - 17.160000 + 8.720000 + 8.720000 @@ -1072,7 +1489,7 @@ - 91.630000 + 540.830000 @@ -1080,46 +1497,46 @@ Electricity kWh - Total lighting - 25.000000 - 18384.912000 - 62.790000 + Interior lighting + 28.705000 + 20062.690000 + 68.453898 Electricity kWh Heating - 30.000000 - 22061.894400 - 75.348000 + 6.722000 + 4698.230000 + 16.030361 Electricity kWh Cooling - 25.000000 - 18384.912000 - 62.790000 + 8.769000 + 6128.870000 + 20.911704 Electricity kWh Domestic hot water - 10.000000 - 7353.964800 - 25.116000 + 10.281000 + 7185.370000 + 24.516482 Electricity kWh Plug load - 5.000000 - 3676.982400 - 12.558000 + 21.379000 + 14942.150000 + 50.982616 @@ -1132,7 +1549,7 @@ 31 Day Month - 6792.890000 + 5933.100000 @@ -1143,7 +1560,7 @@ 28 Day Month - 5841.750000 + 5446.100000 @@ -1154,7 +1571,7 @@ 31 Day Month - 6025.190000 + 5736.490000 @@ -1165,7 +1582,7 @@ 30 Day Month - 4985.300000 + 4980.500000 @@ -1176,7 +1593,7 @@ 31 Day Month - 5184.040000 + 5187.210000 @@ -1187,7 +1604,7 @@ 30 Day Month - 5358.550000 + 5842.950000 @@ -1198,7 +1615,7 @@ 31 Day Month - 5755.670000 + 5801.730000 @@ -1209,7 +1626,7 @@ 31 Day Month - 5981.780000 + 6220.160000 @@ -1220,7 +1637,7 @@ 30 Day Month - 5401.940000 + 5682.870000 @@ -1231,7 +1648,7 @@ 31 Day Month - 5225.840000 + 5571.930000 @@ -1242,7 +1659,7 @@ 30 Day Month - 5672.150000 + 5525.150000 @@ -1253,7 +1670,7 @@ 31 Day Month - 6291.630000 + 5405.940000 @@ -1264,7 +1681,7 @@ 31 Day Month - 5.700000 + 1.720000 @@ -1275,7 +1692,7 @@ 28 Day Month - 4.010000 + 1.250000 @@ -1286,7 +1703,7 @@ 31 Day Month - 0.580000 + 0.410000 @@ -1297,7 +1714,7 @@ 30 Day Month - 0.400000 + 0.430000 @@ -1308,7 +1725,7 @@ 31 Day Month - 0.020000 + 0.010000 @@ -1363,7 +1780,7 @@ 31 Day Month - 0.010000 + 0.200000 @@ -1374,7 +1791,7 @@ 30 Day Month - 0.360000 + 0.400000 @@ -1385,7 +1802,7 @@ 31 Day Month - 6.080000 + 4.300000 @@ -1397,7 +1814,7 @@ 31 Day Month - 15.420000 + 23.580000 @@ -1409,7 +1826,7 @@ 28 Day Month - 15.500000 + 25.380000 @@ -1421,7 +1838,7 @@ 31 Day Month - 16.250000 + 26.040000 @@ -1433,7 +1850,7 @@ 30 Day Month - 16.650000 + 24.450000 @@ -1445,7 +1862,7 @@ 31 Day Month - 18.560000 + 17.030000 @@ -1457,7 +1874,7 @@ 30 Day Month - 20.010000 + 22.710000 @@ -1469,7 +1886,7 @@ 31 Day Month - 20.820000 + 22.010000 @@ -1481,7 +1898,7 @@ 31 Day Month - 21.120000 + 21.810000 @@ -1493,7 +1910,7 @@ 30 Day Month - 20.420000 + 20.630000 @@ -1505,7 +1922,7 @@ 31 Day Month - 20.080000 + 21.870000 @@ -1517,7 +1934,7 @@ 30 Day Month - 17.400000 + 21.630000 @@ -1529,7 +1946,7 @@ 31 Day Month - 16.300000 + 21.780000 @@ -1672,7 +2089,7 @@ 31 Day Month - 520.480000 + 332.160000 @@ -1683,7 +2100,7 @@ 28 Day Month - 451.530000 + 306.290000 @@ -1694,7 +2111,7 @@ 31 Day Month - 464.830000 + 321.720000 @@ -1705,7 +2122,7 @@ 30 Day Month - 389.430000 + 281.540000 @@ -1716,7 +2133,7 @@ 31 Day Month - 403.840000 + 292.530000 @@ -1727,7 +2144,7 @@ 30 Day Month - 416.490000 + 534.100000 @@ -1738,7 +2155,7 @@ 31 Day Month - 445.290000 + 530.450000 @@ -1749,7 +2166,7 @@ 31 Day Month - 461.680000 + 567.490000 @@ -1760,7 +2177,7 @@ 30 Day Month - 419.640000 + 519.930000 @@ -1771,7 +2188,7 @@ 31 Day Month - 406.870000 + 312.970000 @@ -1782,7 +2199,7 @@ 30 Day Month - 439.230000 + 310.490000 @@ -1793,7 +2210,7 @@ 31 Day Month - 484.140000 + 304.150000 @@ -1804,7 +2221,7 @@ 31 Day Month - 30.440000 + 46.690000 @@ -1815,7 +2232,7 @@ 28 Day Month - 21.410000 + 45.930000 @@ -1826,7 +2243,7 @@ 31 Day Month - 3.100000 + 44.550000 @@ -1837,7 +2254,7 @@ 30 Day Month - 2.140000 + 44.580000 @@ -1848,7 +2265,7 @@ 31 Day Month - 0.110000 + 43.900000 @@ -1859,7 +2276,7 @@ 30 Day Month - 0.000000 + 43.880000 @@ -1870,7 +2287,7 @@ 31 Day Month - 0.000000 + 43.880000 @@ -1881,7 +2298,7 @@ 31 Day Month - 0.000000 + 43.880000 @@ -1892,7 +2309,7 @@ 30 Day Month - 0.000000 + 43.880000 @@ -1903,7 +2320,7 @@ 31 Day Month - 0.050000 + 44.210000 @@ -1914,7 +2331,7 @@ 30 Day Month - 1.920000 + 44.530000 @@ -1925,24 +2342,24 @@ 31 Day Month - 32.470000 + 50.920000 - 250953.500000 - 45.600000 - 759011.900000 - 138.000000 - 250953.500000 - 45.600000 - 250.953500 + 238473.656550 + 43.358800 + 737088.900000 + 134.000000 + 238473.656550 + 43.358800 + 238.473657 0.000000 0.000000 0.000000 - 5395.000000 - 0.980000 + 4952.480000 + 0.900000 @@ -1956,18 +2373,19 @@ - 2021-03-24 + 2022-06-01 Portfolio Manager 2019 - 56.000000 + 80.000000 - 274825.000000 - 50.000000 + 238473.656550 + 43.358800 + 4952.480000 @@ -1980,17 +2398,17 @@ - 67181.500000 - 931 - 70.000000 + 39070.530000 + 995 + 89.000000 - 207643.500000 - 37.800000 - 4451.510000 - 0.810000 + 190348.600000 + 34.600000 + 4846.040000 + 0.881000 @@ -2007,13 +2425,13 @@ Capital - 123.000000 - 123 + 35.713000 + 772 Electricity kWh - 123.000000 + 11524.540000 Natural gas @@ -2021,23 +2439,23 @@ 0.000000 - 123.000000 - 123 + 3.220000 + 0 0.000000 0.000000 1 - 0.000000 + 824.000000 0.000000 - 123.000000 + 0.000000 0.000000 0.000000 - 123.000000 - 123.000000 - 123.000000 - 123 - 123 - 123.000000 - 1.000000 + 0.000000 + 0.000000 + 0.000000 + 0 + 0 + 1.070000 + 0.000000 @@ -2054,37 +2472,37 @@ Capital - 123.000000 - 123 + 5.175000 + 9 Electricity kWh - 123.000000 + 207.240000 Natural gas MMBtu - 12.000000 + 4.460000 - 123.000000 - 123 + 0.420000 + 0 0.000000 0.000000 1 - 0.000000 + 2000.000000 0.000000 - 123.000000 + 0.000000 0.000000 0.000000 - 123.000000 - 123.000000 - 123.000000 - 123 - 123 - 123.000000 - 1.000000 + 0.000000 + 0.000000 + 0.000000 + 0 + 0 + 230.150000 + 0.000000 @@ -2093,45 +2511,46 @@ - + - + - + + - Low-Cost or No-Cost - 123.000000 - 123 + Capital + 41.827000 + 781 Electricity kWh - 123.000000 + 11701.620000 Natural gas MMBtu - 0.000000 + 1.890000 - 123.000000 - 123 + 4.700000 + 0 0.000000 0.000000 1 - 0.000000 + 2824.000000 0.000000 - 123.000000 + 0.000000 0.000000 0.000000 - 123.000000 - 123.000000 - 123.000000 - 123 - 123 - 123.000000 - 1.000000 + 0.000000 + 0.000000 + 0.000000 + 0 + 0 + 3.620000 + 0.000000 @@ -2141,6 +2560,7 @@ + Level 2: Energy Survey and Analysis @@ -2148,23 +2568,39 @@ + + --06-01 + --09-30 + --06-01 + --09-30 + 0.088520 + 0.000000 + --01-01 - --01-01 + --05-31 --01-01 - --01-01 - 0.072500 + --05-31 + 0.053140 + 0.000000 + + + --10-01 + --12-31 + --10-01 + --12-31 + 0.053140 0.000000 - https://missoulaelectric.com/member-care/billing-payment/rates/ - 28.000000 + https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/Regulatory'/%'20Filings/CO%20Recent'/%'20Filings/PSCo_Electric_Entire_Tariff.pdf + 16.880000 - 12692 - Missoula Electric Cooperative + 12345 + Xcel Energy Some-meter-ID @@ -2179,16 +2615,17 @@ --01-01 - --01-01 - 5.500000 + --12-31 + 0.163600 - https://naturalgaslocal.com/states/montana/missoula/ + https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/psco_gas_entire_tariff.pdf + 43.880000 - NorthWestern Energy + Xcel Energy Some-meter-ID diff --git a/docs/notebooks/bsync_examples/img/ESPM.png b/docs/notebooks/bsync_examples/img/ESPM.png index 8ba60f8298777eef3592e88b3377da4ab72750cc..224b3d7a6899474f9e5b75c2923a5e65f68cfc8c 100644 GIT binary patch literal 31032 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 Nf{dzkoup~l{{SvZiedl& literal 29708 zcmb@t1yCGM+xEMJ;O-VYSO}2dwm1a$K!Pk5++7w69-QFr9^7Sdx5eGv-Sv?F^PTg) zr|PM%-sd}KsHZ>k8+nss%LfKLp5j|Ds zf?!513a9QaeAKvil8FHEQk8C5Bo*&X5-sdm+0wvOIuhlmwi7Cg(4D3B=DrqA$zV}Q zM2Y9$&;@fZhm+%pr5%+L`9wk_8zxHhrOv;S zLa0LCu>Z=W#$5eZUKiq9?ti5|zkxyjCnXg6cEo4=`WWl!e}#y|keeAEO~=iA^LU?# z=Y|G|L^*j!9OD%gFI3oGi_!$wjef{380mS|ZhAzpiYN^8PZ$abinf2Hg0K*6{&f!h zw{QM-F96_8_!EHePwGD^ru&Z7<@at~I_+M11nr(qL~1TZczQ05@yI>|fQwMB@=576 zY=)o9OFv5CcBS`LKkzx}OvgZL2Uwb$PYVP4c=mhsqvwq3nyAu;q^DlGX-Lw&tN`GSAPn|%=(*(muGdHO33tVnDWBGcv=TI$j z5lRk#w*!&O?LYL(jv-*nC2M<6@byN`%;;sLOrw1mOK`uuaOTk(;Zalx?AL9t112fyF9zSsmTKW?%=-E9)N?M$#$ zAIuWXdmL5^n1!zG@N4))A06G(&X=esF0G{J`a8g17j<`f-9I})jyvAmw^~dx{>Hy& zQEG*~CYF|(WuQlFdcZhP@Nr(wFuv^dQECV!d%9)Y_sFY0Cwi?jO&_oCAD3aKSf&I4<6gj}pE=jds4!@sQ z1XHtA^8F%t?2`s0CRwH2$x!eg*E6mx(8sCA@%>zC4w>gc5VD$ro^3j7>*)0btqUE` z3Nb6MZ8_T#hwBd){@A-H_{Ap;sAGJ5-(pxYzbq@Yil;XDKj%YbN)hYSt=$p~Ii6By z9|tjKe%seL4WaYgV>(Q=wF`|=`>e|nd0H|=reX3nCSIFdt|!OAOcqi z=AkggACth{jhAjOZ7iklxqkgCL-cg_w~^R^R{wyq^fHC%0R2M>m@_(*4hlbC3#g(kd4QZ5@X3(dTf< z)?VjbsE>@*w|yL^QWs4ZU&%V9)f+kqla>5@)0tJI`#J@Maq>U~CFS5G6^HK43HF0U zHuj4}{oQ$%eCwBN?3T+`^ufztwd$p^Y$psvyEl0kG;G^_ttdsMeM2BeUz;f=HxAh6 zCrP1fv+6^R_b++uhak&L;~z=38j+Hs2Yid)Uh+NM#BH92i?GNkVvZY3(;hYHrF-Rt zpFd`T)fU23wbMUZ<$)~%Ws_JFNOGO-PKWfyN=f&?lg6;cZvbnxKj>B{&^kXaZ)U0bg+G-Jy`FlC_i%RHrzIZ@bk+9$;#5jHjaPgJS?L0gS8i%2J&&Y?U1UZpqm_MH6(sD{>1B8?wor_; zVRK`S;U=ljzp@1FZI)b#+p}mMm5$7>QMVf6tv$|9VSdnjX6!n>8t9Qt2+j{#!qhAK z$ozPnG!8(oP@nKWaU1*U_S#JsEsy5>S5!;_)20O^1dply>(2E<*=2)iOws68CowDF zbVeG}dz%wme+HwAqIoh z0tx;|@JlHeq35^&IcR}eSY;4Kva*6JkDt*2@)jrj8h=Ddakm_vnBsPNPh6QO(o=b5 zPTrB^c|EP9E3J&~IGn!^Ny1^j8FQ^7Yv*GG`jnWL#wPAn93*K_He&BQ zKEjS1)`#ACm9lbS)@Z=y%jonqkr5ve9J|i#Jyxl14^reY%&#nU9nev&>4|f;BvhnL=zP^=o`7zfltB@`y4gHu}v_Bg(-l!ys#v8tO2~AKQT>n6W z`@=;B|82LopqqJ1CYgY6Gz~4Pzd^)TXV0}xg>Vnsr0eHr?xWooYSPC|`};wHPBD?m z6#H#lZPyW^Bxfa`=T3FniLHse(fB<1%)*_t>{gy0?pQMi7m4F*vyc<$F0;1nj&&L6 zWImhg7Z`V;5^wJ3=haN0cp^4-V=RM)->gWX;u;-|d42|9cR5zQPN@mCb1+X`Jf z3vA)882R1}xi35Dk-rT>NRuNM+`&qvFuMH&YV1`K@{Kb;)wX^XX~o z1|E6jCVg`0XBL2?qO7@((421id%6rpPXEWr4nNa`3yGCLYN|KQS;C)J6T{7%`KO-k z#bPuIP3wc6fritl7Z14psDeDM+aI5jF**3WZV>K=GYuT{T@pspc!dp((Y0!+vn8!x13_R0w0Bdx) zdigzAn6+Jkd;xw}vH7U_9x<6=xI}rOhCb&S4n&6mH;GTeDt>wE^NkD`!C`MS8kV%p z`M=NUHd~m|kKK{M5Po&}^edL`v7#uH1Yz*=irZ@LPe{a1?bV)SObN4hTq`npYvl2Z z_f;_`0Z!e?+z=6rm^IdJR0lS{yg=cc%q!As3HafpH8p;J6hR)R$M;WyUtT0%&aKJE zS}`7@(HnNILE z0i%_Frd)pEDMy!7zu7b{<1d)CPk-d=*v}fPoXL13Ng{)PUYd5k<$Ccoqi`wL*SkOy zBqDI)RV%-(U51#={sC3;B{6)PKx+QF{7ig6Nj z6s{*XQQ?y}h}Jr|WT5mjw8f25zZfta-AAl1I<@aKMZ{Qr0rYq~qoWP95^d2$Vii4p z+Ug-(kKs9nBvcNoJSS9sk}fc8uYf9yg2}z4TY;Bgx0?;YF=IM;oYv|l+1*$of>ec> zI2}oy*2h7I?s#ZEOR97D@ksjbngYEA|D|n(vDso3x+c9Ji!w|H>MGVUvf3#t!1&VC zq*EHc#St`9)_T+JycuAz<}T4Rr^ZRbrQxyb6@~V-f;&2+wg+!NPrd?_+c0$b*aLL; z)18bwW%}44)M^s&jaN#?WKlpNMO5<~#K zp(=svY>0w>m+ZqXMhIqXE-BYRGcGOkG&-tEideug;MsCD;&K5)Ft4ube9qX*R^POh zl}Bnu+wJwjpNll^GfwQvsQ4G~1U6mJb!Kx1;D$kxxWSB}vcE*rzl=BMe(F7qJ~PQr z9A+r#t`oX`hp4R|D8*lO8(1yl6?dB&^9G#(d4kDnJ94@Ez2B{{M!kXBK5lWwdj>_s zfnnYN1-XS>_`IOtUD{>iprnJTW95zMG^np-OZ2+19l~$!_J_uU%-Kd_002&?w=&%I zd7F76rom*++^9L=kZ6MHON>tO`QG~vk3bu3>-s84WNZO!r5TPRgY;0?f{_r&>hdlxJHSsdpQ zS>PJy7}hFN@&iYpPxOu#FqPquu#h-}!yy7P5|r>1l{T$arny6~*iiZKF0c7T6`pVJ zK0#huy%hNF1u`%M?|~lA@vVK|<}2CqcY|3{MQ3z8KWo3#l#Lq_$f+#d@y0n}cR6Dz zid~!aD0~k&*d4!NsN2DJV_iOCcat}5+8LapF^jBdBYIohcew#p(%<~UUUiH?ju zQaj%K*dFo*(003ZI9KIx87(-ryh57mj82xP@N#J^jjUupGRLOMV~PBv-QBIqBsM%G z!<-W`l3t{5TJyygyNfI6*O^8BJKjMmo;04^3-Aqqo(Y)?CHTT@?Woe6#t<~gZV%ZG zc=&MOgoD#v@pUn)i`^gKjlDCOh;{!Wa1VsMG*PoZ-t9PCZC^(@ea| zRyTn@GS{c=P%pk=qrWGqbRlOd7g1#OylLwZ*9V)9JfV%N2*FrMxTAJG~&EXcGcF0op9m$ zIByzmFO8y2MVAIKVgM`72vHX z4JNZ;Yqdnw`i`p$I*=Sv)y{Tg0{RykFCSB7Up2&=o|=S#ItUUOQ3uhhdY(f)$bCw^f>vzY2bJ%WPpq>C&-((ixiGi^x+z(C zaE=DJR}PtFR@u(7b@V9TBM`c-SHFpK4wZ3@W%;;nX%e2T6=(xbhCA%@p zF);e>EJTz`v9UCnw{D{)EbOhllpeO#P;OwcU7H<_&O#;JMrI4kDGjQiKvN4Ha%&4! zmfHN`yYO=L8^Q-(iJ<};gb}(As_l>!{lBg4aw*2d_8hsN!(Y96?hY&q9|gjj*@dk> zQlD+%Da={KUbWWlBed@DHXkF_9}7NyG2R9e5j#K)E<=J&AS}jcypky5&kIjaqL)`n zLD0ZgPP5tet}zsanwj2%rQ`P-5rRBnmI@c63dY|JfGanKZs#ggl)0xT+CdcRt^vWM zlZ7k^>JMUdm@~e)hdplz2@0H*Y=W|nEI+=E4Gl<`%A4-ldTz4thS^AJj;hMnnhMhf{`X-QxR|b0kA0J31Dkr(HJ8kyvxF^&_*ooi!bi;<=EzY`{vPC8ykd&h$t zTUwkWd{i)JUuG-Wi2yE5A~bV;IE!*@a8>^Uu;?&M_p}h!nwq$xwF;; zr2mpbs?%QYrZWBIt6KWqly8vE>V%tzFV_ck;*D%?=&gUXYA!=}TT)Q;joek_z z(s`l28O`Yl=8diW1v3oOtOe&S`w8vGfw*`I*Nc?DmkVg!Bn*1D8Jqug`Eh}9_xGD= zQhAmm{VDJPMkp4YtS~_7Ee=s3SXDupu?SskSnEZEOgd`V03R+`tI{mh&*C2 z=ncGUUULIM4Ce^{KE@ej0>L;A7?>^8`5z zz3ua{U~$@b%&8D%0RcFL+Uhn7=`(}aQf6r}$xfPL`E7>+;VbkJimSh%*ReZ*R*x!` z-zWqWNJ7PVJRXSHu98u}IbjIA_gh+b`WO~$>=S}~zL^2Lsiay3y_&l|+`0=@qUorM z+E#NjSH-~Vx>W)`l|v4LamZ^;gjurLe23%4uTHak&qNeKYwi8dKZ~ed_}BZ>@1{uQ z-!&kxjef_xV2^Ua!T@B8nYIQQQ)T2c{D@+=GN$hfJ3FOHv;CP^I_#Q>QvNe_`^#8f zdc{M+!1m2mOhBRU7Ze0g*DF(oCp`f}1%=#w*TuprzKKLU8V6YeBoLg{;_AU7l&{^3 zgUz#JEmAz(Q2(UG3mdhqz8mzzhdKD9hMvj0V~doch1;@N+z5fsG_ce_)))*`4#Wpn4p8*rPTx9_6* zNATX5IA*27pf^t12|!KJ{C;B-pJ*bM4p>GI9uj@wf2XnNtY{j%U_ zz)i=EEB-?YE84TrRTT=@prRFp~>36i6= zQ-U_qB9@iL8@_*Z4koE4_0c!5k@4uWS1FfkcsP64PH124yH5(1WeU_S+lcrxP_V!! zUHcqP@DWGpSgLp%)-OF@PJjM^|NEvwXB7 z7&gDh{?)Ck5_|N*wCHBGiB2gSvsU_}j*vNdiiji34d?B=l!m&1Km2i{kadOb&!=6Y zqPml>DfuVgnQ{hMvgCJ?)|a~=;Nv--e9XC4;>_s=!^xTrFU z9jVB(5Y<#g87pKxgrQ@XKTi&t|)RYDSvaWVrFY>WUw<5ZWO%{R?6KEWqi>sZ@(D?I7*gToLsmENlSUsgOT2kmtQ1-Sj34oUOw zKHt-B+I7ds{BY0h^MgWNVWviC>Xaf8e9JsUE)eoYy{{867VYA;`6wAhJ_))d6_J+R zs}?QWYF)vX-+EsES%9SkBR5mIFNIfCOM6Cu-+yyYr?4C02%ATcf9p4H@{J<;tEAL^ zta?U+T3J5zqsv!BHKkaP@rRD`j6KgOY>K%pIMTj6%0D6M?HH+$gnzA;pP z{|}V8ND01Ul^0_5vVr?b&DIyAd)`Fd>`VXotO|Bv$ia$Bb7AkQ zl=<#`_a9voF12SOH;#DmT_oSG*f1;=t_c{TWf}hl)Zka((Ecb#zNEya+J$`v(|cQ zV)&I6QrR3RAI0#{zAZ(1D!cIlg7EO?U{zo2a`Dk3RHm@fcWb>N;jmPL^v5uJSv?4U zB5~$4iv@iZ?*$LBshXBaN)1D7(mUliJY_=0LSQg1-=efTJFC)58||DU>NLE|?-}s6 z!68v_fn#YIMYXqHZ|M+Gu*fN&x|v~9x4>M7D5r2u!XEBGCP1IHJkh7(=?d-3ZXV{I zr-M&Y7)h|*S)M=re*XDh$?$udHA$wYt(IeM-I&tX#L;x+sGWIm2iQ6y4WEdXa6}e_ z;ebU2*R;p`if~c+lExH@9VkC;(80p|SDNKXIpm|S zqF1)z>tLuVcj1l7Q^=mSIAdOD44FshC^W@4z57jCS|b$@CIHg6T~_KM@X`O2HpMTZ zbolev;jg%kC3G$Z796I`DrHsPpo657_x_{kIqttPb?010@Hm_scF;&<_r$>!q?tn@ znA7W?Pb&%!nktGQOOD%#OZr<95;z}&!z)O`U^mRN6yBTPJj-*ktYjQ5tt;S^!#uk) z=R4c%Hc_P7j9xC^$)`$_dPnvKPR9)mC09qK4WlygCfL*t$Oa&k)3R z)!UiTk)zsmK=<{YrHp1R@*xJXqOn%6tM}iJu27?lXLd-C)?TZ$KGQR_+mznI)wdyu z-%Wjo&^XWHFu^@#*Y<5DnCaY#wPUV-51JQJsKY%KSR?m)=T5YGv_tfr3f=(zW%?8M zp8zQ1xJJ5)TQ!2jn=Xq)3x`WI7q93`yFg6OQVMq>I;Ib5;|%40)NBYpphJ@>4QB`M zHEcN@pGq-+U_;8;d#2)hQGO$&th_8`HW{HIZ+(Po-nF$kU@d&FKdi4^hbx`9qGPQ^ z{o5RfV#vtO7lk~|Uw4C(a2AOk-?Lier=))ktm)%vhmg_F7@!CH z2XCdiorbwu9Te2mseA?5efV&ujz~t=qRf&Yj~$AnHS*3hzlGQ!>`be}gu#QIl(KWoDAwp8#{|#*yn*gPdEbR|iFYedfY4P~=~- z5E;f9Qq(S`$MzVPrk?k@` zKU74qtxHrcMyLA1!d`N~!U5&YtKQSSe4PzCYtQa1B-9}ov`zBcYx^q$F;OsADb%=2 zi*MJfU8eDdB>!f5yLkVf*d+cQ`rjn)|JHO7)pdGmqwM8m0=@})e*5=G0H7~0@4#qR zAy^T{b0=l*AHxUqgzv+@6UFl^ZCE~kn*{&}h5iriCI4|TILy_2(}U>Vy$*8C!MJEQ z9b2}^C;yw4Bk>n_SJ~AQ9x0M;TM~={4%fwKIupr~fKyJ(l-iV9&-dY8uVeUIhz>j% z%Z(hLprh-drH7v`R6(?reBeuK4&SBop}B?o2$&gqwZ(DQ;w259v;rV2_yJ|W)s`z? zR6(qVuCfbNTDpT2I*XNy3cTRh+O!^cprK8lV;fOwA zhG-6++h4)>8$bDY2hqLBqZDn3@V23@Mk+l#dH}FBjB<@L4kK&VDSr zJ0{or@!ssesE|{*Ca38LPhS6=tvk@mid)Lcs{g5WLZ!h@iGuiPzntRxZ4l_JL*&PF zu%#OlK#B7ClUb`bw4z{3Z@%ziynPsKszlt5F2wzj7+*OAR3&9z_PB(p>5O@&7suc` zXXHGbn^!z$^3ML7yABiC(6*;G-Oa>M`U2IXrCa9*<4J6_6-JVI z-R&Y_dGmGljBHC4S}{}AY#egC=;3o5x$@*wd(IP)=vcEj=Al9QQE3IEaXNvD^<)Bp zb0YQPvJqoSI>an-Nr;Qv)~?IiA{SA(Lx*0IjlOzE!i>AF(`0|LHR6;P zZmbj^#&b0}p+8Xj6ufnkGI(Ng@=^t&zHT|nE0X{ z${v~1RS*y9zL>~opQ$P2@$e~_wvVhophi_GXb&=u_67i1g5s(!1@fsh-9=K!LoE^u z<5GsoFFbRaC$c_qyDYL!(hJPXEd-%B;?HJHee0EA*6?k0`+TKU$=VRHTft&dV}EYf zXnLk>wiiI~4mUh;9Jbp3xLMh{{M!exiKiIXfuo=(%hHzxd_lZh?PSJM+&9|SoAj#U z8qNN!^!lZncIPN=XJED~_;`owf$(VY>JYV={VU7?;}M#DH~(dJAI;#J1_$vdmm^yC znIYMdPB{Zm5HL&KM2$8RT`TZm-)inOiC%1zIx5=4$h+i(@BRB)$&I7uW}7=%4gDR0 zWQ(+Z!boGpfrje)XI70$9YnLsMX`6)miZ_Tg zS{f40plq&FAYuhXth5FA-v->YfLITaPk-kZpUT?Z1$p651j$->K~h` zKUNy{XDZt>VJLHN)mdYO$!3Z3vJBrZd0Zw6w!%chTv%aLBv)S#0E59yQ0=!LM+E9) zYx~dDKMJNNHe|zv5?AiXP7YeJl<(7UmU}NRbIhPQM`ns9A`37>Yn3iAXeAnOlOld7 zw2qRQ|G{hrLi@?U2(1@lh^IXF+3AmI{kzdG6ta6q(_}jm0@}ZmxEI9&V^Ps)a`P9X zb;s?~NCNNN@qV=h(%sy_T}4xi$Vy;h!yX6Uir569JHl1(H>!`EJeNl+)x0?QE%eJ&T@Zb*)_S*kzK!)s(9xwyf4(yhV~p(MF?@?aoV=KC(2 zS5oEpvAW=5iEQWBU^9ov0cK#=zQZwyVqEED==Wl}6#phmn`J4F0?KUvq`QS*8cP8I zkLVk?D_5egliBdSlzR~%7aMP4twe!Zjc(qp?VoCEj9fd(h*(T=0R2vfE#n_h-n`NC zkFhJyF(yL-A_@uxFbcXux4ZF|o$A&#`hnSsu$%D~EyX6{oqiGl;eO29T`d&Re--&qv*)TWTvy>Wk(@5q*tblI6clH!VD&Wh_kMt3vR4z3#WZ&`o zM@J}mIMTd0(a8WUn*$l##y{Vg=NgOryhRV}ElWi7$pE>am(?IJ@ok>U>eI5ofIynG zz@@53*bk12H;@_?KU?{{S{dj#)lR}h^;I|4yg-vI`nc+wrPR;jJ+{RWKNHLwmmN7e zkuj>-A3ROa8iy=Aj}c1~W9;OOpz>!V%&B5r{Xg^e5~SD;YR57oJEmPWv-0m$&WvP4 z;O*`alFl*|aNIg=72!T}b2^~HzcCnU=7@6^`-mV8%jqsunFQ=hEEH;61ITG#qrL@% zk`<9GR(>bDWCjcR!Y>uKA1|o$?{LyK^!Bn{z!Ku*=++X;rR`u}FLn$h)|qCfjh~9g zh>|t4H6krlNth&VKd6El9-AD>^10}x2@D@(*Xf{`xMYArV~&cAQm@nuU-{WyTn(pI zkI*!%Zq$M1ZT@*4&EBw(C&3(6%Gs$>-N`nn$I-UizB^0h?97A74g=(bdw8Df7y7aw zhhnv~2)rKXc0=!JbkbU@5elSZ36XpZD7bK=&u1(h%XWcf$Ty6zyhcBjB=RfVZgF5` zRFI>Ad?*sK5o;EB4x87`>Bt+p^u==C=Tj%Ni*cgl-vflwW<}N*G=DEYY3{iaD&mP_ z3n53)ojjXkL~-I#ht#THCvX|xKO=r}>m#%w>mqp6Qchn0DezDmJY2a?i?RS|NW&J? zRSOML;UF%o@Q>bOf+9DgM!Y6hm^p`aj!~$4wmU`&H?loR|D_fYmw1dDL9lSbBg`GJ z=F&CmJIC+Rk}&av^Y~j&3LZn6-%6v^YR@v!JL%@%{k#mpkU#jVDmldU5cGU(e$4b! zUrH2mTDyM8Fn8d>{6|6d5h0!uCe|4djCCl#bGhKO)RL^mfffJfw{!S6{Axqy%U5Ro zZ8u>F-~VQMiva!~&+>mPD*v|*=>LlLYi(^U=lO8--}<554TnEM-~oO9au9?qolP1= zv+|=3E8z;*e=%$ujR!bx5ygM%|34Pw|FKy*2k^!{ftTzFmgcxBZbx9|ApvUYJ6pR3 zeEt*uHNDFCv__$Mrh>qJ_(mYNE88nixW*{6RQqMVTq}A9nSUfNp7Z^F;YII6~Xxdbgn^1U(v^z68Sb=w4CD%t+qOu@=IOPYN@m~F;lFLuFA6Z;h;-(h+GrndA% zS?KlK>b1Ba2P9HiTKUp%`AVu>cY!nqkjo4Z3OAfei$!G^e)9HsEbCpf!JKZv zcr{j}*HyYY{%m(T!Qws8R~tw6uip z^TKa7@Wtz7p+{aSYr-l$VA&2Yt7Qc?8q$`U9%H@8t)iky6DWC?TI`N93e;zme$Q7I zskbeO#c%{^(bksf#C`|CQ!x6`qtr;@TU;=V>+6-#__)P+G?K}ay$&vuRwc$)<69v16S1>QDc=-oC6LWoR*%5pN$GoY(F)mdMzww?m z7_lom_B8~DJ-)piW!Qg*%@o?Ovxhe1I%#u*TSUSux+L0c#lI^3hb!3fAk7gtX5bHMEZJ7YNH_c56u>IE#DX*B75#(J z^;uL*yCV|&7kHNp+F)j4`I`hOi{t4n$(cq`)Jj<m^l9Bxc ziQA8NRNAq2SB@k_WKmaPrevp1CK}I51(F zW|x92%PfgJ)Hh1l7(_c*)xrgtIcYdCRXLIzWbkU-xY_P!Jic{#eMhVOCU(9Rv%eFc zyqo+x#V|u7k|4+(Hs4)4-P9_bx}rDss$t(oeN#`f*aA9t-_5p5=ruzeUBEE7 zU-jU|cw6bT8+F1@QCF7s*?bAr%Uv_!a#RLR$(LmW#Q&bGN~=bABy#KVVz#=XQNsqV zy@ugBD3k|x!O+8fb9Y#-{gqTYPV%uR=gArV7$p!K)YuHi4e(ztL1Rz%bGeNJ)ip@F za`CCF?x7_Dz)TuH6#TEW>cf{czFe(TfAz7Wm=qinQ&P}I5-(l33P1|MpIr&Ayyh)J zmdtN?RwZ{)q|STkj9i|iqJUz?pqL!_suWnAATg3X;Os}Hom`@}IQ^a;PBrt-r$6C2 z;>Kbo2F}>UYi$hp66HKUiA{YiJa6)nf$XE7)v4BTD(B)k$4IKanv$6Jp&S7xCW4N` zrP3?J)7s41^VG+`sFOi7#F7UEO_EJIfYXlk?D?xtt_7I^ZAW9MR<0@2uKZL0T;yZN z!wLB~RkJwblVLwd+?z%&`N^iqiv9yXaBu`wa<`+euiUTe9oQye4|i_|5QC&o9^PSX_H=HB*8cE8QB3fdRpgz<$E;H-1}FElB$P2ogS1a9Qde37zvldm9E znbjwf@YJU}LFT?tr`keALtEqrbZ2(*s-|%HR}7)eRt@Mz%qlV1pe0+=KWPtba<8HE zh^H{C$grJB91x7gv7Hr}CV1?>pVb(d_7QO2emRZHEKhQ+L0o`|RBEm6@oi7mox;C? zzL^!B)XhYoBu7quX^E}rGk>kCR_92kRngR5hW>#z7HHy6?*!4$XSb3`HPf+?{ul{m ztf*E%UBk6LQ&7J0!KkU(U>74PeE|!zE=>yTmxn?HugeZt7`KA2KT>3U?#O(qbh~mBtcS)?(1c?bAA4_VzC0>9z@rVBHqESRRgfH$GF5~sHeKOvG z3R~(DU$?|OV8<#Jzs4eE{fz3Uy&a%aS{nVnKU2(1Jt_E}Od}Vl%l?+A5v#58LlL$S zmG3=UnqCg?Cr<`!vO}y*LntwxG^|iXCs5!Ji&Z-^c5&i;XQN$uKZ0$XZgpg>VIb+i zcg5+kNB%r?KL|coluEXAeqy;du_XrU+ph{Kn4hpj#A6i+A0Fs3>J~6=#*K-Jib;wx z8-tAp#@RA)t8R_Xu~%PbYt-Eu8K2nVo1J}#0|!iE-6edSg>4u^5|@R~5u203O-cV=9J*OCo|LVz?~gPCD9#8#(14)J z5!D@`55-g=@o0n~G*p%%|Ee;E)}@V?XFv+G#h!gX4L7eiy}K!+9TU~~ewOpTnt zEZT#gqL81rUA(h0T=_xla+-B2LjMEPXuU<@3U+f&twkER36xLc+8D*hYs4bsV+!5= z>WP9LaU}pZPSyIuVa+WTm1ZwpF)wHsDXlPm>S2iIkG}W5&UT?c6XX+2 zK4nbRAmSOPPQLFMhy;eopzS7kSqbRem|Z-%Dwo~)gIeOz5lnTdoKtc2-;|KXcQ%WfHUT@rWZlbXY@mObXzHmeQp`JxrgBZi!#4Q~*gb;(GJm3Xyi@4= z3CQL5*O`p5`bQh-{_zGx2th`GH^LkSQfv7R|5~Ny4|v0mP4+G7AtR~651}TugW?}P z>HQ1-->g~tFU9sh6n6in*l$8IGWmTdy5$MkSo*(I8{lr#VF~p~3g*=o_RsbidmpCN ze#GG)*|&2;8vE~-!J+-%r49bw^1A=?s!GDVy)~V`-?VK!?VYaN%2`%lM0NC9gII$Z zu2*by6PVr4-=gh(CAi{0-W4dBK^gkXIP;!ju7e^(S(x%sT5kru!J`j(sp*aU*R=v7 z0p+XOdoQp02*Trq^?8AD8^r@PIGIPlv zgSPjWqW(KK)srA%h$S((V$KpbWkn=}tyiiݛ+Tk}Ak5$34$>cEa)|xLo(%s=; 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 From ab8f5d9ff8d3222f1af6926dc91d266433a722ec Mon Sep 17 00:00:00 2001 From: Xiong Date: Tue, 28 Jun 2022 12:12:24 -0600 Subject: [PATCH 4/5] Update example Fix quotes inconsistency and some tiny tweaks --- .../bsync_examples/Small-Office-Level-1.md | 2 +- .../bsync_examples/Small-Office-Level-2.md | 734 +++++++++--------- ...le1.xml => example-smalloffice-level1.xml} | 0 ...el2.xml => example-smalloffice-level2.xml} | 4 +- 4 files changed, 371 insertions(+), 369 deletions(-) rename docs/notebooks/bsync_examples/{example1.xml => example-smalloffice-level1.xml} (100%) rename docs/notebooks/bsync_examples/{example-level2.xml => example-smalloffice-level2.xml} (99%) diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-1.md b/docs/notebooks/bsync_examples/Small-Office-Level-1.md index d9e375b7..b8b65365 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-1.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-1.md @@ -1452,7 +1452,7 @@ Use the line below to write the file to disk ```python -bsync_dump(root) +bsync_dump(root, file='example-smalloffice-level1.xml') ``` diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-2.md b/docs/notebooks/bsync_examples/Small-Office-Level-2.md index 3348cce5..6c2e0576 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-2.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-2.md @@ -27,6 +27,8 @@ By the end of this notebook, you should: ``` - `auc:` is often used as the namespace prefix for elements in a BuildingSync document. If a document declares the BuildingSync namespace prefix to be `auc:`, an element would look like `auc:Facility`. The same element in a BuildingSync document without a namespace prefix would look like `Facility`. Going forward, we will not prefix elements with `auc` - the remaining XML content should only refer to things defined by the BuildingSync schema. - XPath: xpath is basically a syntax for 'walking' an xml tree, mainly used for 'querying' information out of an XML document. In the simple example xml document above, to get the `` element, we would notate this in XPath as `/a-root-node/first-child`. XPath will be used throughout this document to concisely convey where elements can be found in a BuildingSync document. +- We use OpenStudio model to represent the prototype building. By performing simulation on the OS model, we obtain devices sizing properties, energy usage and bills, as well as measure analysis, etc.. +- Referenced prototype building info from [DOE Prototype Building Models](https://www.energycodes.gov/prototype-building-models). ## Caveats - These cells are meant to be run 1x through sequentially. Running a single cell multiple times may give you bad results @@ -336,7 +338,7 @@ Relevant Standard 211 Sections: Space functions are used to define sections of a building used for different purposes. The classic example of this is a mixed use commercial real estate, with retail space on the bottom floor and offices in the remainder of the building. We do this in BuildingSync via the following: - Each space functions gets its own `Section` element -- Each `Section` element should specify the `Section/SectionType` as "Space function" +- Each `Section` element should specify the `Section/SectionType` as 'Space function" The Small Office, as its name suggests, is just an office space, and therefore we will only create one section for it. @@ -415,96 +417,96 @@ In BuildingSync, schedules are defined individually and referred (linked) in dif ```python -schedule_occ = bsync.Schedule(ID="Schedule-Occupancy") -schedule_light = bsync.Schedule(ID="Schedule-Lighting") -schedule_pl = bsync.Schedule(ID="Schedule-PlugLoad") -schedule_hvac = bsync.Schedule(ID="Schedule-HVAC") -schedule_hvac_new = bsync.Schedule(ID="Schedule-HVAC-new") +schedule_occ = bsync.Schedule(ID='Schedule-Occupancy') +schedule_light = bsync.Schedule(ID='Schedule-Lighting') +schedule_pl = bsync.Schedule(ID='Schedule-PlugLoad') +schedule_hvac = bsync.Schedule(ID='Schedule-HVAC') +schedule_hvac_new = bsync.Schedule(ID='Schedule-HVAC-new') # occupancy schedule schedule_occ += bsync.ScheduleDetails( bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(11.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(21.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(53.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(32.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('22:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(11.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('22:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(5.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('23:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekend"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekend'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Holiday"), - bsync.ScheduleCategory("Occupied"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Holiday'), + bsync.ScheduleCategory('Occupied'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ) ) @@ -519,94 +521,94 @@ schedule_occ += bsync.LinkedPremises( # lighting schedule schedule_light += bsync.ScheduleDetails( bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('05:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(18.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("05:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('05:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(23.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(42.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(90.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(80.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(90.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(61.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('20:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(42.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('20:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('22:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(32.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("22:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('22:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(23.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("23:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('23:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(18.) ), bsync.ScheduleDetail( - bsync.DayType("Weekend"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekend'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(18.) ), bsync.ScheduleDetail( - bsync.DayType("Holiday"), - bsync.ScheduleCategory("Lighting"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Holiday'), + bsync.ScheduleCategory('Lighting'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(18.) ) ) @@ -618,59 +620,59 @@ schedule_light += bsync.LinkedPremises( # plug load schedule schedule_pl += bsync.ScheduleDetails( bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(50.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("08:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('08:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(94.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("17:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('17:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(50.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(20.) ), bsync.ScheduleDetail( - bsync.DayType("Weekend"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekend'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(20.) ), bsync.ScheduleDetail( - bsync.DayType("Holiday"), - bsync.ScheduleCategory("Miscellaneous equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Holiday'), + bsync.ScheduleCategory('Miscellaneous equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(20.) ) ) @@ -682,38 +684,38 @@ schedule_pl += bsync.LinkedPremises( # HVAC schedule schedule_hvac += bsync.ScheduleDetails( bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("19:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('19:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("19:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('19:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekend"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekend'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Holiday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Holiday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ) ) @@ -725,66 +727,66 @@ schedule_hvac += bsync.LinkedPremises( # upgraded HVAC schedule (for EEM) schedule_hvac_new += bsync.ScheduleDetails( bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("06:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('06:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(60.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("07:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('07:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("12:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('12:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(80.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("13:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('13:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(100.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("18:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('18:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('20:00:00', '%H:%M:%S').time()), bsync.PartialOperationPercentage(60.) ), bsync.ScheduleDetail( - bsync.DayType("Weekday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("20:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('20:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Weekend"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Weekend'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ), bsync.ScheduleDetail( - bsync.DayType("Holiday"), - bsync.ScheduleCategory("HVAC equipment"), - bsync.DayStartTime(datetime.strptime("00:00:00", "%H:%M:%S").time()), - bsync.DayEndTime(datetime.strptime("23:59:59", "%H:%M:%S").time()), + bsync.DayType('Holiday'), + bsync.ScheduleCategory('HVAC equipment'), + bsync.DayStartTime(datetime.strptime('00:00:00', '%H:%M:%S').time()), + bsync.DayEndTime(datetime.strptime('23:59:59', '%H:%M:%S').time()), bsync.PartialOperationPercentage(0.) ) ) @@ -812,18 +814,18 @@ In addition, 6.2.1.2.e requires information of the building overall tightness, a # 6.2.1.2.a roof roofsys = bsync.RoofSystems() roof = bsync.RoofSystem( - bsync.RoofConstruction("Wood frame"), + bsync.RoofConstruction('Wood frame'), bsync.RoofUFactor(4.706), - ID=f"Roof-1" + ID=f'Roof-1' ) roofsys += roof # 6.2.1.2.b Opaque walls (above ground) wallsys = bsync.WallSystems() wall = bsync.WallSystem( - bsync.ExteriorWallConstruction("Wood frame"), + bsync.ExteriorWallConstruction('Wood frame'), bsync.WallUFactor(0.547), - ID=f"Wall-1" + ID=f'Wall-1' ) wallsys += wall @@ -833,36 +835,36 @@ win1_orig = bsync.FenestrationSystem( bsync.FenestrationType( bsync.Window() ), - bsync.FenestrationFrameMaterial("Vinyl"), - bsync.GlassType("Clear uncoated"), - bsync.FenestrationGlassLayers("Single pane"), + bsync.FenestrationFrameMaterial('Vinyl'), + bsync.GlassType('Clear uncoated'), + bsync.FenestrationGlassLayers('Single pane'), bsync.FenestrationUFactor(3.241), bsync.SolarHeatGainCoefficient(0.391), bsync.VisibleTransmittance(0.391), - ID=f"Window-1-Original" + ID=f'Window-1-Original' ) win1 = bsync.FenestrationSystem( bsync.FenestrationType( bsync.Window() ), - bsync.FenestrationFrameMaterial("Vinyl"), - bsync.GlassType("Low e"), - bsync.FenestrationGlassLayers("Triple pane"), + bsync.FenestrationFrameMaterial('Vinyl'), + bsync.GlassType('Low e'), + bsync.FenestrationGlassLayers('Triple pane'), bsync.FenestrationUFactor(0.3), bsync.SolarHeatGainCoefficient(0.391), bsync.VisibleTransmittance(0.391), - ID=f"Window-1" + ID=f'Window-1' ) door = bsync.FenestrationSystem( bsync.FenestrationType( bsync.Door( - bsync.ExteriorDoorType("Insulated metal"), + bsync.ExteriorDoorType('Insulated metal'), bsync.DoorGlazedAreaFraction(0.5) ) ), - bsync.FenestrationFrameMaterial("Steel"), + bsync.FenestrationFrameMaterial('Steel'), bsync.FenestrationUFactor(2.839), - ID=f"Door-1" + ID=f'Door-1' ) fenestsys += win1_orig fenestsys += win1 @@ -878,34 +880,34 @@ found = bsync.FoundationSystem( ) ) ), - bsync.FloorConstructionType("Concrete poured"), - ID=f"Foundation-1" + bsync.FloorConstructionType('Concrete poured'), + ID=f'Foundation-1' ) foundsys += found # 6.2.1.2.e tightness infiltsys = bsync.AirInfiltrationSystems() infilt = bsync.AirInfiltrationSystem( - bsync.AirInfiltrationNotes("Notes on test"), - bsync.AirInfiltrationSystem.Tightness("Tight"), + bsync.AirInfiltrationNotes('Notes on test'), + bsync.AirInfiltrationSystem.Tightness('Tight'), bsync.AirInfiltrationValue(0.151), - bsync.AirInfiltrationValueUnits("ACHnatural"), - bsync.AirInfiltrationTest("Blower door"), + bsync.AirInfiltrationValueUnits('ACHnatural'), + bsync.AirInfiltrationTest('Blower door'), bsync.LinkedPremises( bsync.LinkedPremises.Section( - bsync.LinkedSectionID(IDref=section_wb["ID"]) + bsync.LinkedSectionID(IDref=section_wb['ID']) ) ), - ID=f"Infiltration-1" + ID=f'Infiltration-1' ) infiltsys += infilt waterinfiltsys = bsync.WaterInfiltrationSystems() waterinfilt = bsync.WaterInfiltrationSystem( - bsync.WaterInfiltrationNotes("Notes on test"), + bsync.WaterInfiltrationNotes('Notes on test'), bsync.LinkedPremises( bsync.LinkedPremises.Section( - bsync.LinkedSectionID(IDref=section_wb["ID"]) + bsync.LinkedSectionID(IDref=section_wb['ID']) ) ) ) @@ -927,31 +929,31 @@ systems += waterinfiltsys ```python # then we link these components to the envelope elements under Section/Sides -section_wb += bsync.FootprintShape("Rectangular") -wallarea = {"A1":909.01223, "B1":606.0082, "C1":909.01223, "D1":606.0082} -windowarea = {"A1":180.18786, "B1":120.12524, "C1":180.18786, "D1":120.12524} -doorarea = {"A1":42.08689, "B1":0.0, "C1":0.0, "D1":0.0} +section_wb += bsync.FootprintShape('Rectangular') +wallarea = {'A1':909.01223, 'B1':606.0082, 'C1':909.01223, 'D1':606.0082} +windowarea = {'A1':180.18786, 'B1':120.12524, 'C1':180.18786, 'D1':120.12524} +doorarea = {'A1':42.08689, 'B1':0.0, 'C1':0.0, 'D1':0.0} section_sides = bsync.Sides() -for sidenumber in ["A1", "B1", "C1", "D1"]: +for sidenumber in ['A1', 'B1', 'C1', 'D1']: section_sides += bsync.Side( bsync.SideNumber(sidenumber), bsync.WallIDs( bsync.WallID( bsync.WallArea(wallarea[sidenumber]), - IDref=wall["ID"] + IDref=wall['ID'] ) ), bsync.WindowIDs( bsync.WindowID( bsync.FenestrationArea(windowarea[sidenumber]), - IDref=win1_orig["ID"] + IDref=win1_orig['ID'] ) ), bsync.DoorIDs( bsync.DoorID( bsync.FenestrationArea(doorarea[sidenumber]), - IDref=door["ID"] + IDref=door['ID'] ) ) ) @@ -960,8 +962,8 @@ section_roofs = bsync.Roofs( bsync.Roof( bsync.RoofID( bsync.RoofArea(6444.999), - bsync.RoofCondition("Good"), - IDref=roof["ID"] + bsync.RoofCondition('Good'), + IDref=roof['ID'] ) ) ) @@ -969,7 +971,7 @@ section_founds = bsync.Foundations( bsync.Foundation( bsync.FoundationID( bsync.FoundationArea(3891.1536), - IDref=found["ID"] + IDref=found['ID'] ) ) ) @@ -995,7 +997,7 @@ Level 2 energy audits require information about the primary systems serving a sp # and air distribution unit is Single zone, constant air volume air distribution, one unit per occupied thermal zone hvac_systems = bsync.HVACSystems() -hvac_system = bsync.HVACSystem(ID="HVACSystem-1") +hvac_system = bsync.HVACSystem(ID='HVACSystem-1') hvac_systems += hvac_system # link hvac to section hvac_system += bsync.LinkedPremises( @@ -1004,14 +1006,14 @@ hvac_system += bsync.LinkedPremises( bsync.LinkedScheduleIDs( bsync.LinkedScheduleID(IDref=schedule_hvac['ID']) ), - IDref=section["ID"] + IDref=section['ID'] ) ) ) # heating and cooling system hc_systems = bsync.HeatingAndCoolingSystems() -hc_systems += bsync.ZoningSystemType("Single zone") +hc_systems += bsync.ZoningSystemType('Single zone') # cooling system css = bsync.CoolingSources() @@ -1020,9 +1022,9 @@ for index, coolingcapacity in enumerate(coolingcapacities): cs = bsync.CoolingSource( bsync.CoolingSourceType( bsync.DX( - bsync.DXSystemType("Packaged/unitary heat pump"), - bsync.CompressorType("Reciprocating"), - bsync.CompressorStaging("Single stage") + bsync.DXSystemType('Packaged/unitary heat pump'), + bsync.CompressorType('Reciprocating'), + bsync.CompressorStaging('Single stage') ) ), bsync.AnnualCoolingEfficiencyValue(2.61), @@ -1040,7 +1042,7 @@ for index, coolingcapacity in enumerate(coolingcapacities): ) ), bsync.YearInstalled(2000), - ID=f"CoolingSource-{index+1}" + ID=f'CoolingSource-{index+1}' ) css += cs @@ -1053,8 +1055,8 @@ for index, heatingcapacity in enumerate(heatingcapacities): hs = bsync.HeatingSource( bsync.HeatingSourceType( bsync.HeatingSourceType.HeatPump( - bsync.HeatPumpType("Packaged Unitary"), - bsync.HeatPumpBackupSystemFuel("Natural gas"), + bsync.HeatPumpType('Packaged Unitary'), + bsync.HeatPumpBackupSystemFuel('Natural gas'), bsync.HeatPumpBackupAFUE(0.0), bsync.CoolingSourceID(IDref=cs['ID']) ) @@ -1075,7 +1077,7 @@ for index, heatingcapacity in enumerate(heatingcapacities): ) ), bsync.YearInstalled(2000), - ID=f"HeatingSource-{index+1}" + ID=f'HeatingSource-{index+1}' ) hss += hs @@ -1087,20 +1089,20 @@ for each in range(1,6): deliver = bsync.Delivery( bsync.DeliveryType( bsync.CentralAirDistribution( - bsync.AirDeliveryType("Central fan"), - bsync.TerminalUnit("CAV terminal box no reheat"), - bsync.ReheatSource("None"), + bsync.AirDeliveryType('Central fan'), + bsync.TerminalUnit('CAV terminal box no reheat'), + bsync.ReheatSource('None'), bsync.FanBased( bsync.AirSideEconomizer( - bsync.AirSideEconomizerType("None"), - bsync.EconomizerControl("Fixed"), - ID=f"AirSideEconomizer-{each}" + bsync.AirSideEconomizerType('None'), + bsync.EconomizerControl('Fixed'), + ID=f'AirSideEconomizer-{each}' ) ) ) ), - bsync.HeatingSourceID(IDref=f"HeatingSource-{each}"), - bsync.CoolingSourceID(IDref=f"CoolingSource-{each}"), + bsync.HeatingSourceID(IDref=f'HeatingSource-{each}'), + bsync.CoolingSourceID(IDref=f'CoolingSource-{each}'), bsync.Delivery.Controls( bsync.Delivery.Controls.Control( bsync.Delivery.Controls.Control.OtherControlTechnology( @@ -1112,8 +1114,8 @@ for each in range(1,6): ), bsync.YearInstalled(2000), bsync.Quantity(1), - bsync.DeliveryCondition("Good"), - ID=f"Delivery-{each}" + bsync.DeliveryCondition('Good'), + ID=f'Delivery-{each}' ) delivers += deliver @@ -1123,17 +1125,17 @@ hc_systems += delivers duct_systems = bsync.DuctSystems() for each in range(1,6): duct = bsync.DuctSystem( - bsync.DuctConfiguration("Single"), - bsync.DuctInsulationCondition("Good"), - bsync.HeatingDeliveryID(IDref=f"Delivery-{each}"), - bsync.CoolingDeliveryID(IDref=f"Delivery-{each}"), - ID=f"DuctSystem-{each}" + bsync.DuctConfiguration('Single'), + bsync.DuctInsulationCondition('Good'), + bsync.HeatingDeliveryID(IDref=f'Delivery-{each}'), + bsync.CoolingDeliveryID(IDref=f'Delivery-{each}'), + ID=f'DuctSystem-{each}' ) duct_systems += duct # HVAC control hvacctl = bsync.HVACControlSystemTypes( - bsync.HVACControlSystemType("Digital") + bsync.HVACControlSystemType('Digital') ) hvac_system += hc_systems @@ -1149,21 +1151,21 @@ for each in range(1,6): bsync.FanEfficiency(0.536), bsync.FanSize(fanflowrate[each-1]), bsync.FanInstalledFlowRate(fanflowrate[each-1]), - bsync.FanControlType("Constant Volume"), + bsync.FanControlType('Constant Volume'), bsync.LinkedSystemIDs( - bsync.LinkedSystemID(IDref=f"Delivery-{each}") + bsync.LinkedSystemID(IDref=f'Delivery-{each}') ), - ID=f"FanSystem-{each}" + ID=f'FanSystem-{each}' ) fan_new = bsync.FanSystem( bsync.FanEfficiency(0.536), bsync.FanSize(fanflowrate_new[each-1]), bsync.InstalledFlowRate(fanflowrate_new[each-1]), - bsync.FanControlType("Variable Volume"), + bsync.FanControlType('Variable Volume'), bsync.LinkedSystemIDs( - bsync.LinkedSystemID(IDref=f"Delivery-{each}") + bsync.LinkedSystemID(IDref=f'Delivery-{each}') ), - ID=f"FanSystem-{each}-new" + ID=f'FanSystem-{each}-new' ) fan_systems += fan fan_systems += fan_new @@ -1192,25 +1194,25 @@ shw = bsync.DomesticHotWaterSystem( bsync.StorageTankInsulationRValue(123.) # arbitrary value, actually not required ) ), - bsync.DomesticHotWaterSystemNotes("Notes"), - bsync.PrimaryFuel("Electricity"), + bsync.DomesticHotWaterSystemNotes('Notes'), + bsync.PrimaryFuel('Electricity'), bsync.Recirculation( bsync.RecirculationLoopCount(1), bsync.RecirculationFlowRate(3.6), - bsync.RecirculationControlType("Continuous"), + bsync.RecirculationControlType('Continuous'), bsync.PipeInsulationThickness(123.), # arbitrary value, actually not required bsync.RecirculationEnergyLossRate(1.870180469) ), - bsync.HotWaterDistributionType("Looped"), + bsync.HotWaterDistributionType('Looped'), bsync.HotWaterSetpointTemperature(140.), bsync.WaterHeaterEfficiency(1.), - bsync.WaterHeaterEfficiencyType("Thermal Efficiency"), + bsync.WaterHeaterEfficiencyType('Thermal Efficiency'), bsync.DailyHotWaterDraw(40.), # arbitrary value, actually not required bsync.ParasiticFuelConsumptionRate(1950.52), # 572 W to Btu/hr bsync.Capacity(11722.84), - bsync.CapacityUnits("W"), + bsync.CapacityUnits('W'), bsync.YearInstalled(2000), - bsync.DomesticHotWaterSystemCondition("Good"), + bsync.DomesticHotWaterSystemCondition('Good'), bsync.DomesticHotWaterSystem.Controls( bsync.DomesticHotWaterSystem.Controls.Control( bsync.DomesticHotWaterSystem.Controls.Control.Manual( @@ -1225,11 +1227,11 @@ shw = bsync.DomesticHotWaterSystem( bsync.LinkedBuildingID(IDref=b1['ID']) ), bsync.LinkedPremises.Section( - bsync.LinkedSectionID(IDref=section["ID"]) + bsync.LinkedSectionID(IDref=section['ID']) ) ), bsync.Quantity(1), - ID=f"SHW-1" + ID=f'SHW-1' ) shw_systems += shw ``` @@ -1248,10 +1250,10 @@ ls1 = bsync.LightingSystem( bsync.OutsideLighting(False), bsync.LampType( bsync.LinearFluorescent( - bsync.LinearFluorescent.LampLabel("T8") + bsync.LinearFluorescent.LampLabel('T8') ) ), - bsync.BallastType("Standard Electronic"), + bsync.BallastType('Standard Electronic'), bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.2) ), @@ -1268,7 +1270,7 @@ ls1 = bsync.LightingSystem( bsync.ControlSystemType( bsync.Digital() ), - bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy("Programmable") + bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy('Programmable') ) ) ), @@ -1278,20 +1280,20 @@ ls1 = bsync.LightingSystem( bsync.LinkedScheduleIDs( bsync.LinkedScheduleID(IDref=schedule_light['ID']) ), - IDref=section["ID"]) + IDref=section['ID']) ) ), - ID="LightingSystem-1" + ID='LightingSystem-1' ) # there is no specific information related to exterior lighting (but it exists) ls2 = bsync.LightingSystem( bsync.OutsideLighting(True), bsync.LampType( bsync.LinearFluorescent( - bsync.LinearFluorescent.LampLabel("T12") + bsync.LinearFluorescent.LampLabel('T12') ) ), - bsync.BallastType("Standard Electronic"), + bsync.BallastType('Standard Electronic'), bsync.InstalledPower(1.582575), bsync.LampPower(316.516), bsync.NumberOfLampsPerBallast(1), @@ -1305,7 +1307,7 @@ ls2 = bsync.LightingSystem( bsync.ControlSystemType( bsync.Digital() ), - bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy("Programmable") + bsync.LightingSystem.Controls.Control.OtherControlTechnology.ControlStrategy('Programmable') ) ) ), @@ -1315,20 +1317,20 @@ ls2 = bsync.LightingSystem( bsync.LinkedScheduleIDs( bsync.LinkedScheduleID(IDref=schedule_light['ID']) ), - IDref=section_wb["ID"]) + IDref=section_wb['ID']) ) ), - ID="LightingSystem-2" + ID='LightingSystem-2' ) # new led lighting system for measure ls_new = bsync.LightingSystem( bsync.OutsideLighting(False), bsync.LampType( bsync.SolidStateLighting( - bsync.SolidStateLighting.LampLabel("LED") + bsync.SolidStateLighting.LampLabel('LED') ) ), - bsync.BallastType("Standard Electronic"), + bsync.BallastType('Standard Electronic'), bsync.DimmingCapability( bsync.MinimumDimmingLightFraction(0.1) ), @@ -1345,8 +1347,8 @@ ls_new = bsync.LightingSystem( bsync.ControlSystemType( bsync.Digital() ), - bsync.Daylighting.ControlSensor("Photocell"), - bsync.Daylighting.ControlStrategy("Continuous") + bsync.Daylighting.ControlSensor('Photocell'), + bsync.Daylighting.ControlStrategy('Continuous') ) ) ), @@ -1356,10 +1358,10 @@ ls_new = bsync.LightingSystem( bsync.LinkedScheduleIDs( bsync.LinkedScheduleID(IDref=schedule_light['ID']) ), - IDref=section["ID"]) + IDref=section['ID']) ) ), - ID="LightingSystem-new" + ID='LightingSystem-new' ) light_systems += ls1 @@ -1378,7 +1380,7 @@ light_systems += ls_new # just assign this EPD to the Section as a whole plug_systems = bsync.PlugLoads() psys = bsync.PlugLoad( - bsync.PlugLoadType("Miscellaneous Electric Load"), + bsync.PlugLoadType('Miscellaneous Electric Load'), bsync.WeightedAverageLoad(0.63), bsync.LinkedPremises( bsync.LinkedPremises.Section( @@ -1386,10 +1388,10 @@ psys = bsync.PlugLoad( bsync.LinkedScheduleIDs( bsync.LinkedScheduleID(IDref=schedule_pl['ID']) ), - IDref=section["ID"]) + IDref=section['ID']) ) ), - ID="PlugLoad-1" + ID='PlugLoad-1' ) plug_systems += psys ``` @@ -1489,19 +1491,19 @@ elec_ut = bsync.Utility( ) ) ), - bsync.ReferenceForRateStructure("https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/Regulatory'/%'20Filings/CO%20Recent'/%'20Filings/PSCo_Electric_Entire_Tariff.pdf"), + bsync.ReferenceForRateStructure('https://www.xcelenergy.com/company/rates_and_regulations/rates/rate_books'), bsync.FixedMonthlyCharge(16.88), - ID="RateSchedule-Electricity" + ID='RateSchedule-Electricity' ) ), bsync.UtilityMeterNumbers( - bsync.UtilityMeterNumber("Some-meter-ID") + bsync.UtilityMeterNumber('Some-meter-ID') ), bsync.EIAUtilityID(12345), - bsync.UtilityName("Xcel Energy"), - bsync.UtilityAccountNumber("some-account-number"), - bsync.UtilityBillpayer("Building Owner"), - ID="Utility-Electric" + bsync.UtilityName('Xcel Energy'), + bsync.UtilityAccountNumber('some-account-number'), + bsync.UtilityBillpayer('Building Owner'), + ID='Utility-Electric' ) ng_ut = bsync.Utility( bsync.RateSchedules( @@ -1517,18 +1519,18 @@ ng_ut = bsync.Utility( ) ) ), - bsync.ReferenceForRateStructure("https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/psco_gas_entire_tariff.pdf"), + bsync.ReferenceForRateStructure('https://www.xcelenergy.com/company/rates_and_regulations/rates/rate_books'), bsync.FixedMonthlyCharge(43.88), - ID="RateSchedule-Natural-Gas" + ID='RateSchedule-Natural-Gas' ) ), bsync.UtilityMeterNumbers( - bsync.UtilityMeterNumber("Some-meter-ID") + bsync.UtilityMeterNumber('Some-meter-ID') ), - bsync.UtilityName("Xcel Energy"), - bsync.UtilityAccountNumber("some-other-account-number"), - bsync.UtilityBillpayer("Building Owner"), - ID="Utility-Natural-Gas" + bsync.UtilityName('Xcel Energy'), + bsync.UtilityAccountNumber('some-other-account-number'), + bsync.UtilityBillpayer('Building Owner'), + ID='Utility-Natural-Gas' ) ``` @@ -1539,7 +1541,7 @@ utilities += ng_ut ``` #### ResourceUses and TimeSeries Data -Now that we have a current building measured scenario, we want to declare energy and monthly billing data. Per Std 211 6.1.2.1, a minimum of 12 months (preferably up to 3 years) of energy use data is required. The mechanical system of the small office prototype is a heatpump air handler with natural gas backup. We know that Missoula is cold, so likely it will use natural gas backup at some point during its operation. We run an example simulation to get estimates for this, which come out as follows: +Now that we have a current building measured scenario, we want to declare energy and monthly billing data. Per Std 211 6.1.2.1, a minimum of 12 months (preferably up to 3 years) of energy use data is required. The mechanical system of the small office prototype is a heatpump air handler with natural gas backup. We run the simulation to get estimates for this, which come out as follows: | Resource Type | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | @@ -1558,14 +1560,14 @@ all_ru = bsync.ResourceUses() # we also connect it up to a utility elec_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), - bsync.ResourceUseNotes("This is required to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found."), + bsync.ResourceUseNotes('This is required to document irregularities in monthly energy patterns (Std 211 6.1.2.1.j). No irregularities found.'), bsync.ResourceUnits('kWh'), bsync.PeakResourceUnits('kW'), bsync.EndUse('All end uses'), bsync.UtilityIDs( bsync.UtilityID(IDref=elec_ut['ID']) ), - ID=f"ResourceUse-Electricity" + ID=f'ResourceUse-Electricity' ) # given the above, we add the annual totals elec_ru += bsync.AnnualFuelUseNativeUnits(67334.15) @@ -1578,13 +1580,13 @@ elec_ru += bsync.AnnualFuelCost(4613.82) # # additional connect it up to the utility ng_ru = bsync.ResourceUse( bsync.EnergyResource('Natural gas'), - bsync.ResourceUseNotes("No irregularities in monthly energy consumption found."), + bsync.ResourceUseNotes('No irregularities in monthly energy consumption found.'), bsync.ResourceUnits('MMBtu'), bsync.EndUse('All end uses'), bsync.UtilityIDs( bsync.UtilityID(IDref=ng_ut['ID']) ), - ID=f"ResourceUse-Natural-gas" + ID=f'ResourceUse-Natural-gas' ) # given the above, we add the annual totals ng_ru += bsync.AnnualFuelUseNativeUnits(8.72) @@ -1600,7 +1602,7 @@ lighting_ru = bsync.ResourceUse( bsync.AnnualFuelUseConsistentUnits(68.45389828), bsync.PercentEndUse(28.705), bsync.ParentResourceUseID(IDref=elec_ru['ID']), - ID=f"ResourceUse-Electricity-Lighting-Submeter" + ID=f'ResourceUse-Electricity-Lighting-Submeter' ) heating_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), @@ -1610,7 +1612,7 @@ heating_ru = bsync.ResourceUse( bsync.AnnualFuelUseConsistentUnits(16.03036076), bsync.PercentEndUse(6.722), bsync.ParentResourceUseID(IDref=elec_ru['ID']), - ID=f"ResourceUse-Electricity-Heating-Submeter" + ID=f'ResourceUse-Electricity-Heating-Submeter' ) cooling_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), @@ -1620,7 +1622,7 @@ cooling_ru = bsync.ResourceUse( bsync.AnnualFuelUseConsistentUnits(20.91170444), bsync.PercentEndUse(8.769), bsync.ParentResourceUseID(IDref=elec_ru['ID']), - ID=f"ResourceUse-Electricity-Cooling-Submeter" + ID=f'ResourceUse-Electricity-Cooling-Submeter' ) shw_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), @@ -1630,7 +1632,7 @@ shw_ru = bsync.ResourceUse( bsync.AnnualFuelUseConsistentUnits(24.51648244), bsync.PercentEndUse(10.281), bsync.ParentResourceUseID(IDref=elec_ru['ID']), - ID=f"ResourceUse-Electricity-SHW-Submeter" + ID=f'ResourceUse-Electricity-SHW-Submeter' ) pl_ru = bsync.ResourceUse( bsync.EnergyResource('Electricity'), @@ -1640,7 +1642,7 @@ pl_ru = bsync.ResourceUse( bsync.AnnualFuelUseConsistentUnits(50.9826158), bsync.PercentEndUse(21.379), bsync.ParentResourceUseID(IDref=elec_ru['ID']), - ID=f"ResourceUse-Electricity-Plugload-Submeter" + ID=f'ResourceUse-Electricity-Plugload-Submeter' ) # add these to the ResourceUses parent element @@ -1697,20 +1699,20 @@ def create_monthly(values, resource_use_id, start_year, tsrq='Energy', rt='Total end_dt = datetime(end_year, end_month, 1) if rt == 'Load factor': - my_id = f"TS-{resource_use_id}-Loadfactor-{start_month}" + my_id = f'TS-{resource_use_id}-Loadfactor-{start_month}' else: - my_id = f"TS-{resource_use_id}-{rt}-{start_month}" + my_id = f'TS-{resource_use_id}-{rt}-{start_month}' if rt == 'Peak': ts = bsync.TimeSeries( bsync.ReadingType(rt), - bsync.PeakType("On-peak"), + bsync.PeakType('On-peak'), bsync.TimeSeriesReadingQuantity(tsrq), bsync.StartTimestamp(start_dt), bsync.EndTimestamp(end_dt), bsync.IntervalDuration(daysinmonth[i-1]), - bsync.IntervalDurationUnits("Day"), - bsync.IntervalFrequency("Month"), + bsync.IntervalDurationUnits('Day'), + bsync.IntervalFrequency('Month'), bsync.IntervalReading(float(val)), bsync.ResourceUseID(IDref=resource_use_id), ID=my_id @@ -1722,8 +1724,8 @@ def create_monthly(values, resource_use_id, start_year, tsrq='Energy', rt='Total bsync.StartTimestamp(start_dt), bsync.EndTimestamp(end_dt), bsync.IntervalDuration(daysinmonth[i-1]), - bsync.IntervalDurationUnits("Day"), - bsync.IntervalFrequency("Month"), + bsync.IntervalDurationUnits('Day'), + bsync.IntervalFrequency('Month'), bsync.IntervalReading(float(val)), bsync.ResourceUseID(IDref=resource_use_id), ID=my_id @@ -1809,7 +1811,7 @@ art = bsync.AllResourceTotals( bsync.SourceEnergyUseIntensity(134.0), # kbtu/ft2 bsync.EnergyCost(4952.48), bsync.EnergyCostIndex(0.90), # $/ft2 - ID="AllResourceTotal-1" + ID='AllResourceTotal-1' ) ) ``` @@ -1841,7 +1843,7 @@ bench_sc = bsync.Scenario( bsync.AllResourceTotal.SiteEnergyUse(238473.65655), bsync.SiteEnergyUseIntensity(43.3588), bsync.EnergyCost(4952.48), - ID="AllResourceTotal-Benchmark" + ID='AllResourceTotal-Benchmark' ) ), bsync.LinkedPremises( @@ -1849,7 +1851,7 @@ bench_sc = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-Benchmark" + ID='Scenario-Benchmark' ) bench_st = bsync.Scenario.ScenarioType() bench = bsync.Benchmark( @@ -1858,7 +1860,7 @@ bench = bsync.Benchmark( bsync.PMBenchmarkDate(date(2022, 6, 1)) ) ), - bsync.BenchmarkTool("Portfolio Manager"), + bsync.BenchmarkTool('Portfolio Manager'), bsync.BenchmarkYear(2019), bsync.BenchmarkValue(80.) ) @@ -1885,7 +1887,7 @@ target_sc = bsync.Scenario( bsync.SiteEnergyUseIntensity(34.6), bsync.EnergyCost(4846.04), bsync.EnergyCostIndex(0.881), - ID="AllResourceTotal-Target" + ID='AllResourceTotal-Target' ) ), bsync.LinkedPremises( @@ -1893,11 +1895,11 @@ target_sc = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-Target" + ID='Scenario-Target' ) target_st = bsync.Scenario.ScenarioType() target = bsync.Target( - bsync.ReferenceCase(IDref=bench_sc["ID"]), + bsync.ReferenceCase(IDref=bench_sc['ID']), bsync.AnnualSavingsSiteEnergy(39070.53), bsync.AnnualSavingsCost(995), bsync.ENERGYSTARScore(89.), @@ -1945,24 +1947,24 @@ hvac_schedule_measure = bsync.Measure( ) ) ), - bsync.SystemCategoryAffected("Air Distribution"), + bsync.SystemCategoryAffected('Air Distribution'), bsync.TechnologyCategories( bsync.TechnologyCategory( bsync.OtherHVAC( - bsync.OtherHVAC.MeasureName("Other distribution") + bsync.OtherHVAC.MeasureName('Other distribution') ) ) ), - bsync.CustomMeasureName("Update HVAC schedule"), - bsync.LongDescription("The current HVAC schedule is set to be at 100'%' fan operation during weekday from 7am - 8pm. This measure would implement a modified schedule to enable pre-cooling/pre-heating from 6am - 7am, and reduce output to 80'%' during peak time 12pm - 1pm. "), - bsync.MeasureScaleOfApplication("Individual system"), + bsync.CustomMeasureName('Update HVAC schedule'), + bsync.LongDescription('The current HVAC schedule is set to be at fully ON fan operation during weekday from 7am - 8pm. This measure would implement a modified schedule to enable pre-cooling/pre-heating from 6am - 7am, and reduce output to 80 percent during peak time 12pm - 1pm.'), + bsync.MeasureScaleOfApplication('Individual system'), bsync.UsefulLife(1.), bsync.MeasureInstallationCost(0.), bsync.MeasureMaterialCost(0.), bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), - ID="Measure-HVAC-schedule-nocost" + ID='Measure-HVAC-schedule-nocost' ) # A measure to upgrade the lighting system to LEDs (low-cost EEM) @@ -1975,23 +1977,23 @@ led_measure = bsync.Measure( ) ) ), - bsync.SystemCategoryAffected("Lighting"), + bsync.SystemCategoryAffected('Lighting'), bsync.TechnologyCategories( bsync.TechnologyCategory( bsync.LightingImprovements( - bsync.LightingImprovements.MeasureName("Retrofit with light emitting diode technologies") + bsync.LightingImprovements.MeasureName('Retrofit with light emitting diode technologies') ) ) ), - bsync.LongDescription("This measure is designed to replace all fluorescent bulbs with LEDs"), - bsync.MeasureScaleOfApplication("Individual system"), + bsync.LongDescription('This measure is designed to replace all fluorescent bulbs with LEDs'), + bsync.MeasureScaleOfApplication('Individual system'), bsync.UsefulLife(1.), bsync.MeasureInstallationCost(50.), bsync.MeasureMaterialCost(774.), bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), - ID="Measure-LEDs" + ID='Measure-LEDs' ) # A measure to upgrade the fans in the RTUs to use VFDs @@ -2009,23 +2011,23 @@ vsd_measure = bsync.Measure( ) ), # could have also used Air Distribution or Motor, this seemed ok too. - bsync.SystemCategoryAffected("Fan"), + bsync.SystemCategoryAffected('Fan'), bsync.TechnologyCategories( bsync.TechnologyCategory( bsync.OtherElectricMotorsAndDrives( - bsync.OtherElectricMotorsAndDrives.MeasureName("Add VSD motor controller") + bsync.OtherElectricMotorsAndDrives.MeasureName('Add VSD motor controller') ) ) ), - bsync.LongDescription("This measure is designed to retrofit all RTU fans with a VSD"), - bsync.MeasureScaleOfApplication("Individual system"), + bsync.LongDescription('This measure is designed to retrofit all RTU fans with a VSD'), + bsync.MeasureScaleOfApplication('Individual system'), bsync.UsefulLife(1.), bsync.MeasureInstallationCost(750.), bsync.MeasureMaterialCost(1250.), # assume $200~300 per fan bsync.StartDate(date(2021,1,1)), bsync.EndDate(date(2021,12,30)), bsync.Recommended(True), - ID="Measure-VSDs" + ID='Measure-VSDs' ) ``` @@ -2052,18 +2054,18 @@ pom_sc_1 = bsync.Scenario( bsync.MeasureIDs( bsync.MeasureID(IDref=led_measure['ID']) ), - bsync.CostCategory("Capital"), + bsync.CostCategory('Capital'), bsync.AnnualSavingsSiteEnergy(35.713), bsync.AnnualSavingsCost(772), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Electricity"), - bsync.ResourceUnits("kWh"), + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), bsync.AnnualSavingsNativeUnits(11524.54) ), bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Natural gas"), - bsync.ResourceUnits("MMBtu"), + bsync.EnergyResource('Natural gas'), + bsync.ResourceUnits('MMBtu'), bsync.AnnualSavingsNativeUnits(0.) ) ), @@ -2084,7 +2086,7 @@ pom_sc_1 = bsync.Scenario( bsync.RecurringIncentives(0), bsync.InternalRateOfReturn(0.), # for the first year the IRR is nagative (payback>1 yr) bsync.SimplePayback(1.07), - ID="POM-LEDs" + ID='POM-LEDs' ) ), bsync.LinkedPremises( @@ -2092,7 +2094,7 @@ pom_sc_1 = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-POM-LEDs" + ID='Scenario-POM-LEDs' ) pom_sc_2 = bsync.Scenario( @@ -2102,18 +2104,18 @@ pom_sc_2 = bsync.Scenario( bsync.MeasureIDs( bsync.MeasureID(IDref=vsd_measure['ID']) ), - bsync.CostCategory("Capital"), + bsync.CostCategory('Capital'), bsync.AnnualSavingsSiteEnergy(5.175), bsync.AnnualSavingsCost(9), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Electricity"), - bsync.ResourceUnits("kWh"), + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), bsync.AnnualSavingsNativeUnits(207.24) ), bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Natural gas"), - bsync.ResourceUnits("MMBtu"), + bsync.EnergyResource('Natural gas'), + bsync.ResourceUnits('MMBtu'), bsync.AnnualSavingsNativeUnits(4.46) ) ), @@ -2134,7 +2136,7 @@ pom_sc_2 = bsync.Scenario( bsync.RecurringIncentives(0), bsync.InternalRateOfReturn(0.), bsync.SimplePayback(230.15), - ID="POM-VSDs" + ID='POM-VSDs' ) ), bsync.LinkedPremises( @@ -2142,7 +2144,7 @@ pom_sc_2 = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-POM-VSDs" + ID='Scenario-POM-VSDs' ) pom_sc_3 = bsync.Scenario( @@ -2153,18 +2155,18 @@ pom_sc_3 = bsync.Scenario( bsync.MeasureID(IDref=led_measure['ID']), bsync.MeasureID(IDref=vsd_measure['ID']), ), - bsync.CostCategory("Capital"), + bsync.CostCategory('Capital'), bsync.AnnualSavingsSiteEnergy(41.827), bsync.AnnualSavingsCost(781), bsync.AnnualSavingsByFuels( bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Electricity"), - bsync.ResourceUnits("kWh"), + bsync.EnergyResource('Electricity'), + bsync.ResourceUnits('kWh'), bsync.AnnualSavingsNativeUnits(11701.62) ), bsync.AnnualSavingsByFuel( - bsync.EnergyResource("Natural gas"), - bsync.ResourceUnits("MMBtu"), + bsync.EnergyResource('Natural gas'), + bsync.ResourceUnits('MMBtu'), bsync.AnnualSavingsNativeUnits(1.89) ) ), @@ -2185,7 +2187,7 @@ pom_sc_3 = bsync.Scenario( bsync.RecurringIncentives(0), bsync.InternalRateOfReturn(0.), bsync.SimplePayback(3.62), - ID="POM-LEDs-VSDs" + ID='POM-LEDs-VSDs' ) ), bsync.LinkedPremises( @@ -2193,7 +2195,7 @@ pom_sc_3 = bsync.Scenario( bsync.LinkedBuildingID(IDref=b1['ID']) ) ), - ID="Scenario-POM-LEDs-VSDs" + ID='Scenario-POM-LEDs-VSDs' ) ``` @@ -2214,7 +2216,7 @@ Use the line below to write the file to disk ```python -bsync_dump(root, file="example-level2.xml") +bsync_dump(root, file='example-smalloffice-level2.xml') ``` diff --git a/docs/notebooks/bsync_examples/example1.xml b/docs/notebooks/bsync_examples/example-smalloffice-level1.xml similarity index 100% rename from docs/notebooks/bsync_examples/example1.xml rename to docs/notebooks/bsync_examples/example-smalloffice-level1.xml diff --git a/docs/notebooks/bsync_examples/example-level2.xml b/docs/notebooks/bsync_examples/example-smalloffice-level2.xml similarity index 99% rename from docs/notebooks/bsync_examples/example-level2.xml rename to docs/notebooks/bsync_examples/example-smalloffice-level2.xml index 89def166..821b846f 100644 --- a/docs/notebooks/bsync_examples/example-level2.xml +++ b/docs/notebooks/bsync_examples/example-smalloffice-level2.xml @@ -2595,7 +2595,7 @@ - https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/Regulatory'/%'20Filings/CO%20Recent'/%'20Filings/PSCo_Electric_Entire_Tariff.pdf + https://www.xcelenergy.com/company/rates_and_regulations/rates/rate_books 16.880000 @@ -2621,7 +2621,7 @@ - https://www.xcelenergy.com/staticfiles/xe-responsive/Company/Rates%20&%20Regulations/psco_gas_entire_tariff.pdf + https://www.xcelenergy.com/company/rates_and_regulations/rates/rate_books 43.880000 From 5985a9884bf86f147c6d4623fc29cb72c512238c Mon Sep 17 00:00:00 2001 From: Xiong Date: Wed, 29 Jun 2022 15:24:14 -0600 Subject: [PATCH 5/5] Update md --- .../notebooks/bsync_examples/Small-Office-Level-2.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/docs/notebooks/bsync_examples/Small-Office-Level-2.md b/docs/notebooks/bsync_examples/Small-Office-Level-2.md index 6c2e0576..fe4cb708 100644 --- a/docs/notebooks/bsync_examples/Small-Office-Level-2.md +++ b/docs/notebooks/bsync_examples/Small-Office-Level-2.md @@ -2208,7 +2208,7 @@ scenarios += pom_sc_3 # Validation -So did what we just went through actually work? Do we have the required information for a Level 1 Audit? Head over to the [use case validator](https://buildingsync.net/validator) to find out! +Now we need to check if everything we went through actually works? Do we have the required information for a Level 2 Audit? Head over to the [use case validator](https://buildingsync.net/validator) to find out! ![Selection Tool](./img/UC-Selection.png) @@ -2220,17 +2220,7 @@ bsync_dump(root, file='example-smalloffice-level2.xml') ``` - - - True - - - You should see a green check mark for the L200 AUDIT use case! ![Valid](./img/valid_level2.png) - -```python - -```