Repository: pyenergyplus/witheppy (language: python)

Issue:
Single function to copy an HVAC system from on IDF to another IDF
Single function to copy an HVAC system from on IDF to another IDF

Use Case:

- To try out different HVAC systems in your building
- Copy HVAC systems from the Example files into your building
- Do a parametric analyssi with this.

`copy_hvac(from_idf, to_idf)`

The `copy_hvac(from_idf, to_idf)` function will need the following functions

- `hvac_remover(idf)`
    - removes the HVAC and returns an IDF that has no HVAC
- `hvac_extractor(idf)`
    - extracts the HVAC objects an IDF and returns just the HVAC and related objects
- `zone_hvac_remover(idf)`
    - cleanly removes the HVAC object from a zone
    - It will remove the zone terminal unit and all it's links back to the splitter and mixer
    - It is useful on it's own as it will let you make a conditioned zone into an unconditioned zone
    - it can be put into a loop run on multiple units
- `zone_hvac_adder(idf)`
    - used when you have working HVAC with terminal units in the zones
    - cleanly adds the HVAC object to a zone (looks at the other zones and creates similar unit)
    - It will add the zone terminal unit and all it's links back to the splitter and mixer
    - It is useful on it's own as it will let you make an unconditioned room into a conditioned room
    - it can be put into a loop run on multiple units
- `thermostat_extractor(idf)`
    - needed to know which zones are contiioned and what the settings are.
- `hvac_inserter(to_idf, fromhvac)`
    
How these can be used implement `copy_hvac(from_idf, to_idf)`    

    def copy_hvac(from_idf, to_idf):
        nohvac_idf = hvac_remover(to_idf)
        fromhvac = hvac_extractor(from_idf)
        from_thermostats = thermostat_extractor(from_idf)
        to_thermostats = thermostat_extractor(to_idf)
        
        # there may be a mismatch in the number of 
        # conditioned zones of from_idf and to_idf
        # compare the from_thermostats and to_thermostats to see the diff
        
        if to_idf_has_more_zones:
            for number of more zones:
                tohvac = zone_hvac_adder( .... )
        elif from_idf_has_less_zones
            for number of less zones:
                fromhvac = zone_hvac_adder( ... )
        else:
            pass
            
        return hvac_inserter(nohvac_idf, tohvac)
            
                
        
        
        
        
        


Discussion / hints:
`copy_hvac(from_idf, to_idf)` is not the best name for this functionality. This function does not just copy the HVAC. It replaces the existing HVAC. So a more descriptive name would be `replace_hvac(from_idf, to_idf)`

Fix patch:
diff --git a/witheppy/eppyhelpers/hvac.py b/witheppy/hvachelpers/exhaust.py
similarity index 100%
rename from witheppy/eppyhelpers/hvac.py
rename to witheppy/hvachelpers/exhaust.py


Test patch:
diff --git a/tests/test_eppyhelpers/test_hvac.py b/tests/test_eppyhelpers/test_hvac.py
index b503086..e25e682 100644
--- a/tests/test_eppyhelpers/test_hvac.py
+++ b/tests/test_eppyhelpers/test_hvac.py
@@ -8,7 +8,7 @@
 
 import pytest
 from io import StringIO
-from witheppy.eppyhelpers import hvac
+from witheppy.hvachelpers import exhaust
 import witheppy.eppyhelpers.extfields as extfields
 
 idftxt = """
@@ -163,10 +163,10 @@ def test_findequipmentconnection(idfsnippet):
     """py.test for findequipmentconnection"""
     idf = idfsnippet
     zone = idf.idfobjects["zone"][0]
-    result = hvac.findequipmentconnection(idf, zone)
+    result = exhaust.findequipmentconnection(idf, zone)
     assert result.Zone_Name == zone.Name
     zone = idf.newidfobject("zone", "gumby")
-    result = hvac.findequipmentconnection(idf, zone)
+    result = exhaust.findequipmentconnection(idf, zone)
     assert result == None
 
 
@@ -174,14 +174,14 @@ def test_findequipmentlist(idfsnippet):
     """py.test for findequipmentlist"""
     idf = idfsnippet
     zone = idf.idfobjects["zone"][0]
-    result = hvac.findequipmentlist(idf, zone, testing=True)
+    result = exhaust.findequipmentlist(idf, zone, testing=True)
     assert result[-1].Zone_Name == zone.Name
     assert result[-1].Zone_Conditioning_Equipment_List_Name == result[0].Name
     zone = idf.newidfobject("zone", "gumby")
-    result = hvac.findequipmentlist(idf, zone)
+    result = exhaust.findequipmentlist(idf, zone)
     assert result == None
     econnction = idf.newidfobject("ZoneHVAC:EquipmentConnections", Zone_Name="gumby")
-    result = hvac.findequipmentlist(idf, zone)
+    result = exhaust.findequipmentlist(idf, zone)
     assert result == None
 
 
@@ -189,13 +189,13 @@ def test_hasexhaust(idfsnippet):
     """py.test for hasexhaust"""
     idf = idfsnippet
     zone = idf.idfobjects["zone"][0]
-    result = hvac.hasexhaust(idf, zone)
+    result = exhaust.hasexhaust(idf, zone)
     assert result == False
     zone = idf.idfobjects["zone"][1]
-    result = hvac.hasexhaust(idf, zone)
+    result = exhaust.hasexhaust(idf, zone)
     assert result == "Zone 2 Exhausts"
     zone = idf.idfobjects["zone"][2]
-    result = hvac.hasexhaust(idf, zone)
+    result = exhaust.hasexhaust(idf, zone)
     assert result == "Zone 3 Exhausts"
 
 
@@ -203,12 +203,12 @@ def test_findexhaust(idfsnippet):
     """py.test for findexhaust"""
     idf = idfsnippet
     zone = idf.idfobjects["zone"][0]
-    result = hvac.findexhaust(idf, zone)
+    result = exhaust.findexhaust(idf, zone)
     assert result == None
     # ---
     exfanname = "Zone 2 Exhaust Fan"
     zone = idf.idfobjects["zone"][1]
-    result = hvac.findexhaust(idf, zone)
+    result = exhaust.findexhaust(idf, zone)
     assert result.Name == exfanname
 
 
@@ -217,11 +217,11 @@ def test_removeexhaust(idfsnippet):
     idf = idfsnippet
     zones = idf.idfobjects["zone"]
     zone = zones[1]
-    eqlist = hvac.findequipmentlist(idf, zone)
-    exfan = hvac.removeexhaust(idf, zone)
+    eqlist = exhaust.findequipmentlist(idf, zone)
+    exfan = exhaust.removeexhaust(idf, zone)
     expectedname = "Zone 2 Exhaust Fan"
     assert exfan.Name == expectedname
-    assert hvac.hasexhaust(idf, zone) == False
+    assert exhaust.hasexhaust(idf, zone) == False
     # test if exhaust fan has been removed from 'ZONEHVAC:EQUIPMENTLIST'
     extlist = extfields.extensiblefields2list(eqlist)
     eqlistitems = [
@@ -230,7 +230,7 @@ def test_removeexhaust(idfsnippet):
     assert not eqlistitems  # list should be empty
     # test when you try to remove a nonexistent 
     zone = zones[0]
-    exfan = hvac.removeexhaust(idf, zone)
+    exfan = exhaust.removeexhaust(idf, zone)
     assert exfan == None
 
 def test_putexhaust(idfsnippet):
@@ -239,19 +239,19 @@ def test_putexhaust(idfsnippet):
     zones = idf.idfobjects["zone"]
     zone = zones[0]
     exfan = idf.newidfobject("Fan:ZoneExhaust", Name="zone1_exhaust_fan")
-    hvac.putexhaust(idf, zone, exfan)
-    assert hvac.hasexhaust(idf, zone) == "zone1_exhaust_fan Node List"
-    assert hvac.findexhaust(idf, zone) == exfan
+    exhaust.putexhaust(idf, zone, exfan)
+    assert exhaust.hasexhaust(idf, zone) == "zone1_exhaust_fan Node List"
+    assert exhaust.findexhaust(idf, zone) == exfan
     # test if ex fan is in equiplist
-    eqlist = hvac.findequipmentlist(idf, zone)
+    eqlist = exhaust.findequipmentlist(idf, zone)
     extlist = extfields.extensiblefields2list(eqlist)
     objecttypes = [item for item in extlist if item[0].upper() == "FAN:ZONEEXHAUST"]
     assert objecttypes # has an item in it ie. "FAN:ZONEEXHAUST"
     # test when there is an existing exhaust
-    with pytest.raises(hvac.HasExhaustFanError):
+    with pytest.raises(exhaust.HasExhaustFanError):
         zone = zones[1]
         exfan = idf.newidfobject("Fan:ZoneExhaust", Name="zone2_exhaust_fan")
-        hvac.putexhaust(idf, zone, exfan)
+        exhaust.putexhaust(idf, zone, exfan)
         
 
 # TODO add and remove exhaust fans in multiple example files - to see how robust it is.