Skip to content

Commit

Permalink
Docs and warnings cleanup for EVs; new check for unexpected vehicle t…
Browse files Browse the repository at this point in the history
…ype.
  • Loading branch information
aspeake committed Jan 14, 2025
1 parent ed998a7 commit 97450dc
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 43 deletions.
10 changes: 5 additions & 5 deletions HPXMLtoOpenStudio/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.1</schema_version>
<name>hpxm_lto_openstudio</name>
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
<version_id>b47e5bc1-d61f-47e6-a666-87ee96ba5a14</version_id>
<version_modified>2025-01-14T17:40:54Z</version_modified>
<version_id>b037a307-ab67-4971-9b3b-116d5b731eb6</version_id>
<version_modified>2025-01-14T20:21:44Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -363,7 +363,7 @@
<filename>hpxml.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>E35D68B4</checksum>
<checksum>9CB0E51C</checksum>
</file>
<file>
<filename>hpxml_schema/HPXML.xsd</filename>
Expand Down Expand Up @@ -645,7 +645,7 @@
<filename>vehicle.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>A355B556</checksum>
<checksum>E49A8C65</checksum>
</file>
<file>
<filename>version.rb</filename>
Expand Down Expand Up @@ -771,7 +771,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>0062A418</checksum>
<checksum>5DB1F814</checksum>
</file>
<file>
<filename>test_vehicle.rb</filename>
Expand Down
43 changes: 22 additions & 21 deletions HPXMLtoOpenStudio/resources/hpxml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9411,13 +9411,12 @@ def to_doc(building)
sys_id = XMLHelper.add_element(vehicle, 'SystemIdentifier')
XMLHelper.add_attribute(sys_id, 'id', @id)
vehicle_type_element = XMLHelper.add_element(vehicle, 'VehicleType')
vehicle_type = XMLHelper.add_element(vehicle_type_element, @vehicle_type)

case @vehicle_type
when HPXML::VehicleTypeBEV
electric_vehicle = XMLHelper.add_element(vehicle_type_element, @vehicle_type)
battery = XMLHelper.add_element(electric_vehicle, 'Battery')

# Battery
battery = XMLHelper.add_element(vehicle_type, 'Battery')
XMLHelper.add_element(battery, 'BatteryType', @battery_type, :string, @battery_type_isdefaulted) unless @battery_type.nil?
if not @nominal_capacity_kwh.nil?
nominal_capacity = XMLHelper.add_element(battery, 'NominalCapacity')
Expand All @@ -9443,16 +9442,16 @@ def to_doc(building)
XMLHelper.add_extension(battery, 'LifetimeModel', @lifetime_model, :string, @lifetime_model_isdefaulted) unless @lifetime_model.nil?

# Battery-Electric Vehicle
fraction_charged_location = XMLHelper.add_element(electric_vehicle, 'FractionChargedLocation') unless @fraction_charged_home.nil?
fraction_charged_location = XMLHelper.add_element(vehicle_type, 'FractionChargedLocation') unless @fraction_charged_home.nil?
XMLHelper.add_element(fraction_charged_location, 'Location', HPXML::ElectricVehicleChargingLocation, :string) unless @fraction_charged_home.nil?
XMLHelper.add_element(fraction_charged_location, 'Percentage', @fraction_charged_home, :float, @fraction_charged_home_isdefaulted) unless @fraction_charged_home.nil?
if not @ev_charger_idref.nil?
charger = XMLHelper.add_element(electric_vehicle, 'ConnectedCharger')
charger = XMLHelper.add_element(vehicle_type, 'ConnectedCharger')
XMLHelper.add_attribute(charger, 'idref', @ev_charger_idref)
end
XMLHelper.add_extension(electric_vehicle, 'WeekdayScheduleFractions', @ev_charging_weekday_fractions, :string, @ev_charging_weekday_fractions_isdefaulted) unless @ev_charging_weekday_fractions.nil?
XMLHelper.add_extension(electric_vehicle, 'WeekendScheduleFractions', @ev_charging_weekend_fractions, :string, @ev_charging_weekend_fractions_isdefaulted) unless @ev_charging_weekend_fractions.nil?
XMLHelper.add_extension(electric_vehicle, 'MonthlyScheduleMultipliers', @ev_charging_monthly_multipliers, :string, @ev_charging_monthly_multipliers_isdefaulted) unless @ev_charging_monthly_multipliers.nil?
XMLHelper.add_extension(vehicle_type, 'WeekdayScheduleFractions', @ev_charging_weekday_fractions, :string, @ev_charging_weekday_fractions_isdefaulted) unless @ev_charging_weekday_fractions.nil?
XMLHelper.add_extension(vehicle_type, 'WeekendScheduleFractions', @ev_charging_weekend_fractions, :string, @ev_charging_weekend_fractions_isdefaulted) unless @ev_charging_weekend_fractions.nil?
XMLHelper.add_extension(vehicle_type, 'MonthlyScheduleMultipliers', @ev_charging_monthly_multipliers, :string, @ev_charging_monthly_multipliers_isdefaulted) unless @ev_charging_monthly_multipliers.nil?
end

# Vehicle
Expand All @@ -9476,19 +9475,21 @@ def from_doc(vehicle)
@fuel_economy = XMLHelper.get_value(vehicle, 'FuelEconomyCombined/Value', :float)
@fuel_economy_units = XMLHelper.get_value(vehicle, 'FuelEconomyCombined/Units', :string)
@vehicle_type = XMLHelper.get_child_name(vehicle, 'VehicleType')
battery_prefix = "VehicleType/#{@vehicle_type}/Battery"
@battery_type = XMLHelper.get_value(vehicle, "#{battery_prefix}/BatteryType", :string)
@nominal_capacity_kwh = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalCapacity[Units='#{UnitsKwh}']/Value", :float)
@nominal_capacity_ah = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalCapacity[Units='#{UnitsAh}']/Value", :float)
@usable_capacity_kwh = XMLHelper.get_value(vehicle, "#{battery_prefix}/UsableCapacity[Units='#{UnitsKwh}']/Value", :float)
@usable_capacity_ah = XMLHelper.get_value(vehicle, "#{battery_prefix}/UsableCapacity[Units='#{UnitsAh}']/Value", :float)
@nominal_voltage = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalVoltage", :float)
@fraction_charged_home = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/FractionChargedLocation/Percentage", :float)
@ev_charger_idref = HPXML::get_idref(XMLHelper.get_element(vehicle, "VehicleType/#{@vehicle_type}/ConnectedCharger"))
@lifetime_model = XMLHelper.get_value(vehicle, "#{battery_prefix}/extension/LifetimeModel", :string)
@ev_charging_weekday_fractions = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/WeekdayScheduleFractions", :string)
@ev_charging_weekend_fractions = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/WeekendScheduleFractions", :string)
@ev_charging_monthly_multipliers = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/MonthlyScheduleMultipliers", :string)
if @vehicle_type == HPXML::VehicleTypeBEV
battery_prefix = "VehicleType/#{@vehicle_type}/Battery"
@battery_type = XMLHelper.get_value(vehicle, "#{battery_prefix}/BatteryType", :string)
@nominal_capacity_kwh = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalCapacity[Units='#{UnitsKwh}']/Value", :float)
@nominal_capacity_ah = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalCapacity[Units='#{UnitsAh}']/Value", :float)
@usable_capacity_kwh = XMLHelper.get_value(vehicle, "#{battery_prefix}/UsableCapacity[Units='#{UnitsKwh}']/Value", :float)
@usable_capacity_ah = XMLHelper.get_value(vehicle, "#{battery_prefix}/UsableCapacity[Units='#{UnitsAh}']/Value", :float)
@nominal_voltage = XMLHelper.get_value(vehicle, "#{battery_prefix}/NominalVoltage", :float)
@fraction_charged_home = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/FractionChargedLocation/Percentage", :float)
@ev_charger_idref = HPXML::get_idref(XMLHelper.get_element(vehicle, "VehicleType/#{@vehicle_type}/ConnectedCharger"))
@lifetime_model = XMLHelper.get_value(vehicle, "#{battery_prefix}/extension/LifetimeModel", :string)
@ev_charging_weekday_fractions = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/WeekdayScheduleFractions", :string)
@ev_charging_weekend_fractions = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/WeekendScheduleFractions", :string)
@ev_charging_monthly_multipliers = XMLHelper.get_value(vehicle, "VehicleType/#{@vehicle_type}/extension/MonthlyScheduleMultipliers", :string)
end
end

# Returns the EV charger for the vehicle.
Expand Down
18 changes: 7 additions & 11 deletions HPXMLtoOpenStudio/resources/vehicle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ class Vehicle
# @return [nil]
def self.apply(runner, model, spaces, hpxml_bldg, schedules_file)
hpxml_bldg.vehicles.each do |vehicle|
next unless vehicle.vehicle_type == HPXML::VehicleTypeBEV

if vehicle.vehicle_type != HPXML::VehicleTypeBEV
runner.registerWarning("Unexpected vehicle type '#{vehicle.vehicle_type}'. Detailed vehicle charging will not be modeled.")
next
end
apply_electric_vehicle(runner, model, spaces, hpxml_bldg, vehicle, schedules_file)
end
end
Expand Down Expand Up @@ -70,27 +72,21 @@ def self.get_ev_charging_schedules(runner, model, vehicle, schedules_file)
def self.apply_electric_vehicle(runner, model, spaces, hpxml_bldg, vehicle, schedules_file)
model.getElectricEquipments.sort.each do |ee|
if ee.endUseSubcategory.start_with? Constants::ObjectTypeMiscElectricVehicleCharging
runner.registerWarning('Electric vehicle was specified as a plug load and as a battery, vehicle charging will be modeled as a plug load.')
runner.registerWarning('Electric vehicle charging was specified as both a PlugLoad and a Vehicle, the latter will be ignored.')
return
end
end

# Assign charging and vehicle space
ev_charger = vehicle.ev_charger
if ev_charger.nil?
runner.registerWarning('Electric vehicle specified with no charger provided; battery will not be modeled.')
runner.registerWarning('Electric vehicle specified with no charger provided; detailed EV charging will not be modeled.')
return
end
vehicle.location = ev_charger.location

# Get schedules to calculate effective discharge power
charging_schedule, discharging_schedule = get_ev_charging_schedules(runner, model, vehicle, schedules_file)
if charging_schedule.nil? && discharging_schedule.nil?
runner.registerWarning('Electric vehicle battery specified with no charging/discharging schedule provided; battery will not be modeled.')
return
end

# Calculate annual driving hours
charging_schedule, discharging_schedule = get_ev_charging_schedules(runner, model, vehicle, schedules_file)
if discharging_schedule.to_ScheduleFile.is_initialized
dis_sch = discharging_schedule.to_ScheduleFile.get
col = dis_sch.columnNumber - 1
Expand Down
6 changes: 5 additions & 1 deletion HPXMLtoOpenStudio/tests/test_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1851,7 +1851,8 @@ def test_ruby_warning_messages
'schedule-file-max-power-ratio-with-single-speed-system' => ['Maximum power ratio schedule is only supported for variable speed systems.'],
'schedule-file-max-power-ratio-with-two-speed-system' => ['Maximum power ratio schedule is only supported for variable speed systems.'],
'schedule-file-max-power-ratio-with-separate-backup-system' => ['Maximum power ratio schedule is only supported for integrated backup system. Schedule is ignored for heating.'],
'ev-charging-methods' => ['Electric vehicle was specified as a plug load and as a battery, vehicle charging will be modeled as a plug load.'] }
'ev-charging-methods' => ['Electric vehicle charging was specified as both a PlugLoad and a Vehicle, the latter will be ignored.'],
'vehicle-phev' => ["Unexpected vehicle type 'PlugInHybridElectricVehicle'. Detailed vehicle charging will not be modeled."] }

all_expected_warnings.each_with_index do |(warning_case, expected_warnings), i|
puts "[#{i + 1}/#{all_expected_warnings.size}] Testing #{warning_case}..."
Expand Down Expand Up @@ -2005,6 +2006,9 @@ def test_ruby_warning_messages
hpxml_bldg.header.schedules_filepaths << File.join(File.dirname(__FILE__), '../resources/schedule_files/hvac-variable-system-maximum-power-ratios-varied.csv')
when 'ev-charging-methods'
hpxml, hpxml_bldg = _create_hpxml('base-battery-ev-plug-load-ev.xml')
when 'vehicle-phev'
hpxml, hpxml_bldg = _create_hpxml('base-battery-ev-scheduled.xml')
hpxml_bldg.vehicles[0].vehicle_type = 'PlugInHybridElectricVehicle'
else
fail "Unhandled case: #{warning_case}."
end
Expand Down
2 changes: 1 addition & 1 deletion docs/source/workflow_inputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4640,7 +4640,7 @@ If not entered, the simulation will not include batteries.
HPXML Vehicles
**************

A vehicle can can be entered in ``/HPXML/Building/BuildingDetails/Systems/Vehicles/Vehicle``. Currently only a battery electric vehicle can be modeled with ``/Vehicle/VehicleType/BatteryElectricVehicle``.
A vehicle can be entered in ``/HPXML/Building/BuildingDetails/Systems/Vehicles/Vehicle``. Currently only a battery electric vehicle can be modeled with ``/Vehicle/VehicleType/BatteryElectricVehicle``.
This provides detailed modeling of electric vehicles (batteries and charging/discharging) as an alternative to the simple EV charging in :ref:`plug_loads`.
If not entered, the simulation will not include a detailed electric vehicle model.

Expand Down
5 changes: 1 addition & 4 deletions workflow/tests/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,8 @@ def _verify_outputs(rundir, hpxml_path, results, hpxml, unit_multiplier)
if !hpxml_bldg.vehicles.empty? && !hpxml_bldg.vehicles[0].ev_charger_idref.nil? && !hpxml_bldg.vehicles[0].ev_charging_weekday_fractions.nil?
next if message.include? 'Electric vehicle hours per week inputted (14.0) do not match the hours per week calculated from the discharging schedule (8.9). The inputted hours per week value will be ignored.'
end
if !hpxml_bldg.vehicles.empty? && hpxml_bldg.vehicles[0].ev_charger_idref.nil?
next if message.include? 'Electric vehicle specified with no charger provided; battery will not be modeled.'
end
if !hpxml_bldg.vehicles.empty? && !hpxml_bldg.plug_loads.select { |p| p.plug_load_type == HPXML::PlugLoadTypeElectricVehicleCharging }.empty?
next if message.include? 'Electric vehicle was specified as a plug load and as a battery, vehicle charging will be modeled as a plug load.'
next if message.include? 'Electric vehicle charging was specified as both a PlugLoad and a Vehicle, the latter will be ignored.'
end
if hpxml_path.include? 'base-location-capetown-zaf.xml'
next if message.include? 'OS Message: Minutes field (60) on line 9 of EPW file'
Expand Down

0 comments on commit 97450dc

Please sign in to comment.