Où placer son routeur Wi-Fi?

Physique et simulations !

En 2014, un doctorant en physique nommé Jason Cole s’intéresse au placement de son routeur Wi-Fi dans son appartement et publie à ce sujet un article de blog où il y décrit la manière dont il s’y est pris pour étudier le problème, en se basant sur la résolution d’un problème de physique (l’article est intitulé helmhurts, pour des raisons qui vont vous sembler évidentes dans quelques instants). 8 ans plus tard, et dans le contexte d’un cours que je dois donner, j’ai décidé d’en coder ma propre implémentation.

Le but ? À partir d’un plan en deux dimensions représentant un appartement avec la position d’un routeur Wi-Fi (opérant à 2.4 GHz), déterminer les endroits de l’appartement qui seront couverts par celui-ci. Par exemple:

routerkitchenhelmholtz.png
Résultat présenté par Jason Cole dans son article, représentant l’intensité du champ électrique généré par le routeur Wi-Fi (point rouge).

Par contre, mes images à moi seront vertes, pour donner un petit côté Matrix à la chose :zorro:

Un peu de maths et de physique

Il est nécessaire de comprendre la notion de dérivée pour suivre cette partie.

À propos des ondes électromagnétiques

Une onde est la propagation d’une perturbation produisant sur son passage une variation réversible des propriétés physiques locales du milieu et dont la vitesse de propagation dépend des caractéristiques du milieu en question. Plus précisément, une onde électromagnétique est l’oscillation du champ électrique (et magnétique) générées par des particules chargées qui accélèrent (ou par un dipôle oscillant).

Quand on parle de rayonnement électromagnétique, les équations de Maxwell ne sont jamais bien loin. Sous les conditions adéquates, la propagation d’une onde est régie par l'équation inhomogène des ondes (ou équation d’Alembert dans sa version homogène):

2E(x,t)1c22t2E(x,t)=S(x,t), avec 2=ix,y,z2xi2,\nabla^2 \mathcal E(\vec x, t) - \frac{1}{c^2}\frac{\partial^2}{\partial t^2}\mathcal E(\vec x, t) = -S(\vec x, t), \text{ avec } \nabla^2 = \sum_i^{x,y,z} \frac{\partial^2}{\partial x_i^2},

cc est la vitesse de l’onde (qui, dans le vide, correspond à la vitesse de la lumière) et S(x,t)S(\vec x, t) est généralement appelée "fonction source", car elle décrit les effets de la source d’onde sur le milieu. C’est une équation différentielle, ce qui signifie que toute fonction E(x,t)\mathcal E(\vec x, t) qui vérifie cette équation décrit effectivement le comportement d’une onde.

Par exemple: une onde monochromatique, c’est à dire E(x,t)=E(x)eiωt\mathcal E(\vec x, t) = E(\vec x)\,e^{-i\omega t}, où ω\omega est la pulsation de l’onde, avec ω=2πcλ\omega = \frac{2\pi\,c}{\lambda} (λ\lambda est la longueur d’onde). En effet, en supposant S(x,t)=s(x)eiωtS(\vec x, t)=s(\vec x)e^{-i\omega t}, si on substitue dans l’équation ci-dessus,1

2E(x,t)1c22t2E(x,t)=S(x,t)2[E(x)eiωt]1c22t2[E(x)eiωt]=s(x)eiωt(substitution)eiωt[2E(x)+ω2c2E(x)]=s(x)eiωt(mise en eˊvidence)2E(x)+ω2c2E(x)=s(x)(simplification)\begin{aligned} \nabla^2 \mathcal E(\vec x, t) - \frac{1}{c^2}\frac{\partial^2}{\partial t^2}\mathcal E(\vec x, t) = -S(\vec x, t) &\Leftrightarrow \nabla^2 [E(\vec x)\,e^{-i\omega t}] - \frac{1}{c^2}\frac{\partial^2}{\partial t^2}[E(\vec x)\,e^{-i\omega t}] = -s(\vec x)\,e^{-i\omega t} & \text{(substitution)} \\ &\Leftrightarrow e^{-i\omega t}\left[\nabla^2 E(\vec x) + \frac{\omega^2}{c^2}\,E(\vec x)\right] = -s(\vec x)\,e^{-i\omega t} & \text{(mise en évidence)}\\ &\Leftrightarrow \nabla^2 E(\vec x) + \frac{\omega^2}{c^2}\,E(\vec x) = -s(\vec x) & \text{(simplification)} \end{aligned}

ou encore, en définissant le nombre d’onde k=ωck = \frac{\omega}{c},

2E(x)+k2E(x)=s(x).\boxed{\nabla^2 E(\vec x) + k^2\,E(\vec x) = -s(\vec x)}.

Cette dernière version est appelée équation (inhomogène) d’Helmholtz. Elle décrit le comportement scalaire d’une onde monochromatique, c’est à dire son intensité en fonction de la position.

Pour ajouter à la difficulté, cette équation n’est valable que pour un milieu homogène, dans lequel la vitesse de l’onde est constante. Si on passe d’un milieu à un autre, la vitesse de l’onde change, selon le principe de la réfraction (qui modifie également l’angle) et plus particulièrement de la loi de Snell-Descartes. Puisqu’on cherche à simuler l’évolution d’une onde dans un milieu complexe (contenant à priori de l’air et des murs), on va donc modifier notre formule:

2E(x)+[n(x)k]2E(x)=s(x),\nabla^2 E(\vec x) + [n(\vec{x})\,k]^2\,E(\vec x) = -s(\vec x),

n(x)n(\vec x) est une fonction dont le sens est le même que celui de l'indice de réfraction: n(x)=1n(\vec x) = 1 pour une portion de l’espace composée d’air, n(x)>1n(\vec x) > 1 si on a autre chose.

Ceci dit, cela ne suffit pas: en effet, cette modification permet de tenir compte des propriétés de réfraction d’un mur (diffusion de l’onde dans le matériau et réflexion partielle de l’onde à l’interface avec celui-ci), mais ne modélise pas l'absorption d’une partie de l’onde par le mur (si ce n’était pas le cas, les ondes traverseraient le mur avec à peu près la même intensité en sortie qu’en entrée, et le monde serait à la fois plus simple et plus compliqué). Pour faire cela, une manière de faire est de donner une certaine conductivité électrique à notre matériau, et donc modifier notre équation comme suis:2

2E(x)+{[n(x)k]2ikσ(x)}E(x)=s(x),\boxed{\nabla^2 E(\vec x) + \left\{[n(\vec{x})\,k]^2-i\,k\,\sigma(\vec x)\right\}\,E(\vec x) = -s(\vec x)},

σ(x)=0\sigma(\vec x) = 0 dans l’air et σ(x)>0\sigma(\vec x) > 0 dans un matériau absorbant, et i=1i=\sqrt{-1}.

Les quantités ni,jn_{i,j} et σi,j\sigma_{i,j}, en plus de dépendre de la position, dépendent aussi de la longeur d’onde. Par exemple, quand on parle de l’indice de réfraction d’un matériau, on parle d’un indice de réfraction mesuré à une certaine longueur d’onde, typiquement aux alentours de 590 nm pour ceux qu'on utilise couramment (dû au fait qu’on utilise généralement la raie D du sodium pour les mesurer). Ici, on considère une onde Wi-Fi, donc λ10cm\lambda \approx 10 cm.

C’est cette équation que nous allons tenter par la suite de résoudre. Encore une fois: toute fonction E(x)E(\vec x) qui vérifie cette équation décrit le comportement de notre onde dans le milieu (complexe) que nous allons considérer. Néanmoins, cette fonction est difficile à obtenir analytiquement pour une raison assez évidente: elle dépend de s(x)s(\vec x). Dit autrement, l’intensité de l’onde à une position donnée dépend de la source qui la génère (oui, ça semble assez logique dit comme ça :-° ).

À la recherche d’une solution

Puisque obtenir une solution analytique est hors de question (exceptés cas très particuliers tels que s(x)=0s(\vec x) = 0), on va se tourner vers une solution numérique en utilisant la méthode des différences finies. Le principe est le suivant: on peut approximer une dérivée sur une dimension comme suis:

dfdx=limh0f(x+h)f(xh)2h et d2fdx2=limh0f(x+h)+f(xh)2f(x)h2,\frac{df}{dx} = \lim_{h\rightarrow 0} \frac{f(x+h)-f(x-h)}{2h} \text{ et } \frac{d^2f}{dx^2} = \lim_{h\rightarrow 0} \frac{f(x+h)+f(x-h)-2\,f(x)}{h^2},

hh est choisi en pratique suffisamment petit pour donner une bonne approximation de la dérivée.

Si on défini une grille de points en 2 dimensions composées de ×L\ell \times L rectangles de taille (hx,hy)(h_x, h_y) et où Ei,jE_{i,j} est la valeur de E(x)E(\vec x) au point x=(i,j)\vec x = (i, j) sur la grille, on a

2E(x)=2E(x)x2+2E(x)y2=Ei1,j+Ei+1,j2Ei,jhx2+Ei,j1+Ei,j+12Ei,jhy2.\nabla^2 E(\vec x) = \frac{\partial^2 E(\vec x)}{\partial x^2}+\frac{\partial^2 E(\vec x)}{\partial y^2} = \frac{E_{i-1,j}+E_{i+1,j}-2E_{i,j}}{h_x^2}+\frac{E_{i,j-1}+E_{i,j+1}-2E_{i,j}}{h_y^2}.

Dès lors, notre équation différentielle devient

Ei1,j+Ei+1,jhx2+Ei,j1+Ei,j+1hy2+{βi,j2hx22hy2}Ei,j=si,j, avec βi,j=[ni,jk]2ikσi,j\frac{E_{i-1,j}+E_{i+1,j}}{h_x^2}+\frac{E_{i,j-1}+E_{i,j+1}}{h_y^2} + \left\{\beta_{i,j}-\frac{2}{h_x^2}-\frac{2}{h_y^2}\right\}\,E_{i,j} = -s_{i,j}, \text{ avec } \beta_{i,j} = [n_{i,j}\,k]^2-i\,k\,\sigma_{i,j}

et ce pour chaque point (i,j)(i, j) de notre grille. Autrement dit, on a un ensemble de ×L\ell \times L équations à résoudre, dont les inconnues sont les Ei,jE_{i,j}. On peut représenter ce problème sous forme matricielle, après avoir condensé nos éléments Ei,jE_{i,j} et si,js_{i,j} en deux vecteurs colonnes:

[1hx21hy2βi,j2hx22hy21hy21hx2][Ei1,jEi,j1Ei,jEi,j+1Ei,j+1]=[si1,jsi,j1si,jsi,j+1si,j+1],\begin{bmatrix} & \vdots & \vdots& \vdots& \vdots& \vdots& \vdots& \vdots &\\ \cdots &\frac{1}{h_x^2} & \cdots & \frac{1}{h_y^2} & \beta_{i,j}-\frac{2}{h_x^2}-\frac{2}{h_y^2}& \frac{1}{h_y^2} & \cdots & \frac{1}{h_x^2} & \cdots \\ & \vdots & \vdots& \vdots& \vdots& \vdots& \vdots& \vdots & \\ \end{bmatrix} \,\begin{bmatrix} \vdots \\ E_{i-1,j} \\ \vdots \\ E_{i,j-1}\\ E_{i,j} \\ E_{i,j+1} \\ \vdots \\ E_{i,j+1} \\ \vdots \end{bmatrix} = -\begin{bmatrix} \vdots \\ s_{i-1,j} \\ \vdots \\ s_{i,j-1}\\ s_{i,j} \\ s_{i,j+1} \\ \vdots \\ s_{i,j+1} \\ \vdots \end{bmatrix},

ou plus simplement AE=s\mathbf A\,\vec E = -\vec s. Déterminer E\vec E revient donc à inverser A\mathbf A, puisque E=A1s\vec E = -\mathbf A^{-1}\,\vec s.

Problème de limites et limites du problème

On ne simule par un problème infini, loin s’en faut. Il faut donc gérer ce qui se passe aux limites de la simulation, en imposant des conditions au limite. Par exemple, pour déterminer E0,0E_{0,0}, on a besoin de E1,0E_{-1,0} et E0,1E_{0,-1}, qui n’existent pas.

Plusieurs solutions s’offrent à nous, mais certaines sont plus intéressantes dans ce cas que d’autre. Soit Ω=[0,)×[0,L)\Omega = [0,\ell) \times [0,L) notre domaine de simulation, dont les limites sont notées Ω\partial\Omega.

  1. Conditions aux limites de Dirichlet: définir aux limites du domaine une valeur pour la fonction. Typiquement, on va définir xΩ:E(x)=0\forall \vec x\in \partial\Omega: E(\vec x)=0. Bien que ce choix semble anodin (voir arbitraire), il a une conséquence intéressante: notre onde ne peut pas sortir du domaine de simulation (puisque sa valeur est de zéro en dehors de Ω\Omega).

  2. Conditions aux limite de Neumann: à l’inverse, c’est cette fois la valeur de la dérivée de E\vec E en Ω\partial\Omega qui sont fixées. En pratique, il suffit alors de rajouter un certain nombres d’équations le long de Ω\partial\Omega dans notre système. Ceci dit, il n’est possible d’obtenir une solution que si s(x)dx=0\int s(\vec x)\,d\vec x = 0, ce qui n’est pas notre cas.

  3. Conditions aux limites de Sommerfled: l’énergie rayonnée des sources doit se disperser à l’infini, et aucune energie ne peut rayonner de l’infini. Dans notre cas, cela revient à satisfaire

    limxx12(xik)E(x)=0\lim_{|\vec x| \to \infty} |\vec x|^{\frac{1}{2}} \left( \frac{\partial}{\partial |\vec x|} - ik \right) E(\vec x) = 0

    dans toutes les directions x\vec x à partir de la source.

Bien entendu, c’est la troisième condition qui est la plus adaptée à notre cas. Néanmoins, elle est un peu compliquée à mettre en place, et je vais donc tricher, en entourant le domaine de simulation d’une couche absorbante3 Ωabs\Omega_{abs} d’une certain épaisseur, et dont les caractéristiques seront xΩabs:n(x)=1σ(x)0\forall \vec x\in\Omega_{abs}: n(\vec x) = 1 \land \sigma(\vec x) \gg 0, combiné avec une condition de Dirichlet aux limites de celle-ci: xΩabs:E(x)=0\forall \vec x \in \partial\Omega_{abs}: E(\vec x)=0.

Au dela de nos problèmes pratico-pratiques, mathématiquement parlant, imposer une condition aux limites est la seule manière d’obtenir une solution unique à notre équation différentielle, qui sinon est obtenue à une constante près.


  1. En fait, on fait la transformée de Fourier du problème
  2. En fait, ça reviendrait au même si on repartait des équations de Maxwell, mais dans un milieu conducteur
  3. formellement, cette idée s’inspire de la méthode dite des couches absorbantes parfaitement adaptées

Un peu de code

Le code est disponible sur Github.

En entrée

Maintenant qu’on sait ce qu’on veut simuler et comment on veut le simuler, voyons comment je m’y suis pris. Je souhaitais pouvoir partir d’une image telle que celle-ci:

Plan d’un appartement. Les murs sont en noir, la source est indiquée en rouge.

Construction de la fonction source, contraste et conductivité

À partir de cette image, j’extrais une matrice I\mathcal I qui contient les valeurs RGB des pixels de l’image, et je construis ni,jn_{i,j}, σi,j\sigma_{i,j} et si,js_{i,j} (chaque pixel correspond à une valeur (i,j)(i,j), par simplicité). En l’occurrence, j’ai simplement choisi:

ni,j={2.4si Ii,j=noir,1sinon.,σi,j={0.1si Ii,j=noir,1 si (i,j)Ωabs,0sinon. et si,j={1si Ii,j=rouge,0sinon.n_{i,j} = \begin{cases}2.4 & \text{si } \mathcal I_{i,j} = \text{noir}, \\ 1 & \text{sinon}.\end{cases}, \sigma_{i,j} = \begin{cases}0.1 & \text{si } \mathcal I_{i,j} = \text{noir}, \\ 1 & \text{ si } (i,j) \in\Omega_{abs},\\ 0 & \text{sinon}.\end{cases} \text{ et } s_{i,j} = \begin{cases}1 & \text{si } \mathcal I_{i,j} = \text{rouge}, \\ 0 & \text{sinon}.\end{cases}

Les valeurs choisies sont purement arbitraires. En pratique, la valeur de 2.4 n’est pas trop éloignée de la valeur de l’indice de réfraction d’un mur (en béton), d’après mes prédécesseurs.1 La valeur de 0.1 pour la conductivité est probablement exagérée au regard des valeurs typiques pour d’autres matériaux (bien que cela dépende de la longeur d’onde employée). Finalement, la valeur de 1 pour la source est purement arbitraire, puisque ce qui m’intéresse ici c’est le contraste.

Je rajoute également une couche d’absorption autour du domaine. Pour sa taille, on conseille de la choisir équivalente à la longueur d’onde (le nombre de cases auquel cela va correspondre dépend de la résolution du plan). Une onde oscillant à 2.4 GHz correspond à une longueur d’onde d’environ 12 cm. À noter que dès lors, k=50.3k=50.3.

À propos de la résolution

Le choix de la résolution est plus important qu’il n’y parrait: on ne peut pas choisir n’importe quoi et espérer s’en sortir. En effet, la solution de l’équation d’Helmholtz dans le cas le plus simple [n(x)=1n(\vec x)=1, σ(x)=0\sigma(\vec x)=0, s(x)=0s(\vec x)=0 et avec une condition limite de type Dirichlet] est sin(kx)\sin(kx).

graph.png
Graphe de la fonction sin(kx)\sin(kx) avec k=50.3k=50.3 (correspondant à une onde de 2.4 GHz). Notez que l’abscisse est en mètres.

La distance entre deux maximums est d’à peu près 12 cm, c’est à dire la longueur d’onde. Si on veut obtenir ce résultat de manière correcte, il faut choisir une résolution suffisante (pour ceux qui savent ce que c’est, ça doit vous rappeler un problème d’échantillonnage). Typiquement,

h=2πkn,h = \frac{2\pi}{k\,n},

nn est le nombre de point qu’on souhaite utiliser pour décrire notre signal entre deux maximum.

Généralement, on veut n10n\geq 10, donc notre résolution pour 24 GHz devrait être de 1 pixel → 1cm. Pour traiter des problèmes intéressants (appartements de 50 à 100m²), il faudra donc utiliser des images dont les dimensions sont de plusieurs centaines de pixels pour chaque côté.

Résolution du système d’équation

Une conséquence du point précédent, c’est que le nombre d’inconnue est très important: autant que le nombre de pixels que contient l’image, plus celles pour la couche absorbante de taille aa, plus celles pour les conditions de Dirichlet, pour un total de N=(+2a+2)×(L+2a+2)2N = (\ell + 2a + 2) \times (L + 2a + 2) - 2. Si ça semble déjà beaucoup, rappelez vous que la matrice A\mathbf A que nous devrons construire contient N2N^2 éléments (puisque chaque ligne correspond à l’équation pour un élément Ei,jE_{i,j}).

Par exemple

Si on prend par exemple L==100L = \ell = 100 et a=12a=12, on a N=15 874 inconnues. A\mathbf A est donc de taille 15 874 x 15 874, soit pas moins de 251 983 876 nombres complexes. Si chaque nombre complexe est stocké sur 128 bits (2 flottants en double précision, double), cette matrice requiert 3.75 Gio de mémoire. Et là, on a juste simulé un carré de 1 mètre de côté, soit rien de bien fou.

Heureusement pour nous, cette matrice est essentiellement vide. En effet, chaque ligne ne contient que 5 valeurs non-nulles, correspondant à Ei1,jE_{i-1,j}, Ei,j1E_{i, j-1}, Ei,jE_{i,j}, Ei,j+1E_{i,j+1} et Ei+1,jE_{i+1,j}. Sur notre exemple précédent, à peu près 15N1-\frac{5}{N} = 99.97% de la matrice est nulle, et ce nombre augmente avec NN. Pour gagner de la place, on peut imaginer partir du principe que les éléments de la matrice sont tous nuls, et ne stocker que les éléments qui ne le sont pas: c’est ce qu’on appelle une matrice creuse.

Toute bibliothèque un peu sérieuse permettant le calcul matriciel propose une structure de matrice creuse (sparse matrix) et les opérations qui lui sont associées. Dans mon cas, puisque j’utilise Python pour des raisons de facilité, c’est scipy.sparse que j’emploierai. À noter que dans la plupart des langages, une matrice creuse est immutable. Autrement dit, lui ajouter un élément après création est impossible, pour des raisons d’optimisation: il faut en recréer une nouvelle.

Pour créer matrice creuse, par exemple

A=[100020003],\mathbf A = \begin{bmatrix} 1 & 0&0 \\ 0 & 2 &0 \\ 0 & 0 &3 \end{bmatrix},

la documentation recommande la manière suivante (qui est courante dans différentes librairies):

from scipy.sparse import csc_matrix # CSC = Compressed Sparse Column

indices_ligne = [0, 1, 2]
indices_colonne = [0, 1, 2]
valeurs = [1, 2, 3]
# autrement dit, A[0,0] = 1, A[1,1] = 2 et A[2,2] = 3

A = csc_matrix((valeurs, (indices_ligne, indices_colonne)), shape=(3, 3))

En effet, la fonction crée la matrice en utilisant la relation A[indice_ligne[k], indices_colonne[k]] = valeurs[k]. Autrement dit, il faut d’abord en lister les différentes valeurs.

Pour rappel, ce qui nous intéresse, c’est de résoudre le système AE=s\mathbf A\,\vec E = \vec s. Ceci dit, si on inverse directement A\mathbf A pour calculer ensuite A1s\mathbf A^{-1}\,\vec s, on risque d’avoir une petite surprise: en effet, autant A\mathbf A est effectivement creuse, autant il y a peu de chance que A1\mathbf A^{-1} le soit, augmentant drastiquement le besoin en stockage ! C’est d’autant plus dommage que A1\mathbf A^{-1} n’est qu’un intermédiaire. Heureusement, le module d'algèbre linéaire de scipy propose directement la fonction spsolve pour résoudre de tels systèmes, sans explicitement stocker A1\mathbf A^{-1}:

import numpy
from scipy.sparse.linalg import spsolve
s = numpy.array([2, 3, 0])
E = spsolve(A, s) # E = [2, 1.5, 0]

Et vous pouvez vérifier que

{x=22y=33z=0[100020003]A[xyz]E=[230]sE=[2320].\begin{cases}x=2\\2y=3\\3z=0\end{cases} \Leftrightarrow \underbrace{\begin{bmatrix} 1 & 0&0 \\ 0 & 2 &0 \\ 0 & 0 &3 \end{bmatrix}}_{\mathbf A}\,\underbrace{\begin{bmatrix}x\\y\\z\end{bmatrix}}_{\vec E} = \underbrace{\begin{bmatrix}2\\3\\0\end{bmatrix}}_{\vec s} \Leftrightarrow \vec E = \begin{bmatrix}2\\\frac{3}{2}\\0\end{bmatrix}.

Bref, il "suffit" de décrire chacun des éléments de A\mathbf A tels que décrit plus haut et le tour est joué. Yapluka :pirate:

En sortie

Une fois E\vec E calculé, il n’y a plus qu’à l’afficher. Plutôt que de représenter directement E\vec E, je vais m’intéresser à la puissance (en décibels), Pi,j=20log10Ei,jP_{i,j} = 20\log_{10}{|E_{i,j}|}, où Ei,j|E_{i,j}| est le module de Ei,jE_{i,j} (qui est un nombre complexe). Une petite échelle de couleur plus tard (et l’utilisation d’un gradient pour détecter le contour des murs), voici le résultat:

Intensité d’une onde de 2.4 GHz dans la pièce présenté plus haut. Noir → P <= -100 dB, vert → P = -85 dB, blanc → P => -70 dB. Notez la réflexion sur le mur de droite.

On voit que la distribution est loin d’être uniforme. Vu la résolution choisie, c’est loin d’être inattendu (voir plus haut). En particulier, on remarque que les tâches (qui sont les endroits ou l’intensité est importante) sont d’à peu près 6px de hauteur, soit 6 cm dans la réalité, ce qui est raccord avec la longueur d’onde.

Suite de l’exemple

Afin de démontrer une dernière fois l’intérêt d’utiliser des matrices creuses, j’utilise l’exemple suivant:2

test2.png tmpz9bouv_1.PNG

Le plan est à gauche, le résultat attendu à droite.

Sur mon Ryzen 5 1500X de 2018 et 8 processeurs (les codes de numpy.linalg et scipy.sparse.linalg étant parallélisé),

  • le code python exploitant scipy.sparse.linalg et une matrice creuse s’exécute en 800 ms et consomme 82 Mio de mémoire
  • le code python utilisant numpy.linalg et donc la matrice complète s’exécute en 2 minutes 32 secondes et consomme 3.98 Gio de mémoire.

Il n’y a pas photo :magicien:


  1. Globalement, trouver des valeurs d’indice de réfraction dans le domaine des Gigahertz, c’est chiant. Je m’y prends probablement mal, mais je ne trouve généralement pas grand chose.
  2. Sur l’image 200x300 ci-dessus, le code s’arrête bien vite avec l’erreur suivante : numpy.core._exceptions._ArrayMemoryError: Unable to allocate 80.9 GiB for an array with shape (73676, 73676) and data type complex128. Ça se passe de commentaires :p

Jouons un peu !

Maintenant que j’ai un code fonctionnel ou toutes les constantes citées plus haut (indice de réfraction, conductivité, etc) sont devenu des variables, on va pouvoir s’amuser un peu. Et pour ce faire, je vous présente le plan de mon (ancien !) appartement. 50 m² (soit plus petit que celui de Jason Cole !) rien que pour moi et mon chat:

Plan à peu près fidèle de mon ancien appartement (j’avais certaines mesures, j’ai improvisé pour les autres). Les lignes plus fines sont les portes et fenêtres, les mur plus épais sont ceux du bâtiment. La cage d’escalier ne faisait pas partie de l’appartement. Pour des raisons de facilité, lorsque j’ai eu la fibre, mon routeur a été placé dans le coin inférieur droit du salon (là ou se trouvait mon bureau).

Disons que le plus intéressant, c’est de capter le Wi-Fi dans la chambre (pour les séries au calme), dans la cuisine (pour les recettes de cuisine et YouTube quand on cuisine) et dans les toilettes (parce que réseaux sociaux). Eh bien le résultat est le suivant:

tmp0gcnv0a6.PNG
Résultat pour le routeur dans le coin inférieur droit du salon. Pour info, le calcul a été effectué en 54 secondes et a demandé 3 Gio de mémoire.

Clairement, la réflexion sur le mur aide à obtenir un bon signal au niveau de la cuisine et de la toilette. Par contre, et on l’avait déjà vu plus haut, les murs sont assez mauvais pour laisser passer du signal, ce qui fait que celui-ci est bien moins important dans la chambre. Notez bien que noir ne veut pas dire absence de signal, c’est juste une question d’échelle (ici entre -100 et -70 dB).

Changer de position

Évidement, je suis libre de déplacer mon routeur (à condition qu’il y ait une prise adaptée pas loin, ou que j’utilise un RJ45 assez long). Voici quelques résultats:

tmpd5mb009x.PNG
Résultat pour l’emplacement du routeur avant que je n’aie la fibre (la prise du téléphone étant placée à cet endroit), dans le coin supérieur droit du salon.
tmpmmo3h9e9.PNG
Résultat pour le routeur placé directement au point d’entrée de la fibre (qui court le long des murs extérieurs de l’appartement, longue histoire) dans l’appartement, dans le coin inférieur droit de la chambre. Mauvaise idée ;)
tmpqouazgxx.PNG
Position irréaliste en pratique, mais sympa pour arroser tout l’appartement.
tmp4a8zgd6j.PNG
Autre position irréaliste en pratique, mais sympa sur le papier. Notez qu’on retrouve ici une transmission radiale du signal, qui n’était pas très visible sur les exemples précédents à cause des interférences dues à la réflexion sur les murs.

Ce qu’il faut retenir, c’est que les murs de ma simulation réfléchissent assez bien les ondes Wi-Fi. Je vais vous montrer quel est l’effet de changer l’indice de réfraction juste ci-dessous, mais notez bien que ce n’est pas tout à fait irréaliste: l’indice de réfraction d’un mur est élevé !

Changer l’indice de réfraction des murs

Pour le fun de la chose, imaginons que nos murs ont un indice de réfraction différent de 2.4. Essayons avec 2 extrêmes :

tmpcwoy63no.PNG
Résultat pour un indice de réfraction de 1.21 pour les murs, à comparer avec celui ci-dessus. La réflexion est bien moins importante, et laisse sa place à la transmission.
tmpzcxm5nld.PNG
Résultat pour un indice de réfraction de 5.2 On voit qu’à l’inverse, tout passe dans la réflexion.

Ces différences s’expliquent par la loi de Fresnel:

Une onde incidente EiE_i passe d’un milieu n1n_1 à un autre, d’indice de réfraction n2n_2: une partie ErE_r est réfléchie, une autre est transmise et réfractée, EtE_t (source: Wikipédia).

La loi de Fresnel énonce que le coefficient de réflexion (c’est à dire le pourcentage de l’onde qui sera réfléchie) évolue comme

n1cosθ1n2cosθ2n1cosθ1+n2cosθ2.\frac{n_1\cos\theta_1-n_2\cos\theta_2}{n_1\cos\theta_1+n_2\cos\theta_2}.

Pour n1n2n_1\approx n_2, le coefficient de réflexion sera très proche de zéro, et une majorité de l’onde sera transmise dans le matériau. À l’inverse, pour n1n2n_1 \ll n_2, le coefficient de transmission sera beaucoup plus important. À noter qu’il existe un angle pour lequel la réflexion est totale, donné par θ=arcsin(n2n1)\theta = \arcsin(\frac{n_2}{n_1}), dont on voit bien qu’il diminue si n2n_2 augmente !

Changer la fréquence

Vous n’êtes pas sans savoir que depuis l’article de Jason Cole en 2014, il y a un peu d’eau qui a coulé sous les ponts et que le Wi-Fi à 5 GHz est maintenant courant (bien que la première implémentation de cette idée correspond à la norme IEEE 802.11a de … 1999). Vu que sa fréquence est plus élevée, la vitesse de transmission des données est supérieure avec cette fréquence. Par contre …

tmptq64rqqg.PNG
Résultat de la simulation pour une fréquence de 5 GHz. Attention: je n’ai pas changé la résolution spaciale pour être cohérent avec les résultats précédents, ce qui est un problème (5 GHz → λ\lambda = 6cm, échantillonnage insuffisant). Encore une fois, il se passe des trucs très marrant avec la réflexion.

… Il passe beaucoup moins bien les murs. Bien que je ne parierais pas ma vie sur la qualité de cette simulation, c’est la réalité: un Wi-Fi 5 GHz est beaucoup plus sensible aux obstacles qu’un Wi-Fi 2.4 GHz, et s’atténuera plus vite.3


  1. Qui déjà plus proche de celui de l’eau ou du bois, si vous voulez un équivalent.
  2. Ce qui est, euuuh … Beaucoup, surtout à cette fréquence : l’indice de réfraction a tendance à tendre vers 1 lorsqu’on augmente la longueur d’onde / diminue la fréquence.
  3. D’autant qu’en pratique, l’indice de réfraction est légèrement supérieur pour une onde à 5 GHz qu’à 2.4 Ghz

Voilà, j’espère que cette petite modélisation vous à intéressé. Si vous deviez retenir quelque chose de tout ça, c’est que oui, vos murs réfléchissent les ondes Wi-Fi.

Bien entendu, la simulation est loin d’être parfaite, et on peut pointer les approximations suivantes:

  1. Il s’agit d’une modélisation en 2 dimensions, alors que vous et moi vivons dans un monde en 3 dimensions. Si ça semble un détail, n’oubliez pas que l’onde peut également se réfléchir sur le plafond et le sol. Par ailleurs, les pièces sont vides: certains objets (en particulier les objets métalliques !) peuvent drastiquement affecter le profil obtenu.
  2. La source est assez mal modélisée: normalement, on utilise une fonction delta de Dirac ou quelque chose qui s’en rapproche pour éviter d’être dépendant à la forme de la source. Néanmoins, dans la vraie vie , c’est une antenne dipôle qui équipe la plupart des routeurs, et qui devrait être décrite différemment (mais on est trop loin de mon domaine de compétence !).
  3. Le choix d’une fréquence fixe et unique de 2.4 GHz est également une approximation, puisque la bande Wi-Fi est découpé en canaux d’une largeur de 22 MHz compris entre 2.4 et 2.5 GHz. C’est un commentaire qui a déjà été fait à Jason Cole, pour ceux que ça intéresse.
  4. Le choix d’une modélisation indépendante du temps (équation de Helmholtz) est une approximation en soit (normalement, elle correspond à une situation d’équilibre). On peut employer une autre méthode basée sur les différences finies, la méthode finite difference time domain (FDTD) qui permet de tenir compte du temps, et inclus également l’effet du champ magnétique. Il n’est pas impossible que je tente cette méthode dans une suite :pirate:

Sources et documents intéressants:

Je vous rappelle à toutes fins utiles que vous pouvez exécuter le code sur votre ordinateur, puisque celui-ci est disponible sur Github (vous avez même les images sources).

  • L'article original de Jason Cole. À noter que dans son article, il écrit que la formule d’Helmholtz qu’il utilise est 2E+k2n2E=f,\nabla^2 E + \frac{k^2}{n^2}E = f, alors que nn doit être au numérateur, ce qu’il a expliqué en commentaire, mais on retrouve du coup cette erreur à d’autres endroits.
  • Deux implémentations en Julia de l’idée originale de Jason Cole: ici et , la seconde étant inspirée de la première. Bien que le Julia employé y soit un peu vieux (version 1.0) et que nn y soit au dénominateur, ça a été la base de mon code.
  • Cet énoncé de projet par Bertrand Thierry, qui a le bon goût d’être en français, et dont vous reconnaîtrez qu’il m’a servi d’inspiration pour les deux premières parties.
  • Cet article scientifique, qui décrit la méthode de l’équation d’Helmholtz (bien que ça ne soit pas le cœur du papier) et ou les constantes sont au bon endroit. L’idée d’utiliser la conductivité dans ma simulation est d’eux.
  • Wikipédia, encore Wikipédia et toujours Wikipédia, comme en témoigne les très nombreux liens qui parsèment le document, bien que comme d’habitude en physique, la version anglaise est généralement plus fournie.

4 commentaires

on va se tourner vers une solution numérique en utilisant la méthode des éléments finis qui est couramment employée dans ce genre de cas. Le principe est le suivant: on peut approximer une dérivée sur une dimension en utilisant une différence finie

La méthode des éléments finis et celle des différences finies n’ont rien à voir. Ce que tu fais sont des différences finies, qui discrétisent l’espace de définition pour obtenir un système d’équations de taille finie. La méthode des éléments finis discrétise à la place l’espace des fonctions solutions (aussi dans le but d’obtenir un système de taille finie). Les deux formulations sont équivalentes dans certains cas dégénérés, mais c’est pas spécialement quelque chose de profond (e.g. chercher des fonctions linéaires par morceaux est trivialement équivalent à chercher des solutions sur un espace discret qu’on prolonge linéairement si les points d’ancrage sont les mêmes).

+3 -0

J’ai relu et je n’ai pas vu de fautes choquantes.

Cependant je pense qu’on donnant un petit plus de détails, tu pourrais le rendre plus accessible. Beaucoup de tes notations ou de tes expressions ne sont pas définies.

Par exemple lambda qui est la longueur d’onde n’est pas définie (même si ça doit être évident). De même pour la conductivité électrique dont la notation apparaît dans l’équation comme ça sans être bien annoncée (ok ça se devine mais bon).

D’un point de vue physique, j’ajouterais des précisions supplémentaires :

  • Évoquer le théorème de Shannon (ou théorème d’échantillonnage) pour justifier ta formule, le lecteur avisé saura plus facilement d’où ça vient (et comprendre la démonstration si nécessaire) ;
  • Justifier pourquoi l’indice de réfraction et la conductivité électrique n’apparaissent pas dans la partie des dérivées partielles secondes de ton équation ;
  • Rappeler (car ce n’est pas intuitif) que le mur réfléchi nos ondes Wifi tout comme ils réfléchissent la lumière, car ce sont aussi des ondes électromagnétiques.

Ce n’est pas grand chose je pense mais ça permettrait de baisser le niveau des pré requis du niveau supérieur au niveau secondaire (ou lycée) qui n’a pas peur d’une grosse formule.

Après on pourrait pousser le vice et modéliser le tout en 3D, avec un immeuble ou une maison remplie. :D Simuler les antennes ne devraient pas être trop difficiles non plus techniquement. Perso dans mon logement le changement de parquet (avec la pose d’une fine couche isolante avec un revêtement métal) a détruit la propagation du signal vers l’étage. J’ai du acheter un routeur Wifi relié par câble pour diffuser séparément à l’étage.

+2 -0

Ah oui j’oubliais, les -dB (ou -dbM, comme tu veux) tu peux aussi donner un ordre de l’échelle de ce que ça donne pour le Wifi et la 4G entre un bon signal et une absence de signal, pour avoir un ordre d’idée en tête.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte