%-----------------------------------------------------------------------
%
%     This file is part of the Code_Saturne Kernel, element of the
%     Code_Saturne CFD tool.
%
%     Copyright (C) 1998-2008 EDF S.A., France
%
%     contact: saturne-support@edf.fr
%
%     The Code_Saturne Kernel is free software; you can redistribute it
%     and/or modify it under the terms of the GNU General Public License
%     as published by the Free Software Foundation; either version 2 of
%     the License, or (at your option) any later version.
%
%     The Code_Saturne Kernel is distributed in the hope that it will be
%     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
%     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with the Code_Saturne Kernel; if not, write to the
%     Free Software Foundation, Inc.,
%     51 Franklin St, Fifth Floor,
%     Boston, MA  02110-1301  USA
%
%-----------------------------------------------------------------------
%

\programme{recvmc}

\vspace{1cm}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Fonction}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Le but de ce sous-programme est de calculer la vitesse au centre des cellules
\`a partir du flux de masse aux faces, par moindres carr\'es. Utilis\'ee apr\`es
l'\'etape de correction de pression ({\it cf.}~\fort{navsto}) cette m\'ethode est une
alternative \`a la technique de reconstruction \`a partir du gradient de
l'incr\'ement de pression (technique standard).
Elle est activ\'ee quand l'indicateur \var{IREVMC} vaut~1 ou 2.

On rappelle que, à la fin de l'étape de correction de pression, le flux de masse aux faces vaut :
\begin{equation}
(\rho \vect{u})^{n+1}_{\,ij}\text{.}\vect{S}_{\,ij} =
(\rho
\vect{\widetilde{u}})^{n+1}_{\,ij}.\,\vect{S}_{\,ij}
-\vect{D}_{\,ij}(\Delta t^n,\delta P^{n+\theta})
+\text{RC}_{\,ij}
\end{equation}
où $\vect{\widetilde{u}}$ est la vitesse issue de l'étape de prédiction, $D_{\,ij}$ un opérateur de gradient aux faces
et $\text{RC}_{\,ij}$ le terme d'Arakawa (cf. \fort{navsto} pour une définition précise des notations).
Une première méthode, activée par \var{IREVMC} = 2, consiste à partir directement de
$(\rho \vect{u})^{n+1}_{\,ij}\text{.}\vect{S}_{\,ij}$ pour calculer $\vect{u}^{n+1}$ par moindres carrés. Son utilisation a
montr\'e qu'elle semblait plus diffusive que la m\'ethode standard (par exemple, dans le cas de la cavit\'e entra\^\i n\'ee)
et pouvait conduire à des résultats erronés sur des maillages ne comportant pas uniquement des tétraèdres
(ou des prismes à base triangulaire en ``2D'') et des pavés (hexaèdres orthogonaux).\\
On note que, dans la méthode ci-dessus, on est parti d'une vitesse $\vect{\widetilde{u}}$ au centre des cellules, qu'on a projetée aux faces pour obtenir le flux de masse, et qu'on ramène au centre des cellules par moindres carrés. Fort de cette constatation, une méthode alternative est disponible, activée par \var{IREVMC} = 1. Elle consiste à n'appliquer la méthode des moindres carrés qu'à la partie $-\vect{D}_{\,ij}(\Delta t^n,\delta P^{n+\theta}) +\text{RC}_{\,ij}$ du flux de masse et à rajouter directement
$\vect{\widetilde{u}}$ (connu au centre des cellules) au résultat obtenu\footnote{cette dernière étape est faite dans
\fort{navsto}.}. Cette méthode donne des résultats sensiblement meilleurs.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Discr\'etisation}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Soit une cellule $\Omega_i$, $\phi_{ij}$  le flux de masse (total ou uniquement la partie en
gradient de pression) \`a travers la face la
s\'eparant d'une cellule voisine $\Omega_j$ et $\phi_{\,b_ik}$ le flux de masse (total ou uniquement la partie en
gradient de pression)\`a travers la face de bord $\,b_{ik}$.
L'id\'eal serait de pouvoir trouver un vecteur $\vect{v}_i$ telle que, pour toute cellule voisine $\Omega_j$ on ait :
\begin{equation}
\rho_i\vect{v}_i.\vect{S}_{ij} = \phi_{ij}
\end{equation}
et l'\'equivalent aux faces de bords, {\it i.e.} :
\begin{equation}
\rho_i \vect{v}_i.\vect{S}_{\,b_{ik}} = \phi_{\,b_{ik}}
\end{equation}
Comme c'est g\'en\'eralement impossible d'obtenir les deux \'egalit\'es pr\'ec\'edentes\footnote{%
sauf en incompressible pour des triangles en 2D et des
t\'etra\`edres en 3D}, on va simplement chercher \`a minimiser la fonction $F_i$ :
\begin{equation}
F_i=\sum\limits_{j\in Vois(i)}\left[
\rho_i\vect{v}_i.\vect{S}_{ij}-\phi_{ij}\right]^2 + \sum\limits_{k\in {\gamma_b(i)}}\left[\rho_i\vect{v}_i.\vect{S}_{\,b_{ik}}-\phi_{\,b_{ik}}\right]^2
\end{equation}

Pour ce faire, on d\'erive $F_i$ par rapport aux trois composantes du vecteur $\vect{v}_i$,
et on r\'esout le syst\`eme $3\times3$ local qui r\'esulte :\\
\begin{equation}
\begin{array}{lll}
&\displaystyle \tens{\mathcal{S}}^{\,i} \,
\left[\begin{array}{c}
v_{i,x} \\ v_{i,y} \\ v_{i,z}
\end{array}\right]
&=\left[\begin{array}{c}
\displaystyle
\frac{1}{\rho_i}(\sum\limits_{j\in Vois(i)}\phi_{ij}S_{ij,x} +\sum\limits_{k\in {\gamma_b(i)}}\phi_{\,b_{ik}}S_{{\,b_{ik}},x})\\
\displaystyle
\frac{1}{\rho_i}(\sum\limits_{j\in Vois(i)}\phi_{ij}S_{ij,y} +\sum\limits_{k\in {\gamma_b(i)}}\phi_{\,b_{ik}}S_{{\,b_{ik}},y})\\
\displaystyle
\frac{1}{\rho_i}(\sum\limits_{j\in Vois(i)}\phi_{ij}S_{ij,z} +\sum\limits_{k\in {\gamma_b(i)}}\phi_{\,b_{ik}}S_{{\,b_{ik}},z})
\end{array}\right]
\end{array}
\end{equation}

avec $\tens{\mathcal{S}}^{\,i}$ matrice carr\'ee $3\times3$ d'\'el\'ement $S^{\,i}_{\,ml}$ courant d\'efini par :\\
\begin{equation}
S^{\,i}_{\,ml} = \sum\limits_{j\in Vois(i)}S_{ij,\,l}\,S_{ij,\,m} + \sum\limits_{k\in {\gamma_b(i)}}S_{{\,b_{ik}},\,l}\,S_{{\,b_{ik}},\,m}
\end{equation}

%\begin{equation}
%\left[\begin{array}{ccc}
%\displaystyle
%\sum\limits_jS_{ij,x}S_{ij,x} & \sum\limits_jS_{ij,x}S_{ij,y}
%& \sum\limits_jS_{ij,x}S_{ij,z}\\
%\displaystyle
%\sum\limits_jS_{ij,x}S_{ij,y} & \sum\limits_jS_{ij,y}S_{ij,y}
%& \sum\limits_jS_{ij,y}S_{ij,z}\\
%\displaystyle
%\sum\limits_jS_{ij,x}S_{ij,z} & \sum\limits_jS_{ij,y}S_{ij,z}
%& \sum\limits_jS_{ij,z}S_{ij,z}
%\end{array}\right]
%\left[\begin{array}{c}
%u_{i,x} \\ u_{i,y} \\ u_{i,z}
%\end{array}\right]
%=\left[\begin{array}{c}
%\displaystyle
%\frac{1}{\rho_i}\sum\limits_j\phi_{ij}S_{ij,x}\\
%\displaystyle
%\frac{1}{\rho_i}\sum\limits_j\phi_{ij}S_{ij,y}\\
%\displaystyle
%\frac{1}{\rho_i}\sum\limits_j\phi_{ij}S_{ij,z}
%\end{array}\right]
%\end{equation}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Mise en \oe uvre}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Le flux de masse est pass\'e par les arguments \var{FLUMAS} et \var{FLUMAB}.

\etape{Calcul de la matrice}
Les \var{NCEL} matrices $3\times 3$ sont stock\'ees dans le tableau de travail
\var{COCG},
de dimension $NCELET\times 3\times 3$. Ce dernier est d'abord mis \`a z\'ero, puis
son remplissage se fait dans des boucles sur les faces internes et les faces de
bord. La matrice \'etant sym\'etrique, ces boucles ne
servent qu'\`a remplir la partie triangulaire sup\'erieure, le reste \'etant
rempli par sym\'etrie \`a la fin.

\etape{Inversion de la matrice}
On calcule les coefficients de la comatrice, puis l'inverse.
Pour des questions de vectorisation, la boucle sur les \var{NCEL} \'el\'ements
est remplac\'ee par une
s\'erie de boucles en vectorisation forc\'ee sur des blocs de \var{NBLOC=1024}
\'el\'ements. Le reliquat ($\var{NCEL}-E(\var{NCEL}/1024)\times 1024$) est
trait\'e apr\`es les boucles.
\`A la fin, la matrice inverse est stock\'ee dans \var{COCG}
(toujours en utilisant sa propri\'et\'e de sym\'etrie).

\etape{Calcul du second membre et r\'esolution}
Le second membre est stock\'e dans \var{BX}, \var{BY} et \var{BZ}. La vitesse
finale est stock\'ee dans \var{UX}, \var{UY} et \var{UZ}.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Points \`a traiter}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\etape{Vectorisation forc\'ee}
Le d\'ecoupage en boucles de 1024 est-il vraiment n\'ecessaire ? Les machines
vectorielles et les compilateurs sont-ils aujourd'hui capables
d'effectuer la vectorisation sans cette aide ? On note cependant que ce
d\'ecoupage en boucles de 1024 n'a pas de co\^ut CPU suppl\'ementaire, et un
co\^ut m\'emoire n\'egligeable. Le seul inconv\'enient r\'eside dans la
complexit\'e de l'\'ecriture.

\etape{Suppression de la méthode \var{IREVMC} = 2}
Sur un maillage ``1D'' d'hexaèdres tous orthogonaux sauf une face, on peut montrer que la méthode fait apparaître
une composante de vitesse aberrante non nulle et directement déterminée par l'angle de non orthogonalité de la
face (non consistance). On pourrait donc songer à supprimer purement cette méthode, dans la mesure où elle n'est
{\em a priori} consistante que sur une classe réduite de maillages.

