Quali sono alcuni buoni tipi di dati per il codice CFD FVM incentrato sulla cellula non strutturato?


12

Sono interessato a un consiglio per strutture dati efficienti per la navigazione cellulare in CFD a volume finito non cellulare basato su cellule.

Un esempio che ho riscontrato (nel codice cfd di Dolfyn ) è il seguente (mostrerò il segmento pertinente) Quindi abbiamo un array NFaces in cui è memorizzato il numero di facce per ogni cella. Quindi l'array CFace che mappa il numero di facce da locale a cella al numero di faccia globale.

\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}

Il codice è basato sulla faccia, quindi esiste un tipo di dati della faccia che memorizza il numero seriale di due celle tra Face (k)% cell1 e Face (k)% cell2.

Eventuali commenti su questo o suggerimenti per un approccio alternativo sono i benvenuti.

Risposte:


9

La struttura che mostri è una scelta comune ed equivalente all'archiviazione delle adiacenze faccia-cellula in un formato matrice CSR, con le celle fantasma al contorno in un posto speciale. Tuttavia, si noti che i metodi FV possono anche essere formulati in modo da consistere interamente o quasi interamente in attraversamento facciale in cui ogni faccia viene visitata una sola volta (ricostruire per affrontare il centroide / quadratura da entrambi i lati, risolvere il problema di Riemann, distribuire il flusso residuo in cellule ). Puoi "fingere" che usando il tuo attraversamento basato su celle e saltando due celle che si trovano al di sotto della "diagonale" nella matrice sparsa, ma un'alternativa popolare è quella di memorizzare(leftCell, rightCell) = support(face), nel qual caso i volti diventano entità di prima classe. Ciò è utile perché in genere è necessario un luogo in cui memorizzare i punti di quadratura (centroidi) delle facce, le normali alle facce. È inoltre possibile inserire parti di ricostruzione (come i minimi quadrati) nelle strutture dati basate sulla faccia. L'incrocio del volto è apparentemente favorevole alla vettorializzazione perché tutte le dimensioni sono regolari, ma d'altra parte ci sono output sovrapposti, quindi è necessario organizzare l'attraversamento per evitare di inserirlo in un circuito interno. Con questa struttura di dati più orientata alle facce, è naturale ordinare i numeri delle facce in modo che ogni tipo di condizione al contorno possa essere applicato usando un attraversamento contiguo di facce (anche favorevole alla vettorializzazione).

Se si sceglie questa struttura di dati, ricordare di ordinare le facce in modo che il traversal riutilizzi i dati delle celle nella cache il più possibile. Consulta i documenti PETSc-FUN3D per l'analisi delle prestazioni degli ordini dei volti e delle relative ottimizzazioni.


Se esegui il ciclo sulle facce, dovrai ottenere informazioni da una sinistra e una destra per calcolare i flussi, ad esempio se la faccia 1 ha lasciato la cella 1 e la destra 10, la faccia 2 ha lasciato la cella 6 e la destra 31, ... saltando così nella memoria . Come sarebbe amichevole la vettorializzazione?
chris,

Come accennato in precedenza (e discusso nei documenti PETSc-FUN3D), ordinate ai volti di riutilizzare la cache. Il risultato è come un attraversamento cellulare "unilaterale" in cui ogni faccia viene visitata una sola volta.
Jed Brown,

3

So che a questa domanda è già stata data una risposta, ma ecco un simile archivio loop basato su una sola faccia che è implementato nella libreria OpenFOAM C ++:

Ogni cella ha un indice (ID) in un elenco di celle. Sono definiti due elenchi per tutti i volti: "volto proprietario interno" e "volto vicino". La lunghezza di entrambi gli elenchi di facce corrisponde al numero di facce interne nella mesh. Il proprietario di una faccia sarà la cella con l'ID inferiore nella cella (a fianco della faccia vicina). Le facce di confine sono scritte per ultime e hanno normali orientate verso l'esterno (dal dominio della soluzione) e, naturalmente, solo una cella del proprietario. L'area del viso normale è orientata in modo che guardi verso l'esterno dalla cella del proprietario alla cella vicina.

Funziona bene, ad esempio per il calcolo del flusso. Il flusso viene valutato una volta per faccia e viene aggiunto alla somma delle facce totali per le celle del proprietario e dedotto dalle celle vicine (la somma / deduzione viene decisa in base all'orientamento dell'area normale della faccia). Le facce di confine vengono ordinate e memorizzate nella parte inferiore dell'elenco delle facce, consentendo di definire le condizioni al contorno come sezioni dell'elenco delle facce (etichetta iniziale, etichetta finale della patch di contorno), semplificando così anche l'implementazione delle condizioni al contorno come inhancing efficienza del processo di aggiornamento per le condizioni al contorno, poiché si basa sulla soluzione fornita dalle operazioni su facce interne.

Poiché le facce di delimitazione sono agglomerate in patch, la comunicazione tra processi è definita per patch accoppiate (processore) e predefinita. Ciò significa che non appena si verifica un loop sulla mesh di confine, le funzioni di accesso di livello superiore invocano chiamate MPI incapsulate, rendendo tale codice "automaticamente" parallelizzato, se si basa sulla connettività basata sul viso sopra spiegata.


Nessun problema, sono contento di vedere che questa descrizione è utile a qualcuno .. :) Lavori anche con OpenFOAM?
tmaric,

Un tempo, un po 'in passato. In genere tendo a stare alla larga dalle tendenze accettate e cerco di reinventare la ruota. Questo è il mio Tao.
Johntra Volta,

1
Il tuo Tao è l'opposto del Tao dell'Informatica: "Non reinventare la ruota". Ma posso capirlo, è interessante fare cose da zero! :)
tmaric,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.