NREL / openstudio-standards

Other
81 stars 58 forks source link

Error in Standards.AirLoopHVAC - no implicit conversion from nil to integer #1590

Closed chriswmackey closed 1 month ago

chriswmackey commented 1 year ago

Hello All,

I have been debugging a fairly large model for which I am trying to perform a sizing run and then set the efficiencies and controls of a VAV air loop based on them. The process is failing in the stage of air_loop_hvac_adjust_minimum_vav_damper_positions and I'm trying to figure out if there is something that I can change about my model to get it to succeed.

I am struggling to get to a minimal sample file that recreates the case and I will post it here if I get there since I know that would be valuable to you for debugging. But I was hoping that maybe the full traceback might be more legible to someone here. Or, in the event this is a recognizable bug or an exception that can be caught, it would be really nice to have the method proceed in future versions of the standards gem.

Here is the full traceback:

[18:01:43.058781 ERROR] no implicit conversion from nil to integer
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:2144:in `min'
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:2144:in `air_loop_hvac_adjust_minimum_vav_damper_positions'
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:18:in `air_loop_hvac_apply_multizone_vav_outdoor_air_sizing'
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.Model.rb:2257:in `block in model_apply_multizone_vav_outdoor_air_sizing'
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.Model.rb:2257:in `each'
:/ruby/2.7.0/gems/openstudio-standards-0.3.0/lib/openstudio-standards/standards/Standards.Model.rb:2257:in `model_apply_multizone_vav_outdoor_air_sizing'
/home/ladybugbot/ladybug_tools/resources/measures/honeybee_openstudio_gem/lib/measures/from_honeybee_model/measure.rb:173:in `run'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:517:in `apply_measure'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:114:in `block in apply_measures'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `each_index'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `apply_measures'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/jobs/run_os_measures.rb:70:in `perform'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:291:in `step'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:233:in `run'
:/openstudio_cli.rb:1184:in `execute'
:/openstudio_cli.rb:814:in `execute'
:/openstudio_cli.rb:1983:in `<main>'
eval:188:in `eval'
eval:188:in `require_embedded_absolute'
eval:173:in `block in require_embedded'
eval:167:in `each'
eval:167:in `require_embedded'
eval:126:in `require'
eval:3:in `<main>'

Do you have any thoughts on what might be going on to result in a Nil value at this stage of the process? Is the sizing calculation returning zero load or something like that?

Any advice would be appreciated and, again, if I manage to narrow down the problematic zones amid this 760-Zone model, I will post a minimal sample file here to recreate the issue.

mdahlhausen commented 1 year ago

@chriswmackey Lots of possible reasons why this could be failing. I do consider it a bug that it's not failing gracefully and pointing out the error.

First off, which version of openstudio-standards is this?

Some things to check:

  1. Do all the air terminals on the air loop where this is failing have an object that starts with AirTerminalSingleDuctVAV (e.g. AirTerminalSingleDuctVAVHeatAndCoolNoReheat)
  2. Are there zones on the air loop without DesignSpecificationOutdoorAir objects?
  3. If there are DesignSpecificationOutdoorAir, is the geometry defined such that it has a closed, defined floor area and volume?
  4. Could be issue #1488 (no load)
chriswmackey commented 1 year ago

Thank you for the response, @mdahlhausen.

This issue is happening with OpenStudio Standards 0.4.0 (the version of standards that shipped with OpenStudio SDK version 3.6.1).

I can say confidently that numbers 1 and 3 are not the issue since they all have AirTerminalSingleDuctVAV objects and, thanks to the validation that we have built in Ladybug Tools, all of the geometry is closed with a correct floor area and volume.

Let me see if item 2 could be to blame and some rooms are missing an outdoor air specification. Just so I understand the limitations here, is it alright if the outdoor air specification is zero as long as there is an outdoor air specification object? Or could a specification of zero outdoor air also trigger this error?

This might answer my last question but, judging from that issue you linked to, I would guess that maybe a zero outdoor air specification is ok as long as there is some thermal load to be met? So maybe I just have a zone with zero outdoor air and zero thermal load. I'll see if setting a non-zero outdoor air specification for the rooms fixes it.

chriswmackey commented 1 year ago

Hey @mdahlhausen ,

I just realized that I said that we were using OpenStudio Standards 0.4.0, which is true, but the traceback that I posted has file paths that reference OpenStudio Standards 0.3.0. I have NOT been able to recreate the issue in 0.4.0 so far and let me see if re-running the large model using 0.4.0 results in no errors.

chriswmackey commented 1 year ago

You can disregard my last staement, @mdahlhausen . It seems the issue is still present in OpenStudio Standards 0.4.0. Here is the full traceback using OpenStudio Standards 0.4.0 in case it is helpful:

[21:30:07.172438 ERROR] no implicit conversion from nil to integer
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:2160:in `min'
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:2160:in `air_loop_hvac_adjust_minimum_vav_damper_positions'
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb:18:in `air_loop_hvac_apply_multizone_vav_outdoor_air_sizing'
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2252:in `block in model_apply_multizone_vav_outdoor_air_sizing'
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2252:in `each'
:/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2252:in `model_apply_multizone_vav_outdoor_air_sizing'
/home/ladybugbot/ladybug_tools/resources/measures/honeybee_openstudio_gem/lib/measures/from_honeybee_model/measure.rb:173:in `run'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:517:in `apply_measure'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:114:in `block in apply_measures'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `each_index'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `apply_measures'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/jobs/run_os_measures.rb:70:in `perform'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:291:in `step'
:/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:233:in `run'
:/openstudio_cli.rb:1187:in `execute'
:/openstudio_cli.rb:817:in `execute'
:/openstudio_cli.rb:1984:in `<main>'
eval:188:in `eval'
eval:188:in `require_embedded_absolute'
eval:173:in `block in require_embedded'
eval:167:in `each'
eval:167:in `require_embedded'
eval:126:in `require'
eval:3:in `<main>'

I will continue to work towards building a minimal sample file that recreate the issue (at the moment, the only file I have that recreates the issue has more than 700 zones).

I think I can rule out the lack of an outdoor air specification as the reason for failure since I have several models succeeding through the whole process when they do not have an outdoor air specification.

Maybe it could still be this issue (https://github.com/NREL/openstudio-standards/issues/1488) but I have put together a few models that have no heating/cooling load and no outdoor air specification and they still run fine through the whole OpenStudio Standards routnie.

mdahlhausen commented 1 year ago

@chriswmackey Do you have terminals with 0 minimum airflow fraction and 0 design air ventilation?

chriswmackey commented 1 year ago

Hi @mdahlhausen ,

I don't know if the model with over 700 zones has terminals with 0 minimum airflow fraction and 0 design air ventilation but I'm not able to create a small scale case with 0 minimum airflow fraction so I think the answer is no?

chriswmackey commented 11 months ago

Hey @mdahlhausen ,

Sorry to revive this again after so much time but I have been able to recreate this type of issue with a somewhat simpler test case and I think I know exactly what is causing it. The OSM and SQL files from the sizing run are pretty large but I think they still help debug what's happening: SR1 OSM Model SR1 eplusout.sql

Also, the error is admittedly a little different than the initial error at the top of this post but I sense the type of error is fundamentally the same.

Here is what the log file says for the sizing run with that OSM model and the SQL:

15:31:16.107636 ERROR] undefined method `*' for nil:NilClass
    :/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb:142:in `coil_heating_dx_single_speed_standard_minimum_cop'
    :/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb:256:in `coil_heating_dx_single_speed_apply_efficiency_and_curves'
    :/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2301:in `block in model_apply_hvac_efficiency_standard'
    :/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2301:in `each'
    :/ruby/2.7.0/gems/openstudio-standards-0.4.0/lib/openstudio-standards/standards/Standards.Model.rb:2301:in `model_apply_hvac_efficiency_standard'
    C:/Program Files/ladybug_tools/resources/measures/honeybee_openstudio_gem/lib/measures/from_honeybee_model/measure.rb:194:in `run'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:517:in `apply_measure'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:114:in `block in apply_measures'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `each_index'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/util/measure.rb:67:in `apply_measures'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/jobs/run_os_measures.rb:70:in `perform'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:291:in `step'
    :/ruby/2.7.0/gems/openstudio-workflow-2.3.1/lib/openstudio/workflow/run.rb:233:in `run'
    :/openstudio_cli.rb:1187:in `execute'
    :/openstudio_cli.rb:817:in `execute'
    :/openstudio_cli.rb:1984:in `<main>'
    eval:188:in `eval'
    eval:188:in `require_embedded_absolute'
    eval:173:in `block in require_embedded'
    eval:167:in `each'
    eval:167:in `require_embedded'
    eval:126:in `require'
    eval:3:in `<main>'

And here's the full log file if you want it.

Clearly, this is the line of the standards gem where it's failing:

https://github.com/NREL/openstudio-standards/blob/master/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb#L142

And the failure at that line seems to be because capacity_btu_per_hr is nil. I assume what happened is that the zone heating load was zero, which meant that the heating capacity of the PTHP was not in the SQL. It seems the standards gem routines that set the efficiencies have not been written in a way to handle these cases where things are autosized to zero.

Is this something that you think the standards gem might eventually be able to support? Or do you have a proposed workaround so that the whole process does not come to a halt when there is one zone that has a zero load?

chriswmackey commented 11 months ago

Actually, forget the test case that I included above. I was able to recreate the exact same HeatingCoil error with a single-zone OSM, which is going to be much easier to debug. Here is the OSM: https://drive.google.com/file/d/1HvtEk8akbEMMnzWEAV2RjBXnTo2WOOQw/view?usp=sharing

And just try running the following standards gem operations on it (where model is the loaded OSM):

require 'openstudio-standards'

building = model.getBuilding
standard = Standard.build('90.1-2019')
# Set the heating and cooling sizing parameters
standard.model_apply_prm_sizing_parameters(model)
# Perform a sizing run
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SR1") == false
  log_messages_to_runner(runner, debug = true)
  return false
end
# If there are any multizone systems, reset damper positions
# to achieve a 60% ventilation effectiveness minimum for the system
# following the ventilation rate procedure from 62.1
standard.model_apply_multizone_vav_outdoor_air_sizing(model)
# get the climate zone  
climate_zone_obj = model.getClimateZones.getClimateZone('ASHRAE', 2006)
climate_zone = climate_zone_obj.value
# get the building type
bldg_type = nil
unless building.standardsBuildingType.empty?
  bldg_type = building.standardsBuildingType.get
end
# Apply the prototype HVAC assumptions
standard.model_apply_prototype_hvac_assumptions(model, bldg_type, climate_zone)
# Apply the HVAC efficiency standard
standard.model_apply_hvac_efficiency_standard(model, climate_zone)

That should allow you to see exactly what is failing here.

mdahlhausen commented 11 months ago

Thanks for highlighting this.

As for a preferred solution - do you think we should remove the piece of equipment if sizing is zero? I'm not sure EnergyPlus handles zero capacity equipment well.

chriswmackey commented 11 months ago

Thanks, @mdahlhausen .

Actually, if you run the sample file and code from my last post, I now think this particular CoilHeatingDXSingleSpeed issue is not that the heating is sized to zero since the one zone in that model has a non-zero peak heating. This might be a bug resulting from E+ changing the name of the output or something like that. But the capacity_btu_per_hr is definitely coming back as nil and that sample should make it clear.

With that said, I think the original bug I posted about the AirLoopHVAC is likely different and might be because of zero flow or zero heating/cooling capacity so your question is likely still relevant. I can say that, whenever I let this equipment be autosized by E+, I have no issues running the E+ simulation. And, in my experience, E+ is generally fine with equipment that has zero capacity or flow rate since this is a very common way of telling E+ not to use certain pieces of HVAC equipment that aren't apart of the real building (eg. I'll put in a zero-capacity heating coil in an FCU if I know the real FCU only has a cooling coil). It's only these sizing and efficiency-setting routines of the standards gem that occasionally result in a failure when they find something with zero capacity. And it's only in very specific circumstances of zero capacity.

I'll keep trying to produce some minimal sample files so that you can recrate the bugs on your end since that seems to be the best way to get to the heart of the problems.

eringold commented 11 months ago

@mdahlhausen @chriswmackey I'm pretty sure the source of the heating coil COP error is that standards data has no value for 'pthp_cop_coefficient_1' (and _2) for a coil that size (>14999 Btu/h): https://github.com/NREL/openstudio-standards/blob/7fd7a7ba32a3acf34d63720806e1f7e02708425b/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb#L133-L134 image

chriswmackey commented 11 months ago

Ah, I think you're right, @eringold . Thank you for pointing this out and sorry that I misdiagnosed which variable was nil.

Is this something that you'll be able to push a fix for? Or is the reason why these coefficients are nil is that there's no recommended value for them when the capacity is outside of those ranges?

eringold commented 11 months ago

@chriswmackey no worries, I'll talk with Matt and work out a fix. It seems that prior standards vintages used the same coefficient values for all capacities, which would be one way to address it.

chriswmackey commented 10 months ago

@eringold and @mdahlhausen ,

I was just digging into this issue again and realized that the most recent issue I brought up about PTHP systems was actually fixed back in March in accordance with this other issue that I opened and Matt addressed. I had just gotten confused because the issue was fixed in March but it was not included in the OpenStudio 3.6.1 release that happened at the end of May this year. Now that OpenStudio 3.7 was released 3 weeks ago, I can see that this PTHP issue has been fixed in this version. Sorry for the confusion.

I am going to see if I can recreate the initial issue I experienced with Standards.AirLoopHVAC using the new OpenStudio 3.7 release.

chriswmackey commented 10 months ago

Hey @mdahlhausen and @eringold .

I was able to recreate the issue with Standards.AirLoopHVAC using OpenStudio 3.7. However, I dug further into it and realized that the particular failure I was having in the large model was because I had assigned an HVAC to a Zone that had no thermostat 🤦 . So just removing the HVAC from these zones has gotten that particular case to succeed.

With all of this said, I was able to make another case that produced this issue with just two zones that both have an HVAC and a thermostat. It's just that the loads in one of the Rooms were so low that we hit the no implicit conversion from nil to integer issue. When I simply ran this model of low-load rooms through EnergyPlus without using the standards gem routines to set the efficiency, the E+ simulation completed successfully. So it's just the efficiency setting routines that were getting choked up.

Here is the model with 2 rooms that you can use to recreate the issue: https://drive.google.com/file/d/1XzLFw6GmuiAV3TB5kGRmY6L3zups3WyR/view?usp=sharing

You'll see that you can simulate it as is using the EPW here: https://energyplus-weather.s3.amazonaws.com/europe_wmo_region_6/PRT/PRT_Lisboa.085360_INETI/PRT_Lisboa.085360_INETI.zip

... but running the following code with produce the failure on this line of the standards gem:

require 'openstudio-standards'

building = model.getBuilding
standard = Standard.build('90.1-2016')
# Set the heating and cooling sizing parameters
standard.model_apply_prm_sizing_parameters(model)
# Perform a sizing run
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SR1") == false
  log_messages_to_runner(runner, debug = true)
  return false
end
# If there are any multizone systems, reset damper positions
# to achieve a 60% ventilation effectiveness minimum for the system
# following the ventilation rate procedure from 62.1
standard.model_apply_multizone_vav_outdoor_air_sizing(model)
# get the climate zone  
climate_zone_obj = model.getClimateZones.getClimateZone('ASHRAE', 2006)
climate_zone = climate_zone_obj.value
# get the building type
bldg_type = nil
unless building.standardsBuildingType.empty?
  bldg_type = building.standardsBuildingType.get
end
# Apply the prototype HVAC assumptions
standard.model_apply_prototype_hvac_assumptions(model, bldg_type, climate_zone)
# Apply the HVAC efficiency standard
standard.model_apply_hvac_efficiency_standard(model, climate_zone)

So my preferred solution would just be to leave the model as it is if you get something sized to zero since E+ is still able to simulate it. Granted, if it's easier to deal with it on your end by just removing the piece of equipment, I would also find that acceptable.

And sorry again that it took to much time and back and forth to get you a minimal sample file that recreates the issue. Hopefully, you should now have everything that you need to fix it. Or, at the very least, you can now catch the exception being thrown and give a better message than "no implicit conversion from nil to integer"

mdahlhausen commented 1 month ago

@chriswmackey

This issue raised several different bugs. I think they've all been addressed:

Please let me know if you encounter any other issues. I'll close this once #1804 is merged.

chriswmackey commented 1 month ago

I know that I'm 2 weeks late but I just wanted to say thank you, @mdahlhausen . I'm very much looking forward to testing this again in the next release.