diff --git a/Project.toml b/Project.toml
index bcf85341..f211f429 100644
--- a/Project.toml
+++ b/Project.toml
@@ -33,6 +33,7 @@ Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
+TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"
[sources]
GetDP = {rev = "main", url = "https://github.com/Electa-Git/GetDP.jl"}
@@ -65,6 +66,7 @@ Reexport = "1.2.2"
Serialization = "1.11.0"
SpecialFunctions = "2.5.0"
Statistics = "1.11.1"
+TestItemRunner = "1.1.0"
[extras]
Coverage = "a2441757-f6aa-5fb2-8edb-039e3f45d037"
diff --git a/examples/18kV_1000mm2_equivalent_ZY.xml b/examples/18kV_1000mm2_equivalent_ZY.xml
new file mode 100644
index 00000000..cdc25366
--- /dev/null
+++ b/examples/18kV_1000mm2_equivalent_ZY.xml
@@ -0,0 +1,24 @@
+
+
+1.3434279069898911E-05+1.7952866255503812E-08i,1.1017765633788020E-11+1.7081287857882299E-08i,1.1017764470276360E-11+1.7010534496485781E-08i,1.1015007112753420E-11+1.5576892169123991E-08i,1.1015007838539930E-11+1.5576896150241041E-08i,1.1015007832216130E-11+1.5576896296215632E-08i,1.1015008907855811E-11+1.5577067525585591E-08i,1.1015009786503661E-11+1.5577073892113442E-08i,1.1015009785051650E-11+1.5577073931078009E-08i
+1.1017765633788020E-11+1.7081287857882319E-08i,4.8965847155552837E-04+1.7053209940201269E-08i,1.1017764436496461E-11+1.7010534018250459E-08i,1.1015007208492361E-11+1.5576891666096819E-08i,1.1015007934228091E-11+1.5576895647213502E-08i,1.1015007927904550E-11+1.5576895793192361E-08i,1.1015009647847549E-11+1.5577051592013609E-08i,1.1015010526527139E-11+1.5577057958287028E-08i,1.1015010525075190E-11+1.5577057997259709E-08i
+1.1017764470276360E-11+1.7010534496485781E-08i,1.1017764436496449E-11+1.7010534018250469E-08i,7.1275338935888172E-04+1.7009694007398330E-08i,1.1015007212246959E-11+1.5576891511375961E-08i,1.1015007937982130E-11+1.5576895492488471E-08i,1.1015007931658590E-11+1.5576895638466728E-08i,1.1015009642246840E-11+1.5577051718596958E-08i,1.1015010520926270E-11+1.5577058084887011E-08i,1.1015010519474310E-11+1.5577058123859229E-08i
+1.1015007112753420E-11+1.5576892169123991E-08i,1.1015007208492361E-11+1.5576891666096809E-08i,1.1015007212246959E-11+1.5576891511375971E-08i,1.3434279070081390E-05+1.7963938465725391E-08i,1.1017951241640630E-11+1.7092387891757259E-08i,1.1017950077073291E-11+1.7021634591932449E-08i,1.1015102403034780E-11+1.5582521805360730E-08i,1.1015102147403959E-11+1.5582506433544761E-08i,1.1015102152293051E-11+1.5582506338279011E-08i
+1.1015007838539939E-11+1.5576896150241041E-08i,1.1015007934228091E-11+1.5576895647213502E-08i,1.1015007937982130E-11+1.5576895492488481E-08i,1.1017951241640630E-11+1.7092387891757259E-08i,4.8965847155570423E-04+1.7064310701644261E-08i,1.1017950119538740E-11+1.7021634707642821E-08i,1.1015103577693039E-11+1.5582521013060809E-08i,1.1015103322040260E-11+1.5582505641055911E-08i,1.1015103326929440E-11+1.5582505545791820E-08i
+1.1015007832216121E-11+1.5576896296215632E-08i,1.1015007927904540E-11+1.5576895793192371E-08i,1.1015007931658590E-11+1.5576895638466718E-08i,1.1017950077073291E-11+1.7021634591932449E-08i,1.1017950119538730E-11+1.7021634707642821E-08i,7.1275338935904880E-04+1.7020794697957151E-08i,1.1015103571670630E-11+1.5582520929618101E-08i,1.1015103316018230E-11+1.5582505557622289E-08i,1.1015103320907400E-11+1.5582505462357939E-08i
+1.1015008907855811E-11+1.5577067525585591E-08i,1.1015009647847549E-11+1.5577051592013619E-08i,1.1015009642246840E-11+1.5577051718596958E-08i,1.1015102403034780E-11+1.5582521805360720E-08i,1.1015103577693039E-11+1.5582521013060789E-08i,1.1015103571670630E-11+1.5582520929618091E-08i,1.3434279070090179E-05+1.7964450625337511E-08i,1.1017957744336239E-11+1.7092889322791409E-08i,1.1017956580156670E-11+1.7022135976960378E-08i
+1.1015009786503649E-11+1.5577073892113442E-08i,1.1015010526527139E-11+1.5577057958287038E-08i,1.1015010520926270E-11+1.5577058084887011E-08i,1.1015102147403950E-11+1.5582506433544751E-08i,1.1015103322040270E-11+1.5582505641055891E-08i,1.1015103316018220E-11+1.5582505557622289E-08i,1.1017957744336239E-11+1.7092889322791409E-08i,4.8965847155571019E-04+1.7064811736840651E-08i,1.1017956552373579E-11+1.7022135740156459E-08i
+1.1015009785051650E-11+1.5577073931077999E-08i,1.1015010525075190E-11+1.5577057997259699E-08i,1.1015010519474310E-11+1.5577058123859229E-08i,1.1015102152293051E-11+1.5582506338279002E-08i,1.1015103326929440E-11+1.5582505545791800E-08i,1.1015103320907391E-11+1.5582505462357910E-08i,1.1017956580156670E-11+1.7022135976960368E-08i,1.1017956552373579E-11+1.7022135740156459E-08i,7.1275338935905086E-04+1.7021295725736878E-08i
+
+
+1.0235427486802910E-12+3.5876442374760141E-12i,-1.0235427486802910E-12-3.5876442374760120E-12i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i
+-1.0235427486802910E-12-3.5876442374760108E-12i,1.6425015376953339E-01+1.5678614572597519E-09i,-1.6425015376850960E-01-1.5642738130222760E-09i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i
+0.0000000000000000E+00+0.0000000000000000E+00i,-1.6425015376850960E-01-1.5642738130222760E-09i,1.6425015376906821E-01+1.5785181589513440E-09i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1878404738314777E-20-5.7120222538543638E-21i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1879257446717906E-20-5.7120900167636763E-21i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,1.0235261510765790E-12+3.5875860608171570E-12i,-1.0235261510765790E-12-3.5875860608171562E-12i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,-1.0235261510765790E-12-3.5875860608171562E-12i,1.6425015376954741E-01+1.5678613990832289E-09i,-1.6425015376852370E-01-1.5642738130224119E-09i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1878404738314741E-20-5.7120222538543638E-21i,0.0000000000000000E+00+0.0000000000000000E+00i,-1.6425015376852370E-01-1.5642738130224119E-09i,1.6425015376908189E-01+1.5785181589523670E-09i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1649474811640504E-20-5.6938296848403217E-21i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,1.0235189000849910E-12+3.5875606451926360E-12i,-1.0235189000849920E-12-3.5875606451926352E-12i,0.0000000000000000E+00+0.0000000000000000E+00i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,-1.0235189000849920E-12-3.5875606451926340E-12i,1.6425015376954749E-01+1.5678613736676110E-09i,-1.6425015376852389E-01-1.5642738130224179E-09i
+0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1879257446717858E-20-5.7120900167636763E-21i,0.0000000000000000E+00+0.0000000000000000E+00i,0.0000000000000000E+00+0.0000000000000000E+00i,7.1649474811640504E-20-5.6938296848403240E-21i,0.0000000000000000E+00+0.0000000000000000E+00i,-1.6425015376852389E-01-1.5642738130224179E-09i,1.6425015376908231E-01+1.5785181589523740E-09i
+
+
diff --git a/examples/18kV_1000mm2_equivalent_export.xml b/examples/18kV_1000mm2_equivalent_export.xml
new file mode 100644
index 00000000..6a7062b1
--- /dev/null
+++ b/examples/18kV_1000mm2_equivalent_export.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/18kV_1000mm2_trifoil_export.pscx b/examples/18kV_1000mm2_trifoil_export.pscx
index 269f4d9d..d29c98fe 100644
--- a/examples/18kV_1000mm2_trifoil_export.pscx
+++ b/examples/18kV_1000mm2_trifoil_export.pscx
@@ -1,2 +1,2 @@
-
+
diff --git a/examples/525kV_1600mm2_bipole_export.pscx b/examples/525kV_1600mm2_bipole_export.pscx
index 496a1c9e..d231cae2 100644
--- a/examples/525kV_1600mm2_bipole_export.pscx
+++ b/examples/525kV_1600mm2_bipole_export.pscx
@@ -1,2 +1,2 @@
-
+
diff --git a/examples/cables_library.json b/examples/cables_library.json
index 60ec2b69..a4c41e5e 100644
--- a/examples/cables_library.json
+++ b/examples/cables_library.json
@@ -305,6 +305,314 @@
}
}
]
+ },
+ "525kV_1600mm2": {
+ "cable_id": "525kV_1600mm2",
+ "nominal_data": {
+ "U": 525,
+ "screen_cross_section": 1000,
+ "capacitance": null,
+ "__julia_type__": "LineCableModels.DataModel.NominalData",
+ "U0": 500,
+ "conductor_cross_section": 1600,
+ "armor_cross_section": null,
+ "resistance": null,
+ "inductance": null,
+ "designation_code": "(N)2XH(F)RK2Y"
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableDesign",
+ "components": [
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1000,
+ "mu_r": 1,
+ "rho": 1000
+ },
+ "radius_in": 0.02382185,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.02582185,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.3,
+ "mu_r": 1,
+ "rho": 197000000000000
+ },
+ "radius_in": 0.02582185,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.05182185,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1000,
+ "mu_r": 1,
+ "rho": 500
+ },
+ "radius_in": 0.05182185,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.053621850000000006,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 32.3,
+ "mu_r": 1,
+ "rho": 5300
+ },
+ "radius_in": 0.053621850000000006,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.05392185000000001,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "core",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "lay_ratio": 0,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 1,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.00183245,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 6,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.00549735,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 12,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.00916225,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 18,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.01282715,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 24,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.01649205,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 30,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.02015695,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00183245,
+ "num_wires": 36,
+ "temperature": 20
+ }
+ ]
+ }
+ },
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.3,
+ "mu_r": 1,
+ "rho": 197000000000000
+ },
+ "radius_in": 0.057221850000000005,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.06022185000000001,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.8,
+ "mu_r": 1,
+ "rho": 1000000000000000
+ },
+ "radius_in": 0.06022185000000001,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.06322185000000001,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "sheath",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.004,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999983,
+ "rho": 2.14e-7
+ },
+ "radius_in": 0.05392185000000001,
+ "__julia_type__": "LineCableModels.DataModel.Tubular",
+ "radius_ext": 0.057221850000000005,
+ "temperature": 20
+ }
+ ]
+ }
+ },
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.8,
+ "mu_r": 1,
+ "rho": 1000000000000000
+ },
+ "radius_in": 0.06904885000000001,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.07904885,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "armor",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "lay_ratio": 10,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.0045,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 300,
+ "rho": 1.38e-7
+ },
+ "lay_direction": 1,
+ "radius_in": 0.06322185000000001,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.0029135,
+ "num_wires": 68,
+ "temperature": 20
+ }
+ ]
+ }
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/examples/materials_library.json b/examples/materials_library.json
index dac01ffa..4a42a68f 100644
--- a/examples/materials_library.json
+++ b/examples/materials_library.json
@@ -15,14 +15,6 @@
"mu_r": 0.999994,
"rho": 3.03e-8
},
- "carbon_pe": {
- "T0": 20,
- "alpha": 0,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 1000,
- "mu_r": 1,
- "rho": 0.06
- },
"bronze": {
"T0": 20,
"alpha": 0.003,
@@ -31,22 +23,6 @@
"mu_r": 1,
"rho": 3.5e-8
},
- "lead": {
- "T0": 20,
- "alpha": 0.004,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 1,
- "mu_r": 0.999983,
- "rho": 2.14e-7
- },
- "steel": {
- "T0": 20,
- "alpha": 0.0045,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 1,
- "mu_r": 300,
- "rho": 1.38e-7
- },
"copper": {
"T0": 20,
"alpha": 0.00393,
@@ -55,14 +31,6 @@
"mu_r": 0.999994,
"rho": 1.7241e-8
},
- "copper_corrected": {
- "T0": 20,
- "alpha": 0.00393,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 1,
- "mu_r": 0.999994,
- "rho": 1.835e-8
- },
"pec": {
"T0": 20,
"alpha": 0,
@@ -79,17 +47,6 @@
"mu_r": 1,
"rho": 18.5
},
- "air": {
- "T0": 20,
- "alpha": 0,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 1,
- "mu_r": 1,
- "rho": {
- "value": "Inf",
- "__type__": "SpecialFloat"
- }
- },
"laminated_paper": {
"T0": 20,
"alpha": 0,
@@ -114,14 +71,6 @@
"mu_r": 1,
"rho": 1000
},
- "epr": {
- "T0": 20,
- "alpha": 0.005,
- "__julia_type__": "LineCableModels.Materials.Material",
- "eps_r": 3,
- "mu_r": 1,
- "rho": 1000000000000000
- },
"xlpe": {
"T0": 20,
"alpha": 0,
@@ -138,6 +87,57 @@
"mu_r": 1,
"rho": 500
},
+ "aluminum": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "carbon_pe": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1000,
+ "mu_r": 1,
+ "rho": 0.06
+ },
+ "lead": {
+ "T0": 20,
+ "alpha": 0.004,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999983,
+ "rho": 2.14e-7
+ },
+ "copper_corrected": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.835e-8
+ },
+ "air": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1,
+ "rho": {
+ "value": "Inf",
+ "__type__": "SpecialFloat"
+ }
+ },
+ "epr": {
+ "T0": 20,
+ "alpha": 0.005,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 3,
+ "mu_r": 1,
+ "rho": 1000000000000000
+ },
"pvc": {
"T0": 20,
"alpha": 0.1,
@@ -154,12 +154,12 @@
"mu_r": 500,
"rho": 7.0e-7
},
- "aluminum": {
+ "steel": {
"T0": 20,
- "alpha": 0.00429,
+ "alpha": 0.0045,
"__julia_type__": "LineCableModels.Materials.Material",
"eps_r": 1,
- "mu_r": 1.000022,
- "rho": 2.8264e-8
+ "mu_r": 300,
+ "rho": 1.38e-7
}
}
\ No newline at end of file
diff --git a/examples/tutorial3.jl b/examples/tutorial3.jl
index dbc7a0a4..a4b1f497 100644
--- a/examples/tutorial3.jl
+++ b/examples/tutorial3.jl
@@ -368,3 +368,7 @@ if !opts.mesh_only
println("L = $(@sprintf("%.6g", L)) mH/km")
println("C = $(@sprintf("%.6g", C)) μF/km")
end
+
+
+output_file = fullfile("$(cable_system.system_id)_export.xml")
+export_data(Val(:atp), line_params, cable_system, problem, file_name=output_file)
\ No newline at end of file
diff --git a/src/ImportExport.jl b/src/ImportExport.jl
index a2058d89..8f60a71f 100644
--- a/src/ImportExport.jl
+++ b/src/ImportExport.jl
@@ -24,13 +24,23 @@ $(EXPORTS)
"""
module ImportExport
+# Export public API
+export export_data
+export read_data
+export save
+export load!
+export get
+export delete!
+
# Load common dependencies
using ..LineCableModels
include("utils/commondeps.jl")
# Module-specific dependencies
using Measurements
-using EzXML, Dates # For PSCAD export
+using EzXML # For PSCAD export
+using Dates # For PSCAD export
+using Printf # For ATP export
using JSON3
using Serialization # For .jls format
using ..Utils
@@ -44,6 +54,6 @@ include("importexport/deserialize.jl")
include("importexport/cableslibrary.jl")
include("importexport/materialslibrary.jl")
include("importexport/pscad.jl")
-
+include("ImportExport/atp.jl")
end # module ImportExport
diff --git a/src/importexport/atp.jl b/src/importexport/atp.jl
new file mode 100644
index 00000000..5d08a0a2
--- /dev/null
+++ b/src/importexport/atp.jl
@@ -0,0 +1,281 @@
+
+"""
+$(TYPEDSIGNATURES)
+
+Exports calculated [`LineParameters`](@ref) to an ATP-style XML file.
+
+This function takes all the system information, cables, ground parameters and frequency and assembles the XML to be used in ATPDraw
+
+# Arguments
+
+- `problem`: A [`LineParametersProblem`](@ref) object used to retrieve the frequency vector for the export.
+- `file_name`: The path to the output XML file (default: "*_export.xml").
+
+# Returns
+
+- The absolute path of the saved file.
+"""
+function export_data(::Val{:atp},
+ cable_system::LineCableSystem,
+ earth_props::EarthModel;
+ base_freq=f₀,
+ file_name::String="$(cable_system.system_id)_export.xml"
+)::Union{String,Nothing}
+
+ function _set_attributes!(element::EzXML.Node, attrs::Dict)
+ for (k, v) in attrs
+ element[k] = string(v)
+ end
+ end
+ # --- 1. Setup Constants and Variables ---
+ file_name = isabspath(file_name) ? file_name : joinpath(@__DIR__, file_name)
+ num_phases = length(cable_system.cables)
+
+ # Create XML Structure and LCC Component
+ doc = XMLDocument()
+ project = ElementNode("project")
+ setroot!(doc, project)
+ _set_attributes!(project, Dict("Application" => "ATPDraw", "Version" => "7.3", "VersionXML" => "1"))
+ header = addelement!(project, "header")
+ _set_attributes!(header, Dict("Timestep" => 1e-6, "Tmax" => 0.1, "XOPT" => 0, "COPT" => 0, "SysFreq" => base_freq, "TopLeftX" => 200, "TopLeftY" => 0))
+ objects = addelement!(project, "objects")
+ variables = addelement!(project, "variables")
+ comp = addelement!(objects, "comp")
+ _set_attributes!(comp, Dict("Name" => "LCC", "Id" => "$(cable_system.system_id)_1", "Capangl" => 90, "CapPosX" => -10, "CapPosY" => -25, "Caption" => ""))
+ comp_content = addelement!(comp, "comp_content")
+ _set_attributes!(comp_content, Dict("PosX" => 280, "PosY" => 360, "NumPhases" => num_phases, "Icon" => "default", "SinglePhaseIcon" => "true"))
+ for side in ["IN", "OUT"]; y0 = -20; for k in 1:num_phases; y0 += 10; node = addelement!(comp_content, "node"); _set_attributes!(node, Dict("Name" => "$side$k", "Value" => "C$(k)$(side=="IN" ? "SND" : "RCV")", "UserNamed" => "true", "Kind" => k, "PosX" => side == "IN" ? -20 : 20, "PosY" => y0, "NamePosX" => 0, "NamePosY" => 0)); end; end
+ soil_rho = earth_props.layers[end].base_rho_g
+ for (name, value) in [("Length", cable_system.line_length), ("Freq", base_freq), ("Grnd resis", soil_rho)]; data_node = addelement!(comp_content, "data"); _set_attributes!(data_node, Dict("Name" => name, "Value" => value)); end
+
+ # Populate the LCC Sub-structure with CORRECTLY Structured Cable Data
+ lcc_node = addelement!(comp, "LCC")
+ _set_attributes!(lcc_node, Dict("NumPhases" => num_phases, "IconLength" => "true", "LineCablePipe" => 2, "ModelType" => 1))
+ cable_header = addelement!(lcc_node, "cable_header")
+ _set_attributes!(cable_header, Dict("InAirGrnd" => 1, "MatrixOutput" => "true", "ExtraCG"=>"$(num_phases)"))
+
+ for (k, cable) in enumerate(cable_system.cables)
+ cable_node = addelement!(cable_header, "cable")
+
+ num_components = length(cable.design_data.components)
+ outermost_radius = cable.design_data.components[end].insulator_group.radius_ext
+
+ _set_attributes!(cable_node, Dict(
+ "NumCond" => num_components,
+ "Rout" => outermost_radius,
+ "PosX" => cable.horz,
+ "PosY" => cable.vert
+ ))
+
+ for component in cable.design_data.components
+ conductor_node = addelement!(cable_node, "conductor")
+
+ cond_group = component.conductor_group
+ ins_group = component.insulator_group
+
+ rho_eq = calc_equivalent_rho(cond_group.resistance, cond_group.radius_ext, cond_group.radius_in)
+ mu_r_cond = calc_equivalent_mu(cond_group.gmr, cond_group.radius_ext, cond_group.radius_in)
+ mu_r_ins = ins_group.layers[1].material_props.mu_r
+ eps_eq = calc_equivalent_eps(ins_group.shunt_capacitance, ins_group.radius_in, ins_group.radius_ext)
+
+ _set_attributes!(conductor_node, Dict(
+ "Rin" => cond_group.radius_in,
+ "Rout" => cond_group.radius_ext,
+ "rho" => rho_eq,
+ "muC" => mu_r_cond,
+ "muI" => mu_r_ins,
+ "epsI" => eps_eq,
+ "Cext" => ins_group.shunt_capacitance,
+ "Gext" => ins_group.shunt_conductance
+ ))
+ end
+ end
+
+ # Finalize and Write to File
+ _set_attributes!(variables, Dict("NumSim" => 1, "IOPCVP" => 0, "UseParser" => "false"))
+
+ try
+ open(file_name, "w") do fid
+ prettyprint(fid, doc)
+ end
+ @info "XML file saved to: $(_display_path(file_name))"
+ return file_name
+ catch e
+ @error "Failed to write XML file '$file_name'" exception=(e, catch_backtrace())
+ return nothing
+ end
+end
+
+
+"""
+ read_atp_data(file_name::String, cable_system::LineCableSystem)
+
+Reads an ATP `.lis` output file, extracts the Ze and Zi matrices, and dynamically
+reorders them to a grouped-by-phase format based on the provided `cable_system`
+structure. It correctly handles systems with a variable number of components per cable.
+
+# Arguments
+- `file_name`: The path to the `.lis` file.
+- `cable_system`: The `LineCableSystem` object corresponding to the data in the file.
+
+# Returns
+- `Array{T, 2}`: A 2D complex matrix representing the total reordered series
+ impedance `Z = Ze + Zi` for a single frequency.
+- `nothing`: If the file cannot be found, parsed, or if the matrix dimensions in the
+ file do not match the provided `cable_system` structure.
+"""
+function read_data(::Val{:atp},
+ cable_system::LineCableSystem,
+ freq::AbstractFloat;
+ file_name::String="$(cable_system.system_id)_1.lis"
+ )::Union{Array{COMPLEXSCALAR, 2}, Nothing}
+ # --- Inner helper function to parse a matrix block from text lines ---
+ function parse_block(block_lines::Vector{String})
+ data_lines = filter(line -> !isempty(strip(line)), block_lines)
+ if isempty(data_lines) return Matrix{ComplexF64}(undef, 0, 0) end
+ matrix_size = length(split(data_lines[1]))
+ real_parts = zeros(Float64, matrix_size, matrix_size)
+ imag_parts = zeros(Float64, matrix_size, matrix_size)
+ row_counter = 1
+ for i in 1:2:length(data_lines)
+ if i + 1 > length(data_lines) break end
+ real_line, imag_line = data_lines[i], data_lines[i+1]
+ try
+ real_parts[row_counter, :] = [parse(Float64, s) for s in split(real_line)[1:matrix_size]]
+ imag_parts[row_counter, :] = [parse(Float64, s) for s in split(imag_line)[1:matrix_size]]
+ catch e; @error "Parsing failed" exception=(e, catch_backtrace()); return nothing end
+ row_counter += 1
+ if row_counter > matrix_size break end
+ end
+ return real_parts + im * imag_parts
+ end
+
+ # --- Main Function Logic ---
+ if !isfile(file_name) @error "File not found: $file_name"; return nothing end
+ lines = readlines(file_name)
+ ze_start_idx = findfirst(occursin.("Earth impedance [Ze]", lines))
+ zi_start_idx = findfirst(occursin.("Conductor internal impedance [Zi]", lines))
+ if isnothing(ze_start_idx) || isnothing(zi_start_idx) @error "Could not find Ze/Zi headers."; return nothing end
+
+ Ze = parse_block(lines[ze_start_idx + 1 : zi_start_idx - 1])
+ Zi = parse_block(lines[zi_start_idx + 1 : end])
+ if isnothing(Ze) || isnothing(Zi) return nothing end
+
+ # --- DYNAMICALLY GENERATE PERMUTATION INDICES (Numerical Method) ---
+ component_counts = [length(c.design_data.components) for c in cable_system.cables]
+ total_conductors = sum(component_counts)
+ num_phases = length(component_counts)
+ max_components = isempty(component_counts) ? 0 : maximum(component_counts)
+
+ if size(Ze, 1) != total_conductors
+ @error "Matrix size from file ($(size(Ze,1))x$(size(Ze,1))) does not match total components in cable_system ($total_conductors)."
+ return nothing
+ end
+
+ num_conductors_per_type = [sum(c >= i for c in component_counts) for i in 1:max_components]
+ type_offsets = cumsum([0; num_conductors_per_type[1:end-1]])
+
+ permutation_indices = Int[]
+ sizehint!(permutation_indices, total_conductors)
+ instance_counters = ones(Int, max_components)
+ for phase_idx in 1:num_phases
+ for comp_type_idx in 1:component_counts[phase_idx]
+ instance = instance_counters[comp_type_idx]
+ original_idx = type_offsets[comp_type_idx] + instance
+ push!(permutation_indices, original_idx)
+ instance_counters[comp_type_idx] += 1
+ end
+ end
+
+ Ze_reordered = Ze[permutation_indices, permutation_indices]
+ Zi_reordered = Zi[permutation_indices, permutation_indices]
+
+ return Ze_reordered+Zi_reordered
+end
+
+
+"""
+$(TYPEDSIGNATURES)
+
+Exports calculated [`LineParameters`](@ref) to an ATP-style XML file.
+
+This function takes the results of a simulation (Z and Y matrices) and writes them
+into a structured XML format for use in other programs.
+
+# Arguments
+
+- `line_params`: A [`LineParameters`](@ref) object containing the calculated Z and Y matrices to be exported.
+- `cable_system`: A [`LineCableSystem`](@ref) object used for metadata (e.g., the default filename).
+- `problem`: A [`LineParametersProblem`](@ref) object used to retrieve the frequency vector for the export.
+- `file_name`: The path to the output XML file (default: "*_export.xml").
+
+# Returns
+
+- The absolute path of the saved file.
+"""
+function export_data(::Val{:atp},
+ line_params::LineParameters,
+ freq::Vector{BASE_FLOAT};
+ file_name::String="ZY_export.xml",
+ cable_system::Union{LineCableSystem,Nothing}=nothing
+ )::Union{String,Nothing}
+ # Construct the file name with system_id if cable_system is provided
+ file_name = isnothing(cable_system) ? file_name : "$(cable_system.system_id)_ZY_export.xml"
+
+ cable_length = 1.0
+ atp_format = "G+Bi"
+ file_name = isabspath(file_name) ? file_name : joinpath(@__DIR__, file_name)
+
+ open(file_name, "w") do fid
+ num_phases = size(line_params.Z, 1)
+ y_fmt = (atp_format == "C") ? "C" : "G+Bi"
+
+ @printf(fid, "\n", num_phases, cable_length, y_fmt)
+
+ # --- Z Matrix Printing ---
+ for (k, freq_val) in enumerate(freq)
+ @printf(fid, " \n", freq_val)
+ for i in 1:num_phases
+ row_str = join([@sprintf("%.16E%+.16Ei", real(line_params.Z[i, j, k]), imag(line_params.Z[i, j, k])) for j in 1:num_phases], ",")
+ println(fid, row_str)
+ end
+ @printf(fid, " \n")
+ end
+
+ # --- Y Matrix Printing ---
+ if atp_format == "C"
+ freq1 = f[1]
+ @printf(fid, " \n", freq1)
+ for i in 1:num_phases
+ row_str = join([@sprintf("%.16E", imag(line_params.Y[i, j, 1]) / (2 * pi * freq1)) for j in 1:num_phases], ",")
+ println(fid, row_str)
+ end
+ @printf(fid, " \n")
+ else # Case for "G+Bi"
+ for (k, freq_val) in enumerate(freq)
+ @printf(fid, " \n", freq_val)
+ for i in 1:num_phases
+ row_str = join([@sprintf("%.16E%+.16Ei", real(line_params.Y[i, j, k]), imag(line_params.Y[i, j, k])) for j in 1:num_phases], ",")
+ println(fid, row_str)
+ end
+ @printf(fid, " \n")
+ end
+ end
+
+ # --- Footer ---
+ println(fid, "")
+ end
+ try
+ # Use pretty print option for debugging comparisons if needed
+ # open(filename, "w") do io; prettyprint(io, doc); end
+ if isfile(file_name)
+ @info "XML file saved to: $(file_name)"
+ end
+ return file_name
+ catch e
+ @error "Failed to write XML file '$(file_name)': $(e)"
+ isa(e, SystemError) && println("SystemError details: ", e.extrainfo)
+ return nothing
+ rethrow(e) # Rethrow to indicate failure clearly
+ end
+end
\ No newline at end of file
diff --git a/test/cable_test.json b/test/cable_test.json
new file mode 100644
index 00000000..0a75ce9a
--- /dev/null
+++ b/test/cable_test.json
@@ -0,0 +1,310 @@
+{
+ "__julia_type__": "LineCableModels.DataModel.CablesLibrary",
+ "data": {
+ "test_cable": {
+ "cable_id": "test_cable",
+ "nominal_data": {
+ "U": 30,
+ "screen_cross_section": 35,
+ "capacitance": 0.39,
+ "__julia_type__": "LineCableModels.DataModel.NominalData",
+ "U0": 18,
+ "conductor_cross_section": 1000,
+ "armor_cross_section": null,
+ "resistance": 0.0291,
+ "inductance": 0.3,
+ "designation_code": "NA2XS(FL)2Y"
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableDesign",
+ "components": [
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 32.3,
+ "mu_r": 1,
+ "rho": 5300
+ },
+ "radius_in": 0.02115,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.02145,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1000,
+ "mu_r": 1,
+ "rho": 1000
+ },
+ "radius_in": 0.02145,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.02205,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.3,
+ "mu_r": 1,
+ "rho": 197000000000000
+ },
+ "radius_in": 0.02205,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.03005,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1000,
+ "mu_r": 1,
+ "rho": 500
+ },
+ "radius_in": 0.03005,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.030350000000000002,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 32.3,
+ "mu_r": 1,
+ "rho": 5300
+ },
+ "radius_in": 0.030350000000000002,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.030650000000000004,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "core",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "lay_ratio": 0,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00235,
+ "num_wires": 1,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 15,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.00235,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00235,
+ "num_wires": 6,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 13.5,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.007050000000000001,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00235,
+ "num_wires": 12,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 12.5,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.01175,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00235,
+ "num_wires": 18,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 11,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.01645,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.00235,
+ "num_wires": 24,
+ "temperature": 20
+ }
+ ]
+ }
+ },
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 32.3,
+ "mu_r": 1,
+ "rho": 5300
+ },
+ "radius_in": 0.031700000000000006,
+ "__julia_type__": "LineCableModels.DataModel.Semicon",
+ "radius_ext": 0.03200000000000001,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "sheath",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "lay_ratio": 10,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.030650000000000004,
+ "__julia_type__": "LineCableModels.DataModel.WireArray",
+ "radius_wire": 0.000475,
+ "num_wires": 49,
+ "temperature": 20
+ },
+ {
+ "lay_ratio": 10,
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00393,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 0.999994,
+ "rho": 1.7241e-8
+ },
+ "lay_direction": 1,
+ "radius_in": 0.0316,
+ "__julia_type__": "LineCableModels.DataModel.Strip",
+ "width": 0.01,
+ "radius_ext": 0.031700000000000006,
+ "temperature": 20
+ }
+ ]
+ }
+ },
+ {
+ "insulator_group": {
+ "__julia_type__": "LineCableModels.DataModel.InsulatorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.3,
+ "mu_r": 1,
+ "rho": 197000000000000
+ },
+ "radius_in": 0.032150000000000005,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.032200000000000006,
+ "temperature": 20
+ },
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 2.3,
+ "mu_r": 1,
+ "rho": 197000000000000
+ },
+ "radius_in": 0.032200000000000006,
+ "__julia_type__": "LineCableModels.DataModel.Insulator",
+ "radius_ext": 0.034600000000000006,
+ "temperature": 20
+ }
+ ]
+ },
+ "__julia_type__": "LineCableModels.DataModel.CableComponent",
+ "id": "jacket",
+ "conductor_group": {
+ "__julia_type__": "LineCableModels.DataModel.ConductorGroup",
+ "layers": [
+ {
+ "material_props": {
+ "T0": 20,
+ "alpha": 0.00429,
+ "__julia_type__": "LineCableModels.Materials.Material",
+ "eps_r": 1,
+ "mu_r": 1.000022,
+ "rho": 2.8264e-8
+ },
+ "radius_in": 0.03200000000000001,
+ "__julia_type__": "LineCableModels.DataModel.Tubular",
+ "radius_ext": 0.032150000000000005,
+ "temperature": 20
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/export_xml.jl b/test/export_xml.jl
new file mode 100644
index 00000000..772c4091
--- /dev/null
+++ b/test/export_xml.jl
@@ -0,0 +1,165 @@
+# test/test_atp_export.jl
+
+using Test
+using TestItemRunner
+using LineCableModels
+
+# Add your setup snippets here if they are in this file
+# @testsnippet defaults begin ... end
+# @testsnippet cable_system_export begin ... end
+
+@testsnippet deps_export_atp begin
+ using EzXML
+end
+
+@testitem "Export to ATPDraw LCC format" setup=[defaults, cable_system_export, deps_export_atp] begin
+
+ # All variables from the setup snippets are available here (problem_atp, cable_system, etc.)
+
+ # 1. ARRANGE & ACT: Run the export in a temporary directory
+ mktempdir() do tmpdir
+ output_file = joinpath(tmpdir, "atp_export_test.xml")
+ result_path = export_data(Val(:atp), cable_system, earth_props, file_name=output_file)
+
+ # 2. ASSERT: Basic file checks (unchanged)
+ @test result_path == output_file
+ @test isfile(output_file)
+ @test filesize(output_file) > 500
+
+ # 3. ASSERT: General XML structure and LCC data
+ println(" Performing high-level XML structure checks...")
+ doc = readxml(output_file)
+ root_node = root(doc)
+
+ @test nodename(root_node) == "project"
+ @test root_node["Application"] == "ATPDraw"
+
+ # Find the main LCC component content node
+ comp_content_node = findfirst("/project/objects/comp/comp_content", root_node)
+ @test !isnothing(comp_content_node)
+
+ # Verify general parameters like Length, Freq, and Ground Resistivity
+ println(" Verifying general LCC data (Length, Freq, Grnd resis)...")
+ @test parse(Float64, findfirst("data[@Name='Length']", comp_content_node)["Value"]) ≈ cable_system.line_length
+ @test parse(Float64, findfirst("data[@Name='Freq']", comp_content_node)["Value"]) ≈ problem_atp.frequencies[1]
+ @test parse(Float64, findfirst("data[@Name='Grnd resis']", comp_content_node)["Value"]) ≈ problem_atp.earth_props.layers[end].base_rho_g
+
+ # 4. ASSERT: Detailed validation of ALL cables and conductors
+ println(" Verifying all cables and their conductors...")
+ lcc_node = findfirst("/project/objects/comp/LCC", root_node)
+ cable_header = findfirst("cable_header", lcc_node)
+ cable_nodes = findall("cable", cable_header)
+
+ @test length(cable_nodes) == num_phases
+
+ # Loop through each cable exported in the XML and compare it to the source
+ for (i, cable_node) in enumerate(cable_nodes)
+ println(" -> Checking Cable #$i...")
+ source_cable = cable_system.cables[i]
+
+ # Verify position of EACH cable
+ @test parse(Float64, cable_node["PosX"]) ≈ source_cable.horz
+ @test parse(Float64, cable_node["PosY"]) ≈ source_cable.vert
+
+ # Verify the number of conductor components inside this cable
+ num_components = length(source_cable.design_data.components)
+ @test parse(Int, cable_node["NumCond"]) == num_components
+
+ conductor_nodes = findall("conductor", cable_node)
+ @test length(conductor_nodes) == num_components
+
+ # Loop through each conductor component within the cable
+ for (j, conductor_node) in enumerate(conductor_nodes)
+ source_component = source_cable.design_data.components[j]
+ cond_group = source_component.conductor_group
+ ins_group = source_component.insulator_group
+
+ # Pre-calculate the expected values using the same functions as the export
+ expected_rho = calc_equivalent_rho(cond_group.resistance, cond_group.radius_ext, cond_group.radius_in)
+ expected_muC = calc_equivalent_mu(cond_group.gmr, cond_group.radius_ext, cond_group.radius_in)
+ expected_epsI = calc_equivalent_eps(ins_group.shunt_capacitance, ins_group.radius_in, ins_group.radius_ext)
+
+ # Assert that every attribute matches the expected value
+ @test parse(Float64, conductor_node["Rin"]) ≈ cond_group.radius_in
+ @test parse(Float64, conductor_node["Rout"]) ≈ cond_group.radius_ext
+ @test parse(Float64, conductor_node["rho"]) ≈ expected_rho
+ @test parse(Float64, conductor_node["muC"]) ≈ expected_muC
+ @test parse(Float64, conductor_node["muI"]) ≈ ins_group.layers[1].material_props.mu_r
+ @test parse(Float64, conductor_node["epsI"]) ≈ expected_epsI
+ @test parse(Float64, conductor_node["Cext"]) ≈ ins_group.shunt_capacitance
+ @test parse(Float64, conductor_node["Gext"]) ≈ ins_group.shunt_conductance
+ end
+ end
+ println(" All detailed checks passed!")
+ end
+end
+
+# Run the test
+# @run_package_tests filter = ti -> occursin("Export to ATPDraw LCC format", ti.name)
+
+
+@testitem "Export to ATP format" setup=[defaults, cable_system_export, deps_export_atp] begin
+
+ # The ACT and ASSERT parts of your test go here.
+ # All variables from the snippets are already defined.
+
+ # 1. RUN THE TEST IN A TEMPORARY DIRECTORY
+ mktempdir() do tmpdir
+ output_file = joinpath(tmpdir, "atp_export_test.xml")
+ println(" Exporting ATP XML file to: ", output_file)
+ Z_matrix = randn(ComplexF64, num_phases, num_phases, length(freqs))
+ Y_matrix = randn(ComplexF64, num_phases, num_phases, length(freqs))
+ line_params = LineParameters(Z_matrix, Y_matrix)
+
+ # Call the function we want to test
+ result_path = export_data(Val(:atp), line_params, freqs; file_name=output_file)
+
+ # 2. BASIC FILE CHECKS
+ @test result_path == output_file
+ @test isfile(output_file)
+ @test filesize(output_file) > 100
+
+ xml_content = read(output_file, String)
+ @test occursin("", xml_content)
+
+ # 3. XML STRUCTURE AND DATA VALIDATION
+ println(" Performing XML structure checks via XPath...")
+ xml_doc = readxml(output_file)
+ root_node = root(xml_doc)
+
+ @test nodename(root_node) == "ZY"
+ @test parse(Int, root_node["NumPhases"]) == num_phases
+
+ z_blocks = findall("//Z", root_node)
+ @test length(z_blocks) == length(freqs)
+
+ # 4. DETAILED DATA VERIFICATION (for the first frequency)
+ println(" Verifying numerical data for first frequency...")
+ first_z_block = z_blocks[1]
+ @test parse(Float64, first_z_block["Freq"]) ≈ freqs[1]
+
+ z_matrix_rows = split(strip(nodecontent(first_z_block)), '\n')
+ @test length(z_matrix_rows) == num_phases
+
+ first_row_elements = split(z_matrix_rows[1], ',')
+ @test length(first_row_elements) == num_phases
+ number_pattern = r"(-?[\d\.]+E[+-]\d+)"
+ complex_pattern = Regex("$(number_pattern.pattern)([+-][\\d\\.]+E[+-]\\d+)i")
+
+ match_result = match(complex_pattern, first_row_elements[1])
+
+ if !isnothing(match_result)
+ # The captures are now guaranteed to be valid Float64 strings
+ real_part = parse(Float64, match_result.captures[1])
+ imag_part = parse(Float64, match_result.captures[2])
+ parsed_z11 = complex(real_part, imag_part)
+
+ expected_z11 = Z_matrix[1, 1, 1]
+ @test parsed_z11 ≈ expected_z11 rtol=1e-12
+ end
+ end
+end
+
+
+@run_package_tests filter = ti -> occursin("Export to ATP format", ti.name)
\ No newline at end of file
diff --git a/test/runtests.jl b/test/runtests.jl
index c09ffefd..388868af 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -17,4 +17,39 @@ end
semicon_props = Material(1000.0, 1000.0, 1.0, 20.0, 0.0)
end
-@run_package_tests verbose = true
\ No newline at end of file
+@testsnippet cable_system_export begin
+
+ cables_library = CablesLibrary()
+ cables_library = load!(cables_library, file_name=joinpath(@__DIR__, "./cable_test.json"))
+
+ # Retrieve the reloaded design
+ cable_design = collect(values(cables_library.data))[1]
+ x0, y0 = 0.0, -1.0
+ xa, ya, xb, yb, xc, yc = trifoil_formation(x0, y0, 0.035);
+
+ # Initialize the `LineCableSystem` with the first cable (phase A):
+ cablepos = CablePosition(cable_design, xa, ya,
+ Dict("core" => 1, "sheath" => 0, "jacket" => 0))
+ cable_system = LineCableSystem("test_cable_sys", 1000.0, cablepos)
+
+ # Add remaining cables (phases B and C):
+ add!(cable_system, cable_design, xb, yb,
+ Dict("core" => 2, "sheath" => 0, "jacket" => 0))
+ add!(cable_system, cable_design, xc, yc,
+ Dict("core" => 3, "sheath" => 0, "jacket" => 0))
+
+ freqs = sort(abs.(randn(3)))
+ earth_params_atp = EarthModel(freqs, 100.0, 10.0, 1.0)
+ num_phases = cable_system.num_phases
+
+ # Create minimal mock objects for the other required arguments
+ problem_atp = LineParametersProblem(
+ cable_system,
+ temperature=20.0, # Operating temperature
+ earth_props=earth_params_atp,
+ frequencies=freqs, # Frequency for the analysis
+ );
+
+end
+
+@run_package_tests verbose = true