Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions doc/source/_ext/itu_materials_table.py
Original file line number Diff line number Diff line change
@@ -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('<span'):
p = nodes.paragraph()
p += nodes.raw('', text, format='html')
entry += p
else:
p = nodes.paragraph('', text)
entry += p
return entry

for name, ranges in ITU_MATERIALS_PROPERTIES.items():
if name == "vacuum":
color_col = ""
else:
color = ITURadioMaterial.ITU_MATERIAL_COLORS.get(name, (0.0, 0.0, 0.0))
r, g, b = int(color[0]*255), int(color[1]*255), int(color[2]*255)
color_col = f'<span style="display:inline-block;width:15px;height:15px;background-color:rgb({r},{g},{b});border:1px solid #aaa;"></span>'

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,
}
44 changes: 3 additions & 41 deletions doc/source/api/radio_materials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"sphinx_copybutton",
"nbsphinx",
"_ext.list_registry",
"_ext.itu_materials_table",
]
autodoc_typehints = "description"
typehints_fully_qualified = True
Expand Down
4 changes: 2 additions & 2 deletions doc/source/em_primer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions doc/source/rt.bib
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
47 changes: 37 additions & 10 deletions src/sionna/rt/radio_materials/itu.py
Original file line number Diff line number Diff line change
Expand Up @@ -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) },

Expand Down
8 changes: 6 additions & 2 deletions src/sionna/rt/radio_materials/itu_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/sionna/rt/utils/electromagnetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions test/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""

Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down