diff --git a/doc/source/_ext/itu_materials_table.py b/doc/source/_ext/itu_materials_table.py new file mode 100644 index 00000000..a602705a --- /dev/null +++ b/doc/source/_ext/itu_materials_table.py @@ -0,0 +1,139 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +"""Sphinx extension: auto-generate ITU materials table. + +Provides the ``itu-materials-table`` directive. +""" + +from docutils import nodes +from docutils.parsers.rst import Directive + +class ITUMaterialsTableDirective(Directive): + def run(self): + from sionna.rt.radio_materials.itu import ITU_MATERIALS_PROPERTIES + from sionna.rt.radio_materials.itu_material import ITURadioMaterial + + table = nodes.table() + tgroup = nodes.tgroup(cols=7) + table += tgroup + + # Col specs + for w in [20, 10, 10, 10, 15, 10, 20]: + tgroup += nodes.colspec(colwidth=w) + + thead = nodes.thead() + tgroup += thead + + # Header Row 1 + row1 = nodes.row() + + entry_mat = nodes.entry(morerows=1) + entry_mat += nodes.paragraph('', 'Material type') + row1 += entry_mat + + entry_color = nodes.entry(morerows=1) + entry_color += nodes.paragraph('', 'Color') + row1 += entry_color + + entry_perm = nodes.entry(morecols=1) + entry_perm += nodes.paragraph('', 'Real part of relative permittivity') + row1 += entry_perm + + entry_cond = nodes.entry(morecols=1) + entry_cond += nodes.paragraph('', 'Conductivity [S/m]') + row1 += entry_cond + + entry_freq = nodes.entry(morerows=1) + entry_freq += nodes.paragraph('', 'Frequency range (GHz)') + row1 += entry_freq + + thead += row1 + + # Header Row 2 + row2 = nodes.row() + for text in ['a', 'b', 'c', 'd']: + entry = nodes.entry() + entry += nodes.paragraph('', text) + row2 += entry + thead += row2 + + tbody = nodes.tbody() + tgroup += tbody + + def create_entry(text, morerows=0): + entry = nodes.entry(morerows=morerows) + if text.startswith(':math:`') and text.endswith('`'): + math_text = text[7:-1] + p = nodes.paragraph() + p += nodes.math('', math_text) + entry += p + elif text.startswith('' + + num_ranges = len(ranges) + + for i, (f_range, params) in enumerate(ranges.items()): + row = nodes.row() + + if i == 0: + row += create_entry(name, morerows=num_ranges-1) + row += create_entry(color_col, morerows=num_ranges-1) + + a, b, c, d = params + + if c == 0: + c_str = "0" + elif c >= 0.0001: + c_str = str(c) + else: + c_str = f"{c:g}" + if "e" in c_str: + base, exp = c_str.split("e") + exp_val = int(exp) + c_str = f":math:`{base} \\times 10^{{{exp_val}}}`" + if c == 1e7: + c_str = r":math:`10^7`" + + if f_range[1] == 10.0 and name in ["very_dry_ground", "medium_dry_ground", "wet_ground"]: + freq_str = f"{f_range[0]:.1f} -- {f_range[1]:.0f} only" + else: + if f_range[0] == 0.001: + freq_str = f"{f_range[0]} -- {f_range[1]:.0f}" + elif f_range[0] == 0.1: + freq_str = f"{f_range[0]} -- {f_range[1]:.0f}" + else: + freq_str = f"{f_range[0]:.0f} -- {f_range[1]:.0f}" + + row += create_entry(str(a)) + row += create_entry(str(b)) + row += create_entry(c_str) + row += create_entry(str(d)) + row += create_entry(freq_str) + + tbody += row + + return [table] + +def setup(app): + app.add_directive("itu-materials-table", ITUMaterialsTableDirective) + return { + "version": "0.1", + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/source/api/radio_materials.rst b/doc/source/api/radio_materials.rst index d0c259c8..4ff9797d 100644 --- a/doc/source/api/radio_materials.rst +++ b/doc/source/api/radio_materials.rst @@ -53,7 +53,7 @@ are automatically updated according to the configured :attr:`~sionna.rt.Scene.fr .. _provided-materials: Through the :class:`~sionna.rt.ITURadioMaterial` class, Sionna provides the models of all of the materials -defined in the ITU-R P.2040-3 recommendation :cite:p:`ITURP20403`. These models are based on curve fitting to +defined in the ITU-R P.2040-4 recommendation :cite:p:`ITURP20404`. These models are based on curve fitting to measurement results and assume non-ionized and non-magnetic materials (:math:`\mu_r = 1`). Frequency dependence is modeled by @@ -67,52 +67,14 @@ Frequency dependence is modeled by where :math:`f_{\text{GHz}}` is the frequency in GHz, and the constants :math:`a`, :math:`b`, :math:`c`, and :math:`d` characterize the material. The table below provides their values which are used in Sionna -(from :cite:p:`ITURP20403`). +(from :cite:p:`ITURP20404`). Note that the relative permittivity :math:`\varepsilon_r` and conductivity :math:`\sigma` of all materials are updated automatically when the frequency is set through the scene's property :class:`~sionna.rt.Scene.frequency`. Moreover, by default, the scattering coefficient, :math:`S`, of these materials is set to 0, leading to no diffuse reflection. -+---------------------------+------------------------------------+--------------------------+-----------------------+ -| Material type | Real part of relative permittivity | Conductivity [S/m] | Frequency range (GHz) | -+ +-------------------+----------------+---------------+----------+ + -| | a | b | c | d | | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| vacuum | 1 | 0 | 0 | 0 | 0.001 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| concrete | 5.24 | 0 | 0.0462 | 0.7822 | 1 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| brick | 3.91 | 0 | 0.0238 | 0.16 | 1 -- 40 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| plasterboard | 2.73 | 0 | 0.0085 | 0.9395 | 1 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| wood | 1.99 | 0 | 0.0047 | 1.0718 | 0.001 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| glass | 6.31 | 0 | 0.0036 | 1.3394 | 0.1 -- 100 | -+ +-------------------+----------------+---------------+----------+-----------------------+ -| | 5.79 | 0 | 0.0004 | 1.658 | 220 -- 450 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| ceiling_board | 1.48 | 0 | 0.0011 | 1.0750 | 1 -- 100 | -+ +-------------------+----------------+---------------+----------+-----------------------+ -| | 1.52 | 0 | 0.0029 | 1.029 | 220 -- 450 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| chipboard | 2.58 | 0 | 0.0217 | 0.7800 | 1 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| plywood | 2.71 | 0 | 0.33 | 0 | 1 -- 40 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| marble | 7.074 | 0 | 0.0055 | 0.9262 | 1 -- 60 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| floorboard | 3.66 | 0 | 0.0044 | 1.3515 | 50 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| metal | 1 | 0 | :math:`10^7` | 0 | 1 -- 100 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| very_dry_ground | 3 | 0 | 0.00015 | 2.52 | 1 -- 10 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| medium_dry_ground | 15 | -0.1 | 0.035 | 1.63 | 1 -- 10 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ -| wet_ground | 30 | -0.4 | 0.15 | 1.30 | 1 -- 10 | -+---------------------------+-------------------+----------------+---------------+----------+-----------------------+ +.. itu-materials-table:: .. autoclass:: sionna.rt.RadioMaterialBase diff --git a/doc/source/conf.py b/doc/source/conf.py index b1de9614..81f20711 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -37,6 +37,7 @@ "sphinx_copybutton", "nbsphinx", "_ext.list_registry", + "_ext.itu_materials_table", ] autodoc_typehints = "description" typehints_fully_qualified = True diff --git a/doc/source/em_primer.rst b/doc/source/em_primer.rst index 202829ea..a8523d0b 100644 --- a/doc/source/em_primer.rst +++ b/doc/source/em_primer.rst @@ -431,7 +431,7 @@ The baseband equivalent channel impulse reponse is then defined as (Eq. 2.28) :c Reflection and Refraction ************************* -When a plane wave hits a plane interface which separates two materials, e.g., air and concrete, a part of the wave gets reflected and the other transmitted (or *refracted*), i.e., it propagates into the other material. We assume in the following description that both materials are uniform non-magnetic dielectrics, i.e., :math:`\mu_r=1`, and follow the definitions as in :cite:p:`ITURP20403`. The incoming wave phasor :math:`\mathbf{E}_\text{i}` is expressed by two arbitrary orthogonal polarization components, i.e., +When a plane wave hits a plane interface which separates two materials, e.g., air and concrete, a part of the wave gets reflected and the other transmitted (or *refracted*), i.e., it propagates into the other material. We assume in the following description that both materials are uniform non-magnetic dielectrics, i.e., :math:`\mu_r=1`, and follow the definitions as in :cite:p:`ITURP20404`. The incoming wave phasor :math:`\mathbf{E}_\text{i}` is expressed by two arbitrary orthogonal polarization components, i.e., .. math:: \mathbf{E}_\text{i} = E_{\text{i},s} \hat{\mathbf{e}}_{\text{i},s} + E_{\text{i},p} \hat{\mathbf{e}}_{\text{i},p} @@ -589,7 +589,7 @@ to assume that the object has a finite thickness. In such cases, the object can be modeled as a slab consisting of a single layer made of the same material, as shown in :numref:`fig_slab`. The reflection and transmission coefficients, which should be used instead of -:eq:`fresnel_vac`, are then computed as described in (Section 2.2.2.2) :cite:p:`ITURP20403`: +:eq:`fresnel_vac`, are then computed as described in (Section 2.2.2.2) :cite:p:`ITURP20404`: .. math:: :label: fresnel_slab diff --git a/doc/source/rt.bib b/doc/source/rt.bib index 5e4f061f..a5a5c1d5 100644 --- a/doc/source/rt.bib +++ b/doc/source/rt.bib @@ -79,8 +79,8 @@ @misc{Fresnel year = {}, } -@misc{ITURP20403, - title = {Recommendation {ITU-R} P.2040-3: Effects of building materials and structures on radiowave propagation above about 100 {MHz}}, +@misc{ITURP20404, + title = {Recommendation {ITU-R} P.2040-4: Effects of building materials and structures on radio-wave propagation in the range of 1 {MHz} to 450 {GHz}}, author = {{ITU}}, howpublished = {ITU-R Recommendation}, url = {https://www.itu.int/rec/R-REC-P.2040/en}, diff --git a/src/sionna/rt/radio_materials/itu.py b/src/sionna/rt/radio_materials/itu.py index 9bd7183f..c321aa7a 100644 --- a/src/sionna/rt/radio_materials/itu.py +++ b/src/sionna/rt/radio_materials/itu.py @@ -16,27 +16,54 @@ # Structure : # material_name: { (min_freq [GHz], max_freq [GHz]): (a, b, c, d) } ITU_MATERIALS_PROPERTIES = { - "concrete" : { (1., 100.) : (5.24, 0.0, 0.0462, 0.7822) }, + "vacuum" : { (0.001, 100.) : (1.0, 0.0, 0.0, 0.0) }, + + "concrete" : { (1., 100.) : (5.24, 0.0, 0.0462, 0.7822), + (110., 330.) : (5.17, 0.0, 0.0145, 1.0900) }, - "brick" : { (1., 40.) : (3.91, 0.0, 0.0238, 0.16) }, + "brick" : { (1., 40.) : (3.91, 0.0, 0.0238, 0.16), + (110., 330.) : (4.15, 0.0, 0.0006, 1.5712) }, - "plasterboard" : { (1., 100.) : (2.73, 0.0, 0.0085, 0.9395) }, + "plasterboard" : { (1., 100.) : (2.73, 0.0, 0.0085, 0.9395), + (110., 330.) : (2.56, 0.0, 0.0001, 1.7799), + (100., 400.) : (2.65, 0.0, 0.0002, 1.598) }, - "wood" : { (0.001, 100.) : (1.99, 0.0, 0.0047, 1.0718) }, + "wood" : { (0.001, 100.) : (1.99, 0.0, 0.0047, 1.0718), + (110., 330.) : (1.82, 0.0, 0.0040, 1.0761), + (100., 400.) : (2.1183, 0.0, 0.0055, 1.1113) }, "glass" : { (0.1, 100.) : (6.31, 0.0, 0.0036, 1.3394), - (220., 450.) : (5.79, 0.0, 0.0004, 1.658) }, + (220., 450.) : (5.79, 0.0, 0.0004, 1.658), + (100., 400.) : (6.5767, 0.0, 0.0012, 1.4697) }, + + "clear_acrylic" : { (110., 330.) : (2.58, 0.0, 0.0001, 1.6524) }, "ceiling_board" : { (1.0, 100.) : (1.48, 0.0, 0.0011, 1.0750), - (220., 450.) : (1.52, 0.0, 0.0029, 1.029) }, + (220., 450.) : (1.52, 0.0, 0.0029, 1.029), + (100., 400.) : (1.2567, 0.0, 0.00013, 1.454) }, + + "chipboard" : { (1.0, 100.) : (2.58, 0.0, 0.0217, 0.7800), + (100., 200.) : (2.16, 0.0, 0.0023, 1.359) }, + + "plywood" : { (1.0, 40.) : (2.71, 0.0, 0.33, 0.0), + (110., 330.) : (1.94, 0.0, 0.0067, 0.9982), + (100., 400.) : (2.17, 0.0, 0.0063, 1.045) }, + + "marble" : { (1.0, 60.) : (7.074, 0.0, 0.0055, 0.9262), + (110., 330.) : (7.94, 0.0, 0.0001, 1.7330), + (100., 400.) : (8.62, 0.0, 0.0027, 1.15) }, - "chipboard" : { (1.0, 100.) : (2.58, 0.0, 0.0217, 0.7800) }, + "floorboard" : { (50., 100.) : (3.66, 0.0, 0.0044, 1.3515), + (220., 300.) : (5.27, 0.0, 2.22e-17, 7.3413), + (300., 400.) : (5.27, 0.0, 0.0003, 2.0298), + (400., 450.) : (5.27, 0.0, 49.8726, 0.0), + (100., 400.) : (3.1575, 0.0, 0.001675, 1.32775) }, - "plywood" : { (1.0, 40.) : (2.71, 0.0, 0.33, 0.0) }, + "vinyl_tile" : { (1.0, 40.) : (3.62, 0.0, 0.0051, 0.8422) }, - "marble" : { (1.0, 60.) : (7.074, 0.0, 0.0055, 0.9262) }, + "carpet_tile" : { (1.0, 40.) : (2.08, 0.0, 0.0009, 0.8200) }, - "floorboard" : { (50., 100.) : (3.66, 0.0, 0.0044, 1.3515) }, + "asphalt_concrete" : { (1.0, 40.) : (4.83, 0.0, 0.0108, 1.3969) }, "metal" : { (1.0, 100.) : (1.0, 0.0, 1e7, 0.0) }, diff --git a/src/sionna/rt/radio_materials/itu_material.py b/src/sionna/rt/radio_materials/itu_material.py index f84110b3..f9db2cc5 100644 --- a/src/sionna/rt/radio_materials/itu_material.py +++ b/src/sionna/rt/radio_materials/itu_material.py @@ -14,11 +14,11 @@ class ITURadioMaterial(RadioMaterial): # pylint: disable=line-too-long r""" - Class implementing the materials defined in the ITU-R P.2040-3 recommendation :cite:p:`ITURP20403` + Class implementing the materials defined in the ITU-R P.2040-4 recommendation :cite:p:`ITURP20404` This class inherits from :class:`~sionna.rt.RadioMaterial`. - The models from the ITU-R P.2040-3 recommendation are based on curve fitting + The models from the ITU-R P.2040-4 recommendation are based on curve fitting to measurement results and assume non-ionized and non-magnetic materials (:math:`\mu_r = 1`). Frequency dependence is modeled by @@ -63,6 +63,10 @@ class ITURadioMaterial(RadioMaterial): "chipboard": (0.509, 0.159, 0.323), "plasterboard": (0.051, 0.539, 0.133), "plywood": (0.136, 0.076, 0.539), + "clear_acrylic": (0.8, 0.9, 0.95), + "vinyl_tile": (0.75, 0.75, 0.72), + "carpet_tile": (0.32, 0.35, 0.42), + "asphalt_concrete": (0.18, 0.18, 0.18), "very_dry_ground": (0.539, 0.319, 0.223), "medium_dry_ground": (0.539, 0.181, 0.076), "wet_ground": (0.539, 0.027, 0.147) diff --git a/src/sionna/rt/utils/electromagnetics.py b/src/sionna/rt/utils/electromagnetics.py index ebe84025..7caf9570 100644 --- a/src/sionna/rt/utils/electromagnetics.py +++ b/src/sionna/rt/utils/electromagnetics.py @@ -67,10 +67,10 @@ def itu_coefficients_single_layer_slab( r""" Computes the single-layer slab Fresnel transverse electric and magnetic reflection and refraction coefficients assuming the incident wave - propagates in vacuum using recommendation ITU-R P.2040 :cite:p:`ITURP20403` + propagates in vacuum using recommendation ITU-R P.2040-4 :cite:p:`ITURP20404` More precisely, this function implements equations (43) and (44) from - :cite:p:`ITURP20403`. + :cite:p:`ITURP20404`. :param cos_theta: Cosine of the angle of incidence :param eta: Complex-valued relative permittivity of the medium upon which the wave is incident diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 6d42641b..dfc40086 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -64,7 +64,7 @@ def ref_fresnel_reflection_coefficients_simplified(cos_theta, eta): def ref_itu_coefficient_multi_layer_slab(theta0, eta, d, wavelength, fix_sign=True): """ - Implements the multi-layer model from ITU-R P2040 for computing reflection + Implements the multi-layer model from ITU-R P.2040-4 for computing reflection and refraction coefficients """ @@ -159,13 +159,13 @@ def itu_concrete(fc): fc_GHz = fc / 1e9 - # From ITU-R P.2040, Table 3 + # From ITU-R P.2040-4, Table 3 a = 5.24 b = 0.0 c = 0.0462 d = 0.7822 - # From ITU-R P.2040, Equations (28), (29) + # From ITU-R P.2040-4, Equations (28), (29) sigma = c*np.power(fc_GHz, d) eta_r = a*np.power(fc_GHz, b) @@ -179,13 +179,13 @@ def itu_metal(fc): fc_GHz = fc / 1e9 - # From ITU-R P.2040, Table 3 + # From ITU-R P.2040-4, Table 3 a = 1.0 b = 0.0 c = 1e7 d = 0.0 - # From ITU-R P.2040, Equations (28), (29) + # From ITU-R P.2040-4, Equations (28), (29) sigma = c*np.power(fc_GHz, d) eta_r = a*np.power(fc_GHz, b)