Come implementare in modo efficiente le condizioni al contorno di Dirichlet nelle matrici rigide globali di elementi finiti sparsi


9

Mi chiedo come le condizioni al contorno di Dirichlet nelle matrici globali di elementi finiti sparsi siano effettivamente implementate in modo efficiente. Ad esempio, supponiamo che la nostra matrice globale di elementi finiti fosse:

K=[520-102410001632-1037000203]e il lato destro vettoreB=[B1B2B3B4B5]

Quindi per applicare una condizione di Dirichlet sul primo nodo ( ) dovremmo azzerare la prima riga, mettere un 1 in e sottrarre la prima colonna dal lato destro. Ad esempio il nostro sistema diventerebbe: K = \ begin {bmatrix} 1 & 0 & 0 & 0 & 0 \\ 0 & 4 & 1 & 0 & 0 \\ 0 & 1 & 6 & 3 & 2 \\ 0 & 0 & 3 & 7 & 0 \\ 0 & 0 & 2 & 0 & 3 \ end {bmatrix} \ hspace {5mm} \ text {e vettore sul lato destro} \ hspace {5mm} b = \ begin {bmatrix} c \\ b2-2 \ times {c} \\ b3-0 \ times {c} \\ b4 + 1 \ times {c} \\ b5-0 \ times {c} \\ \ end {bmatrix} K 11 K = [ 1 0 0 0 0 0 4 1 0 0 0 1 6 3 2 0 0 3 7 0 0 0 2 0 3 ]X1=cK11

K=[1000004100016320037000203]e il lato destro vettoreB=[cB2-2×cB3-0×cB4+1×cB5-0×c]

Questo va bene in teoria, ma se la nostra matrice K è memorizzata nel formato di riga compressa (CRS), spostare le colonne sul lato destro diventa costoso per i sistemi di grandi dimensioni (con molti nodi che sono dirichlet). Un'alternativa sarebbe quella di non spostare le colonne corrispondenti a una condizione di Dirichlet sul lato destro, ovvero il nostro sistema diventerebbe:

K=[100002410001632-1037000203]e il lato destro vettoreB=[cB2B3B4B5]

Ciò ha tuttavia un grande inconveniente in quanto il sistema non è più simmetrico e quindi non potremmo più utilizzare il gradiente coniugato precondizionato (o altri solutori simmetrici). Una soluzione interessante che ho trovato è il "Metodo dei grandi numeri" che ho trovato nel libro "Programmazione di elementi finiti in Java" di Gennadiy Nikishkov. Questo metodo utilizza il fatto che la doppia precisione contiene solo circa 16 cifre di precisione. Invece di mettere un 1 nella posizione posizioniamo un numero elevato. Ad esempio il nostro sistema diventa: K = [ 1.0 e 64 2 0 - 1 0 2 4 1 0 0 0 1 6 3 2 - 1 0 3 7 0 0 0 2 0 3 ]K11

K=[1.0e6420-102410001632-1037000203]e il lato destro vettoreB=[c×1.0e64B2B3B4B5]

I vantaggi di questo metodo sono che mantiene la simmetria della matrice pur essendo molto efficiente per i formati di archiviazione sparsi. Le mie domande quindi sono le seguenti:

Come vengono tipicamente implementate le condizioni al contorno di Dirichlet in codici ad elementi finiti per calore / fluidi? Le persone usano il metodo di grandi numeri di solito o fanno qualcos'altro? C'è qualche svantaggio nel metodo dei grandi numeri che qualcuno può vedere? Suppongo che ci sia probabilmente un metodo standard efficiente usato nella maggior parte dei codici commerciali e non commerciali che risolve questo problema (ovviamente non mi aspetto che le persone conoscano tutti i meccanismi interni di ogni risolutore di elementi finiti commerciali, ma questo problema sembra fondamentale / fondamentale abbastanza che qualcuno probabilmente ha lavorato a tali progetti e potrebbe fornire una guida).


2
Hai prove che questo ti stia sostanzialmente rallentando?
Bill Barth,

@BillBarth Sì, anche se c'è sempre la possibilità che io faccia qualcosa in modo inefficiente. Gennadily stesso scrive che mentre il metodo esplicito è facile per le matrici 2d complete, "..non è sempre facile accedere alle righe e alle colonne della matrice quando una matrice è in formato compatto". suggerendo che il metodo esplicito potrebbe essere più difficile da attuare in modo efficiente. Dato che il mio codice è attualmente scritto, il metodo esplicito può richiedere più tempo della risoluzione effettiva.
James,

1
fallo come dice Wolfgang e applica le condizioni al contorno alle matrici degli elementi prima di assemblare.
Bill Barth,

@BillBarth Sì, penso che lo farò. I suoi video sono fantastici! Ho appena lasciato un commento / domanda per lui sull'opportunità di riassemblare le matrici globali in ogni momento, dopo di che penso che accetterò la sua risposta.
James,

Risposte:


11

In deal.II ( http://www.dealii.org - disclaimer: sono uno dei principali autori di quella libreria), eliminiamo intere righe e colonne, e nel complesso non è troppo costoso. Il trucco è utilizzare il fatto che il modello di sparsità è tipicamente simmetrico, quindi sai quali righe devi esaminare quando elimini un'intera colonna.

L'approccio migliore, a mio avviso, è quello di eliminare queste righe e colonne nelle matrici delle celle, prima che vengano aggiunte alla matrice globale. Lì lavori con matrici complete, quindi tutto è efficiente.

Non ho mai sentito parlare dell'approccio di grandi numeri e non lo userei perché sicuramente porterà a problemi terribilmente mal condizionati.

Per riferimento, gli algoritmi che utilizziamo in deal.II sono descritti concettualmente nelle lezioni 21.6 e 21.65 su http://www.math.colostate.edu/~bangerth/videos.html . Corrispondono strettamente alla tua descrizione.


2
Nel caso di un problema dipendente dal tempo (ad esempio l'equazione del calore), riassemblare la matrice globale ad ogni intervallo di tempo? Il motivo per cui ti chiedo è che nel caso di condizioni di Dirichlet diverse da zero hai bisogno di informazioni dalla matrice globale originale quando modifichi il lato destro, ma se hai azzerato quelle colonne durante il timestep precedente, queste informazioni vanno perse (a meno che non le memorizzi in array aggiuntivi). Questo non sarebbe un problema se la matrice globale venisse riassemblata ogni volta che è quello che sto considerando di fare e che cosa dovrebbe essere fatto comunque se si usasse la mesh adattiva.
James,

1
Dipende dall'applicazione. Tutti i "grandi" codici risolvono problemi non lineari dipendenti dal tempo e per questi è chiaro che è necessario riassemblare in un modo o nell'altro. Per i codici lineari, puoi semplicemente memorizzare la matrice originale e, in ogni momento, copiarla da qualche altra parte, applicare condizioni al contorno e quindi usarla nel solutore. Ciò richiede solo più memoria, ma è comunque economico.
Wolfgang Bangerth,

1
Ah, vedo che è quello che sospettavo. Realizzerò come hai suggerito. Ok questo è per il tuo aiuto. Quei video tutorial di Deallii sono davvero buoni tra noi!
James,

2

I BC zero sono facili. Per BC non zero puoi anche usare i moltiplicatori di Lagrange. Ad esempio, vedi qui . Un vantaggio di LM è che puoi usare qualsiasi equazione di vincolo, anche se il sistema diventa indefinito, quindi hai bisogno di un risolutore appropriato.

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.