Quels sont les bons types de données pour le code CFD FVM centré sur les cellules non structuré?

12

Je suis intéressé par un conseil pour des structures de données efficaces pour la navigation cellulaire dans les CFD à volume fini à base de cellules non structurées.

Un exemple que j'ai rencontré (dans le code dolfyn cfd) va comme ceci (je vais montrer le segment pertinent) Nous avons donc un tableau NFaces où le nombre de faces pour chaque cellule est stocké. Ensuite, un tableau CFace qui mappe le numéro de face local à cellule au numéro de face global.

\begin{listing}do ip=1,Ncel         ...         do j=1,NFaces(ip)           k   = CFace(ip,j)           ipp = Face(k)%cell1           inn = Face(k)%cell2           if( inn > 0 )then             ! internal\end{listing}

Le code est basé sur le visage, il existe donc un type de données de visage qui stocke le numéro de série de deux cellules, il se situe entre Face (k)% cell1 et Face (k)% cell2.

Tout commentaire à ce sujet ou suggestions pour une approche alternative sont les bienvenus.

John Travolta
la source

Réponses:

9

La structure que vous montrez est un choix courant et équivaut à stocker des contiguïtés de face de cellule dans un format de matrice CSR, avec les cellules fantômes de frontière à un endroit spécial. Cependant, notez que les méthodes FV peuvent également être formulées pour consister entièrement ou presque entièrement en travers de face où chaque face n'est visitée qu'une seule fois (reconstruire pour centrer le visage / point de quadrature des deux côtés, résoudre le problème de Riemann, distribuer le flux en retour dans les cellules résiduelles ). Vous pouvez "simuler" cela en utilisant votre traversée basée sur les cellules et en sautant deux cellules qui sont en dessous de la "diagonale" dans la matrice clairsemée, mais une alternative populaire consiste à stocker(leftCell, rightCell) = support(face), auquel cas les visages deviennent des entités de première classe. Cela est utile car vous avez généralement besoin d'un emplacement pour stocker des points de quadrature de face (centroïdes), des normales de face. Vous pouvez également placer des pièces de reconstruction (comme les moindres carrés) dans les structures de données basées sur les faces. La traversée du visage est apparemment conviviale pour la vectorisation car toutes les tailles sont régulières, mais d'un autre côté, il y a des sorties qui se chevauchent, vous devez donc organiser la traversée pour éviter de la mettre dans une boucle interne. Avec cette structure de données plus orientée face, il est naturel de classer les numéros de face de sorte que chaque type de condition aux limites puisse être appliqué en utilisant une traversée contiguë de faces (également adaptée à la vectorisation).

Si vous choisissez cette structure de données, n'oubliez pas de trier les faces afin que la traversée réutilise autant que possible les données de cellule dans le cache. Voir l'un des papiers PETSc-FUN3D pour une analyse des performances de l'ordre des visages et des optimisations associées.

Jed Brown
la source
Si vous faites une boucle sur les faces, vous devrez obtenir des informations à partir d'une cellule gauche et d'une cellule droite pour calculer les flux, par exemple, la face 1 a la cellule gauche 1 et la cellule droite 10, la face 2 a la cellule gauche 6 et la cellule droite 31, ... sautant ainsi dans la mémoire. . En quoi cela serait-il convivial pour la vectorisation?
chris
Comme mentionné ci-dessus (et discuté dans les articles PETSc-FUN3D), vous ordonnez aux faces de réutiliser le cache. Le résultat est comme une traversée de cellule "unilatérale" dans laquelle chaque face n'est visitée qu'une seule fois.
Jed Brown
3

Je sais que cette question a déjà reçu une réponse, mais voici un stockage en boucle basé sur une seule face similaire qui est implémenté dans la bibliothèque OpenFOAM C ++:

Chaque cellule a un index (ID) dans un cellList. Deux listes sont définies pour toutes les faces: "face interne propriétaire" et "face voisin". La longueur des deux listes de faces correspond au nombre de faces internes dans le maillage. Un propriétaire de visage sera la cellule dont l'ID est le plus bas dans la cellule (en face pour le voisin de visage). Les faces frontières sont écrites en dernier, et elles ont des normales orientées vers l'extérieur (du domaine de la solution), et bien sûr, une seule cellule propriétaire. La zone du visage normale est orientée de façon à ce qu'elle regarde vers l'extérieur de la cellule propriétaire vers la cellule voisine.

Cela fonctionne bien, par exemple pour le calcul de flux. Le flux est évalué une fois par face, et il est ajouté à la somme des faces totales pour les cellules propriétaires, et déduit des cellules voisines (la sommation / déduction est décidée en fonction de l'orientation normale de la zone du visage). Les faces limites sont triées et stockées au bas de la liste des faces, ce qui permet de définir les conditions aux limites comme des tranches de la liste des faces (étiquette de début, étiquette de fin du patch de limite), simplifiant ainsi la mise en œuvre des conditions aux limites. comme une amélioration de l'efficacité du processus de mise à jour des conditions aux limites, puisqu'il s'appuie sur la solution apportée par les opérations sur les faces internes.

Étant donné que les faces limites sont agglomérées en patchs, la communication interprocessus est définie pour les patchs couplés (processeur) et prédéfinie. Cela signifie que dès qu'il y a une boucle sur le maillage de limite, les fonctions d'accès de niveau supérieur envoient des appels MPI enveloppés, rendant ce code parallélisé "automatiquement", s'il s'appuie sur la connectivité basée sur le visage expliquée ci-dessus.

tmaric
la source
Pas de problème, je suis content de voir que cette description est utile à quelqu'un .. :) Travaillez-vous également avec OpenFOAM?
tmaric
Je le faisais un peu dans le passé. J'ai généralement tendance à rester loin des tendances acceptées et à essayer de réinventer la roue. C'est mon Tao.
Johntra Volta
1
Votre Tao est l'opposé du Tao de l'informatique: "Ne réinventez pas la roue". Mais je peux le comprendre, c'est attrayant de faire des trucs à partir de zéro! :)
tmaric