Skip to content
Snippets Groups Projects
Commit 7bb46eca authored by Lionel GUEZ's avatar Lionel GUEZ
Browse files

`delta_out` and `delta_in` should not increase

Bug fix in procedure overlap: `delta_out` and `delta_in` should not increase.
parent 8c9b7b72
No related branches found
No related tags found
No related merge requests found
......@@ -8,3 +8,4 @@ window.pdf
periodicity.pdf
copy.pdf
set_all_outerm.pdf
overlap.pdf
sources = window processes m3 call_graph input_output degeneracy periodicity copy set_all_outerm
sources = window processes m3 call_graph input_output degeneracy periodicity copy set_all_outerm overlap
objects := $(addsuffix .pdf, ${sources})
......
No preview for this file type
File added
......@@ -59,6 +59,8 @@ de la vitesse.
But du programme : produire une base de données de tourbillons. Le
programme ne traite qu'une date.
Compilation et exécution testées avec NAG Fortran Compiler Release 6.2.
\subsection{Cas pathologiques}
\verb+out_cont+ est vide si et seulement s'il n'y a
......@@ -950,6 +952,13 @@ Le graphe est orienté acyclique. L'ordre topologique est tout trouvé :
numérotation par dates successives. Le graphe non orienté associé est
une forêt.
Notons ici $k_b$, $k_e$, $\max \delta$ et $n_p$ les valeurs contenues
dans les variables Fortran \verb+k_begin+, \verb+k_end+,
\verb+max_delta+ et \verb+n_proc+ respectivement.
On ne cherche des superpositions qu'entres tourbillons visibles, en
excluant les tourbillons interpolés.
Pour comparer les tourbillons à deux dates, il semble coûteux de
n'utiliser que les listes de tourbillons aux deux dates. Cela implique
une double boucle sur les listes de tourbillons, à l'intérieur d'une
......@@ -958,11 +967,33 @@ $8000 \times 8000 \times 5000$ comparaisons. Pour éviter cette
comparaison aveugle, on peut conserver l'information sur la position
des tourbillons dans des cartes aux différentes dates. La conservation
en mémoire vive à 5000 dates semble aussi trop lourde. Il faut se
restreindre aux cinq (\verb+max_delta+ + 1) dates nécessaires à la
restreindre aux cinq ($\max \delta$ + 1) dates nécessaires à la
profondeur de vue.
Un tourbillon donné $i_1$ à une date donnée $k$ peut avoir des
successeurs à différentes distances temporelles. Supposons que nous
ayons trouvé un successeur du tourbillon $(k, i_1)$ à une distance
$\delta$. Un tourbillon $(k + \delta', i_2)$ à une distance
$\delta' > \delta$ peut être enregistré comme successeur de $(k, i_1)$
si $(k + \delta', i_2)$ n'a pas de prédécesseur à distance strictement
inférieure à $\delta'$. De même, un tourbillon donné à une date donnée
peut avoir des prédécesseurs à différentes distances
temporelles. Cf. figure (\ref{fig:overlap}) et commentaires sur
overlap.
\begin{figure}[htbp]
\centering
\includegraphics{overlap}
\caption{Un morceau d'un graphe de recouvrement. Un tourbillon peut
avoir des prédécesseurs et des successeurs à différentes distances
temporelles. Dans cet exemple, $i_1$ ne peut pas avoir de
successeur à distance strictement inférieure à $\delta$. $i_2$ ne
peut pas être le successeur de $i'_1$ : le recouvrement de $i_2$
et $i'_1$ n'est pas examiné dans la procédure overlap.}
\label{fig:overlap}
\end{figure}
Lorsqu'on compare des tourbillons à distance temporelle delta (entre 1
et \verb+max_delta+), on veut tester s'ils n'ont pas de prédécesseur ou
et $\max \delta$), on veut tester s'ils n'ont pas de prédécesseur ou
successeur visible à une date intermédiaire. Il faut donc, si on crée
un arc entre deux dates successives, ou delta arcs à distance delta
(par interpolation de tourbillons invisibles), enregistrer ce fait en
......@@ -975,11 +1006,8 @@ chaque tourbillon, non seulement s'il a des prédécesseurs visibles et
s'il a des successeurs visibles, mais aussi à quelle distance
temporelle.
On ne cherche des superpositions qu'entres tourbillons visibles, en
excluant les tourbillons interpolés.
On pourrait écrire l'algorithme principal en explicitant les
\verb+get_snpashot+, en explicitant le cas m < \verb+n_proc+ et en supprimant la
\verb+get_snpashot+, en explicitant le cas m < $n_p$ et en supprimant la
variable \verb+k_end_main_loop+. Ce serait mieux du point de vue de la
performance, mais je pense que ce serait finalement moins clair.
......@@ -1003,6 +1031,8 @@ Ces procédures sont appelées par :
\end{itemize}
Cf. discussion autour de l'équation~(\ref{eq:length_pi}).
Compilation et exécution testées avec NAG Fortran Compiler Release 6.2.
\subsection{Entrées et sorties}
On n'enregistre pas de contours pour les tourbillons interpolés. Les
......@@ -1057,8 +1087,8 @@ suivants :
Les entrées-sorties sont dans : l'algorithme principal directement
(lecture de longitude et latitude), \verb+get_snapshot+ (lecture des
shapefiles), \verb+overlap+ (écriture dans
\verb+edgelist_$m.txt+, arcs entre \verb+k_begin+(m) et
shapefiles), \verb+write_overlap+ (écriture dans
\verb+edgelist_$m.txt+, arcs entre $k_b$(m) et
\verb+k_end_main_loop+(m)), \verb+write_eddy+ (écriture dans
\verb+extremum+, \verb+outermost_contour+, \verb+max_speed_contour+),
\verb+dispatch_snapshot+ directement (écriture dans
......@@ -1087,9 +1117,9 @@ par \verb+overlap+.
\begin{description}
\item[max\_delta] Scalaire entier. Intervalle maximal d'indices de
dates auxquelles on cherche des recouvrements. Normalement 4.
\item[flow] : Vecteur de type snapshot, de taille \verb+max_delta+ +
\item[flow] : Vecteur de type snapshot, de taille $\max \delta$ +
1, chaque élément correspondant à une date. Environ 40 MiB pour
\verb+max_delta+ = 4.
$\max \delta$ = 4.
\item[dist\_lim] Scalaire entier constant, = 3° / résolution.
\item[weight\_delta] Scalaire réel.
\end{description}
......@@ -1100,7 +1130,7 @@ différents appels à overlap avec delta $\ge 2$ : il faut que le numéro
de tourbillon interpolé soit bien incrémenté.
i désigne un indice de tourbillon, j un indice de position dans la
fenêtre temporelle (entre 1 et \verb+max_delta+ + 1) et k un indice de
fenêtre temporelle (entre 1 et $\max \delta$ + 1) et k un indice de
date. Cf. figure (\ref{fig:window}) et algorithme
(\ref{alg:main_sequential}).
\begin{figure}[htbp]
......@@ -1112,21 +1142,21 @@ date. Cf. figure (\ref{fig:window}) et algorithme
\end{figure}
\begin{algorithm}[htbp]
\begin{algorithmic}
\STATE \COMMENT{\{max\_delta $\ge 1$; n\_dates $\ge$ max\_delta +
\STATE \COMMENT{\{$\max \delta$ $\ge 1$; n\_dates $\ge$ $\max \delta$ +
1\}}
\STATE \COMMENT{prologue}
\STATE entrer(longitude, latitude)
\STATE \COMMENT{longitude et latitude dans l'ordre croissant}
\FOR{k = 1 \TO max\_delta + 1}
\FOR{k = 1 \TO $\max \delta$ + 1}
\STATE appel de get\_snapshot(flow(k), k)
\ENDFOR
\FOR{delta = 1 \TO max\_delta}
\FOR{delta = 1 \TO $\max \delta$}
\FOR{k = delta + 1 \TO max\_delta + 1}
\FOR{k = delta + 1 \TO $\max \delta$ + 1}
\STATE appel de overlap(flow, k, k, delta)
......@@ -1135,24 +1165,24 @@ date. Cf. figure (\ref{fig:window}) et algorithme
\STATE \COMMENT{boucle principale}
\FOR{k = max\_delta + 2 \TO n\_dates}
\FOR{k = $\max \delta$ + 2 \TO n\_dates}
\STATE appel de dispatch\_snapshot(flow(1), k - max\_delta - 1)
\STATE flow(:max\_delta) = flow(2:)
\STATE appel de dispatch\_snapshot(flow(1), k - $\max \delta$ - 1)
\STATE flow(:$\max \delta$) = flow(2:)
\STATE appel de get\_snapshot(flow(max\_delta + 1), k)
\STATE appel de get\_snapshot(flow($\max \delta$ + 1), k)
\FOR{delta = 1 \TO max\_delta}
\FOR{delta = 1 \TO $\max \delta$}
\STATE appel de overlap(flow, max\_delta + 1, k, delta)
\STATE appel de overlap(flow, $\max \delta$ + 1, k, delta)
\ENDFOR
\ENDFOR
\STATE \COMMENT{épilogue}
\FOR{j = 1 \TO max\_delta + 1}
\FOR{j = 1 \TO $\max \delta$ + 1}
\STATE appel de dispatch\_snapshot(flow(j), n\_dates - max\_delta - 1
\STATE appel de dispatch\_snapshot(flow(j), n\_dates - $\max \delta$ - 1
+ j)
\ENDFOR
\end{algorithmic}
......@@ -1171,119 +1201,130 @@ Cf. figure (\ref{fig:processes}).
boucle principale, en bleu, vert et marron dans l'épilogue.}
\label{fig:processes}
\end{figure}
Il faut, pour m < \verb+n_proc+ :
Il faut, pour $m < n_p$ :
\begin{equation}
\label{eq:stitching}
\mathtt{k\_end}(m)
= \mathtt{k\_begin}(m + 1) + \mathtt{max\_delta} - 1
k_e(m)
= k_b(m + 1) + \max \delta - 1
\end{equation}
k\_end - \verb+k_begin+ + 1 appels à \verb+get_snapshot+, pour les
dates \verb+k_begin+ à k\_end. k\_end - \verb+k_begin+ + 1 appels à
\verb+dispatch_snapshot+, pour les dates \verb+k_begin+ à k\_end. Si m
> 1 alors \verb+max_delta+ envois. Si m < \verb+n_proc+ alors
\verb+max_delta+ réceptions.
Notons, pour un processus donné :
\begin{equation*}
\Delta k := k_e - k_b
\end{equation*}
$\Delta k + 1$ appels à \verb+get_snapshot+, pour les dates $k_b$ à
$k_e$. $\Delta k + 1$ appels à \verb+dispatch_snapshot+, pour les
dates $k_b$ à $k_e$. Si $m > 1$ alors $\max \delta$ envois. Si
$m < n_p$ alors $\max \delta$ réceptions.
Nombre d'appels à \verb+get_snapshot+ avec lecture. Si m <
\verb+n_proc+ : k\_end - \verb+k_begin+ - \verb+max_delta+ + 1. Si m =
\verb+n_proc+ : k\_end - \verb+k_begin+ + 1.
Nombre d'appels à \verb+get_snapshot+ avec lecture. Si $m < n_p$ :
$\Delta k - \max \delta + 1$. Si $m = n_p$ : $k_e - k_b + 1$.
overlap avec delta = 1 est appelé pour tous les indices k compris
entre \verb+k_begin+ + 1 et \verb+k_end_main_loop+, seulement. Nombre
d'appels à overlap avec delta = 1 : \verb+k_end_main_loop+ -
\verb+k_begin+. Donc si m < \verb+n_proc+ : k\_end - \verb+k_begin+ -
\verb+max_delta+ + 1 appels. Si m = \verb+n_proc+ : k\_end -
\verb+k_begin+ appels.
entre $k_b + 1$ et \verb+k_end_main_loop+, seulement. Nombre d'appels
à overlap avec delta = 1 : \verb+k_end_main_loop+ - $k_b$. Donc si
$m < n_p$ : $k_e - k_b - \max \delta + 1$ appels. Si $m = n_p$ :
$k_e - k_b$ appels.
Nombre d'appels à overlap avec delta $\ge 2$ dans le prologue :
\begin{equation*}
\sum_{\delta = 2} ^{\mathtt{max\_delta}}
(\mathtt{max\_delta} - \delta +1)
= \frac{\mathtt{max\_delta} (\mathtt{max\_delta} - 1)}{2}
\sum_{\delta = 2} ^{\max \delta} (\max \delta - \delta +1)
= \frac{\max \delta (\max \delta - 1)}{2}
\end{equation*}
Dans la boucle principale : (\verb+max_delta+ - 1)(\verb+k_end_main_loop+ -
\verb+k_begin+ - \verb+max_delta+). Dans l'épilogue, si m < \verb+n_proc+ :
Dans la boucle principale :
$(\max \delta - 1)(\mathtt{k\_end\_main\_loop} - k_b - \max
\delta)$. Dans l'épilogue, si $m < n_p$ :
\begin{equation*}
\frac{\mathtt{max\_delta} (\mathtt{max\_delta} - 1)}{2}
\frac{\max \delta (\max \delta - 1)}{2}
\end{equation*}
Total si m < \verb+n_proc+ : (\verb+max_delta+ - 1)(k\_end -
\verb+k_begin+ - \verb+max_delta+ + 1). Total si m = \verb+n_proc+ :
Total si $m < n_p$ :
$(\max \delta - 1)(k_e - k_b - \max \delta + 1)$. Total si m =
$n_p$ :
\begin{equation*}
(\mathtt{max\_delta} - 1)
\left(
\mathtt{k\_end} - \mathtt{k\_begin} - \frac{\mathtt{max\_delta}}{2}
\right)
(\max \delta - 1) \left(k_e - k_b - \frac{\max \delta}{2} \right)
\end{equation*}
Si k\_end - \verb+k_begin+ était le même pour m = \verb+n_proc+ et m <
\verb+n_proc+, le processus m=\verb+n_proc+ aurait des plus grands nombres
d'appels aux trois procédures. Notons $\Delta k$ = k\_end - \verb+k_begin+,
considéré comme une fonction de m. Si, pour m < \verb+n_proc+ :
Si $k_e - k_b$ était le même pour $m = n_p$ et $m < n_p$, le processus
$m = n_p$ aurait des plus grands nombres d'appels aux trois
procédures. Considérons $\Delta k$ comme une fonction de $m$. Si, pour
$m < n_p$ :
\begin{equation}
\label{eq:charge}
\Delta k(m) \approx \Delta k(\mathtt{n\_proc}) + \mathtt{max\_delta}
\Delta k(m) \approx \Delta k(n_p) + \max \delta
\end{equation}
alors la charge devrait être à peu près équilibrée.
On peut prendre, pour tout m :
\begin{equation*}
\mathtt{k\_begin}(m)
= 1 + E[(m - 1) \mathtt{n\_dates} / \mathtt{n\_proc}]
k_b(m) = 1 + E[(m - 1) \mathtt{n\_dates} / n_p]
\end{equation*}
(On prend la partie entière au lieu de nint pour pouvoir démontrer des
encadrements.) D'où, avec la contrainte (\ref{eq:stitching}), pour m
< \verb+n_proc+ :
encadrements.) D'où, avec la contrainte (\ref{eq:stitching}), pour
$m < n_p$ :
\begin{equation*}
\mathtt{k\_end}(m)
= E(m\ \mathtt{n\_dates} / \mathtt{n\_proc}) + \mathtt{max\_delta}
k_e(m) = E(m\ \mathtt{n\_dates} / n_p) + \max \delta
\end{equation*}
Alors on peut montrer que $\Delta k(m) - \Delta k(\mathtt{n\_proc})$
vaut \verb+max_delta+ ou \verb+max_delta+ - 1. On a donc l'approximation
Alors on peut montrer que $\Delta k(m) - \Delta k(n_p)$
vaut $\max \delta$ ou $\max \delta$ - 1. On a donc l'approximation
(\ref{eq:charge}). Chaque processus fait aussi le même nombre de
lectures de ssh, u, v.
Pour \verb+n_proc+ $\ne 1$ et m < \verb+n_proc+, le processus m + 1 ne doit pas
relire une date déjà lue par le processus m. On doit donc avoir :
Pour $n_p \ne 1$ et $m < n_p$, le processus $m + 1$ ne doit pas relire
une date déjà lue par le processus $m$. On doit donc avoir :
\begin{equation}
\label{eq:min_delta_k}
\mathtt{k\_begin}(m + 1) > \mathtt{k\_begin}(m) + \mathtt{max\_delta}
k_b(m + 1) > k_b(m) + \max \delta
\end{equation}
Ce qui est équivalent à :
\begin{equation*}
E(m \mathtt{n\_dates} / \mathtt{n\_proc})
- E[(m - 1) \mathtt{n\_dates} / \mathtt{n\_proc}]
> \mathtt{max\_delta}
E(m \mathtt{n\_dates} / n_p)
- E[(m - 1) \mathtt{n\_dates} / n_p]
> \max \delta
\end{equation*}
Or on peut montrer que :
\begin{equation*}
E(m \mathtt{n\_dates} / \mathtt{n\_proc})
- E[(m - 1) \mathtt{n\_dates} / \mathtt{n\_proc}]
> E(\mathtt{n\_dates} / \mathtt{n\_proc}) - 1
E(m \mathtt{n\_dates} / n_p)
- E[(m - 1) \mathtt{n\_dates} / n_p]
> E(\mathtt{n\_dates} / n_p) - 1
\end{equation*}
Il suffit donc que :
\begin{equation*}
E(\mathtt{n\_dates} / \mathtt{n\_proc}) \ge \mathtt{max\_delta} + 1
E(\mathtt{n\_dates} / n_p) \ge \max \delta + 1
\end{equation*}
Si $m < n_p$ alors :
\begin{equation*}
\Delta k > \frac{\mathtt{n\_dates}}{n_p} + \max \delta - 2
\end{equation*}
Or :
\begin{equation*}
\frac{\mathtt{n\_dates}}{n_p} \ge \max \delta + 1
\end{equation*}
donc :
\begin{equation}
\label{eq:Delta_k}
\Delta k \ge 2 \max \delta
\end{equation}
L'équation (\ref{eq:stitching}) et l'inégalité (\ref{eq:min_delta_k})
impliquent que, pour m < \verb+n_proc+ :
L'équation (\ref{eq:stitching}) et l'inégalité (\ref{eq:min_delta_k}),
ou encore l'équation (\ref{eq:Delta_k}), impliquent que, pour
$m < n_p$ :
\begin{equation}
\label{eq:delta_k}
\mathtt{k\_begin} + \mathtt{max\_delta}
\le \mathtt{k\_end} - \mathtt{max\_delta}
\label{eq:Delta_k_2}
k_b + \max \delta
\le k_e - \max \delta
\end{equation}
donc les appels de \verb+get_snapshot+ dans le prologue font des
lectures. Les appels de \verb+get_snapshot+ dans l'épilogue font des
réceptions. L'inégalité (\ref{eq:delta_k}) implique en outre que, pour
m < \verb+n_proc+, la boucle principale fait au moins une
itération. Si m < \verb+n_proc+ : tous les appels à
\verb+get_snapshot+ de la boucle principale sauf le dernier font des
lectures ; le dernier appel à \verb+get_snapshot+ de la boucle
principale fait une réception.
réceptions. L'inégalité (\ref{eq:Delta_k_2}) implique en outre que, pour
$m < n_p$, la boucle principale fait au moins une itération. Si
$m < n_p$ : tous les appels à \verb+get_snapshot+ de la boucle
principale sauf le dernier font des lectures ; le dernier appel à
\verb+get_snapshot+ de la boucle principale fait une réception.
Si $m \ge 2$ alors :
\begin{equation*}
\mathtt{k\_end\_main\_loop}(m - 1) = \mathtt{k\_begin}(m)
\mathtt{k\_end\_main\_loop}(m - 1) = k_b(m)
\end{equation*}
Exemples : cf. tableaux (\ref{tab:m2}) et (\ref{tab:m3}) et figure
......@@ -1291,33 +1332,33 @@ Exemples : cf. tableaux (\ref{tab:m2}) et (\ref{tab:m3}) et figure
\begin{table}[htbp]
\centering
\begin{tabular}{llll}
m & \verb+k_begin+ & k\_end & \verb+k_end_main_loop+ \\
$m$ & $k_b$ & $k_e$ & \verb+k_end_main_loop+ \\
\hline
1 & 1 & 9 & 6 \\
2 & 6 & 10 & 10
\end{tabular}
\caption{max\_delta = 4, n\_dates = 10, n\_proc = 2. m = 1 : lecture
dates 1 à 5, écriture date 1, réception date 6, écriture dates 2 à
4, réception dates 7 à 9, écriture dates 5 à 9. m = 2 : lecture 6
à 10, envoi 6 à 9, écriture 10.}
\caption{$\max \delta = 4$, n\_dates = 10, $n_p = 2$. $m = 1$ :
lecture dates 1 à 5, écriture date 1, réception date 6, écriture
dates 2 à 4, réception dates 7 à 9, écriture dates 5 à 9. $m = 2$
: lecture 6 à 10, envoi 6 à 9, écriture 10.}
\label{tab:m2}
\end{table}
\begin{table}[htbp]
\centering
\begin{tabular}{llll}
m & \verb+k_begin+ & k\_end & \verb+k_end_main_loop+ \\
$m$ & $k_b$ & $k_e$ & \verb+k_end_main_loop+ \\
\hline
1 & 1 & 9 & 6 \\
2 & 6 & 14 & 11 \\
3 & 11 & 15 & 15
\end{tabular}
\caption{max\_delta = 4, n\_dates = 15, n\_proc = 3}
\caption{$\max \delta = 4$, n\_dates = 15, $n_p = 3$}
\label{tab:m3}
\end{table}
\begin{figure}[htbp]
\centering
\includegraphics[width=\textwidth]{m3}
\caption{max\_delta = 4, n\_dates = 15, n\_proc = 3. Les numéros
\caption{$\max \delta = 4$, n\_dates = 15, $n_p = 3$. Les numéros
sont les indices de date. En bleu le prologue, en noir la boucle
principale, en rouge l'épilogue. Pour un processus donné, les
actions sur une même colonne sont dans une même boucle de
......@@ -1326,21 +1367,160 @@ Exemples : cf. tableaux (\ref{tab:m2}) et (\ref{tab:m3}) et figure
\end{figure}
Le \verb+dispatch_snapshot+ dans la dernière boucle sur j n'est pas
forcément une écriture. Exemple : \verb+n_proc+ = 2, \verb+max_delta+ = 4,
n\_dates = 10, m = 2.
forcément une écriture. Exemple : $n_p = 2$, $\max \delta = 4$,
n\_dates = 10, $m = 2$.
Si $m = 1$ alors \verb+write_eddy+ est appelé pour les dates $k_b$ à
$k_e$. Si $m > 1$ alors \verb+write_eddy+ est appelé pour les dates
$k_b + \max \delta$ à $k_e$. Avec l'équation (\ref{eq:stitching}), une
date donnée est bien écrite par un seul processus.
Pour tout processus $m$, appelons \og domaine du processus $m$\fg{}
l'ensemble $\{k_b(m), \dots, k_e(m)\}$. Soit $m \le n_p - 2$. Avec les
équations (\ref{eq:stitching}) et (\ref{eq:Delta_k}) :
\begin{equation*}
k_e(m) \le k_e(m + 1) - \max \delta - 1
\end{equation*}
C'est-à-dire :
\begin{equation*}
k_e(m) \le k_b(m + 2) - 2
\end{equation*}
Ainsi les domaines des processus $m$ et $m + 2$ sont disjoints. Les
domaines de deux processus n'ont une intersection non vide que si les
numéros des processus sont adjacents.
Si m = 1 alors \verb+write_eddy+ est appelé pour les dates
\verb+k_begin+ à k\_end. Si m > 1 alors \verb+write_eddy+ est appelé
pour les dates \verb+k_begin+ + \verb+max_delta+ à k\_end. Avec
l'équation (\ref{eq:stitching}), une date donnée est bien écrite par
un seul processus.
\subsubsection{Successeurs d'une date donnée}
Soit un processus. Un appel à overlap dans ce processus peut avoir
lieu dans le prologue, la boucle principale ou l'épilogue. Dans le
prologue :
\begin{equation*}
k_b \le k - \delta \le k_b + \max \delta - 1
\end{equation*}
Dans la boucle principale :
\begin{equation}
\label{eq:pred_main_loop}
k_b + 1 \le k - \delta \le k_e - 1
\end{equation}
Dans l'épilogue :
\begin{equation*}
k_e - 2 \max \delta + 2 \le k - \delta \le k_e - \max \delta
\end{equation*}
Donc, dans l'épilogue, avec l'équation (\ref{eq:Delta_k}) (si on est
dans l'épilogue, c'est qu'on a $m < n_p$) :
\begin{equation*}
k_b + 2 \le k - \delta \le k_e - \max \delta
\end{equation*}
Donc, dans tous les cas, au moment d'un appel à overlap :
\begin{equation}
\label{eq:pred}
k_b \le k - \delta \le k_e - 1
\end{equation}
Soit un processus $m < n_p$, au moment d'un appel à overlap. On peut
resserrer l'encadrement (\ref{eq:pred_main_loop}) dans la boucle
principale :
\begin{equation*}
k_b + 1 \le k - \delta \le \mathtt{k\_end\_main\_loop} - 1 = k_e - \max \delta
\end{equation*}
Avec l'inégalité (\ref{eq:Delta_k_2}), on a dans le prologue :
\begin{equation*}
k_b \le k - \delta \le k_e - \max \delta - 1
\end{equation*}
Donc, quelle que soit la partie, prologue, boucle principale ou
épilogue, on a si $m < n_p$, au moment d'un appel à overlap :
\begin{equation*}
k_b(m) \le k - \delta \le k_e(m) - \max \delta = k_b(m + 1) - 1
\end{equation*}
C'est-à-dire :
\begin{equation*}
k_b(m) \le k - \delta \le k_b(m + 1) - 1
\end{equation*}
Donc il ne peut y avoir deux appels à overlap avec la même valeur de
$k - \delta$ dans deux processus différents. En d'autres termes, les
successeurs des tourbillons à une date donnée sont cherchés par un
seul processus.
Soient deux appels à overlap, avec $(k_1, \delta_1)$ et $(k_2,
\delta_2)$ tels que :
\begin{align*}
& k_1 - \delta_1 = k_2 - \delta_2 \\
& \delta_1 < \delta_2
\end{align*}
Comme démontré plus haut, les deux appels sont forcément dans le même processus.
\begin{equation*}
k_1 - k_2 = \delta_1 - \delta_2
\end{equation*}
donc $k_1 < k_2$. Si les deux appels sont dans le prologue alors la
boucle extérieure sur $\delta$ est dans l'ordre croissant donc l'appel
$(k_1, \delta_1)$ est avant l'appel $(k_2, \delta_2)$. Si un appel est
dans le prologue et l'autre non alors celui dans le prologue est
forcément à une date $k$ antérieure, donc c'est l'appel
$(k_1, \delta_1)$. Si les deux appels sont dans la boucle principale
alors la boucle extérieure sur $k$ est dans l'ordre croissant donc
l'appel $(k_1, \delta_1)$ est avant l'appel $(k_2, \delta_2)$. Si un
appel est dans la boucle principale et l'autre dans l'épilogue alors
celui dans la boucle principale est forcément à une date $k$
antérieure, donc c'est l'appel $(k_1, \delta_1)$. Si les deux appels
sont dans l'épilogue alors la boucle extérieure sur $k$ est dans
l'ordre croissant donc l'appel $(k_1, \delta_1)$ est avant l'appel
$(k_2, \delta_2)$. Ainsi, dans tous les cas, l'appel $(k_1, \delta_1)$
a lieu avant l'appel $(k_2, \delta_2)$. En d'autres termes, les
successeurs d'une date donnée sont cherchés dans l'ordre croissant des
$\delta$.
\subsubsection{Prédécesseurs d'une date donnée}
Pour un processus quelconque, au moment d'un appel à overlap :
\begin{equation*}
k_b + 1 \le k \le k_e
\end{equation*}
Soient deux appels à overlap, avec une même valeur de $k$ : avec
$(k, \delta_1)$ dans un processus $m_1$ et $(k, \delta_2)$ dans un
processus $m_2$.
Si $m_1 = m_2$ alors, puisque les deux appels ont le même $k$, ils
sont dans la même partie (prologue, boucle principale ou
épilogue). Les boucles sur $\delta$ dans les trois parties étant dans
l'ordre croissant, si $\delta_1 < \delta_2$ alors l'appel
$(k, \delta_1)$ a lieu avant l'appel $(k, \delta_2)$.
Si $m_1 \ne m_2$ alors $k$ appartient aux domaines de $m_1$ et $m_2$
donc $|m_1 - m_2| = 1$. Quitte à intervertir $m_1$ et $m_2$, on peut
supposer sans perte de généralité que $m_1 = m_2 + 1$.
\begin{equation*}
k \le k_e(m_2) = k_b(m_2 + 1) + \max \delta - 1 = k_b(m_1) + \max \delta - 1
\end{equation*}
Donc l'appel $(k, \delta_1, m_1)$ est dans le prologue. Donc :
\begin{equation*}
\delta_1 \le k - k_b(m_1)
\end{equation*}
Par ailleurs :
\begin{equation*}
k \ge k_b(m_1) + 1 = k_b(m_2 + 1) + 1 = k_e(m2) - \max \delta + 2
\end{equation*}
Donc l'appel $(k, \delta_2, m_2)$ est dans l'épilogue. Donc :
\begin{equation*}
\delta_2 \ge k - k_e(m_2) + \max \delta = k - k_b(m_1) + 1
\end{equation*}
Donc $\delta_2 > \delta_1$. L'appel à overlap dans $m_2$ est précédé
d'un \verb+receive_snapshot+ bloquant de la date $k$ en provenance du
processus $m_1$. Le send correspondant dans le processus $m_1$ est
après le prologue. Donc l'appel $(k, \delta_1, m_1)$ est terminé avant
l'appel $(k, \delta_2, m_2)$.
En résumé, dans tous les cas, si $\delta_1 < \delta_2$ alors l'appel
$(k, \delta_1, m_1)$ est terminé avant l'appel $(k, \delta_2,
m_2)$. Les prédécesseurs d'une date donnée sont cherchés dans l'ordre
croissant des $\delta$.
\subsection{Algorithme principal, parallèle}
\begin{algorithmic}
\STATE \COMMENT{\{max\_delta $\ge 1$; n\_dates $\ge$ max\_delta + 1;
n\_proc
$\le E\left(\frac{\mathtt{n\_dates}}{\mathtt{max\_delta} + 1}
\STATE \COMMENT{\{$\max \delta$ $\ge 1$; n\_dates $\ge$ $\max \delta$ + 1;
$n_p$
$\le E\left(\frac{\mathtt{n\_dates}}{\max \delta + 1}
\right)$\}}
\STATE \COMMENT{prologue}
......@@ -1359,72 +1539,72 @@ un seul processus.
\STATE recevoir longitude, latitude du processus 1
\ENDIF
\STATE k\_begin = 1 + E[(m - 1) n\_dates / n\_proc]
\STATE $k_b$ = 1 + E[(m - 1) n\_dates / $n_p$]
\IF{m < n\_proc}
\IF{m < $n_p$}
\STATE k\_end = E(m n\_dates / n\_proc) + max\_delta
\STATE $k_e$ = E(m n\_dates / $n_p$) + $\max \delta$
\STATE k\_end\_main\_loop = k\_end - max\_delta + 1
\STATE k\_end\_main\_loop = $k_e$ - $\max \delta$ + 1
\ELSE
\STATE k\_end = n\_dates
\STATE k\_end\_main\_loop = k\_end
\STATE $k_e$ = n\_dates
\STATE k\_end\_main\_loop = $k_e$
\ENDIF
\FOR{k = k\_begin \TO k\_begin + max\_delta}
\FOR{k = $k_b$ \TO $k_b$ + $\max \delta$}
\STATE appel de get\_snapshot(flow(k - k\_begin + 1), k)
\STATE appel de get\_snapshot(flow(k - $k_b$ + 1), k)
\COMMENT{lecture}
\ENDFOR
\FOR{delta = 1 \TO max\_delta}
\FOR{delta = 1 \TO $\max \delta$}
\FOR{k = k\_begin + delta \TO k\_begin + max\_delta}
\FOR{k = $k_b$ + delta \TO $k_b$ + $\max \delta$}
\STATE appel de overlap(flow, k - k\_begin + 1, k, delta)
\STATE appel de overlap(flow, k - $k_b$ + 1, k, delta)
\ENDFOR
\ENDFOR
\STATE \COMMENT{boucle principale}
\FOR{k = k\_begin + max\_delta + 1 \TO k\_end\_main\_loop}
\FOR{k = $k_b$ + $\max \delta$ + 1 \TO k\_end\_main\_loop}
\STATE appel de dispatch\_snapshot(flow(1), k - max\_delta - 1)
\STATE appel de dispatch\_snapshot(flow(1), k - $\max \delta$ - 1)
\STATE flow(:max\_delta) = flow(2:)
\STATE flow(:$\max \delta$) = flow(2:)
\STATE appel de get\_snapshot(flow(max\_delta + 1), k)
\STATE appel de get\_snapshot(flow($\max \delta$ + 1), k)
\FOR{delta = 1 \TO max\_delta}
\FOR{delta = 1 \TO $\max \delta$}
\STATE appel de overlap(flow, max\_delta + 1, k, delta)
\STATE appel de overlap(flow, $\max \delta$ + 1, k, delta)
\ENDFOR
\ENDFOR
\STATE \COMMENT{épilogue}
\FOR{k = k\_end\_main\_loop + 1 \TO k\_end}
\FOR{k = k\_end\_main\_loop + 1 \TO $k_e$}
\STATE \COMMENT{m < n\_proc et k $\ge$ k\_end - max\_delta + 2}
\STATE appel de dispatch\_snapshot(flow(1), k - max\_delta - 1)
\STATE \COMMENT{m < $n_p$ et k $\ge$ $k_e$ - $\max \delta$ + 2}
\STATE appel de dispatch\_snapshot(flow(1), k - $\max \delta$ - 1)
\STATE flow(:max\_delta) = flow(2:)
\STATE flow(:$\max \delta$) = flow(2:)
\STATE appel de get\_snapshot(flow(max\_delta + 1), k)
\STATE appel de get\_snapshot(flow($\max \delta$ + 1), k)
\COMMENT{réception} \STATE \COMMENT{stitching}
\FOR{delta = k - k\_end + max\_delta \TO max\_delta}
\FOR{delta = k - $k_e$ + $\max \delta$ \TO $\max \delta$}
\STATE appel de overlap(max\_delta + 1, k, delta, flow)
\STATE appel de overlap(flow, $\max \delta$ + 1, k, delta)
\ENDFOR
\ENDFOR
\FOR{j = 1 \TO max\_delta + 1}
\FOR{j = 1 \TO $\max \delta$ + 1}
\STATE appel de dispatch\_snapshot(flow(j), k\_end - max\_delta - 1
\STATE appel de dispatch\_snapshot(flow(j), $k_e$ - $\max \delta$ - 1
+ j)
\ENDFOR
......@@ -1472,6 +1652,15 @@ le multiple de $2 \pi$ à ajouter aux longitudes doit être le même pour
tous les points du contour, et égal au multiple à ajouter à la
longitude de l'extremum i2.
Comment définir les composants \verb+delta_in+ et \verb+delta_out+ ?
Cf. l'exemple de la figure \ref{fig:overlap}. Lorsqu'on arrive à
$i'_1$, on ne veut pas tester le recouvrement de $i'_1$ et $i_2$. Il
faut donc avoir conservé dans \verb+delta_in+ pour $i_2$ la distance
strictement inférieure à $\delta$. \verb+delta_in+ doit donc contenir
la distance temporelle minimale à laquelle des prédécesseurs ont été
trouvés. De même, \verb+delta_out+ doit contenir la distance
temporelle minimale à laquelle des successeurs ont été trouvés.
\subsubsection{weight}
D'autant plus proche de 0 que les tourbillons sont
......
......@@ -6,8 +6,9 @@ contains
function candidate_overlap(extr_map, list_vis, cyclone, delta_out, delta)
! Find the eddies in extr_map that are valid and have a given
! cyclonicity.
! Find the eddies in extr_map that are valid, have a given
! cyclonicity. Also, if delta_out < delta then the eddies should
! not have a predecessor at time distance < delta.
use derived_types, only: eddy
......@@ -18,11 +19,17 @@ contains
! extremum. 0 at other points.
type(eddy), intent(in):: list_vis(:)
! Visible eddies at a given date. We need components valid and
! cyclone to be defined.
! Visible eddies at a given date. We need components valid,
! cyclone and delta_in to be defined. Arriving in this subroutine,
! list_vis%delta_in could be <= delta or huge(0).
logical, intent(in):: cyclone ! cyclonicity of the target extremum
integer, intent(in):: delta_out, delta
integer, intent(in):: delta_out
! Arriving in this subroutine, delta_out could be <= delta or
! huge(0).
integer, intent(in):: delta
!---------------------------------------------------------------------
......
......@@ -27,12 +27,12 @@ module derived_types
logical interpolated
integer:: delta_in = huge(0)
! Maximum difference in time subscript where there is a direct
! predecessor. huge means there is no direct predecessor.
! Minimum difference in time subscript where there is a direct
! predecessor. Huge means there is no direct predecessor.
integer:: delta_out = huge(0)
! Maximum difference in time subscript where there is a direct
! successor. huge means there is no direct succcessor.
! Minimum difference in time subscript where there is a direct
! successor. Huge means there is no direct succcessor.
integer radius4
! ind_extr + radius4 - 1 in all four directions is inside outermost
......
......@@ -52,7 +52,9 @@ contains
! Local:
integer i1, i2, l, n_select, m
integer i1 ! eddy index of predecessor
integer i2 ! eddy index of successor
integer l, n_select, m
type(polyline) polyline_1, polyline_2
type(polygon) res_pol
......@@ -80,10 +82,12 @@ contains
urc(1) = min(urc(1), nlon)
end if
! Pre-select potential successors:
selection = candidate_overlap(flow(j)%extr_map(llc(1):urc(1), &
llc(2):urc(2)), flow(j)%list_vis, &
flow(j - delta)%list_vis(i1)%cyclone, &
flow(j - delta)%list_vis(i1)%delta_out, delta)
n_select = size(selection)
if (n_select /= 0) polyline_1 &
= merge(flow(j - delta)%list_vis(i1)%speed_cont%polyline, &
......@@ -92,6 +96,8 @@ contains
DO l = 1, n_select
i2 = selection(l)
! assertion {flow(j - delta)%list_vis(i1)%delta_out >=
! delta .or. flow(j)%list_vis(i2)%delta_in >= delta}
polyline_2 = merge(flow(j)%list_vis(i2)%speed_cont%polyline, &
flow(j)%list_vis(i2)%out_cont%polyline, &
flow(j)%list_vis(i2)%speed_cont%n_points /= 0)
......@@ -127,8 +133,10 @@ contains
flow(j)%list_vis(i2)%ssh_extr, &
weight(flow(j - delta)%list_vis(i1), &
flow(j)%list_vis(i2)))
flow(j - delta)%list_vis(i1)%delta_out = delta
flow(j)%list_vis(i2)%delta_in = delta
flow(j - delta)%list_vis(i1)%delta_out &
= min(flow(j - delta)%list_vis(i1)%delta_out, delta)
flow(j)%list_vis(i2)%delta_in &
= min(flow(j)%list_vis(i2)%delta_in, delta)
end if
end if
end DO
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment