diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a0f960c7..260d015bc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] ### Added - +- Introduce data model for cable types [#1669](https://github.com/ie3-institute/PowerSystemDataModel/issues/1669) ### Fixed - Fixed issues regarding determination of additional parameters [#1661](https://github.com/ie3-institute/PowerSystemDataModel/issues/1661) diff --git a/build.gradle b/build.gradle index 853681a810..a17c3c7ef2 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ repositories { dependencies { // ie³ power system utils - implementation 'com.github.ie3-institute:PowerSystemUtils:3.2.1' + implementation 'com.github.ie3-institute:PowerSystemUtils:3.2.2' implementation 'tech.units:indriya:2.2.4' @@ -65,6 +65,10 @@ dependencies { implementation 'org.locationtech.jts.io:jts-io-common:1.20.0' + // parsing json + implementation 'com.fasterxml.jackson.core:jackson-databind:2.22.0' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.2' + // Graphs implementation 'org.jgrapht:jgrapht-core:1.5.3' diff --git a/docs/readthedocs/_static/bibliography/bibtex.bib b/docs/readthedocs/_static/bibliography/bibtex.bib new file mode 100644 index 0000000000..6c59cd4caa --- /dev/null +++ b/docs/readthedocs/_static/bibliography/bibtex.bib @@ -0,0 +1,59 @@ + @book{luecking_1981, address={Wiesbaden}, edition={1st ed. 1981}, title={Energiekabeltechnik}, ISBN={9783322843128}, DOI={10.1007/978-3-322-84312-8}, publisher={Imprint: Vieweg+Teubner Verlag}, author={Lücking, H. Wilhelm}, year={1981} } +@misc{wiki:thermal_conductivity_resistivity, + author = {{Wikipedia contributors}}, + title = {Thermal conductivity and resistivity --- {Wikipedia}{,} The Free Encyclopedia}, + year = {2026}, + url = {https://en.wikipedia.org/wiki/Thermal_conductivity_and_resistivity}, + note = {[Online; accessed 3 June 2026]} +} +@misc{wiki:Copper, + author = {{Wikipedia contributors}}, + title = {Copper --- {Wikipedia}{,} The Free Encyclopedia}, + year = {2026}, + url = {https://en.wikipedia.org/wiki/Copper}, + note = {[Online; accessed 3 June 2026]} +} +@misc{wiki:Aluminium, + author = {{Wikipedia contributors}}, + title = {Aluminium --- {Wikipedia}{,} The Free Encyclopedia}, + year = {2026}, + url = {https://en.wikipedia.org/wiki/Aluminium}, + note = {[Online; accessed 3 June 2026]} +} +@misc{wiki:specific_heat_capacities, + author = {{Wikipedia contributors}}, + title = {Table of specific heat capacities --- {Wikipedia}{,} The Free Encyclopedia}, + year = {2026}, + url = {https://en.wikipedia.org/wiki/Table_of_specific_heat_capacities}, + note = {[Online; accessed 3 June 2026]} +} +@misc{wiki:thermal_conductivities, + author = {{Wikipedia contributors}}, + title = {List of thermal conductivities --- {Wikipedia}{,} The Free Encyclopedia}, + year = {2026}, + url = {https://en.wikipedia.org/wiki/List_of_thermal_conductivities}, + note = {[Online; accessed 3 June 2026]} +} + +@book{andersRatingElectricPower1997, + title = {Rating of Electric Power Cables: Ampacity Computations for Transmission, Distribution, and Industrial Applications}, + shorttitle = {Rating of Electric Power Cables}, + author = {Anders, George J.}, + year = 1997, + series = {{{IEEE Press}} Power Engineering Series}, + publisher = {McGraw-Hill [u.a.]}, + address = {New York, NY}, + isbn = {978-0-07-001791-7 978-0-7803-1177-0}, + langid = {english}, + file = {C:\Users\smdafeis\Zotero\storage\9DR3K43F\Anders - 1997 - Rating of electric power cables ampacity computations for transmission, distribution, and industria.pdf} +} +@techreport{CIGRE_TB880_2022, + author = {{CIGR\'{E} Working Group B1.56}}, + title = {Power cable rating examples for calculation tool verification}, + institution = {{Conseil International des Grands R\'{e}seaux \'{E}lectriques (CIGR\'{E})}}, + type = {Technical Brochure}, + number = {880}, + address = {Paris, France}, + year = {2022}, + isbn = {978-2-85873-585-3} +} \ No newline at end of file diff --git a/docs/readthedocs/conf.py b/docs/readthedocs/conf.py index 4616a14847..3af2d07db9 100644 --- a/docs/readthedocs/conf.py +++ b/docs/readthedocs/conf.py @@ -36,9 +36,13 @@ # ones. extensions = [ 'sphinx.ext.intersphinx', - 'myst_parser' + 'myst_parser', + 'sphinxcontrib.bibtex' ] +bibtex_bibfiles = ["_static/bibliography/bibtex.bib"] +bibtex_default_style = 'plain' + myst_enable_extensions = ["dollarmath", "amsmath"] myst_heading_anchors = 4 diff --git a/docs/readthedocs/index.md b/docs/readthedocs/index.md index f73b866a1f..b8e4020a3e 100644 --- a/docs/readthedocs/index.md +++ b/docs/readthedocs/index.md @@ -12,6 +12,7 @@ Effective handling of geographic information related to power grids is also poss gettingstarted models/models io/basiciousage +references ``` ## Contact the (Main) Maintainers diff --git a/docs/readthedocs/models/input/grid/cableMaterial.md b/docs/readthedocs/models/input/grid/cableMaterial.md new file mode 100644 index 0000000000..15efc5aeee --- /dev/null +++ b/docs/readthedocs/models/input/grid/cableMaterial.md @@ -0,0 +1,126 @@ +(cable-material)= +# Cable Material + +## Overview + +The `CableMaterial` enum represents various materials used in electrical cable construction, providing their default thermal and electrical properties. This is primarily used for physical modeling and simulation of distribution grids, allowing for accurate calculations of thermal states, ampacity, and electrical losses. + +## Properties + +### Thermal Properties + +Retrieved via `getThermalProperties()`. Returns a `ThermalProperties` container providing **Thermal Resistivity** ($K \cdot m/W$) and **Thermal Capacitance** ($J / (m^3 \cdot K)$). + +```{list-table} + :widths: auto + :class: wrapping + :header-rows: 1 + + * - Material + - Thermal Resistivity [] + - Thermal Capacitance [1/K] + - source + - Notes + + * - `Copper` + - 1/384 + - 3,449,600.0 + - {cite:cts}`wiki:thermal_conductivity_resistivity`, {cite:cts}`wiki:Copper` + - c = 385 J/(kg * K), rho= 8.96 g/cm³ => 3449600 J / (m³ * K) + + * - `Aluminium` + - 1/237 + - 2,420,913.3 + - {cite:cts}`wiki:thermal_conductivity_resistivity`, {cite:cts}`wiki:Aluminium` + - c = 897 J/(kg * K), rho= 2.6989 g/cm³ => 2420913.3 J / (m³ * K) + + * - `XLPE (Cross-linked polyethylene)` + - 3.5 + - 2.4 + - {cite:cts}`andersRatingElectricPower1997` p. 400 + - - + + * - `PE (Polyethylene)` + - 3.5 + - 2.4 + - {cite:cts}`andersRatingElectricPower1997` p. 400 + - - + + * - `PVC (Polyvinyl chloride)` + - 3.5 + - 1.7 + - {cite:cts}`andersRatingElectricPower1997` p. 400 + - - + + * - `Semi-Conductive Screen` + - 2.5 + - 2.4 + - Th. Res.: {cite:cts}`CIGRE_TB880_2022` p. 28; Th. Capa.: Same as adjacent dielectric material see {cite:cts}`andersRatingElectricPower1997` p. 400 + - - + + * - `SC-Tape (Screen Tape)` + - 6.0 + - 2.4 + - Th. Res.: {cite:cts}`CIGRE_TB880_2022` p. 28; Th. Capa.: Same as adjacent dielectric material see {cite:cts}`andersRatingElectricPower1997` p. 400 + - - + + * - `Lead` + - 1/35 + - 1,463,892.0 + - Th. Res.: {cite:cts}`wiki:thermal_conductivities`; Th. Capa.: {cite:cts}`wiki:specific_heat_capacities` + - c = 129 J/(kg * K), rho= 11.348 g/cm³ => 1,463,892.0 J / (m³ * K) + + * - `Steel` + - 1/45 + - 3,756,000.0 + - Th. Res.:{cite:cts}`wiki:thermal_conductivity_resistivity`; Th. Capa.: {cite:cts}`wiki:specific_heat_capacities` + - - + + * - `Polypropylen` + - 6.0 + - 2.0 + - Th. Res.: {cite:cts}`CIGRE_TB880_2022` p. 28; Th. Capa.: Asumed to be clos to Paper-polypropylene-paper (PPL) in {cite:cts}`andersRatingElectricPower1997` p. 400 + - - +``` + +**Note:** Metals inherently define their thermal resistivity as the inverse of their thermal conductivity $\lambda$ (e.g., $\lambda_{Copper} = 384 \, W/(m \cdot K)$). + +### Electrical Properties + +Electrical parameters define the conductive aspects of the materials, heavily utilized for power flow and loss calculations. + +* **Electrical Resistivity:** Retrieved via `getElectricalResistivity()` (at standard reference temperature). +* **Temperature Coefficient:** Retrieved via `getElectricalResistivityTemperatureCoefficient()`. + +```{list-table} + :widths: auto + :class: wrapping + :header-rows: 1 + + * - Material + - Electrical Resistivity [] + - Temp. Coefficient [1/K] + - source + + * - `Copper` + - $1.7241 \times 10^{-8}$ + - $3.93 \times 10^{-3}$ + - {cite:cts}`luecking_1981` p. 94 + + * - `Aluminium` + - $2.8264 \times 10^{-8}$ + - $4.03 \times 10^[-3}$ + - {cite:cts}`luecking_1981` p. 94 + + * - `Lead` + - $21.4 \times 10^{-8}$ + - $4.0 \times 10^[-3}$ + - {cite:cts}`luecking_1981` p. 94 + + * - `Steel` + - $13.8 \times 10^{-8}$ + - $4.5 \times 10^[-3}$ + - {cite:cts}`luecking_1981` p. 94 +``` + +Calling these methods on non-conductive insulation materials will throw an `IllegalArgumentException`. \ No newline at end of file diff --git a/docs/readthedocs/models/input/grid/cableType.md b/docs/readthedocs/models/input/grid/cableType.md new file mode 100644 index 0000000000..166e529609 --- /dev/null +++ b/docs/readthedocs/models/input/grid/cableType.md @@ -0,0 +1,199 @@ +# Cable Type + +Representation of a cable type. + +## Attributes, Units and Remarks + +### Type Model + +Type model of a cable. + +```{list-table} + :widths: auto + :class: wrapping + :header-rows: 1 + + * - Attribute + - Unit + - Remarks + + * - uuid + - – + - Identifier + + * - id + - – + - Human readable identifier + + * - core number + - – + - Number of conductor cores in the cable + + * - conductor + - ConductorInput + - Layer model that represents the attributes and geometry of the conductor. + + * - isolation + - List of LayerInput + - List of insulation layers (from inner to outer) + + * - screenLayer + - Optional ScreenLayer + - Optional cable screen layer + + * - filler + - List of LayerInput + - List of filler layers (from inner to outer) + + * - armor + - List of LayerInput + - List of armor layers (from inner to outer) + + * - jack + - List of LayerInput + - List of outer sheath or jack layers (from inner to outer) + + * - limit temperature + - °C + - Maximum permissible operating temperature + + * - frequency + - Hz + - Rated frequency of the system + + * - skin effect coefficient + - - + - Skin effect coefficient + + * - proximity effect coefficient + - + - Proximity effect coefficient + + * - electrical capacitance + - F/m + - Capacitance per unit length + + * - Dielectric loss factor tanDelta + - - + - Dielectric loss factor tan(δ) + + * - circulatingLossFactor + - - + - Circulating loss factor + + * - eddyCurrentLossFactor + - - + - Eddy current loss factor +``` + +A list with some standard line types can be found here: [Standard Cable Type Parameter](#standard-cable-type-parameter) + +### Cable Layers + +Cables are modeled as a series of concentric layers. These layers—which include insulation, filler, armor, and outer sheaths—are defined using the LayerInput class. Each layer tracks its physical dimensions and thermal properties to support precise electrical and thermal simulations. + +#### LayerInput Attributes + +The following table details the attributes required to define a single cable + +```{list-table} + :widths: auto + :class: wrapping + :header-rows: 1 + +* - Layer Attribute + - Type + - Description + +* - name + - String + - Designation of the layer (e.g., "Main insulation") + +* - material + - CableMaterial + - Material of the layer + +* - innerDiameter + - Length + - Inner diameter of the layer + +* - outerDiameter + - Length + - Outer diameter of the layer + +* - thermalResistivity + - (K·m/W) + - Thermal resistivity of the material + +* - thermalCapacitance + - J/(m³·K) + - Thermal capacitance of the material + +* - area + - Optional Area + - Real cross-sectional area. If none, area will be calculated from geometry. +``` + +Different cable materials and their thermal and electrical parameter are also given as described in [cableMaterial](#cable-material) + +## Standard Cable Type Parameter + +Following there are some standard line types with their source. To retrieve the data call the method `TypeSource.getStandardLineTypes()`. +A ``csv file`` containing the types listed below can be found [here](https://github.com/ie3-institute/PowerSystemDataModel/tree/dev/input/StandardAssetTypes). +This file can be used directly for any simulation with ``simona``. + +### Cables + +Some standard cables type parameter and geometries. + +```{list-table} + :widths: auto + :class: wrapping + :header-rows: 1 + + +* - uuid + - id + - core_number + - conductor + - isolation + - screen + - filler + - armor + - jack + - limit_temperature + - frequency + - skin_effect_coefficient + - proximity_effect_coefficient + - electrical_capacitance + - tan_delta + - circulating_loss_factor + - eddy_current_loss_factor + - source + +* - b8152c3f-d12f-4857-9746-a30aef6aee08 + - CigreT880_33kVLandCable + - 1 + - "{""name"":""conductor"",""material"":""COPPER"",""crossSection"":""240.0"",""diameter"":""18.4"",""thermalResistivity"":""0.0026"",""thermalCapacitance"":""3.4e6"",""area"":""240.0"",""isCompacted"":false}" + - "[{""name"":""conductorScreen"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""18.4"",""outerDiameter"":""19.4"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null},{""name"":""insulation"",""material"":""XLPE"",""innerDiameter"":""19.4"",""outerDiameter"":""34.8"",""thermalResistivity"":""3.5"",""thermalCapacitance"":""2.4e6"",""area"":null},{""name"":""insulationScreen"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""34.8"",""outerDiameter"":""35.8"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null},{""name"":""screenTape"",""material"":""SC_TAPE"",""innerDiameter"":""35.8"",""outerDiameter"":""36.8"",""thermalResistivity"":""0.01"",""thermalCapacitance"":""3.0e6"",""area"":null}]", + - "{""name"":""screen"",""material"":""COPPER"",""innerDiameter"":""36.8"",""outerDiameter"":""38.6"",""thermalResistivity"":""0.0026"",""thermalCapacitance"":""3.4e6"",""area"":""35.62566"",""wiresNumber"":56,""wireDiameter"":""0.9"",""electricalResistivity"":""1.7241e-8""}" + - - + - - + - "[{""name"":""jackTape"",""material"":""SC_TAPE"",""innerDiameter"":""38.6"",""outerDiameter"":""39.2"",""thermalResistivity"":""0.01"",""thermalCapacitance"":""3.0e6"",""area"":null},{""name"":""jack"",""material"":""XLPE"",""innerDiameter"":""39.2"",""outerDiameter"":""43.6"",""thermalResistivity"":""3.5"",""thermalCapacitance"":""2.4e6"",""area"":null},{""name"":""outerCover"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""43.6"",""outerDiameter"":""44.0"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null}]" + - 90.0 + - 50.0 + - 1.0 + - 1.0 + - 0.000000000237683304 + - 0.004 + - 0.0435122656 + - 0.0 + - CIGRE TB880 B1.56 Power cable rating examples for calculation tool verification + +``` + + +## Caveats + +Nothing - at least not known. +If you found something, please contact us! diff --git a/docs/readthedocs/models/models.md b/docs/readthedocs/models/models.md index 43769a4c76..28d36621cd 100644 --- a/docs/readthedocs/models/models.md +++ b/docs/readthedocs/models/models.md @@ -124,6 +124,8 @@ input/grid/transformer2w input/grid/transformer3w input/grid/measurementunit input/grid/gridcontainer +input/grid/cableMaterial +input/grid/cableType ``` #### Thermal Grid diff --git a/docs/readthedocs/references.md b/docs/readthedocs/references.md new file mode 100644 index 0000000000..79d778b13c --- /dev/null +++ b/docs/readthedocs/references.md @@ -0,0 +1,8 @@ +# References + +References of publications PSDM referred on: + +```{bibliography} _static/bibliography/bibtex.bib +:style: plain +:all: +``` diff --git a/docs/readthedocs/requirements.txt b/docs/readthedocs/requirements.txt index dc3b1d65ac..ccc69d87b0 100644 --- a/docs/readthedocs/requirements.txt +++ b/docs/readthedocs/requirements.txt @@ -4,3 +4,4 @@ Sphinx==9.1.0 sphinx-rtd-theme==3.1.0 myst-parser==5.1.0 markdown-it-py==4.2.0 +sphinxcontrib-bibtex==2.7.0 diff --git a/input/StandardAssetTypes/cable_type_input.csv b/input/StandardAssetTypes/cable_type_input.csv new file mode 100644 index 0000000000..e19a3c2afe --- /dev/null +++ b/input/StandardAssetTypes/cable_type_input.csv @@ -0,0 +1,2 @@ +uuid,id,core_number,conductor,isolation,screen,filler,armor,jack,limit_temperature,frequency,skin_effect_coefficient,proximity_effect_coefficient,electrical_capacitance,tan_delta,circulating_loss_factor,eddy_current_loss_factor +b8152c3f-d12f-4857-9746-a30aef6aee08,CigreT880_33kVLandCable,1,"{""name"":""conductor"",""material"":""COPPER"",""crossSection"":""240.0"",""diameter"":""18.4"",""thermalResistivity"":""0.0026"",""thermalCapacitance"":""3.4e6"",""area"":""240.0"",""isCompacted"":false}","[{""name"":""conductorScreen"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""18.4"",""outerDiameter"":""19.4"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null},{""name"":""insulation"",""material"":""XLPE"",""innerDiameter"":""19.4"",""outerDiameter"":""34.8"",""thermalResistivity"":""3.5"",""thermalCapacitance"":""2.4e6"",""area"":null},{""name"":""insulationScreen"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""34.8"",""outerDiameter"":""35.8"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null},{""name"":""screenTape"",""material"":""SC_TAPE"",""innerDiameter"":""35.8"",""outerDiameter"":""36.8"",""thermalResistivity"":""0.01"",""thermalCapacitance"":""3.0e6"",""area"":null}]","{""name"":""screen"",""material"":""COPPER"",""innerDiameter"":""36.8"",""outerDiameter"":""38.6"",""thermalResistivity"":""0.0026"",""thermalCapacitance"":""3.4e6"",""area"":""35.62566"",""wiresNumber"":56,""wireDiameter"":""0.9"",""electricalResistivity"":""1.7241e-8""}",,,"[{""name"":""jackTape"",""material"":""SC_TAPE"",""innerDiameter"":""38.6"",""outerDiameter"":""39.2"",""thermalResistivity"":""0.01"",""thermalCapacitance"":""3.0e6"",""area"":null},{""name"":""jack"",""material"":""XLPE"",""innerDiameter"":""39.2"",""outerDiameter"":""43.6"",""thermalResistivity"":""3.5"",""thermalCapacitance"":""2.4e6"",""area"":null},{""name"":""outerCover"",""material"":""SEMI_COND_SCREEN"",""innerDiameter"":""43.6"",""outerDiameter"":""44.0"",""thermalResistivity"":""4.0"",""thermalCapacitance"":""2.0e6"",""area"":null}]",90.0,50.0,1.0,1.0,0.000000000237683304,0.004,0.0435122656,0.0 \ No newline at end of file diff --git a/input/StandardAssetTypes/line_type_input.csv b/input/StandardAssetTypes/line_type_input.csv index 3ef2d756b8..7f2592b4a4 100644 --- a/input/StandardAssetTypes/line_type_input.csv +++ b/input/StandardAssetTypes/line_type_input.csv @@ -1,34 +1,34 @@ -uuid,b,g,i_max,id,r,v_rated,x -91617ab8-3de2-4fba-be45-a54473ba09a9,3.61283,0.0,1300.0,LineType_1,0.08,380.0,0.32 -b3b231ae-a971-4432-80d7-4ce2f2a56a32,3.22799,0.0,1950.0,LineType_4,0.033333,380.0,0.333333 -24595f91-8295-41f8-a3d8-c9418d860d9c,1.076,0.0,650.0,LineType_6,0.1,380.0,1.0 -f0fc57ec-aa5a-4484-b870-be70a5428cbd,6.45597,0.0,3900.0,LineType_9,0.016667,380.0,0.166667 -ba70d8e7-b082-49bc-8c45-3c10e1236c3e,8.60796,0.0,5200.0,LineType_10,0.0125,380.0,0.125 -eee8eeed-62c9-4345-aa5a-3743fe32007d,12.9119,0.0,7800.0,LineType_11,0.008333,380.0,0.083333 -d2b16935-dcd7-44d2-8623-cec4c703ccdc,17.2159,0.0,10400.0,LineType_12,0.00625,380.0,0.0625 -a490c96e-6e90-485a-b0d7-adeb81fa09cd,4.30398,0.0,2600.0,LineType_2,0.025,220.0,0.25 -5272bcbc-7d0e-4759-85fa-27943fd8d19c,2.15199,0.0,1300.0,LineType_3,0.05,220.0,0.5 -dd0bac07-de8d-4608-af36-b8ff2819f55a,7.22566,0.0,2600.0,LineType_5,0.04,220.0,0.16 -64c1dcb5-57a5-4f35-b2bf-9ae4e6cc4943,1.80642,0.0,650.0,LineType_7,0.16,220.0,0.64 -bdc83a85-c796-4bcb-8b79-8988dc2804f8,5.41925,0.0,1950.0,LineType_8,0.053333,220.0,0.213333 -3d75fb6b-f0be-4451-ab4c-7f00c0ebd619,2.8274,0.0,680.0,Al/St_265/35,0.1095,110.0,0.296 -f5dcaf44-7a9a-4b85-89ba-5c15c04c5766,3.45575,0.0,105.0,15-AL1/3-ST1A 20.0,1.8769,20.0,0.409 -9cbf484b-7256-4e7a-9c35-3e1049909aa0,3.53429,0.0,140.0,24-AL1/4-ST1A 20.0,1.2012,20.0,0.394 -5b542a50-b0c2-4497-ba90-b2b31aafaa0b,2.87456,0.0,170.0,34-AL1/6-ST1A 20.0,0.8342,20.0,0.382 -d594cd67-4459-44bc-9594-db710372db71,2.98451,0.0,210.0,48-AL1/8-ST1A 20.0,0.5939,20.0,0.372 -305e60ad-cfd2-4127-9d83-8d9b21942d93,3.04734,0.0,290.0,70-AL1/11-ST1A 20.0,0.4132,20.0,0.36 -cc59abd4-770b-45d2-98c8-919c91f1ca4b,58.7478,0.0,652.0,1x630_RM/50,0.122,110.0,0.122522 -82ea1b98-2b21-48bd-841a-8d17d8ac20c9,59.3761,0.0,158.0,NA2XS2Y 1x50 RM/25 12/20 kV,0.64,20.0,0.145 -4adef9e6-5e40-416d-8bd2-b6768d156c54,59.6903,0.0,220.0,NA2XS2Y 1x70 RM/25 12/20 kV,0.443,20.0,0.132 -d5c03484-59c2-44d5-a2ee-63a5a0d623b4,67.8584,0.0,252.0,NA2XS2Y 1x95 RM/25 12/20 kV,0.313,20.0,0.132 -9c13909d-1dd1-4e2d-980b-55345bdf0fd0,72.2566,0.0,283.0,NA2XS2Y 1x120 RM/25 12/20 kV,0.253,20.0,0.119 -36243493-eb31-4e81-bd13-b54ef59c4cbe,78.5398,0.0,319.0,NA2XS2Y 1x150 RM/25 12/20 kV,0.206,20.0,0.116 -437689f8-366d-4b04-b42d-d7a754db074b,85.7655,0.0,362.0,NA2XS2Y 1x185 RM/25 12/20 kV,0.161,20.0,0.117 -b459115d-d4eb-47d4-b7ec-625339ee0dcc,95.5044,0.0,421.0,NA2XS2Y 1x240 RM/25 12/20 kV,0.122,20.0,0.112 -9aed5818-c037-4033-8d15-806c62d70b8f,113.097,0.0,315.0,NA2XS2Y 1x150 RM/25 6/10 kV,0.206,10.0,0.11 -60d37bc7-157a-4c32-b1b5-e74c10d70531,127.549,0.0,358.0,NA2XS2Y 1x185 RM/25 6/10 kV,0.161,10.0,0.11 -a3ced617-2ffd-4593-b8e9-bcad9a521aab,143.257,0.0,416.0,NA2XS2Y 1x240 RM/25 6/10 kV,0.122,10.0,0.105 -f0484bb6-9d0d-4d13-bfbe-b83783b8352a,150.796,0.0,471.0,NA2XS2Y 1x300 RM/25 6/10 kV,0.1,10.0,0.0974 -6b223bc3-69e2-4eb8-a2c0-76be1cd2c998,169.646,0.0,535.0,NA2XS2Y 1x400 RM/25 6/10 kV,0.078,10.0,0.0942 -65181464-230a-487b-978f-81e406e9eb22,260.752,0.0,270.0,NAYY 4x150SE 0.6/1kV,0.2067,0.4,0.0804248 -1200d9eb-6d10-47f3-8543-abea43b128d3,273.319,0.0,357.0,NAYY 4x240SE 0.6/1kV,0.1267,0.4,0.0797965 +uuid,b,g,i_max,id,r,v_rated,x,cable_type +91617ab8-3de2-4fba-be45-a54473ba09a9,3.61283,0.0,1300.0,LineType_1,0.08,380.0,0.32,b8152c3f-d12f-4857-9746-a30aef6aee08 +b3b231ae-a971-4432-80d7-4ce2f2a56a32,3.22799,0.0,1950.0,LineType_4,0.033333,380.0,0.333333, +24595f91-8295-41f8-a3d8-c9418d860d9c,1.076,0.0,650.0,LineType_6,0.1,380.0,1.0, +f0fc57ec-aa5a-4484-b870-be70a5428cbd,6.45597,0.0,3900.0,LineType_9,0.016667,380.0,0.166667, +ba70d8e7-b082-49bc-8c45-3c10e1236c3e,8.60796,0.0,5200.0,LineType_10,0.0125,380.0,0.125, +eee8eeed-62c9-4345-aa5a-3743fe32007d,12.9119,0.0,7800.0,LineType_11,0.008333,380.0,0.083333, +d2b16935-dcd7-44d2-8623-cec4c703ccdc,17.2159,0.0,10400.0,LineType_12,0.00625,380.0,0.0625, +a490c96e-6e90-485a-b0d7-adeb81fa09cd,4.30398,0.0,2600.0,LineType_2,0.025,220.0,0.25, +5272bcbc-7d0e-4759-85fa-27943fd8d19c,2.15199,0.0,1300.0,LineType_3,0.05,220.0,0.5, +dd0bac07-de8d-4608-af36-b8ff2819f55a,7.22566,0.0,2600.0,LineType_5,0.04,220.0,0.16, +64c1dcb5-57a5-4f35-b2bf-9ae4e6cc4943,1.80642,0.0,650.0,LineType_7,0.16,220.0,0.64, +bdc83a85-c796-4bcb-8b79-8988dc2804f8,5.41925,0.0,1950.0,LineType_8,0.053333,220.0,0.213333, +3d75fb6b-f0be-4451-ab4c-7f00c0ebd619,2.8274,0.0,680.0,Al/St_265/35,0.1095,110.0,0.296, +f5dcaf44-7a9a-4b85-89ba-5c15c04c5766,3.45575,0.0,105.0,15-AL1/3-ST1A 20.0,1.8769,20.0,0.409, +9cbf484b-7256-4e7a-9c35-3e1049909aa0,3.53429,0.0,140.0,24-AL1/4-ST1A 20.0,1.2012,20.0,0.394, +5b542a50-b0c2-4497-ba90-b2b31aafaa0b,2.87456,0.0,170.0,34-AL1/6-ST1A 20.0,0.8342,20.0,0.382, +d594cd67-4459-44bc-9594-db710372db71,2.98451,0.0,210.0,48-AL1/8-ST1A 20.0,0.5939,20.0,0.372, +305e60ad-cfd2-4127-9d83-8d9b21942d93,3.04734,0.0,290.0,70-AL1/11-ST1A 20.0,0.4132,20.0,0.36, +cc59abd4-770b-45d2-98c8-919c91f1ca4b,58.7478,0.0,652.0,1x630_RM/50,0.122,110.0,0.122522, +82ea1b98-2b21-48bd-841a-8d17d8ac20c9,59.3761,0.0,158.0,NA2XS2Y 1x50 RM/25 12/20 kV,0.64,20.0,0.145, +4adef9e6-5e40-416d-8bd2-b6768d156c54,59.6903,0.0,220.0,NA2XS2Y 1x70 RM/25 12/20 kV,0.443,20.0,0.132, +d5c03484-59c2-44d5-a2ee-63a5a0d623b4,67.8584,0.0,252.0,NA2XS2Y 1x95 RM/25 12/20 kV,0.313,20.0,0.132, +9c13909d-1dd1-4e2d-980b-55345bdf0fd0,72.2566,0.0,283.0,NA2XS2Y 1x120 RM/25 12/20 kV,0.253,20.0,0.119, +36243493-eb31-4e81-bd13-b54ef59c4cbe,78.5398,0.0,319.0,NA2XS2Y 1x150 RM/25 12/20 kV,0.206,20.0,0.116, +437689f8-366d-4b04-b42d-d7a754db074b,85.7655,0.0,362.0,NA2XS2Y 1x185 RM/25 12/20 kV,0.161,20.0,0.117, +b459115d-d4eb-47d4-b7ec-625339ee0dcc,95.5044,0.0,421.0,NA2XS2Y 1x240 RM/25 12/20 kV,0.122,20.0,0.112, +9aed5818-c037-4033-8d15-806c62d70b8f,113.097,0.0,315.0,NA2XS2Y 1x150 RM/25 6/10 kV,0.206,10.0,0.11, +60d37bc7-157a-4c32-b1b5-e74c10d70531,127.549,0.0,358.0,NA2XS2Y 1x185 RM/25 6/10 kV,0.161,10.0,0.11, +a3ced617-2ffd-4593-b8e9-bcad9a521aab,143.257,0.0,416.0,NA2XS2Y 1x240 RM/25 6/10 kV,0.122,10.0,0.105, +f0484bb6-9d0d-4d13-bfbe-b83783b8352a,150.796,0.0,471.0,NA2XS2Y 1x300 RM/25 6/10 kV,0.1,10.0,0.0974, +6b223bc3-69e2-4eb8-a2c0-76be1cd2c998,169.646,0.0,535.0,NA2XS2Y 1x400 RM/25 6/10 kV,0.078,10.0,0.0942, +65181464-230a-487b-978f-81e406e9eb22,260.752,0.0,270.0,NAYY 4x150SE 0.6/1kV,0.2067,0.4,0.0804248, +1200d9eb-6d10-47f3-8543-abea43b128d3,273.319,0.0,357.0,NAYY 4x240SE 0.6/1kV,0.1267,0.4,0.0797965, \ No newline at end of file diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInput.java b/src/main/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInput.java new file mode 100644 index 0000000000..6ac83d0499 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInput.java @@ -0,0 +1,79 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector; + +import java.util.Objects; +import javax.measure.quantity.Length; +import org.jspecify.annotations.NonNull; +import tech.units.indriya.ComparableQuantity; + +/** + * Represents the installation environment and deployment parameters of a cable. This data describes + * the concrete installation level of a cable and is associated with some LineInput. + * + * @param layoutFormation Layout formation type (e.g., "TREFOIL", "FLAT"). + * @param depthCables Laying depth of the cables from ground level to cable center. We keep the + * negative sign for easier integration with Coordinates, thus depthCables must be negative. + * @param distanceCables Distance between cable phases/cores from center to center. + */ +public record CableDeploymentInput( + String layoutFormation, + ComparableQuantity depthCables, + ComparableQuantity distanceCables) { + /** + * Create a new CableDeploymentInput with all required parameters. + * + * @param layoutFormation Layout formation type. + * @param depthCables Laying depth of the cables from ground level to cable center. We keep the + * negative sign for easier integration with Coordinates, thus depthCables must be negative. + * @param distanceCables Distance between cables/phases from center to center. + * @throws IllegalArgumentException if validation constraints are violated. + */ + public CableDeploymentInput { // Validation + Objects.requireNonNull(layoutFormation, "Layout formation cannot be null"); + Objects.requireNonNull(depthCables, "Depth cables cannot be null"); + Objects.requireNonNull(distanceCables, "Distance cables cannot be null"); + + if (layoutFormation.isEmpty()) { + throw new IllegalArgumentException("Layout formation cannot be empty"); + } + + // Not possible values check + if (depthCables.getValue().doubleValue() >= 0) { + throw new IllegalArgumentException("Depth cables must be < 0"); + } + if (distanceCables.getValue().doubleValue() <= 0) { + throw new IllegalArgumentException("Distance cables must be > 0"); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o + instanceof + CableDeploymentInput( + String formation, + ComparableQuantity cables, + ComparableQuantity distanceCables1))) return false; + return layoutFormation.equals(formation) + && depthCables.equals(cables) + && distanceCables.equals(distanceCables1); + } + + @Override + public @NonNull String toString() { + return "CableDeploymentInput{" + + "layoutFormation='" + + layoutFormation + + '\'' + + ", depthCables=" + + depthCables + + ", distanceCables=" + + distanceCables + + '}'; + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableMaterial.java b/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableMaterial.java new file mode 100644 index 0000000000..85a03178c6 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableMaterial.java @@ -0,0 +1,187 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static edu.ie3.util.quantities.PowerSystemUnits.*; + +import edu.ie3.util.quantities.interfaces.ElectricalResistivity; +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; + +/** + * Enumeration of cable materials with their default thermal and electrical properties. Provides + * default values based on physical material properties. + */ +public enum CableMaterial { + /** Copper conductor material */ + COPPER, + /** Aluminium conductor material */ + ALUMINIUM, + /** Cross-linked polyethylene (XLPE) insulation */ + XLPE, + /** Polyethylene (PE) insulation */ + PE, + /** Polyvinyl chloride (PVC) insulation */ + PVC, + /** Semi-conductive screen material */ + SEMI_COND_SCREEN, + /** Screening tape material */ + SC_TAPE, + /** Lead sheathing material */ + LEAD, + /** Steel armoring material */ + STEEL, + /** Polypropylene material */ + POLYPROPYLEN, + /** Unknown material type */ + UNKNOWN; + + /** + * Parses a material string into a Cable Material. + * + * @return An enum of the cable material if it can be parsed. + */ + public static CableMaterial fromString(String s) { + if (s == null) return UNKNOWN; + switch (s.trim().toLowerCase()) { + case "copper": + case "copperwoventape": + case "sc_tape": + return COPPER; + case "aluminium": + return ALUMINIUM; + case "xlpe": + return XLPE; + case "pe": + return PE; + case "pvc": + return PVC; + case "semicondscreen": + case "semi_cond_screen": + return SEMI_COND_SCREEN; + case "lead": + return LEAD; + case "steel": + return STEEL; + case "polypropylen": + case "pp": + return POLYPROPYLEN; + default: + return UNKNOWN; + } + } + + /** + * Get the default thermal properties resistivity and capacitance for this material. + * + * @return A pair of thermal resistivity and thermal capacitance + * @throws IllegalArgumentException if the material type is unknown + */ + public ThermalProperties getThermalProperties() { + return switch (this) { + case COPPER -> + new ThermalProperties( + Quantities.getQuantity(1.0 / 384.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(3449600.0, JOULE_PER_CUBIC_METRE_KELVIN)); + case ALUMINIUM -> + new ThermalProperties( + Quantities.getQuantity(1.0 / 237.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(2420913.3, JOULE_PER_CUBIC_METRE_KELVIN)); + case XLPE, PE -> + new ThermalProperties( + Quantities.getQuantity(3.5, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN)); + case PVC -> + new ThermalProperties( + Quantities.getQuantity(5.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(1.7, JOULE_PER_CUBIC_METRE_KELVIN)); + case SEMI_COND_SCREEN -> + new ThermalProperties( + Quantities.getQuantity(2.5, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN)); + case SC_TAPE -> + new ThermalProperties( + Quantities.getQuantity(6.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN)); + case LEAD -> + new ThermalProperties( + Quantities.getQuantity(1.0 / 35.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(1463892.0, JOULE_PER_CUBIC_METRE_KELVIN)); + case STEEL -> + new ThermalProperties( + Quantities.getQuantity(1.0 / 45.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(3756000.0, JOULE_PER_CUBIC_METRE_KELVIN)); + case POLYPROPYLEN -> + new ThermalProperties( + Quantities.getQuantity(6.0, KELVIN_METRE_PER_WATT), + Quantities.getQuantity(2.0, JOULE_PER_CUBIC_METRE_KELVIN)); + case UNKNOWN -> + throw new IllegalArgumentException( + "Cannot provide thermal properties for unknown material"); + }; + } + + /** + * Get the default electrical resistivity for this material at reference conditions. + * + * @return Electrical resistivity + * @throws IllegalArgumentException if the material type is unknown + */ + public ComparableQuantity getElectricalResistivity() { + return switch (this) { + case COPPER -> Quantities.getQuantity(1.7241e-8, OHM_METRE); + case ALUMINIUM -> Quantities.getQuantity(2.8264e-8, OHM_METRE); + case STEEL -> Quantities.getQuantity(13.8e-8, OHM_METRE); + case LEAD -> Quantities.getQuantity(21.4e-8, OHM_METRE); + case UNKNOWN -> + throw new IllegalArgumentException( + "Cannot provide electrical resistivity for unknown material"); + default -> + throw new IllegalArgumentException( + "No electrical resistivity data available for material: " + this); + }; + } + + /** + * Get the temperature coefficient for electrical resistivity of this material. + * + * @return Temperature coefficient + * @throws IllegalArgumentException if the material type is unknown + */ + public double getElectricalResistivityTemperatureCoefficient() { + return switch (this) { + case COPPER -> 3.93e-3; + case ALUMINIUM -> 4.03e-3; + case LEAD -> 4.0e-3; + case STEEL -> 4.5e-3; + case UNKNOWN -> + throw new IllegalArgumentException( + "Cannot provide temperature coefficient for unknown material"); + default -> + throw new IllegalArgumentException( + "No temperature coefficient data available for material: " + this); + }; + } + + /** Container class for thermal properties of a cable material. */ + public record ThermalProperties( + ComparableQuantity resistivity, + ComparableQuantity capacitance) { + + /** + * Compact constructor for validation of record components. + * + * @throws IllegalArgumentException if any property is null + */ + public ThermalProperties { + if (resistivity == null || capacitance == null) { + throw new IllegalArgumentException("Thermal properties must not be null."); + } + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInput.java b/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInput.java new file mode 100644 index 0000000000..44f3e0c6f1 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInput.java @@ -0,0 +1,446 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import edu.ie3.datamodel.models.input.AssetTypeInput; +import edu.ie3.datamodel.models.input.InputEntity; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.ElectricCapacitance; +import javax.measure.quantity.Frequency; +import javax.measure.quantity.Temperature; +import org.jspecify.annotations.NonNull; +import tech.units.indriya.ComparableQuantity; + +/** + * Represents detailed cable construction data at the type/catalog level. This class contains the + * complete specification of a cable type including conductors, insulation layers, screens, armor, + * and jacket elements, as well as electrical and thermal parameters. + */ +public class CableTypeInput extends AssetTypeInput implements InputEntity { + + private final int coreNumber; + private final ConductorInput conductor; + private final List isolation; + private final Optional screen; + private final List filler; + private final List armor; + private final List jack; + private final ComparableQuantity limitTemperature; + private final ComparableQuantity frequency; + private final double skinEffectCoefficient; + private final double proximityEffectCoefficient; + private final ComparableQuantity electricalCapacitance; + private final double tanDelta; + private final double circulatingLossFactor; + private final double eddyCurrentLossFactor; + + /** + * Represents detailed cable construction data at the type/catalog level. This class contains the + * complete specification of a cable type including conductors, insulation layers, screens, armor, + * and jacket elements, as well as electrical and thermal parameters. + * + * @param uuid Unique identifier for this cable type + * @param id Human-readable identifier/name for this cable type (e.g., "NA2XS2Y 1x120 RM/25 12/20 + * kV") + * @param coreNumber Number of cores/conductors in the cable (e.g., 1 for single-core, 3 for + * three-phase) + * @param conductor The innermost conductor/core + * @param isolation List of insulation layers (from inner to outer) + * @param screen Optional cable screen layer + * @param filler List of filler layers (from inner to outer) + * @param armor List of armor layers (from inner to outer) + * @param jack List of jacket/outer sheath layers (from inner to outer) + * @param limitTemperature Maximum permissible operating temperature (°C) + * @param frequency Rated frequency + * @param skinEffectCoefficient Skin effect coefficient + * @param proximityEffectCoefficient Proximity effect coefficient + * @param electricalCapacitance Capacitance per unit length + * @param tanDelta Dielectric loss factor tan(δ) + * @param circulatingLossFactor Circulating loss factor + * @param eddyCurrentLossFactor Eddy current loss factor + */ + public CableTypeInput( + UUID uuid, + String id, + int coreNumber, + ConductorInput conductor, + List isolation, + Optional screen, + List filler, + List armor, + List jack, + ComparableQuantity limitTemperature, + ComparableQuantity frequency, + double skinEffectCoefficient, + double proximityEffectCoefficient, + ComparableQuantity electricalCapacitance, + double tanDelta, + double circulatingLossFactor, + double eddyCurrentLossFactor) { + + super(uuid, id); + + Objects.requireNonNull(conductor, "Conductor cannot be null"); + Objects.requireNonNull(isolation, "Isolation elements list cannot be null"); + Objects.requireNonNull(screen, "Screen layer Optional cannot be null"); + Objects.requireNonNull(filler, "Filler elements list cannot be null"); + Objects.requireNonNull(armor, "Armor elements list cannot be null"); + Objects.requireNonNull(jack, "Jack elements list cannot be null"); + Objects.requireNonNull(limitTemperature, "Limit temperature cannot be null"); + Objects.requireNonNull(frequency, "Frequency cannot be null"); + Objects.requireNonNull(electricalCapacitance, "Electric capacitance cannot be null"); + + if (id.isEmpty()) { + throw new IllegalArgumentException("ID cannot be empty"); + } + + if (coreNumber < 1) { + throw new IllegalArgumentException("Core number must be >= 1"); + } + + if (limitTemperature.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Limit temperature must be >= 0"); + } + if (frequency.getValue().doubleValue() <= 0) { + throw new IllegalArgumentException("Frequency must be > 0"); + } + if (electricalCapacitance.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Electric capacitance must be >= 0"); + } + if (skinEffectCoefficient < 0) { + throw new IllegalArgumentException("Skin effect coefficient must be >= 0"); + } + if (proximityEffectCoefficient < 0) { + throw new IllegalArgumentException("Proximity effect coefficient must be >= 0"); + } + if (tanDelta < 0) { + throw new IllegalArgumentException("Tan delta must be >= 0"); + } + if (circulatingLossFactor < 0) { + throw new IllegalArgumentException("Circulating loss factor must be >= 0"); + } + if (eddyCurrentLossFactor < 0) { + throw new IllegalArgumentException("Eddy current loss factor must be >= 0"); + } + + this.coreNumber = coreNumber; + this.conductor = conductor; + this.isolation = Collections.unmodifiableList(isolation); + this.screen = screen; + this.filler = Collections.unmodifiableList(filler); + this.armor = Collections.unmodifiableList(armor); + this.jack = Collections.unmodifiableList(jack); + this.limitTemperature = limitTemperature; + this.frequency = frequency; + this.skinEffectCoefficient = skinEffectCoefficient; + this.proximityEffectCoefficient = proximityEffectCoefficient; + this.electricalCapacitance = electricalCapacitance; + this.tanDelta = tanDelta; + this.circulatingLossFactor = circulatingLossFactor; + this.eddyCurrentLossFactor = eddyCurrentLossFactor; + } + + @com.fasterxml.jackson.annotation.JsonProperty("core_number") + public int getCoreNumber() { + return coreNumber; + } + + public ConductorInput getConductor() { + return conductor; + } + + public List getIsolation() { + return isolation; + } + + public Optional getScreen() { + return screen; + } + + public List getFiller() { + return filler; + } + + public List getArmor() { + return armor; + } + + public List getJack() { + return jack; + } + + public ComparableQuantity getLimitTemperature() { + return limitTemperature; + } + + public ComparableQuantity getFrequency() { + return frequency; + } + + public double getSkinEffectCoefficient() { + return skinEffectCoefficient; + } + + public double getProximityEffectCoefficient() { + return proximityEffectCoefficient; + } + + public ComparableQuantity getElectricalCapacitance() { + return electricalCapacitance; + } + + public double getTanDelta() { + return tanDelta; + } + + public double getCirculatingLossFactor() { + return circulatingLossFactor; + } + + public double getEddyCurrentLossFactor() { + return eddyCurrentLossFactor; + } + + @Override + public CableTypeInputCopyBuilder copy() { + return new CableTypeInputCopyBuilder(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CableTypeInput that)) return false; + if (!super.equals(o)) return false; + + return coreNumber == that.coreNumber + && Double.compare(that.skinEffectCoefficient, skinEffectCoefficient) == 0 + && Double.compare(that.proximityEffectCoefficient, proximityEffectCoefficient) == 0 + && Double.compare(that.tanDelta, tanDelta) == 0 + && Double.compare(that.circulatingLossFactor, circulatingLossFactor) == 0 + && Double.compare(that.eddyCurrentLossFactor, eddyCurrentLossFactor) == 0 + && conductor.equals(that.conductor) + && isolation.equals(that.isolation) + && screen.equals(that.screen) + && filler.equals(that.filler) + && armor.equals(that.armor) + && jack.equals(that.jack) + && limitTemperature.equals(that.limitTemperature) + && frequency.equals(that.frequency) + && electricalCapacitance.equals(that.electricalCapacitance); + } + + @Override + public int hashCode() { + return Objects.hash( + super.hashCode(), + coreNumber, + conductor, + isolation, + screen, + filler, + armor, + jack, + limitTemperature, + frequency, + skinEffectCoefficient, + proximityEffectCoefficient, + electricalCapacitance, + tanDelta, + circulatingLossFactor, + eddyCurrentLossFactor); + } + + @Override + public @NonNull String toString() { + return "CableTypeInput{" + + "uuid=" + + getUuid() + + ", id=" + + getId() + + ", coreNumber=" + + coreNumber + + ", conductor=" + + conductor + + ", isolation=" + + isolation + + ", screen=" + + screen + + ", filler=" + + filler + + ", armor=" + + armor + + ", jack=" + + jack + + ", limitTemperature=" + + limitTemperature + + ", frequency=" + + frequency + + ", skinEffectCoefficient=" + + skinEffectCoefficient + + ", proximityEffectCoeff=" + + proximityEffectCoefficient + + ", electricalCapacitance=" + + electricalCapacitance + + ", tanDelta=" + + tanDelta + + ", circulatingLossFactor=" + + circulatingLossFactor + + ", eddyCurrentLossFactor=" + + eddyCurrentLossFactor + + '}'; + } + + /** + * Abstract class for all builder that build child entities of abstract class {@link + * CableTypeInput} + */ + public static final class CableTypeInputCopyBuilder + extends AssetTypeInput.AssetTypeInputCopyBuilder { + + private int coreNumber; + private ConductorInput conductor; + private List isolation; + private Optional screen; + private List filler; + private List armor; + private List jack; + private ComparableQuantity limitTemperature; + private ComparableQuantity frequency; + private double skinEffectCoefficient; + private double proximityEffectCoefficient; + private ComparableQuantity electricalCapacitance; + private double tanDelta; + private double circulatingLossFactor; + private double eddyCurrentLossFactor; + + protected CableTypeInputCopyBuilder(CableTypeInput entity) { + super(entity); + this.coreNumber = entity.coreNumber; + this.conductor = entity.conductor; + this.isolation = entity.isolation; + this.screen = entity.screen; + this.filler = entity.filler; + this.armor = entity.armor; + this.jack = entity.jack; + this.limitTemperature = entity.limitTemperature; + this.frequency = entity.frequency; + this.skinEffectCoefficient = entity.skinEffectCoefficient; + this.proximityEffectCoefficient = entity.proximityEffectCoefficient; + this.electricalCapacitance = entity.electricalCapacitance; + this.tanDelta = entity.tanDelta; + this.circulatingLossFactor = entity.circulatingLossFactor; + this.eddyCurrentLossFactor = entity.eddyCurrentLossFactor; + } + + public CableTypeInputCopyBuilder coreNumber(int coreNumber) { + this.coreNumber = coreNumber; + return thisInstance(); + } + + public CableTypeInputCopyBuilder conductor(ConductorInput conductor) { + this.conductor = conductor; + return thisInstance(); + } + + public CableTypeInputCopyBuilder isolation(List isolation) { + this.isolation = isolation; + return thisInstance(); + } + + public CableTypeInputCopyBuilder screen(Optional screen) { + this.screen = screen; + return thisInstance(); + } + + public CableTypeInputCopyBuilder filler(List filler) { + this.filler = filler; + return thisInstance(); + } + + public CableTypeInputCopyBuilder armor(List armor) { + this.armor = armor; + return thisInstance(); + } + + public CableTypeInputCopyBuilder jack(List jack) { + this.jack = jack; + return thisInstance(); + } + + public CableTypeInputCopyBuilder limitTemperature( + ComparableQuantity limitTemperature) { + this.limitTemperature = limitTemperature; + return thisInstance(); + } + + public CableTypeInputCopyBuilder frequency(ComparableQuantity frequency) { + this.frequency = frequency; + return thisInstance(); + } + + public CableTypeInputCopyBuilder skinEffectCoefficient(double value) { + this.skinEffectCoefficient = value; + return thisInstance(); + } + + public CableTypeInputCopyBuilder proximityEffectCoefficient(double value) { + this.proximityEffectCoefficient = value; + return thisInstance(); + } + + public CableTypeInputCopyBuilder electricalCapacitance( + ComparableQuantity value) { + this.electricalCapacitance = value; + return thisInstance(); + } + + public CableTypeInputCopyBuilder tanDelta(double value) { + this.tanDelta = value; + return thisInstance(); + } + + public CableTypeInputCopyBuilder circulatingLossFactor(double value) { + this.circulatingLossFactor = value; + return thisInstance(); + } + + public CableTypeInputCopyBuilder eddyCurrentLossFactor(double value) { + this.eddyCurrentLossFactor = value; + return thisInstance(); + } + + @Override + public CableTypeInput build() { + return new CableTypeInput( + getUuid(), + getId(), + coreNumber, + conductor, + isolation, + screen, + filler, + armor, + jack, + limitTemperature, + frequency, + skinEffectCoefficient, + proximityEffectCoefficient, + electricalCapacitance, + tanDelta, + circulatingLossFactor, + eddyCurrentLossFactor); + } + + @Override + protected CableTypeInputCopyBuilder thisInstance() { + return this; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/type/ConductorInput.java b/src/main/java/edu/ie3/datamodel/models/input/connector/type/ConductorInput.java new file mode 100644 index 0000000000..6defe585e9 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/type/ConductorInput.java @@ -0,0 +1,125 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import edu.ie3.datamodel.models.input.InputEntity; +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import org.jspecify.annotations.NonNull; +import tech.units.indriya.ComparableQuantity; + +/** + * Represents the conducting core of a cable with its specific geometric and thermal properties. + * Unlike {@link LayerInput} layers, the conductor has no inner diameter and includes compaction + * information. + * + * @param uuid UUID of the ConductorInput + * @param name Human-readable id + * @param material Material of the conductor (e.g., copper or aluminium) + * @param crossSection Real nominal cross-sectional area (electrically effective) + * @param diameter Geometric outer diameter of the conductor + * @param isCompacted Whether the conductor is compacted + * @param thermalResistivity Thermal resistivity of the conductor material + * @param thermalCapacitance Thermal capacitance of the conductor material + * @param area Optional real cross-sectional area (if different from geometric calculation) + */ +public record ConductorInput( + UUID uuid, + String name, + CableMaterial material, + ComparableQuantity crossSection, + ComparableQuantity diameter, + boolean isCompacted, + ComparableQuantity thermalResistivity, + ComparableQuantity thermalCapacitance, + Optional> area) + implements InputEntity, Serializable { + /** + * Create a new conductor with all required parameters. + * + * @param uuid UUID of the ConductorInput + * @param name Human-readable id + * @param material Material of the conductor + * @param crossSection Real nominal cross-sectional area (electrically effective) + * @param diameter Geometric outer diameter + * @param isCompacted Whether the conductor is compacted + * @param thermalResistivity Thermal resistivity + * @param thermalCapacitance Thermal capacitance + * @param area Optional real cross-sectional area + * @throws IllegalArgumentException if validation constraints are violated + */ + public ConductorInput { + // Validation + Objects.requireNonNull(uuid, "Conductor UUID cannot be null"); + Objects.requireNonNull(name, "Conductor name cannot be null"); + Objects.requireNonNull(material, "Conductor material cannot be null"); + Objects.requireNonNull(crossSection, "Cross section cannot be null"); + Objects.requireNonNull(diameter, "Diameter cannot be null"); + Objects.requireNonNull(thermalResistivity, "Thermal resistivity cannot be null"); + Objects.requireNonNull(thermalCapacitance, "Thermal capacitance cannot be null"); + Objects.requireNonNull(area, "Area optional must not be null"); + + if (name.isEmpty()) { + throw new IllegalArgumentException("Conductor name must not be empty"); + } + + // Positive values check + if (crossSection.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Cross section must be >= 0"); + } + if (diameter.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Diameter must be >= 0"); + } + if (thermalResistivity.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Thermal resistivity must be >= 0"); + } + if (thermalCapacitance.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Thermal capacitance must be >= 0"); + } + area.ifPresent( + a -> { + if (a.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Area must be >= 0"); + } + }); + } + + @Override + public Map getAdditionalInformation() { + return Map.of(); + } + + @Override + public @NonNull String toString() { + return "ConductorInput{" + + "uuid=" + + uuid + + ", name=" + + name + + ", material=" + + material + + ", crossSection=" + + crossSection + + ", diameter=" + + diameter + + ", isCompacted=" + + isCompacted + + ", thermalResistivity=" + + thermalResistivity + + ", thermalCapacitance=" + + thermalCapacitance + + ", area=" + + area + + '}'; + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/type/LayerInput.java b/src/main/java/edu/ie3/datamodel/models/input/connector/type/LayerInput.java new file mode 100644 index 0000000000..6479b9f7a7 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/type/LayerInput.java @@ -0,0 +1,105 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import edu.ie3.datamodel.models.input.InputEntity; +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import tech.units.indriya.ComparableQuantity; + +/** + * Represents a concentric layer of a cable, including insulation, filler, armor, and jacket layers. + * + * @param uuid UUID of this layer + * @param name Name/designation of this layer + * @param material Material of this layer + * @param innerDiameter Inner diameter of this layer + * @param outerDiameter Outer diameter of this layer + * @param thermalResistivity Thermal resistivity of the material + * @param thermalCapacitance Thermal capacitance of the material + * @param area Optional real cross-sectional area (if different from geometry) + */ +public record LayerInput( + UUID uuid, + String name, + CableMaterial material, + ComparableQuantity innerDiameter, + ComparableQuantity outerDiameter, + ComparableQuantity thermalResistivity, + ComparableQuantity thermalCapacitance, + Optional> area) + implements InputEntity, Serializable { + /** + * Create a new layer with all required parameters. + * + * @param name Designation of this layer + * @param material Material of this layer + * @param innerDiameter Inner diameter + * @param outerDiameter Outer diameter + * @param thermalResistivity Thermal resistivity + * @param thermalCapacitance Thermal capacitance + * @param area Optional real cross-sectional area + * @throws IllegalArgumentException if validation constraints are violated + */ + public LayerInput { + // Validation + Objects.requireNonNull(uuid, "Layer UUID cannot be null"); + Objects.requireNonNull(name, "Layer name cannot be null"); + Objects.requireNonNull(material, "Layer material cannot be null"); + Objects.requireNonNull(innerDiameter, "Inner diameter cannot be null"); + Objects.requireNonNull(outerDiameter, "Outer diameter cannot be null"); + Objects.requireNonNull(thermalResistivity, "Thermal resistivity cannot be null"); + Objects.requireNonNull(thermalCapacitance, "Thermal capacitance cannot be null"); + Objects.requireNonNull(area, "Area optional must not be null"); + + if (name.isEmpty()) { + throw new IllegalArgumentException("Layer name cannot be empty"); + } + + double inner = innerDiameter.getValue().doubleValue(); + double outer = outerDiameter.getValue().doubleValue(); + double rho = thermalResistivity.getValue().doubleValue(); + double cap = thermalCapacitance.getValue().doubleValue(); + + // Geometry consistency: outerDiameter >= innerDiameter + if (outer < inner) { + throw new IllegalArgumentException( + String.format("Outer diameter (%.6f) must be >= inner diameter (%.6f)", outer, inner)); + } + + // Positive values check + if (inner < 0) { + throw new IllegalArgumentException("Inner diameter must be >= 0"); + } + if (outer < 0) { + throw new IllegalArgumentException("Outer diameter must be >= 0"); + } + if (rho < 0) { + throw new IllegalArgumentException("Thermal resistivity must be >= 0"); + } + if (cap < 0) { + throw new IllegalArgumentException("Thermal capacitance must be >= 0"); + } + area.ifPresent( + a -> { + if (a.getValue().doubleValue() < 0) { + throw new IllegalArgumentException("Area must be >= 0"); + } + }); + } + + @Override + public Map getAdditionalInformation() { + return Map.of(); + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInput.java b/src/main/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInput.java new file mode 100644 index 0000000000..9de08f8d0d --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInput.java @@ -0,0 +1,169 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import edu.ie3.datamodel.models.input.InputEntity; +import edu.ie3.util.quantities.interfaces.ElectricalResistivity; +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import org.jspecify.annotations.NonNull; +import tech.units.indriya.ComparableQuantity; + +/** + * Represents a cable screen layer with specific parameters for conductor shielding. Extends the + * properties of a standard layer with wire-specific parameters. + * + * @param uuid UUID of the screen layer + * @param name Name/designation of this screen layer + * @param material Material of the screen + * @param innerDiameter Inner diameter of the screen layer + * @param outerDiameter Outer diameter of the screen layer + * @param thermalResistivity Thermal resistivity of the material + * @param thermalCapacitance Thermal capacitance of the material + * @param area Optional real cross-sectional area (e.g. if different from geometry) + * @param wiresNumber Number of individual wires in the screen + * @param wireDiameter Diameter of an individual wire in the screen + * @param lengthOfLay Optional length of lay (pitch) of the screen winding + * @param electricalResistivity Electrical resistivity specific to the screen material + */ +public record ScreenLayerInput( + UUID uuid, + String name, + CableMaterial material, + ComparableQuantity innerDiameter, + ComparableQuantity outerDiameter, + ComparableQuantity thermalResistivity, + ComparableQuantity thermalCapacitance, + Optional> area, + int wiresNumber, + ComparableQuantity wireDiameter, + Optional> lengthOfLay, + ComparableQuantity electricalResistivity) + implements InputEntity, Serializable { + /** + * Create a new screen layer with all required parameters. + * + * @param uuid UUID of the screen layer + * @param name Designation of this screen layer + * @param material Material of the screen + * @param innerDiameter Inner diameter + * @param outerDiameter Outer diameter + * @param thermalResistivity Thermal resistivity + * @param thermalCapacitance Thermal capacitance + * @param area Optional real cross-sectional area + * @param wiresNumber Number of individual wires + * @param wireDiameter Diameter of individual wire + * @param lengthOfLay Optional length of lay (pitch) + * @param electricalResistivity Electrical resistivity of the screen material + */ + public ScreenLayerInput { + // Validation + Objects.requireNonNull(uuid, "Screen layer UUID cannot be null"); + Objects.requireNonNull(name, "Screen layer name cannot be null"); + Objects.requireNonNull(material, "Screen material cannot be null"); + Objects.requireNonNull(innerDiameter, "Inner diameter cannot be null"); + Objects.requireNonNull(outerDiameter, "Outer diameter cannot be null"); + Objects.requireNonNull(thermalResistivity, "Thermal resistivity cannot be null"); + Objects.requireNonNull(thermalCapacitance, "Thermal capacitance cannot be null"); + Objects.requireNonNull(wireDiameter, "Wire diameter cannot be null"); + Objects.requireNonNull(area, "Area optional must not be null"); + Objects.requireNonNull(lengthOfLay, "Length of lay optional must not be null"); + Objects.requireNonNull(electricalResistivity, "Material resistivity cannot be null"); + + if (name.isEmpty()) { + throw new IllegalArgumentException("Screen layer name cannot be empty"); + } + + double inner = innerDiameter.getValue().doubleValue(); + double outer = outerDiameter.getValue().doubleValue(); + double rhoT = thermalResistivity.getValue().doubleValue(); + double capT = thermalCapacitance.getValue().doubleValue(); + double wireD = wireDiameter.getValue().doubleValue(); + double rhoE = electricalResistivity.getValue().doubleValue(); + + // Geometry consistency: outerDiameter >= innerDiameter + if (outer < inner) { + throw new IllegalArgumentException( + String.format("Outer diameter (%.6f) must be >= inner diameter (%.6f)", outer, inner)); + } + + // Positive values check + if (inner < 0) { + throw new IllegalArgumentException("Inner diameter must be >= 0"); + } + if (outer < 0) { + throw new IllegalArgumentException("Outer diameter must be >= 0"); + } + if (rhoT < 0) { + throw new IllegalArgumentException("Thermal resistivity must be >= 0"); + } + if (capT < 0) { + throw new IllegalArgumentException("Thermal capacitance must be >= 0"); + } + if (wiresNumber < 1) { + throw new IllegalArgumentException("Number of wires must be >= 1"); + } + if (wireD < 0) { + throw new IllegalArgumentException("Wire diameter must be >= 0"); + } + if (rhoE < 0) { + throw new IllegalArgumentException("Material resistivity must be >= 0"); + } + area.ifPresent( + a -> { + double val = a.getValue().doubleValue(); + if (val < 0) throw new IllegalArgumentException("Area must be >= 0"); + }); + + lengthOfLay.ifPresent( + l -> { + double val = l.getValue().doubleValue(); + if (val < 0) throw new IllegalArgumentException("Length of lay must be >= 0"); + }); + } + + @Override + public Map getAdditionalInformation() { + return Map.of(); + } + + @Override + public @NonNull String toString() { + return "ScreenLayerInput{" + + "uuid=" + + uuid + + ", name=" + + name + + ", material=" + + material + + ", innerDiameter=" + + innerDiameter + + ", outerDiameter=" + + outerDiameter + + ", thermalResistivity=" + + thermalResistivity + + ", thermalCapacitance=" + + thermalCapacitance + + ", area=" + + area + + ", wiresNumber=" + + wiresNumber + + ", wireDiameter=" + + wireDiameter + + ", lengthOfLay=" + + lengthOfLay + + ", electricalResistivity=" + + electricalResistivity + + '}'; + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInputTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInputTest.java new file mode 100644 index 0000000000..fa9fc4a233 --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/CableDeploymentInputTest.java @@ -0,0 +1,148 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector; + +import static org.junit.jupiter.api.Assertions.*; + +import javax.measure.quantity.Length; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; + +/** Unit tests for CableDeploymentInput class. */ +@DisplayName("CableDeploymentInput Tests") +class CableDeploymentInputTest { + + private ComparableQuantity depthCables; + private ComparableQuantity distanceCables; + + @BeforeEach + void setUp() { + depthCables = Quantities.getQuantity(-1.0, Units.METRE); + distanceCables = Quantities.getQuantity(0.3, Units.METRE); + } + + @Test + @DisplayName("Test CableDeploymentInput creation with valid parameters") + void testCableDeploymentInputCreation() { + CableDeploymentInput env = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + assertNotNull(env); + assertEquals("TREFOIL", env.layoutFormation()); + assertEquals(depthCables, env.depthCables()); + assertEquals(distanceCables, env.distanceCables()); + } + + @Test + @DisplayName("Test CableDeploymentInput with FLAT layout") + void testCableDeploymentInputFlat() { + CableDeploymentInput env = new CableDeploymentInput("FLAT", depthCables, distanceCables); + assertEquals("FLAT", env.layoutFormation()); + } + + @Test + @DisplayName("Test CableDeploymentInput null layoutFormation validation") + void testCableDeploymentInputNullLayoutFormation() { + assertThrows( + NullPointerException.class, + () -> new CableDeploymentInput(null, depthCables, distanceCables)); + } + + @Test + @DisplayName("Test CableDeploymentInput empty layoutFormation validation") + void testCableDeploymentInputEmptyLayoutFormation() { + assertThrows( + IllegalArgumentException.class, + () -> new CableDeploymentInput("", depthCables, distanceCables)); + } + + @Test + @DisplayName("Test CableDeploymentInput positive depthCables validation") + void testCableDeploymentInputNegativeDepth() { + ComparableQuantity positiveDepth = Quantities.getQuantity(1.0, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> new CableDeploymentInput("TREFOIL", positiveDepth, distanceCables)); + } + + @Test + @DisplayName("Test CableDeploymentInput zero distanceCables validation") + void testCableDeploymentInputNegativeDistance() { + ComparableQuantity zeroDistance = Quantities.getQuantity(0.0, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> new CableDeploymentInput("TREFOIL", depthCables, zeroDistance)); + } + + @Test + @DisplayName("Test CableDeploymentInput equals method") + void testCableDeploymentInputEquals() { + CableDeploymentInput env1 = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + CableDeploymentInput env2 = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + assertEquals(env1, env2); + } + + @Test + @DisplayName("Test CableDeploymentInput hashCode consistency") + void testCableDeploymentInputHashCode() { + CableDeploymentInput env1 = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + CableDeploymentInput env2 = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + assertEquals(env1.hashCode(), env2.hashCode()); + } + + @Test + @DisplayName("Test CableDeploymentInput toString") + void testCableDeploymentInputToString() { + CableDeploymentInput env = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + String str = env.toString(); + assertNotNull(str); + assertTrue(str.contains("TREFOIL")); + } + + @Test + @DisplayName("Test CableDeploymentInput null depthCables validation") + void testCableDeploymentInputNullDepth() { + assertThrows( + NullPointerException.class, + () -> new CableDeploymentInput("TREFOIL", null, distanceCables)); + } + + @Test + @DisplayName("Test CableDeploymentInput null distanceCables validation") + void testCableDeploymentInputNullDistance() { + assertThrows( + NullPointerException.class, () -> new CableDeploymentInput("TREFOIL", depthCables, null)); + } + + @Test + @DisplayName("Test CableDeploymentInput not equals for different layouts") + void testCableDeploymentInputNotEqualsLayout() { + CableDeploymentInput env1 = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + CableDeploymentInput env2 = new CableDeploymentInput("FLAT", depthCables, distanceCables); + assertNotEquals(env1, env2); + } + + @Test + @DisplayName("Test CableDeploymentInput with zero depths") + void testCableDeploymentInputZeroDepths() { + ComparableQuantity zeroDepth = Quantities.getQuantity(0.0, Units.METRE); + ComparableQuantity zeroDistance = Quantities.getQuantity(0.0, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> new CableDeploymentInput("TREFOIL", zeroDepth, zeroDistance)); + } + + @Test + @DisplayName("Test CableDeploymentInput getters") + void testCableDeploymentInputGetters() { + CableDeploymentInput env = new CableDeploymentInput("TREFOIL", depthCables, distanceCables); + assertEquals("TREFOIL", env.layoutFormation()); + assertEquals(depthCables, env.depthCables()); + assertEquals(distanceCables, env.distanceCables()); + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableMaterialTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableMaterialTest.java new file mode 100644 index 0000000000..ba401d385f --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableMaterialTest.java @@ -0,0 +1,154 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** Unit tests for CableMaterial enum and its thermal/electrical property methods. */ +@DisplayName("CableMaterial Tests") +class CableMaterialTest { + + @Test + @DisplayName("Test COPPER thermal properties") + void testCopperThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.COPPER.getThermalProperties(); + assertNotNull(props); + assertNotNull(props.resistivity()); + assertNotNull(props.capacitance()); + assertEquals(0.002604166667, props.resistivity().getValue().doubleValue(), 1e-12); + assertEquals(3449600.0, props.capacitance().getValue().doubleValue(), 1e-5); + } + + @Test + @DisplayName("Test ALUMINIUM thermal properties") + void testAluminiumThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.ALUMINIUM.getThermalProperties(); + assertNotNull(props); + assertEquals(0.0042194092827, props.resistivity().getValue().doubleValue(), 1e-12); + assertEquals(2420913.3, props.capacitance().getValue().doubleValue(), 1e-5); + } + + @Test + @DisplayName("Test XLPE thermal properties") + void testXlpeThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.XLPE.getThermalProperties(); + assertNotNull(props); + assertEquals(3.5, props.resistivity().getValue().doubleValue(), 1e-3); + assertEquals(2.4, props.capacitance().getValue().doubleValue(), 1e-3); + } + + @Test + @DisplayName("Test UNKNOWN material throws exception for thermal properties") + void testUnknownThermalProperties() { + assertThrows(IllegalArgumentException.class, CableMaterial.UNKNOWN::getThermalProperties); + } + + @Test + @DisplayName("Test COPPER electrical resistivity") + void testCopperElectricalResistivity() { + var resistivity = CableMaterial.COPPER.getElectricalResistivity(); + assertNotNull(resistivity); + assertEquals(1.7241e-8, resistivity.getValue().doubleValue(), 1e-12); + } + + @Test + @DisplayName("Test ALUMINIUM electrical resistivity") + void testAluminiumElectricalResistivity() { + var resistivity = CableMaterial.ALUMINIUM.getElectricalResistivity(); + assertNotNull(resistivity); + assertEquals(2.8264e-8, resistivity.getValue().doubleValue(), 1e-12); + } + + @Test + @DisplayName("Test STEEL electrical resistivity") + void testSteelElectricalResistivity() { + var resistivity = CableMaterial.STEEL.getElectricalResistivity(); + assertNotNull(resistivity); + assertEquals(13.8e-8, resistivity.getValue().doubleValue(), 1e-12); + } + + @Test + @DisplayName("Test UNKNOWN material throws exception for electrical resistivity") + void testUnknownElectricalResistivity() { + assertThrows(IllegalArgumentException.class, CableMaterial.UNKNOWN::getElectricalResistivity); + } + + @Test + @DisplayName("Test COPPER temperature coefficient") + void testCopperTemperatureCoefficient() { + double coeff = CableMaterial.COPPER.getElectricalResistivityTemperatureCoefficient(); + assertEquals(3.93e-3, coeff, 1e-8); + } + + @Test + @DisplayName("Test ALUMINIUM temperature coefficient") + void testAluminiumTemperatureCoefficient() { + double coeff = CableMaterial.ALUMINIUM.getElectricalResistivityTemperatureCoefficient(); + assertEquals(4.03e-3, coeff, 1e-8); + } + + @Test + @DisplayName("Test LEAD temperature coefficient") + void testLeadTemperatureCoefficient() { + double coeff = CableMaterial.LEAD.getElectricalResistivityTemperatureCoefficient(); + assertEquals(4.0e-3, coeff, 1e-8); + } + + @Test + @DisplayName("Test STEEL temperature coefficient") + void testSteelTemperatureCoefficient() { + double coeff = CableMaterial.STEEL.getElectricalResistivityTemperatureCoefficient(); + assertEquals(4.5e-3, coeff, 1e-8); + } + + @Test + @DisplayName("Test UNKNOWN material throws exception for temperature coefficient") + void testUnknownTemperatureCoefficient() { + assertThrows( + IllegalArgumentException.class, + CableMaterial.UNKNOWN::getElectricalResistivityTemperatureCoefficient); + } + + @Test + @DisplayName("Test all non-UNKNOWN materials have thermal properties") + void testAllMaterialsHaveThermalProperties() { + for (CableMaterial material : CableMaterial.values()) { + if (material != CableMaterial.UNKNOWN) { + assertDoesNotThrow(material::getThermalProperties); + } + } + } + + @Test + @DisplayName("Test PVC thermal properties") + void testPvcThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.PVC.getThermalProperties(); + assertNotNull(props); + assertEquals(5.0, props.resistivity().getValue().doubleValue(), 1e-3); + assertEquals(1.7, props.capacitance().getValue().doubleValue(), 1e-3); + } + + @Test + @DisplayName("Test SEMI_COND_SCREEN thermal properties") + void testSemiCondScreenThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.SEMI_COND_SCREEN.getThermalProperties(); + assertNotNull(props); + assertEquals(2.5, props.resistivity().getValue().doubleValue(), 1e-3); + assertEquals(2.4, props.capacitance().getValue().doubleValue(), 1e-3); + } + + @Test + @DisplayName("Test SC_TAPE thermal properties") + void testScTapeThermalProperties() { + CableMaterial.ThermalProperties props = CableMaterial.SC_TAPE.getThermalProperties(); + assertNotNull(props); + assertEquals(6.0, props.resistivity().getValue().doubleValue(), 1e-3); + assertEquals(2.4, props.capacitance().getValue().doubleValue(), 1e-3); + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInputTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInputTest.java new file mode 100644 index 0000000000..9e158bde00 --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/type/CableTypeInputTest.java @@ -0,0 +1,558 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static edu.ie3.util.quantities.PowerSystemUnits.*; +import static org.junit.jupiter.api.Assertions.*; + +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; + +/** Unit tests for CableTypeInput class. */ +@DisplayName("CableTypeInput Tests") +class CableTypeInputTest { + + private UUID testUuid; + private ConductorInput conductor; + private List isolation; + private List filler; + private List armor; + private List jack; + private ComparableQuantity limitTemperature; + private ComparableQuantity frequency; + private ComparableQuantity electricalCapacitance; + + @BeforeEach + void setUp() { + testUuid = UUID.randomUUID(); + + // conductor + ComparableQuantity crossSection = Quantities.getQuantity(400.0e-6, Units.SQUARE_METRE); + ComparableQuantity diameter = Quantities.getQuantity(0.0225, Units.METRE); + ComparableQuantity thermalResistivity = + Quantities.getQuantity(1.0 / 384.0, KELVIN_METRE_PER_WATT); + ComparableQuantity thermalCapacitance = + Quantities.getQuantity(3449600.0, JOULE_PER_CUBIC_METRE_KELVIN); + conductor = + new ConductorInput( + UUID.fromString("793da55e-6021-4468-af1c-5ec61576bb20"), + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + + // isolation + isolation = new ArrayList<>(); + ComparableQuantity innerDiam = Quantities.getQuantity(0.0225, Units.METRE); + ComparableQuantity outerDiam = Quantities.getQuantity(0.027, Units.METRE); + ComparableQuantity layerThermalRes = + Quantities.getQuantity(3.5, KELVIN_METRE_PER_WATT); + ComparableQuantity layerThermalCap = + Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN); + + LayerInput isolationLayer = + new LayerInput( + UUID.randomUUID(), + "Main insulation", + CableMaterial.XLPE, + innerDiam, + outerDiam, + layerThermalRes, + layerThermalCap, + Optional.empty()); + isolation.add(isolationLayer); + + // other layers + filler = new ArrayList<>(); + armor = new ArrayList<>(); + jack = new ArrayList<>(); + + limitTemperature = Quantities.getQuantity(90.0, Units.CELSIUS); + frequency = Quantities.getQuantity(50.0, Units.HERTZ); + electricalCapacitance = Quantities.getQuantity(350e-9, Units.FARAD); + } + + @Test + @DisplayName("Test CableTypeInput creation with valid parameters") + void testCableTypeInputCreation() { + CableTypeInput cable = + new CableTypeInput( + testUuid, + "NA2XS2Y 1x120 RM/25 12/20 kV", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertNotNull(cable); + assertEquals(testUuid, cable.getUuid()); + assertEquals("NA2XS2Y 1x120 RM/25 12/20 kV", cable.getId()); + assertEquals(1, cable.getCoreNumber()); + } + + @Test + @DisplayName("Test CableTypeInput with three cores") + void testCableTypeInputThreeCores() { + CableTypeInput cable = + new CableTypeInput( + testUuid, + "3-core cable", + 3, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertEquals(3, cable.getCoreNumber()); + } + + @Test + @DisplayName("Test CableTypeInput empty ID validation") + void testCableTypeInputEmptyId() { + assertThrows(IllegalArgumentException.class, this::createCableTypeInputWithEmptyId); + } + + private void createCableTypeInputWithEmptyId() { + new CableTypeInput( + testUuid, + "", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + } + + @Test + @DisplayName("Test CableTypeInput invalid coreNumber validation") + void testCableTypeInputInvalidCoreNumber() { + assertThrows(IllegalArgumentException.class, this::createCableTypeInputWithInvalidCoreNumber); + } + + private void createCableTypeInputWithInvalidCoreNumber() { + new CableTypeInput( + testUuid, + "Test cable", + 0, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + } + + @Test + @DisplayName("Test CableTypeInput invalid frequency validation") + void testCableTypeInputInvalidFrequency() { + assertThrows(IllegalArgumentException.class, this::createCableTypeInputWithInvalidFrequency); + } + + private void createCableTypeInputWithInvalidFrequency() { + ComparableQuantity negativeFrequency = Quantities.getQuantity(-50.0, Units.HERTZ); + + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + negativeFrequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + } + + @Test + @DisplayName("Test CableTypeInput with screen layer") + void testCableTypeInputWithScreen() { + ComparableQuantity screenInner = Quantities.getQuantity(0.027, Units.METRE); + ComparableQuantity screenOuter = Quantities.getQuantity(0.028, Units.METRE); + ComparableQuantity wireDiameter = Quantities.getQuantity(0.0005, Units.METRE); + ComparableQuantity screenThermalRes = + Quantities.getQuantity(2.5, KELVIN_METRE_PER_WATT); + ComparableQuantity screenThermalCap = + Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN); + var electricResistivity = Quantities.getQuantity(1.7e-7, OHM_METRE); + + ScreenLayerInput screen = + new ScreenLayerInput( + UUID.randomUUID(), + "Copper screen", + CableMaterial.COPPER, + screenInner, + screenOuter, + screenThermalRes, + screenThermalCap, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + electricResistivity); + + CableTypeInput cable = + new CableTypeInput( + testUuid, + "Cable with screen", + 1, + conductor, + isolation, + Optional.of(screen), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertTrue(cable.getScreen().isPresent()); + assertEquals(screen, cable.getScreen().get()); + } + + @Test + @DisplayName("Test CableTypeInput equals method") + void testCableTypeInputEquals() { + CableTypeInput cable1 = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + CableTypeInput cable2 = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertEquals(cable1, cable2); + } + + @Test + @DisplayName("Test CableTypeInput hashCode consistency") + void testCableTypeInputHashCode() { + CableTypeInput cable1 = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + CableTypeInput cable2 = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertEquals(cable1.hashCode(), cable2.hashCode()); + } + + @Test + @DisplayName("Test CableTypeInput toString") + void testCableTypeInputToString() { + CableTypeInput cable = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + String str = cable.toString(); + assertNotNull(str); + assertTrue(str.contains("Test cable")); + } + + @Test + @DisplayName("Test CableTypeInput invalid skinEffectCoefficient validation") + void testCableTypeInputInvalidSkinEffectCoefficient() { + assertThrows( + IllegalArgumentException.class, this::createCableTypeInputWithInvalidSkinEffectCoefficient); + } + + private void createCableTypeInputWithInvalidSkinEffectCoefficient() { + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + -1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + } + + @Test + @DisplayName("Test CableTypeInput invalid tanDelta validation") + void testCableTypeInputInvalidTanDelta() { + assertThrows(IllegalArgumentException.class, this::createCableTypeInputWithInvalidTanDelta); + } + + private void createCableTypeInputWithInvalidTanDelta() { + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + -0.1, + 0.0, + 0.0); + } + + @Test + @DisplayName("Test CableTypeInput getters") + void testCableTypeInputGetters() { + CableTypeInput cable = + new CableTypeInput( + testUuid, + "Test cable", + 2, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.5, + 2.0, + electricalCapacitance, + 0.15, + 0.05, + 0.02); + + assertEquals(testUuid, cable.getUuid()); + assertEquals("Test cable", cable.getId()); + assertEquals(2, cable.getCoreNumber()); + assertEquals(conductor, cable.getConductor()); + assertEquals(isolation, cable.getIsolation()); + assertEquals(filler, cable.getFiller()); + assertEquals(armor, cable.getArmor()); + assertEquals(jack, cable.getJack()); + assertEquals(1.5, cable.getSkinEffectCoefficient(), 0.001); + assertEquals(2.0, cable.getProximityEffectCoefficient(), 0.001); + assertEquals(0.15, cable.getTanDelta(), 0.001); + assertEquals(0.05, cable.getCirculatingLossFactor(), 0.001); + assertEquals(0.02, cable.getEddyCurrentLossFactor(), 0.001); + } + + @Test + @DisplayName("Test CableTypeInput not equals for different UUIDs") + void testCableTypeInputNotEqualsUuid() { + UUID differentUuid = UUID.randomUUID(); + CableTypeInput cable1 = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + CableTypeInput cable2 = + new CableTypeInput( + differentUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + assertNotEquals(cable1, cable2); + } + + @Test + @DisplayName("Test CableTypeInput isolationElements list is immutable") + void testCableTypeInputIsolationElementsImmutable() { + CableTypeInput cable = + new CableTypeInput( + testUuid, + "Test cable", + 1, + conductor, + isolation, + Optional.empty(), + filler, + armor, + jack, + limitTemperature, + frequency, + 1.0, + 1.0, + electricalCapacitance, + 0.1, + 0.0, + 0.0); + + List retrievedLayers = cable.getIsolation(); + assertThrows(UnsupportedOperationException.class, () -> retrievedLayers.add(null)); + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/type/ConductorInputTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/type/ConductorInputTest.java new file mode 100644 index 0000000000..d7091ca8c6 --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/type/ConductorInputTest.java @@ -0,0 +1,417 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static edu.ie3.util.quantities.PowerSystemUnits.JOULE_PER_CUBIC_METRE_KELVIN; +import static edu.ie3.util.quantities.PowerSystemUnits.KELVIN_METRE_PER_WATT; +import static org.junit.jupiter.api.Assertions.*; + +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; + +/** Unit tests for ConductorInput class. */ +@DisplayName("ConductorInput Tests") +class ConductorInputTest { + + private UUID uuid; + private ComparableQuantity crossSection; + private ComparableQuantity diameter; + private ComparableQuantity thermalResistivity; + private ComparableQuantity thermalCapacitance; + + @BeforeEach + void setUp() { + uuid = UUID.fromString("d2074b88-1b54-4032-b721-e71f96f6b3ac"); + crossSection = Quantities.getQuantity(400e-6, Units.SQUARE_METRE); + diameter = Quantities.getQuantity(0.0225, Units.METRE); + thermalResistivity = Quantities.getQuantity(1.0 / 384.0, KELVIN_METRE_PER_WATT); + thermalCapacitance = Quantities.getQuantity(3449600.0, JOULE_PER_CUBIC_METRE_KELVIN); + } + + @Test + @DisplayName("Test ConductorInput creation with valid parameters") + void testConductorInputCreation() { + ConductorInput conductor = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertNotNull(conductor); + assertEquals(CableMaterial.COPPER, conductor.material()); + assertEquals(crossSection, conductor.crossSection()); + assertFalse(conductor.isCompacted()); + } + + @Test + @DisplayName("Test ConductorInput with compacted") + void testConductorInputCompacted() { + ConductorInput conductor = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + true, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertTrue(conductor.isCompacted()); + } + + @Test + @DisplayName("Test ConductorInput null material validation") + void testConductorInputNullMaterial() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + null, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput negative crossSection validation") + void testConductorInputNegativeCrossSection() { + ComparableQuantity negativeCrossSection = + Quantities.getQuantity(-1e-6, Units.SQUARE_METRE); + assertThrows( + IllegalArgumentException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + negativeCrossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput negative diameter validation") + void testConductorInputNegativeDiameter() { + ComparableQuantity negativeDiameter = Quantities.getQuantity(-0.001, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + negativeDiameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput with optional area") + void testConductorInputWithArea() { + ComparableQuantity area = Quantities.getQuantity(380e-6, Units.SQUARE_METRE); + ConductorInput conductor = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.of(area)); + assertTrue(conductor.area().isPresent()); + assertEquals(area, conductor.area().get()); + } + + @Test + @DisplayName("Test ConductorInput equals method") + void testConductorInputEquals() { + ConductorInput conductor1 = createValidConductor(); + ConductorInput conductor2 = createValidConductor(); + + assertEquals(conductor1, conductor2); + } + + @Test + @DisplayName("Test ConductorInput hashCode consistency") + void testConductorInputHashCode() { + ConductorInput conductor1 = createValidConductor(); + ConductorInput conductor2 = createValidConductor(); + + assertEquals(conductor1.hashCode(), conductor2.hashCode()); + } + + @Test + @DisplayName("Test ConductorInput toString") + void testConductorInputToString() { + ConductorInput conductor = createValidConductor(); + + String str = conductor.toString(); + assertNotNull(str); + assertTrue(str.contains("COPPER")); + } + + @Test + void testAreaOptionalEmptyByDefault() { + ConductorInput conductor = createValidConductor(); + assertTrue(conductor.area().isEmpty()); + } + + @Test + void testConductorInputNullOptionalArea() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + null)); + } + + @Test + void testConductorInputNullThermalResistivity() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + null, + thermalCapacitance, + Optional.empty())); + } + + @Test + void testConductorInputNullThermalCapacitance() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + null, + Optional.empty())); + } + + @Test + void testConductorInputNullName() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + null, + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + void testConductorInputEmptyName() { + assertThrows( + IllegalArgumentException.class, + () -> + new ConductorInput( + uuid, + "", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput with ALUMINIUM material") + void testConductorInputWithAluminium() { + ConductorInput conductor = + new ConductorInput( + uuid, + "conductor", + CableMaterial.ALUMINIUM, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertEquals(CableMaterial.ALUMINIUM, conductor.material()); + } + + @Test + @DisplayName("Test ConductorInput null crossSection validation") + void testConductorInputNullCrossSection() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + null, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput null diameter validation") + void testConductorInputNullDiameter() { + assertThrows( + NullPointerException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + null, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput negative thermalCapacitance validation") + void testConductorInputNegativeThermalCapacitance() { + ComparableQuantity negativeThermalCap = + Quantities.getQuantity(-1.0, JOULE_PER_CUBIC_METRE_KELVIN); + assertThrows( + IllegalArgumentException.class, + () -> + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + negativeThermalCap, + Optional.empty())); + } + + @Test + @DisplayName("Test ConductorInput not equals for different materials") + void testConductorInputNotEquals() { + ConductorInput conductor1 = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + ConductorInput conductor2 = + new ConductorInput( + uuid, + "conductor", + CableMaterial.ALUMINIUM, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertNotEquals(conductor1, conductor2); + } + + @Test + @DisplayName("Test ConductorInput not equals for different compacted state") + void testConductorInputNotEqualsCompacted() { + ConductorInput conductor1 = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + ConductorInput conductor2 = + new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + true, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertNotEquals(conductor1, conductor2); + } + + private ConductorInput createValidConductor() { + return new ConductorInput( + uuid, + "conductor", + CableMaterial.COPPER, + crossSection, + diameter, + false, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/type/LayerInputTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/type/LayerInputTest.java new file mode 100644 index 0000000000..56a5cedab7 --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/type/LayerInputTest.java @@ -0,0 +1,357 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static edu.ie3.util.quantities.PowerSystemUnits.JOULE_PER_CUBIC_METRE_KELVIN; +import static edu.ie3.util.quantities.PowerSystemUnits.KELVIN_METRE_PER_WATT; +import static org.junit.jupiter.api.Assertions.*; + +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; + +/** Unit tests for LayerInput class. */ +@DisplayName("LayerInput Tests") +class LayerInputTest { + private UUID uuid; + private ComparableQuantity innerDiameter; + private ComparableQuantity outerDiameter; + private ComparableQuantity thermalResistivity; + private ComparableQuantity thermalCapacitance; + + @BeforeEach + void setUp() { + uuid = UUID.randomUUID(); + innerDiameter = Quantities.getQuantity(0.01, Units.METRE); + outerDiameter = Quantities.getQuantity(0.015, Units.METRE); + thermalResistivity = Quantities.getQuantity(3.5, KELVIN_METRE_PER_WATT); + thermalCapacitance = Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN); + } + + @Test + @DisplayName("Test LayerInput creation with valid parameters") + void testLayerInputCreation() { + LayerInput layer = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertNotNull(layer); + assertEquals("Main insulation", layer.name()); + assertEquals(CableMaterial.XLPE, layer.material()); + } + + @Test + void testLayerInputNullName() { + assertThrows(NullPointerException.class, this::createLayerWithNullName); + } + + private void createLayerWithNullName() { + new LayerInput( + uuid, + null, + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + } + + @Test + void testLayerInputEmptyName() { + assertThrows(IllegalArgumentException.class, this::createLayerWithEmptyName); + } + + private void createLayerWithEmptyName() { + new LayerInput( + uuid, + "", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + } + + @Test + void testLayerInputNegativeOuterDiameter() { + ComparableQuantity negativeOuter = Quantities.getQuantity(-0.001, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> + new LayerInput( + uuid, + "Invalid", + CableMaterial.XLPE, + innerDiameter, + negativeOuter, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + void testAreaOptionalEmptyByDefault() { + LayerInput layer = createValidLayer(); + assertTrue(layer.area().isEmpty()); + } + + @Test + @DisplayName("Test LayerInput outerDiameter < innerDiameter validation") + void testLayerInputOuterDiameterLessThanInner() { + ComparableQuantity invalidOuter = Quantities.getQuantity(0.005, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> + new LayerInput( + uuid, + "Invalid layer", + CableMaterial.XLPE, + innerDiameter, + invalidOuter, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test LayerInput negative innerDiameter validation") + void testLayerInputNegativeInnerDiameter() { + ComparableQuantity negativeInner = Quantities.getQuantity(-0.001, Units.METRE); + assertThrows( + IllegalArgumentException.class, + () -> + new LayerInput( + uuid, + "Invalid layer", + CableMaterial.XLPE, + negativeInner, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test LayerInput negative thermalResistivity validation") + void testLayerInputNegativeThermalResistivity() { + ComparableQuantity negativeThermalRes = + Quantities.getQuantity(-1.0, KELVIN_METRE_PER_WATT); + assertThrows( + IllegalArgumentException.class, + () -> + new LayerInput( + uuid, + "Invalid layer", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + negativeThermalRes, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test LayerInput with optional area") + void testLayerInputWithArea() { + ComparableQuantity area = Quantities.getQuantity(50e-6, Units.SQUARE_METRE); + LayerInput layer = + new LayerInput( + uuid, + "Layer with area", + CableMaterial.PE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.of(area)); + assertTrue(layer.area().isPresent()); + assertEquals(area, layer.area().get()); + } + + @Test + @DisplayName("Test LayerInput equals method") + void testLayerInputEquals() { + LayerInput layer1 = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + LayerInput layer2 = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertEquals(layer1, layer2); + } + + @Test + @DisplayName("Test LayerInput hashCode consistency") + void testLayerInputHashCode() { + LayerInput layer1 = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + LayerInput layer2 = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertEquals(layer1.hashCode(), layer2.hashCode()); + } + + @Test + @DisplayName("Test LayerInput toString") + void testLayerInputToString() { + LayerInput layer = + new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + String str = layer.toString(); + assertNotNull(str); + assertTrue(str.contains("Main insulation")); + assertTrue(str.contains("XLPE")); + } + + @Test + @DisplayName("Test LayerInput with PVC material") + void testLayerInputWithPVC() { + LayerInput layer = + new LayerInput( + uuid, + "PVC jacket", + CableMaterial.PVC, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertEquals(CableMaterial.PVC, layer.material()); + } + + @Test + @DisplayName("Test LayerInput null material validation") + void testLayerInputNullMaterial() { + assertThrows( + NullPointerException.class, + () -> + new LayerInput( + uuid, + "Layer", + null, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test LayerInput null innerDiameter validation") + void testLayerInputNullInnerDiameter() { + assertThrows( + NullPointerException.class, + () -> + new LayerInput( + uuid, + "Layer", + CableMaterial.XLPE, + null, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty())); + } + + @Test + @DisplayName("Test LayerInput null Optional parameter validation") + void testLayerInputNullOptional() { + assertThrows( + NullPointerException.class, + () -> + new LayerInput( + uuid, + "Layer", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + null)); + } + + @Test + @DisplayName("Test LayerInput zero diameter validation") + void testLayerInputZeroDiameters() { + ComparableQuantity zeroDiameter = Quantities.getQuantity(0.0, Units.METRE); + LayerInput layer = + new LayerInput( + uuid, + "Zero layer", + CableMaterial.XLPE, + zeroDiameter, + zeroDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + assertNotNull(layer); + } + + private LayerInput createValidLayer() { + return new LayerInput( + uuid, + "Main insulation", + CableMaterial.XLPE, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty()); + } +} diff --git a/src/test/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInputTest.java b/src/test/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInputTest.java new file mode 100644 index 0000000000..3f5af3540a --- /dev/null +++ b/src/test/java/edu/ie3/datamodel/models/input/connector/type/ScreenLayerInputTest.java @@ -0,0 +1,377 @@ +/* + * © 2026. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.connector.type; + +import static edu.ie3.util.quantities.PowerSystemUnits.*; +import static org.junit.jupiter.api.Assertions.*; + +import edu.ie3.util.quantities.interfaces.ElectricalResistivity; +import edu.ie3.util.quantities.interfaces.ThermalCapacitance; +import edu.ie3.util.quantities.interfaces.ThermalResistivity; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Area; +import javax.measure.quantity.Length; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; + +/** Unit tests for ScreenLayerInput class. */ +@DisplayName("ScreenLayerInput Tests") +class ScreenLayerInputTest { + private UUID uuid; + private ComparableQuantity innerDiameter; + private ComparableQuantity outerDiameter; + private ComparableQuantity thermalResistivity; + private ComparableQuantity thermalCapacitance; + private ComparableQuantity wireDiameter; + private ComparableQuantity materialResistivity; + + @BeforeEach + void setUp() { + uuid = UUID.randomUUID(); + innerDiameter = Quantities.getQuantity(0.025, Units.METRE); + outerDiameter = Quantities.getQuantity(0.027, Units.METRE); + thermalResistivity = Quantities.getQuantity(2.5, KELVIN_METRE_PER_WATT); + thermalCapacitance = Quantities.getQuantity(2.4, JOULE_PER_CUBIC_METRE_KELVIN); + wireDiameter = Quantities.getQuantity(0.0005, Units.METRE); + materialResistivity = Quantities.getQuantity(1.7e-7, OHM_METRE); + } + + @Test + @DisplayName("Test ScreenLayerInput creation with valid parameters") + void testScreenLayerInputCreation() { + ScreenLayerInput screen = createValidScreenLayer(); + + assertNotNull(screen); + assertEquals("Copper screen", screen.name()); + assertEquals(CableMaterial.COPPER, screen.material()); + assertEquals(20, screen.wiresNumber()); + } + + @Test + @DisplayName("Test ScreenLayerInput null name validation") + void testScreenLayerInputNullName() { + assertThrows(NullPointerException.class, this::createScreenLayerInputWithNullName); + } + + private void createScreenLayerInputWithNullName() { + new ScreenLayerInput( + uuid, + null, + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput empty name validation") + void testScreenLayerInputEmptyName() { + assertThrows(IllegalArgumentException.class, this::createScreenLayerInputWithEmptyName); + } + + private void createScreenLayerInputWithEmptyName() { + new ScreenLayerInput( + uuid, + "", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput outerDiameter < innerDiameter validation") + void testScreenLayerInputOuterDiameterLessThanInner() { + assertThrows( + IllegalArgumentException.class, this::createScreenLayerInputWithInvalidOuterDiameter); + } + + private void createScreenLayerInputWithInvalidOuterDiameter() { + ComparableQuantity invalidOuter = Quantities.getQuantity(0.02, Units.METRE); + + new ScreenLayerInput( + uuid, + "Invalid screen", + CableMaterial.COPPER, + innerDiameter, + invalidOuter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput zero or negative wiresNumber validation") + void testScreenLayerInputNegativeWiresNumber() { + assertThrows( + IllegalArgumentException.class, this::createScreenLayerInputWithInvalidWiresNumber); + } + + private void createScreenLayerInputWithInvalidWiresNumber() { + new ScreenLayerInput( + uuid, + "Invalid screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 0, + wireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput negative wireDiameter validation") + void testScreenLayerInputNegativeWireDiameter() { + assertThrows( + IllegalArgumentException.class, this::createScreenLayerInputWithNegativeWireDiameter); + } + + private void createScreenLayerInputWithNegativeWireDiameter() { + ComparableQuantity negativeWireDiameter = Quantities.getQuantity(-0.001, Units.METRE); + + new ScreenLayerInput( + uuid, + "Invalid screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + negativeWireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput with optional lengthOfLay") + void testScreenLayerInputWithLengthOfLay() { + ComparableQuantity lengthOfLay = Quantities.getQuantity(0.02, Units.METRE); + ScreenLayerInput screen = + new ScreenLayerInput( + uuid, + "Copper screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.of(lengthOfLay), + materialResistivity); + assertTrue(screen.lengthOfLay().isPresent()); + assertEquals(lengthOfLay, screen.lengthOfLay().get()); + } + + @Test + @DisplayName("Test ScreenLayerInput with optional area") + void testScreenLayerInputWithArea() { + ComparableQuantity area = Quantities.getQuantity(5e-6, Units.SQUARE_METRE); + ScreenLayerInput screen = + new ScreenLayerInput( + uuid, + "Copper screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.of(area), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + assertTrue(screen.area().isPresent()); + assertEquals(area, screen.area().get()); + } + + @Test + @DisplayName("Test ScreenLayerInput equals method") + void testScreenLayerInputEquals() { + ScreenLayerInput screen1 = createValidScreenLayer(); + ScreenLayerInput screen2 = createValidScreenLayer(); + + assertEquals(screen1, screen2); + } + + @Test + @DisplayName("Test ScreenLayerInput hashCode consistency") + void testScreenLayerInputHashCode() { + ScreenLayerInput screen1 = createValidScreenLayer(); + ScreenLayerInput screen2 = createValidScreenLayer(); + + assertEquals(screen1.hashCode(), screen2.hashCode()); + } + + @Test + @DisplayName("Test ScreenLayerInput toString") + void testScreenLayerInputToString() { + ScreenLayerInput screen = createValidScreenLayer(); + + String str = screen.toString(); + assertNotNull(str); + assertTrue(str.contains("Copper screen")); + } + + @Test + @DisplayName("Test ScreenLayerInput with STEEL material") + void testScreenLayerInputWithSteel() { + ScreenLayerInput screen = + new ScreenLayerInput( + uuid, + "Steel screen", + CableMaterial.STEEL, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + assertEquals(CableMaterial.STEEL, screen.material()); + } + + @Test + @DisplayName("Test ScreenLayerInput null material validation") + void testScreenLayerInputNullMaterial() { + assertThrows(NullPointerException.class, this::createScreenLayerInputWithNullMaterial); + } + + private void createScreenLayerInputWithNullMaterial() { + new ScreenLayerInput( + uuid, + "Screen", + null, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput null materialResistivity validation") + void testScreenLayerInputNullMaterialResistivity() { + assertThrows( + NullPointerException.class, this::createScreenLayerInputWithNullMaterialResistivity); + } + + private void createScreenLayerInputWithNullMaterialResistivity() { + new ScreenLayerInput( + uuid, + "Screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + null); + } + + @Test + @DisplayName("Test ScreenLayerInput negative materialResistivity validation") + void testScreenLayerInputNegativeMaterialResistivity() { + assertThrows( + IllegalArgumentException.class, + this::createScreenLayerInputWithNegativeMaterialResistivity); + } + + private void createScreenLayerInputWithNegativeMaterialResistivity() { + ComparableQuantity negativeResistivity = + Quantities.getQuantity(-1.0, OHM_METRE); + + new ScreenLayerInput( + uuid, + "Screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + negativeResistivity); + } + + @Test + @DisplayName("Test ScreenLayerInput not equals for different wires number") + void testScreenLayerInputNotEqualsWires() { + ScreenLayerInput screen1 = createValidScreenLayer(); + + ScreenLayerInput screen2 = + new ScreenLayerInput( + uuid, + "Copper screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 30, // changed + wireDiameter, + Optional.empty(), + materialResistivity); + + assertNotEquals(screen1, screen2); + } + + private ScreenLayerInput createValidScreenLayer() { + return new ScreenLayerInput( + uuid, + "Copper screen", + CableMaterial.COPPER, + innerDiameter, + outerDiameter, + thermalResistivity, + thermalCapacitance, + Optional.empty(), + 20, + wireDiameter, + Optional.empty(), + materialResistivity); + } +}