From a836f5671b194130568cb11e866bdd79365246b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pedro=20L=2E=20Magalh=C3=A3es?= <pmlpm@posteo.de>
Date: Sun, 16 Jun 2024 13:06:00 +0200
Subject: [PATCH] Revised the io routine. Revised tests.

---
 src/topupheat/pipes/single.py |  32 ++-
 tests/test_pipes.py           | 137 ++++++++++++-
 tests/test_system.py          | 102 +++++-----
 tests/test_trenches.py        | 372 +++++++++++++++++++++++++++++-----
 4 files changed, 529 insertions(+), 114 deletions(-)

diff --git a/src/topupheat/pipes/single.py b/src/topupheat/pipes/single.py
index 98bafee..f5cf01c 100644
--- a/src/topupheat/pipes/single.py
+++ b/src/topupheat/pipes/single.py
@@ -125,6 +125,10 @@ class StandardisedPipeDatabase:
         number_header_lines = 0 # the first line is for the labels/names
         
         number_footer_lines = 0 # no lines after the data
+        
+        # string_dtype = "|S10"
+        # string_dtype = str
+        string_dtype = "S"
       
         if concerns_twin_pipes:
             
@@ -143,8 +147,8 @@ class StandardisedPipeDatabase:
                            float,       #length
                            float,       #p_rated
                            float,       #e_eff
-                           "|S10",     # make
-                           "|S10",     # ref
+                           string_dtype,     # make
+                           string_dtype,     # ref
                            float)       # pipe_dist         
             
         else:
@@ -162,10 +166,11 @@ class StandardisedPipeDatabase:
                            float,       #length
                            float,       #p_rated
                            float,       #e_eff
-                           "|S10",      # make
-                           "|S10")      # ref
+                           string_dtype,      # make
+                           string_dtype)      # ref
             
         # str does not work, only "|S10"
+        file_dtypes = None
 
         #**********************************************************************
     
@@ -197,6 +202,7 @@ class StandardisedPipeDatabase:
         e_eff = {}
         make_ref_tuples = {}
         pipe_dist = {}
+        is_twin = {}
         
         # for each tuple
         
@@ -211,7 +217,6 @@ class StandardisedPipeDatabase:
             i_s = npdata['S'][i]
             
             # get make
-            
             i_make = npdata['make'][i].decode()
             
             # get reference
@@ -273,16 +278,17 @@ class StandardisedPipeDatabase:
             make_ref_tuples.update({tuple_entry: (i_make,i_ref)})
             
             # twin pipes
-            
+            _twin = False
             try:
                 
                 pipe_dist.update(
                     {tuple_entry: float(npdata[label_twinpipedist][i])})
-                
+                _twin = True
             except ValueError:
                 
                 pipe_dist.update({tuple_entry: None})
                 
+            is_twin.update({tuple_entry: _twin})
         #**********************************************************************
 
         # return 
@@ -301,7 +307,8 @@ class StandardisedPipeDatabase:
             p_rated,
             e_eff,
             make_ref_tuples,
-            pipe_dist
+            pipe_dist,
+            is_twin
             )
 
     #**************************************************************************
@@ -336,6 +343,8 @@ class StandardisedPipeDatabase:
         
         self.pipe_dist = {}
         
+        self.is_twin = {}
+        
         label_twinpipedist = 'pipe_dist'
         
         for iteration, file in enumerate(source):
@@ -369,7 +378,8 @@ class StandardisedPipeDatabase:
              tmp_p_rated,
              temp_e_eff,
              temp_make_ref_tuples,
-             temp_pipe_dist) = self.read(
+             temp_pipe_dist,
+             temp_is_twin) = self.read(
                  file,
                  concerns_twin_pipes=concerns_twin_pipes,
                  label_twinpipedist=label_twinpipedist)
@@ -408,6 +418,8 @@ class StandardisedPipeDatabase:
                 
                 self.pipe_dist = temp_pipe_dist
                 
+                self.is_twin = temp_is_twin
+                
             else:
                 
                 # check for redundancies
@@ -445,6 +457,8 @@ class StandardisedPipeDatabase:
                 # twin pipes
                 
                 self.pipe_dist.update(temp_pipe_dist)
+                
+                self.is_twin.update(temp_is_twin)
                     
             #******************************************************************
                 
diff --git a/tests/test_pipes.py b/tests/test_pipes.py
index 21355f3..7c5f643 100644
--- a/tests/test_pipes.py
+++ b/tests/test_pipes.py
@@ -2,12 +2,11 @@
 #******************************************************************************
 
 # import libraries
-
+from numbers import Real
 from src.topupheat.pipes.single import StandardisedPipeDatabase, InsulatedPipe
 from src.topupheat.pipes.single import StandardisedPipe, Pipe
 from src.topupheat.pipes.twin import AsymmetricalTwinPipe
 from src.topupheat.pipes.twin import StandardisedTwinPipe, SymmetricalTwinPipe
-# import numbers
 
 class TestPipe:
     
@@ -315,6 +314,140 @@ class TestPipe:
         # verify pipe
         
         pipe.ValidateStandardisedPipe()
+        
+        
+        
+    # *************************************************************************
+    # *************************************************************************
+        
+    def test_create_single_standardised_db(self):
+        
+        pipe_files = [
+            'tests/data/caldopex_single.csv',
+            ]
+        pipedb = StandardisedPipeDatabase(source=pipe_files)
+        
+        # specify
+        true_pipe_tuples = [
+            # single
+            (25,1,'caldopex','25-76'),
+            (25,2,'caldopex','PLUS 25-91'),
+            (32,1,'caldopex','32-76'),
+            (32,2,'caldopex','PLUS 32-91'),
+            (40,1,'caldopex','40-91'),
+            (40,2,'caldopex','PLUS 40-111'),
+            (50,1,'caldopex','50-111'),
+            (50,2,'caldopex','PLUS 50-126'),
+            (63,1,'caldopex','63-126'),
+            (63,2,'caldopex','PLUS 63-142'),
+            (75,1,'caldopex','75-142'),
+            (75,2,'caldopex','PLUS 75-162'),
+            (90,1,'caldopex','90-162'),
+            (90,2,'caldopex','PLUS 90-182'),
+            (110,1,'caldopex','110-162'),
+            (110,2,'caldopex','110-182'),
+            (110,3,'caldopex','PLUS 110-202'),
+            (125,1,'caldopex','125-182'),
+            (125,2,'caldopex','PLUS 125-202'),
+            (140,1,'caldopex','140-202'),
+            (160,1,'caldopex','160-250'),
+            ]
+        pipe_tuples = list(pipedb.pipe_tuples)
+        assert len(pipe_tuples) == len(true_pipe_tuples)
+        # make sure the tuples match
+        for pipe_tuple, true_pipe_tuple in zip(pipe_tuples, true_pipe_tuples):
+            assert pipe_tuple == true_pipe_tuple
+                    
+    # *************************************************************************
+    # *************************************************************************
+        
+    def test_create_twin_standardised_db(self):
+        
+        pipe_files = [
+            'tests/data/caldopex_twin.csv'
+            ]
+        pipedb = StandardisedPipeDatabase(source=pipe_files)
+        
+        # specify
+        true_pipe_tuples = [
+            # twin
+            (20,1,'caldopex','25+25-91'),
+            (20,2,'caldopex','PLUS 25+25-111'),
+            (25,1,'caldopex','32+32-111'),
+            (25,2,'caldopex','PLUS 32 +32-126'),
+            (32,1,'caldopex','40+40-126'),
+            (32,2,'caldopex','PLUS 40+40-142'),
+            (40,1,'caldopex','50+50-162'),
+            (40,2,'caldopex','PLUS 50+50-182'),
+            (50,1,'caldopex','63+63-182'),
+            (50,2,'caldopex','PLUS 63+63-202'),
+            (65,1,'caldopex','75+75-202'),
+            ]
+        pipe_tuples = list(pipedb.pipe_tuples)
+        assert len(pipe_tuples) == len(true_pipe_tuples)
+        # make sure the tuples match
+        for pipe_tuple, true_pipe_tuple in zip(pipe_tuples, true_pipe_tuples):
+            assert pipe_tuple == true_pipe_tuple
+            # confirm that twin pipes are recognised
+            if pipedb.is_twin[pipe_tuple]:
+                assert isinstance(pipedb.pipe_dist[pipe_tuple], Real)
+                    
+    # *************************************************************************
+    # *************************************************************************
+        
+    def test_create_mixed_standardised_db(self):
+        
+        pipe_files = [
+            'tests/data/caldopex_single.csv',
+            'tests/data/caldopex_twin.csv'
+            ]
+        pipedb = StandardisedPipeDatabase(source=pipe_files)
+        
+        # specify
+        true_pipe_tuples = [
+            # single
+            (25,1,'caldopex','25-76'),
+            (25,2,'caldopex','PLUS 25-91'),
+            (32,1,'caldopex','32-76'),
+            (32,2,'caldopex','PLUS 32-91'),
+            (40,1,'caldopex','40-91'),
+            (40,2,'caldopex','PLUS 40-111'),
+            (50,1,'caldopex','50-111'),
+            (50,2,'caldopex','PLUS 50-126'),
+            (63,1,'caldopex','63-126'),
+            (63,2,'caldopex','PLUS 63-142'),
+            (75,1,'caldopex','75-142'),
+            (75,2,'caldopex','PLUS 75-162'),
+            (90,1,'caldopex','90-162'),
+            (90,2,'caldopex','PLUS 90-182'),
+            (110,1,'caldopex','110-162'),
+            (110,2,'caldopex','110-182'),
+            (110,3,'caldopex','PLUS 110-202'),
+            (125,1,'caldopex','125-182'),
+            (125,2,'caldopex','PLUS 125-202'),
+            (140,1,'caldopex','140-202'),
+            (160,1,'caldopex','160-250'),
+            # twin
+            (20,1,'caldopex','25+25-91'),
+            (20,2,'caldopex','PLUS 25+25-111'),
+            (25,1,'caldopex','32+32-111'),
+            (25,2,'caldopex','PLUS 32 +32-126'),
+            (32,1,'caldopex','40+40-126'),
+            (32,2,'caldopex','PLUS 40+40-142'),
+            (40,1,'caldopex','50+50-162'),
+            (40,2,'caldopex','PLUS 50+50-182'),
+            (50,1,'caldopex','63+63-182'),
+            (50,2,'caldopex','PLUS 63+63-202'),
+            (65,1,'caldopex','75+75-202'),
+            ]
+        pipe_tuples = list(pipedb.pipe_tuples)
+        assert len(pipe_tuples) == len(true_pipe_tuples)
+        # make sure the tuples match
+        for pipe_tuple, true_pipe_tuple in zip(pipe_tuples, true_pipe_tuples):
+            assert pipe_tuple == true_pipe_tuple
+            # confirm that twin pipes are recognised
+            if pipedb.is_twin[pipe_tuple]:
+                assert isinstance(pipedb.pipe_dist[pipe_tuple], Real)
 
 # *****************************************************************************
 # *****************************************************************************
\ No newline at end of file
diff --git a/tests/test_system.py b/tests/test_system.py
index 0f66084..4a8273d 100644
--- a/tests/test_system.py
+++ b/tests/test_system.py
@@ -5,7 +5,7 @@ from src.topupheat.pipes.system import SupplyReturnPipeSystem
 from src.topupheat.pipes.single import StandardisedPipeDatabase
 from src.topupheat.pipes.single import Pipe, InsulatedPipe,StandardisedPipe
 from src.topupheat.pipes.twin import SymmetricalTwinPipe, StandardisedTwinPipe
-from math import isclose, inf
+from math import isclose, inf, ceil
 
 # *****************************************************************************
 # *****************************************************************************
@@ -16,7 +16,7 @@ class TestPipeSystem:
         
         # load pipe data
             
-        singlepipedata_files = ['tests/data/caldoplex_single.csv']
+        singlepipedata_files = ['tests/data/caldopex_single.csv']
         singlepipedb = StandardisedPipeDatabase(source=singlepipedata_files)
         
         # water 
@@ -234,7 +234,7 @@ class TestPipeSystem:
         
         # load pipe data
             
-        singlepipedata_files = ['tests/data/caldoplex_single.csv']
+        singlepipedata_files = ['tests/data/caldopex_single.csv']
         singlepipedb = StandardisedPipeDatabase(source=singlepipedata_files)
         
         # water 
@@ -1289,9 +1289,9 @@ class TestPipeSystem:
             phase=phase,
             source=waterdata_file
             )
-        
-        supply_temperature = 70+273.15
-        return_temperature = 40+273.15
+        # should be 80/50, which only increases the error
+        supply_temperature = 80+273.15
+        return_temperature = 50+273.15
         pressure = 1e5
         max_specific_pressure_loss = 100 # Pa/m
         
@@ -1332,18 +1332,18 @@ class TestPipeSystem:
             2061.87e3,
             3969.41e3
             ]
-        
-        rated_heat_capacity_tol = [
-            127, # 126.99937119106471
-            256, # 255.7967837826509
-            1308, # 1307.91125542394
-            2774.1, # 2774.0678334724507
-            4579.4, # 4579.386440035771
-            12933, # 12932.995288044156
-            17733.4, # 17733.337934178766
-            29023, # 29022.9469330227
-            35771, # 35770.98168226797
-            69648, # 69647.97366023948
+            
+        rated_heat_capacity_tol = [ 
+            649.0234398117755,
+            707.9785184791763,
+            2985.4500344650005,
+            145.80255162678077,
+            604.362226480036,
+            4940.196158739855,
+            5163.079628209467,
+            8332.16420539096,
+            7349.462600139203,
+            17180.801863817032
             ]
         
         # pipe
@@ -1363,11 +1363,11 @@ class TestPipeSystem:
             
             # assert that the method for the number of options works
             assert srps.number_options() == 1
-            
+            # print(srps.rated_heat_capacity()-rhc)
             # rated heat capacity
             assert isclose(
                 srps.rated_heat_capacity(),
-                rhc,
+                ceil(rhc), # round it up
                 abs_tol=rhc_tol
                 )
             
@@ -1375,7 +1375,7 @@ class TestPipeSystem:
             ucf = 2
             assert isclose(
                 srps.rated_heat_capacity(unit_conversion_factor=ucf),
-                rhc*ucf,
+                ucf*ceil(rhc), # round it up
                 abs_tol=rhc_tol*ucf
                 )
         
@@ -1434,7 +1434,7 @@ class TestPipeSystem:
                 max_specific_pressure_loss=max_specific_pressure_loss, # Pa/m
                 use_median_fluid_temperature=False
                 )
-         
+            # TODO: this
             error_raised = False
             try:
                 # rated heat capacity
@@ -1476,8 +1476,8 @@ class TestPipeSystem:
             source=waterdata_file
             )
         
-        supply_temperature = 70+273.15
-        return_temperature = 40+273.15
+        supply_temperature = 80+273.15
+        return_temperature = 50+273.15
         pressure = 1e5
         max_specific_pressure_loss = 100 # Pa/m
         
@@ -1581,8 +1581,8 @@ class TestPipeSystem:
             source=waterdata_file
             )
         
-        supply_temperature = 70+273.15
-        return_temperature = 40+273.15
+        supply_temperature = 80+273.15
+        return_temperature = 50+273.15
         pressure = 1e5
         max_specific_pressure_loss = 100 # Pa/m
         
@@ -1629,17 +1629,17 @@ class TestPipeSystem:
             3969.41e3
             ]
         
-        rated_heat_capacity_tol = [
-            127, # 126.99937119106471
-            256, # -255.7967837826509
-            1308, # 1307.91125542394
-            2774.1, # 2774.0678334724507
-            4579.4, # 4579.386440035771
-            12933, # 12932.995288044156
-            17733.4, # 17733.337934178766
-            29023, # -29022.9469330227
-            35771, # 35770.98168226797
-            69648, # 69647.97366023948
+        rated_heat_capacity_tol = [ 
+            649.0234398117755,
+            707.9785184791763,
+            2985.4500344650005,
+            145.80255162678077,
+            604.362226480036,
+            4940.196158739855,
+            5163.079628209467,
+            8332.16420539096,
+            7349.462600139203,
+            17180.801863817032
             ]
         
         # pipe
@@ -1702,7 +1702,7 @@ class TestPipeSystem:
                 max_specific_pressure_loss=max_specific_pressure_loss, # Pa/m
                 use_median_fluid_temperature=False
                 )
-            
+            # TODO: this too
             error_raised = False
             try:
                 # rated heat capacity
@@ -1727,8 +1727,8 @@ class TestPipeSystem:
             source=waterdata_file
             )
         
-        supply_temperature = 70+273.15
-        return_temperature = 40+273.15
+        supply_temperature = 80+273.15
+        return_temperature = 50+273.15
         pressure = 1e5
         max_specific_pressure_loss = 100 # Pa/m
         
@@ -1797,17 +1797,17 @@ class TestPipeSystem:
             3969.41e3
             ]
         
-        rated_heat_capacity_tol = [
-            127, # 126.99937119106471
-            256, # -255.7967837826509
-            1308, # 1307.91125542394
-            2774.1, # 2774.0678334724507
-            4579.4, # 4579.386440035771
-            12933, # 12932.995288044156
-            17733.4, # 17733.337934178766
-            29023, # -29022.9469330227
-            35771, # 35770.98168226797
-            69648, # 69647.97366023948
+        rated_heat_capacity_tol = [ 
+            649.0234398117755,
+            707.9785184791763,
+            2985.4500344650005,
+            145.80255162678077,
+            604.362226480036,
+            4940.196158739855,
+            5163.079628209467,
+            8332.16420539096,
+            7349.462600139203,
+            17180.801863817032
             ]
         
         # pipe
diff --git a/tests/test_trenches.py b/tests/test_trenches.py
index 0876e42..c288613 100644
--- a/tests/test_trenches.py
+++ b/tests/test_trenches.py
@@ -5,8 +5,8 @@ from src.topupheat.common.fluids import FluidDatabase, Fluid
 from src.topupheat.pipes import trenches, fic
 from src.topupheat.pipes.single import InsulatedPipe, StandardisedPipeDatabase
 from src.topupheat.pipes.single import StandardisedPipe
-from src.topupheat.pipes.twin import SymmetricalTwinPipe
-from math import isclose, inf
+from src.topupheat.pipes.twin import SymmetricalTwinPipe, StandardisedTwinPipe
+from math import isclose, inf, ceil
 from src.topupheat.common.factors import shape_factor_buried_horizontal_isothermal_cylinder
 from src.topupheat.common.factors import thermal_resistance_from_shape_factor
 
@@ -2510,12 +2510,15 @@ class TestPipeTrench:
        
     # *************************************************************************
     
-    def test_roder2021_losses(self):
+    def test_roder2021(self):
         
         # load pipe data
             
-        singlepipedata_files = ['tests/data/caldoplex_single.csv']
-        singlepipedb = StandardisedPipeDatabase(source=singlepipedata_files)
+        singlepipedata_files = [
+            'tests/data/caldopex_single.csv',
+            'tests/data/caldopex_twin.csv'
+            ]
+        pipedb = StandardisedPipeDatabase(source=singlepipedata_files)
         
         # water 
         
@@ -2538,6 +2541,43 @@ class TestPipeTrench:
         ground_thermal_conductivity = 1.0
         temperature_surroundings = 10+273.15
         
+        pipe_tuples = [
+            # single
+            # (25,1,'caldopex','25/76'),
+            # (25,2,'caldopex','PLUS 25/91'),
+            # (32,1,'caldopex','32/76'),
+            # (32,2,'caldopex','PLUS 32/91'),
+            # (40,1,'caldopex','40/91'),
+            # (40,2,'caldopex','PLUS 40/111'),
+            # (50,1,'caldopex','50/111'),
+            # (50,2,'caldopex','PLUS 50/126'),
+            # (63,1,'caldopex','63/126'),
+            # (63,2,'caldopex','PLUS 63/142'),
+            # (75,1,'caldopex','75/142'),
+            (75,2,'caldopex','PLUS 75/162'),
+            # (90,1,'caldopex','90/162'),
+            (90,2,'caldopex','PLUS 90/182'),
+            # (110,1,'caldopex','110/162'),
+            # (110,2,'caldopex','110/182'),
+            (110,3,'caldopex','PLUS 110/202'),
+            # (125,1,'caldopex','125/182'),
+            (125,2,'caldopex','PLUS 125/202'),
+            # (140,1,'caldopex','140/202'),
+            (160,1,'caldopex','160/250'),
+            # twin
+            # (20,1,'caldopex','25+25/91'),
+            (20,2,'caldopex','PLUS 25+25/111'),
+            # (25,1,'caldopex','32+32/111'),
+            (25,2,'caldopex','PLUS 32 +32/126'),
+            # (32,1,'caldopex','40+40/126'),
+            (32,2,'caldopex','PLUS 40+40/142'),
+            # (40,1,'caldopex','50+50/162'),
+            (40,2,'caldopex','PLUS 50+50/182'),
+            # (50,1,'caldopex','63+63/182'),
+            (50,2,'caldopex','PLUS 63+63/202'),
+            (65,1,'caldopex','75+75/202'),
+            ]
+        
         pipe_tuples = [
             (25,2),     # 1
             (32,2),     # 2
@@ -2555,9 +2595,23 @@ class TestPipeTrench:
         pipes = {
             pipe_tuple[0:2]: StandardisedPipe(
                 pipe_tuple=pipe_tuple,
-                db=singlepipedb)
-            for pipe_tuple in singlepipedb.pipe_tuples
+                db=pipedb)
+            for pipe_tuple in pipedb.pipe_tuples
             }
+        # TODO: remove?
+        # pipes = {
+        #     pipe_tuple[0:2]: (
+        #         StandardisedPipe(
+        #             pipe_tuple=pipe_tuple,
+        #             db=pipedb) 
+        #         if not pipedb.is_twin[pipe_tuple] else 
+        #         StandardisedTwinPipe(
+        #             pipe_tuple=pipe_tuple,
+        #             db=pipedb
+        #             )
+        #         )
+        #     for pipe_tuple in pipedb.pipe_tuples
+        #     }
                 
         # specific heat losses extracted graphically from the paper
         specific_heat_losses = [
@@ -2588,63 +2642,80 @@ class TestPipeTrench:
             5.703, # 11: 5.702268587107991 = error in the model?
             ]
         
-        # # rated capacities extracted graphically from the paper
-        # rhcs = [
-        #     27.05e3,
-        #     53.21e3,
-        #     95.27e3,
-        #     178.6e3,
-        #     331.04e3,
-        #     533.06e3,
-        #     863.46e3,
-        #     1471.64e3,
-        #     2061.87e3,
-        #     3969.41e3
-        #     ]
-        
-        # rhcs_tol = [
-        #     127, # 126.99937119106471
-        #     256, # 255.7967837826509
-        #     1308, # 1307.91125542394
-        #     2774.1, # 2774.0678334724507
-        #     4579.4, # 4579.386440035771
-        #     12933, # 12932.995288044156
-        #     17733.4, # 17733.337934178766
-        #     29023, # 29022.9469330227
-        #     35771, # 35770.98168226797
-        #     69648, # 69647.97366023948
-        #     ]
+        # rated capacities extracted graphically from the paper
+        rhcs = [
+            27.05e3,
+            53.21e3,
+            95.27e3,
+            178.6e3,
+            331.04e3,
+            533.06e3,
+            863.46e3,
+            1471.64e3,
+            2061.87e3,
+            3969.41e3
+            ]
+        
+        rhcs_tol = [
+            127, # 126.99937119106471
+            256, # 255.7967837826509
+            1308, # 1307.91125542394
+            2774.1, # 2774.0678334724507
+            4579.4, # 4579.386440035771
+            12933, # 12932.995288044156
+            17733.4, # 17733.337934178766
+            29023, # 29022.9469330227
+            35771, # 35770.98168226797
+            69648, # 69647.97366023948
+            ]
         
         # pipe
-        for pipe_tuple, sht, sht_tol in zip( # , rhc, rhc_tol
+        for pipe_tuple, sht, sht_tol, rhc, rhc_tol in zip(
                 pipe_tuples, 
                 specific_heat_losses, 
                 specific_heat_losses_tol,
-                # rhcs,
-                # rhcs_tol
+                rhcs,
+                rhcs_tol
                 ):
             
-            trench = trenches.SupplyReturnPipeTrench(
-                pipe_center_depth=(
-                    pipe_depth_top+pipes[pipe_tuple].d_cas/2
-                    ), 
-                pipe_center_distance=(
-                    pipe_distance_edge+pipes[pipe_tuple].d_cas
-                    ), 
-                fluid_db=fluid_db, 
-                phase=phase, 
-                pressure=pressure, 
-                supply_temperature=supply_temperature, 
-                return_temperature=return_temperature, 
-                max_specific_pressure_loss=max_specific_pressure_loss, 
-                supply_pipe=pipes[pipe_tuple])
+            if isinstance(pipes[pipe_tuple], StandardisedTwinPipe):
+                # twin pipe
+                trench = trenches.TwinPipeTrench(
+                    pipe_center_depth=(
+                        pipe_depth_top+pipes[pipe_tuple].d_cas/2
+                        ), 
+                    fluid_db=fluid_db, 
+                    phase=phase, 
+                    pressure=pressure, 
+                    supply_temperature=supply_temperature, 
+                    return_temperature=return_temperature, 
+                    max_specific_pressure_loss=max_specific_pressure_loss, 
+                    supply_pipe=pipes[pipe_tuple])
+            else:
+                trench = trenches.SupplyReturnPipeTrench(
+                    pipe_center_depth=(
+                        pipe_depth_top+pipes[pipe_tuple].d_cas/2
+                        ), 
+                    pipe_center_distance=(
+                        pipe_distance_edge+pipes[pipe_tuple].d_cas
+                        ), 
+                    fluid_db=fluid_db, 
+                    phase=phase, 
+                    pressure=pressure, 
+                    supply_temperature=supply_temperature, 
+                    return_temperature=return_temperature, 
+                    max_specific_pressure_loss=max_specific_pressure_loss, 
+                    supply_pipe=pipes[pipe_tuple])
     
-            # # rated heat capacity
+            # rated heat capacity
             # assert isclose(
             #     trench.rated_heat_capacity(),
             #     rhc,
             #     abs_tol=rhc_tol
             #     )
+            # print('next')
+            # print(rhc)
+            # print(trench.rated_heat_capacity())
             
             # specific heat transfer
             assert isclose(
@@ -2660,6 +2731,203 @@ class TestPipeTrench:
             
             assert type(trench.printable_description()) == str
     
+    def test_caldopex(self):
+        
+        # load pipe data
+        pipedata_files = [
+            'tests/data/caldopex_single.csv',
+            'tests/data/caldopex_twin.csv'
+            ]
+        pipedb = StandardisedPipeDatabase(source=pipedata_files)
+        
+        # water 
+        waterdata_file = 'tests/data/incropera2006_saturated_water.csv'
+        phase = FluidDatabase.fluid_LIQUID
+        fluid_db = FluidDatabase(
+            fluid='fluid',
+            phase=phase,
+            source=waterdata_file
+            )
+        
+        supply_temperature = 80+273.15
+        return_temperature = 50+273.15
+        pressure = 1e5
+        max_specific_pressure_loss = 100 # Pa/m
+        pipe_depth_top = 0.8 # m
+        pipe_distance_edge = 0.1 # m
+        
+        ground_air_heat_transfer_coefficient = inf
+        ground_thermal_conductivity = 1.0
+        temperature_surroundings = 10+273.15
+        
+        pipe_tuples = [
+            # single
+            (25,1,'caldopex','25-76'),
+            (25,2,'caldopex','PLUS 25-91'),
+            (32,1,'caldopex','32-76'),
+            (32,2,'caldopex','PLUS 32-91'),
+            (40,1,'caldopex','40-91'),
+            (40,2,'caldopex','PLUS 40-111'),
+            (50,1,'caldopex','50-111'),
+            (50,2,'caldopex','PLUS 50-126'),
+            (63,1,'caldopex','63-126'),
+            (63,2,'caldopex','PLUS 63-142'),
+            (75,1,'caldopex','75-142'),
+            (75,2,'caldopex','PLUS 75-162'),
+            (90,1,'caldopex','90-162'),
+            (90,2,'caldopex','PLUS 90-182'),
+            (110,1,'caldopex','110-162'),
+            (110,2,'caldopex','110-182'),
+            (110,3,'caldopex','PLUS 110-202'),
+            (125,1,'caldopex','125-182'),
+            (125,2,'caldopex','PLUS 125-202'),
+            (140,1,'caldopex','140-202'),
+            (160,1,'caldopex','160-250'),
+            # twin
+            (20,1,'caldopex','25+25-91'),
+            (20,2,'caldopex','PLUS 25+25-111'),
+            (25,1,'caldopex','32+32-111'),
+            (25,2,'caldopex','PLUS 32 +32-126'),
+            (32,1,'caldopex','40+40-126'),
+            (32,2,'caldopex','PLUS 40+40-142'),
+            (40,1,'caldopex','50+50-162'),
+            (40,2,'caldopex','PLUS 50+50-182'),
+            (50,1,'caldopex','63+63-182'),
+            (50,2,'caldopex','PLUS 63+63-202'),
+            (65,1,'caldopex','75+75-202'),
+            ]
+        
+        pipes = {
+            pipe_tuple: (
+                StandardisedPipe(
+                    pipe_tuple=pipe_tuple,
+                    db=pipedb) 
+                if not pipedb.is_twin[pipe_tuple] else 
+                StandardisedTwinPipe(
+                    pipe_tuple=pipe_tuple,
+                    db=pipedb
+                    )
+                )
+            for pipe_tuple in pipedb.pipe_tuples
+            }
+        
+        true_capacity = {
+            (25, 1, 'caldopex', '25-76'): 20881.479233138303,  
+            (25, 2, 'caldopex', 'PLUS 25-91'): 20881.479233138303,        
+            (32, 1, 'caldopex', '32-76'):40793.37028711016,            
+            (32, 2, 'caldopex', 'PLUS 32-91'): 40793.37028711016,
+            (40, 1, 'caldopex', '40-91'): 73880.93921875181,
+            (40, 2, 'caldopex', 'PLUS 40-111'): 73880.93921875181,
+            (50, 1, 'caldopex', '50-111'): 134495.59672187426,
+            (50, 2, 'caldopex', 'PLUS 50-126'): 134495.59672187426,
+            (63, 1, 'caldopex', '63-126'):
+            249246.5864686179,
+            (63, 2, 'caldopex', 'PLUS 63-142'):
+            249246.5864686179,
+            (75, 1, 'caldopex', '75-142'):
+            398186.48902504705,
+            (75, 2, 'caldopex', 'PLUS 75-162'):
+            398186.48902504705,
+            (90, 1, 'caldopex', '90-162'):
+            645626.6619794322,
+            (90, 2, 'caldopex', 'PLUS 90-182'):
+            645626.6619794322,
+            (110, 1, 'caldopex', '110-162'):
+            1099995.669180083,
+            (110, 2, 'caldopex', '110-182'):
+            1099995.669180083,
+            (110, 3, 'caldopex', 'PLUS 110-202'):
+            1099995.669180083,
+            (125, 1, 'caldopex', '125-182'):
+            1541776.6632286548,
+            (125, 2, 'caldopex', 'PLUS 125-202'):
+            1541776.6632286548,
+            (140, 1, 'caldopex', '140-202'):
+            2083512.017509401,
+            (160, 1, 'caldopex', '160-250'):
+            2960054.629960731,
+            (20, 1, 'caldopex', '25+25-91'): 20881.479233138303,
+            (20, 2, 'caldopex', 'PLUS 25+25-111'): 20881.479233138303,            
+            (25, 1, 'caldopex', '32+32-111'): 40793.37028711016,            
+            (25, 2, 'caldopex', 'PLUS 32 +32-126'): 40793.37028711016,
+            (32, 1, 'caldopex', '40+40-126'): 73880.93921875181,
+            (32, 2, 'caldopex', 'PLUS 40+40-142'): 73880.93921875181,
+            (40, 1, 'caldopex', '50+50-162'): 134495.59672187426,
+            (40, 2, 'caldopex', 'PLUS 50+50-182'): 134495.59672187426,
+            (50, 1, 'caldopex', '63+63-182'): 249246.5864686179,
+            (50, 2, 'caldopex', 'PLUS 63+63-202'): 249246.5864686179,
+            (65, 1, 'caldopex', '75+75-202'): 398186.48902504705,
+            }
+        
+        # pipe
+        for pipe_tuple in pipe_tuples:
+        # for pipe_tuple, sht, sht_tol, rhc, rhc_tol in zip(
+        #         pipe_tuples, 
+        #         specific_heat_losses, 
+        #         specific_heat_losses_tol,
+        #         rhcs,
+        #         rhcs_tol
+        #         ):
+            
+            if isinstance(pipes[pipe_tuple], StandardisedTwinPipe):
+                # twin pipe
+                trench = trenches.TwinPipeTrench(
+                    pipe_center_depth=(
+                        pipe_depth_top+pipes[pipe_tuple].d_cas/2
+                        ), 
+                    fluid_db=fluid_db, 
+                    phase=phase, 
+                    pressure=pressure, 
+                    supply_temperature=supply_temperature, 
+                    return_temperature=return_temperature, 
+                    max_specific_pressure_loss=max_specific_pressure_loss, 
+                    supply_pipe=pipes[pipe_tuple])
+            else:
+                trench = trenches.SupplyReturnPipeTrench(
+                    pipe_center_depth=(
+                        pipe_depth_top+pipes[pipe_tuple].d_cas/2
+                        ), 
+                    pipe_center_distance=(
+                        pipe_distance_edge+pipes[pipe_tuple].d_cas
+                        ), 
+                    fluid_db=fluid_db, 
+                    phase=phase, 
+                    pressure=pressure, 
+                    supply_temperature=supply_temperature, 
+                    return_temperature=return_temperature, 
+                    max_specific_pressure_loss=max_specific_pressure_loss, 
+                    supply_pipe=pipes[pipe_tuple])
+    
+            # rated heat capacity
+            assert isclose(
+                trench.rated_heat_capacity(),
+                ceil(true_capacity[pipe_tuple]), # round it up
+                abs_tol=1
+                )
+            # print('next')
+            # print(pipe_tuple)
+            # print(trench.rated_heat_capacity())
+            # print(trench.specific_heat_transfer_surroundings(
+            # ground_air_heat_transfer_coefficient=ground_air_heat_transfer_coefficient,
+            # ground_thermal_conductivity=ground_thermal_conductivity,
+            # temperature_surroundings=temperature_surroundings))
+            
+            # # specific heat transfer
+            # assert isclose(
+            #     sum(
+            #         trench.specific_heat_transfer_surroundings(
+            #         ground_air_heat_transfer_coefficient=ground_air_heat_transfer_coefficient,
+            #         ground_thermal_conductivity=ground_thermal_conductivity,
+            #         temperature_surroundings=temperature_surroundings)
+            #         ),
+            #     sht,
+            #     abs_tol=sht_tol
+            #     )
+            
+            # assert type(trench.printable_description()) == str
+            
+    # TODO: test the simplified specific heat transfer method using trench objects
+    
     # *************************************************************************
         
     def test_different_single_pipes(self):
@@ -2901,7 +3169,7 @@ class TestPipeTrench:
         
         # load pipe data
             
-        singlepipedata_files = ['tests/data/caldoplex_single.csv']
+        singlepipedata_files = ['tests/data/caldopex_single.csv']
         singlepipedb = StandardisedPipeDatabase(source=singlepipedata_files)
         
         # water 
-- 
GitLab