Jakie są dobre typy danych dla nieustrukturyzowanego kodu FVM CFD skoncentrowanego na komórkach?


12

Interesuje mnie rada dotycząca wydajnych struktur danych do przeglądania komórek w niestrukturalnej CFD o skończonej objętości opartej na komórkach.

Jeden przykład, który napotkałem (w kodzie dolfyn cfd) wygląda następująco (pokażę odpowiedni segment) Mamy więc tablicę NFaces, w której przechowywana jest liczba twarzy dla każdej komórki. Następnie tablica CFace, która odwzorowuje numer twarzy lokalnej na komórkę na globalną liczbę twarzy.

\ 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) to! wewnętrzna \ koniec {listowanie}

Kod jest oparty na twarzach, dlatego istnieje typ danych twarzy, który przechowuje numer seryjny dwóch komórek pomiędzy Face (k)% cell1 i Face (k)% cell2.

Wszelkie uwagi dotyczące tego lub sugestie dotyczące alternatywnego podejścia są mile widziane.

Odpowiedzi:


9

Struktura, którą pokazujesz, jest częstym wyborem i równoważnym do przechowywania przylegania powierzchni komórki w formacie matrycy CSR, z granicznymi komórkami-widmami w specjalnym miejscu. Należy jednak pamiętać, że metody FV można również sformułować tak, aby składały się w całości lub prawie w całości z ruchu twarzy, przy czym każda twarz jest odwiedzana tylko raz (zrekonstruować do punktu środkowego / kwadratury twarzy z obu stron, rozwiązać problem Riemanna, rozprowadzić strumień z powrotem do pozostałości na komórkach ). Możesz to „sfałszować”, wykorzystując przechodzenie przez komórkę i pomijając dowolne dwie komórki poniżej „przekątnej” w rzadkiej matrycy, ale popularną alternatywą jest przechowywanie(leftCell, rightCell) = support(face), w którym to przypadku twarze stają się pierwszorzędnymi bytami. Jest to przydatne, ponieważ zazwyczaj potrzebujesz miejsca do przechowywania punktów kwadratury twarzy (centroidy), normalnych twarzy. Możesz również umieścić części rekonstrukcyjne (jak najmniejsze kwadraty) w strukturach danych opartych na twarzach. Przechodzenie przez twarz jest pozornie przyjazne dla wektoryzacji, ponieważ wszystkie rozmiary są regularne, ale z drugiej strony istnieją nakładające się wyjścia, więc musisz zorganizować przejście, aby uniknąć umieszczenia go w wewnętrznej pętli. Przy tej strukturze danych bardziej zorientowanej na twarz naturalne jest porządkowanie numerów ścian, aby można było zastosować każdy typ warunków brzegowych za pomocą ciągłego przechodzenia ścian (również wektoryzacji).

Jeśli wybierzesz tę strukturę danych, pamiętaj, aby posortować twarze, aby przemieszczenie wykorzystało dane komórki w pamięci podręcznej w jak największym stopniu. Zobacz dowolny z artykułów PETSc-FUN3D, aby uzyskać analizę wydajności zamawiania twarzy i powiązanych optymalizacji.


Jeśli zapętlisz twarze, będziesz musiał uzyskać informacje z lewej komórki i prawej komórki, aby obliczyć strumienie, powiedzmy, że twarz 1 ma lewą komórkę 1 i prawą komórkę 10, twarz 2 ma lewą komórkę 6 i prawą komórkę 31, ... w ten sposób przeskakując pamięć . W jaki sposób byłoby to przyjazne dla wektoryzacji?
Chris

Jak wspomniano powyżej (i omówione w dokumentach PETSc-FUN3D), każesz twarzom ponownie użyć pamięci podręcznej. Rezultat jest jak „jednostronny” ruch komórek, w którym każda twarz jest odwiedzana tylko raz.
Jed Brown

3

Wiem, że na to pytanie już udzielono odpowiedzi, ale oto podobna pamięć pętli oparta na pojedynczej twarzy, która jest zaimplementowana w bibliotece OpenFOAM C ++:

Każda komórka ma indeks (ID) w cellList. Dla wszystkich twarzy zdefiniowane są dwie listy: „twarz wewnętrzny właściciel” i „twarz sąsiad”. Długość obu list ścian odpowiada liczbie ścian wewnętrznych w siatce. Właścicielem twarzy będzie komórka o niższym identyfikatorze w cellList (odwrotnie dla sąsiada twarzy). Ściany graniczne są zapisywane jako ostatnie i mają normalne zorientowane na zewnątrz (z domeny rozwiązania) i oczywiście tylko jedną komórkę właściciela. Normalny obszar twarzy jest zorientowany tak, że wygląda na zewnątrz od komórki właściciela do komórki sąsiedniej.

Działa to dobrze np. Przy obliczaniu strumienia. Strumień jest oceniany raz na twarz i jest dodawany do sumy wszystkich twarzy dla komórek właściciela i odejmowany od sąsiednich komórek (sumowanie / odejmowanie jest ustalane na podstawie orientacji normalnej powierzchni twarzy). Ściany graniczne są sortowane i przechowywane na dole listy ścian, umożliwiając zdefiniowanie warunków brzegowych jako wycinków listy ścian (etykieta początkowa, etykieta końcowa łaty granicznej), co upraszcza w ten sposób również realizację warunków brzegowych jako zmniejszająca wydajność procesu aktualizacji warunków brzegowych, ponieważ polega on na rozwiązaniu zapewnianym przez operacje na powierzchniach wewnętrznych.

Ponieważ ściany graniczne są scalane w plastry, komunikacja między procesami jest zdefiniowana dla łat połączonych (procesorowych) i wstępnie zdefiniowana. Oznacza to, że gdy tylko pętla znajdzie się nad siatką graniczną, funkcje dostępu najwyższego poziomu wywołują zawinięte wywołania MPI, dzięki czemu taki kod jest „automatycznie” równoległy, jeśli opiera się na wyżej opisanej łączności opartej na twarzach.


Nie ma problemu, cieszę się, że ten opis jest przydatny dla kogoś .. :) Czy pracujesz również z OpenFOAM?
tmaric

Kiedyś, trochę w przeszłości. Generalnie staram się trzymać z daleka od przyjętych trendów i próbuję wynaleźć koło na nowo. To moje Tao.
Johntra Volta,

1
Twoje Tao jest przeciwieństwem Tao Informatyki: „Nie wymyślaj na nowo koła”. Ale rozumiem to, że robienie rzeczy od zera jest atrakcyjne! :)
tmaric
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.