aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/analytic-k2.pngbin0 -> 11210 bytes
-rw-r--r--doc/analytic.pngbin0 -> 17892 bytes
-rw-r--r--doc/excerpt.cc19
-rw-r--r--doc/excerpt2.cc14
-rw-r--r--doc/line-sol-k2.pngbin0 -> 14810 bytes
-rw-r--r--doc/line-supg-sol-k2.pngbin0 -> 8614 bytes
-rw-r--r--doc/paper-excerpt1.cc24
-rw-r--r--doc/paper-excerpt2.cc19
-rw-r--r--doc/report.pdfbin222163 -> 314605 bytes
-rw-r--r--doc/report.tex270
-rw-r--r--doc/sources.bib32
11 files changed, 340 insertions, 38 deletions
diff --git a/doc/analytic-k2.png b/doc/analytic-k2.png
new file mode 100644
index 0000000..6389688
--- /dev/null
+++ b/doc/analytic-k2.png
Binary files differ
diff --git a/doc/analytic.png b/doc/analytic.png
new file mode 100644
index 0000000..83078d0
--- /dev/null
+++ b/doc/analytic.png
Binary files differ
diff --git a/doc/excerpt.cc b/doc/excerpt.cc
new file mode 100644
index 0000000..5a57a0d
--- /dev/null
+++ b/doc/excerpt.cc
@@ -0,0 +1,19 @@
1for (int i = 0; i < ir->GetNPoints(); ++i) {
2 // Get shape functions, coefficients at this integration point.
3 ...
4
5 // Calculate phi_grad.
6 phi_grad = 0.0;
7 for (int b = 0; b < nen; ++b) {
8 for (int j = 0; j < nsd; ++j) {
9 phi_grad(j) += dshape(b, j) * elfun(b);
10 }
11 }
12
13 // Calculate SUPG term.
14 for (int a = 0; a < nen; ++a) {
15 dshape.GetRow(a, Na_grad);
16 double tau_tmp = (A_ip*Na_grad)*tau_ip;
17 elvec(a) += tau_tmp * (A_ip * phi_grad) * wdetj;
18 }
19}
diff --git a/doc/excerpt2.cc b/doc/excerpt2.cc
new file mode 100644
index 0000000..765e338
--- /dev/null
+++ b/doc/excerpt2.cc
@@ -0,0 +1,14 @@
1for (int i = 0; i < ir->GetNPoints(); ++i) {
2 // Get shape functions, coefficients at this integration point.
3 ...
4
5 // Calculate tangent matrix.
6 for (int a = 0; a < nen; ++a) {
7 dshape.GetRow(a, Na_grad);
8 double tau_tmp = (A_ip*Na_grad)*tau_ip;
9 for (int b = 0; b < nen; ++b) {
10 dshape.GetRow(b, Nb_grad);
11 elmat(a, b) += tau_tmp * (A_ip * Nb_grad) * wdetj;
12 }
13 }
14}
diff --git a/doc/line-sol-k2.png b/doc/line-sol-k2.png
new file mode 100644
index 0000000..aba807f
--- /dev/null
+++ b/doc/line-sol-k2.png
Binary files differ
diff --git a/doc/line-supg-sol-k2.png b/doc/line-supg-sol-k2.png
new file mode 100644
index 0000000..1acd732
--- /dev/null
+++ b/doc/line-supg-sol-k2.png
Binary files differ
diff --git a/doc/paper-excerpt1.cc b/doc/paper-excerpt1.cc
new file mode 100644
index 0000000..d34bce3
--- /dev/null
+++ b/doc/paper-excerpt1.cc
@@ -0,0 +1,24 @@
1for (int i = 0; i < ir->GetNPoints(); ++i) {
2 // Get shape functions, coefficients at this integration point.
3 const IntegrationPoint& ip = ir->IntPoint(i);
4 Tr.SetIntPoint(&ip);
5 el.CalcPhysDShape(Tr, dshape);
6 A_ir.GetColumn(i, A_ip);
7 double tau_ip = tau->Eval(Tr, ip);
8 const double wdetj = ip.weight * Tr.Weight();
9
10 // Calculate phi_grad.
11 phi_grad = 0.0;
12 for (int b = 0; b < nen; ++b) {
13 for (int j = 0; j < nsd; ++j) {
14 phi_grad(j) += dshape(b, j) * elfun(b);
15 }
16 }
17
18 // Calculate SUPG term.
19 for (int a = 0; a < nen; ++a) {
20 dshape.GetRow(a, Na_grad);
21 double tau_tmp = (A_ip*Na_grad)*tau_ip;
22 elvec(a) += tau_tmp * (A_ip * phi_grad) * wdetj;
23 }
24}
diff --git a/doc/paper-excerpt2.cc b/doc/paper-excerpt2.cc
new file mode 100644
index 0000000..5843c4d
--- /dev/null
+++ b/doc/paper-excerpt2.cc
@@ -0,0 +1,19 @@
1for (int i = 0; i < ir->GetNPoints(); ++i) {
2 // Get shape functions, coefficients at this integration point.
3 const IntegrationPoint& ip = ir->IntPoint(i);
4 Tr.SetIntPoint(&ip);
5 el.CalcPhysDShape(Tr, dshape);
6 A_ir.GetColumn(i, A_ip);
7 double tau_ip = tau->Eval(Tr, ip);
8 double wdetj = ip.weight * Tr.Weight();
9
10 // Calculate tangent matrix.
11 for (int a = 0; a < nen; ++a) {
12 dshape.GetRow(a, Na_grad);
13 double tau_tmp = (A_ip*Na_grad)*tau_ip;
14 for (int b = 0; b < nen; ++b) {
15 dshape.GetRow(b, Nb_grad);
16 elmat(a, b) += tau_tmp * (A_ip * Nb_grad) * wdetj;
17 }
18 }
19}
diff --git a/doc/report.pdf b/doc/report.pdf
index c45cdcc..e9709a0 100644
--- a/doc/report.pdf
+++ b/doc/report.pdf
Binary files differ
diff --git a/doc/report.tex b/doc/report.tex
index 9c72b59..510637f 100644
--- a/doc/report.tex
+++ b/doc/report.tex
@@ -5,13 +5,15 @@
5\usepackage{amsmath} 5\usepackage{amsmath}
6\usepackage{graphicx} 6\usepackage{graphicx}
7\usepackage{hyperref} 7\usepackage{hyperref}
8\usepackage{tabularx}
9\usepackage{listings}
8 10
9\usepackage[backend=biber]{biblatex} 11\usepackage[backend=biber]{biblatex}
10\addbibresource{sources.bib} 12\addbibresource{sources.bib}
11 13
12\title{% 14\title{
13Term Project Report \\ 15 SUPG Stabilization for Advection-Diffusion with MFEM \\
14MANE 6660: Finite Element Method 16 \large{MANE 6660: Finite Element Method Final Project Report}
15} 17}
16\author{Aiden Woodruff} 18\author{Aiden Woodruff}
17\date{\today} 19\date{\today}
@@ -19,67 +21,102 @@ MANE 6660: Finite Element Method
19\begin{document} 21\begin{document}
20\maketitle 22\maketitle
21 23
22\section*{MFEM SUPG miniapp} 24\section{Introduction}
23My project proposal for the FEM term project is a SUPG miniapp implemented
24with MFEM. This is an independent project related to my graduate research
25(which has focused on shock processing).
26 25
27\subsection*{Advection-diffusion equation} 26The advection-diffusion equation, also known as the
28The complete strong form of the advection-diffusion equation is given: 27convection-diffusion equation, is a PDE that combines advection and diffusion
28to describe fluid flow:
29 29
30\begin{gather} 30\begin{gather} \label{eq:pde}
31 \frac{\delta\phi}{\delta t} + \nabla\cdot\pmb F(\phi) = s \\ 31 \frac{\delta\phi}{\delta t} + \nabla\cdot\pmb F(\phi) = s \\
32 \pmb F(\phi) = \pmb F^\text{adv} + \pmb F^\text{diff} = 32 \pmb F(\phi) = \pmb F^\text{adv}(\phi) + \pmb F^\text{diff}(\phi) =
33 \pmb a\phi + (-\kappa\nabla\phi) 33 \pmb a\phi + (-\kappa\nabla\phi)
34\end{gather} 34\end{gather}
35 35
36Where \(\phi\) is the solution variable (i.e. pressure or temperature), 36The solution variable \(\phi\) may be a number of quantities such as pressure,
37\(\pmb a\) is the advection velocity vector, \(\kappa\) is diffusivity, and 37temperature, or species concentration. \(\pmb a\) is the advection velocity,
38\(s\) is the source term. I make the following simplifying assumptions: 38\(\kappa\) is diffusivity, and \(s\) is the source term. In this project, a
39simplified form of the equation is solved with the following assumptions:
39 40
40\begin{itemize} 41\begin{itemize}
41 \item No time dependent term. 42 \item No time dependent term.
42 \item Constant \(\pmb a\) and \(\kappa\). 43 \item Constant \(\pmb a\) and \(\kappa\) (w.r.t. \(\phi\)).
43 \item No source term; \(s=0\). 44 \item No source term, i.e. \(s=0\).
44 \item Only Dirichlet boundary conditions. 45 \item Only Dirichlet boundary conditions.
45 \item Linear finite elements. 46 \item Linear finite elements.
46\end{itemize} 47\end{itemize}
47 48
48Then the simplified strong form residual follows: 49The resulting strong form residual is:
49 50
50\begin{equation} 51\begin{equation} \label{eq:strong}
51 R(\phi) = \nabla\cdot\left(\pmb a\phi - \kappa\nabla\phi\right) = 0 52 R(\phi) = \nabla\cdot\left(\pmb a\phi - \kappa\nabla\phi\right) = 0
52\end{equation} 53\end{equation}
53 54
54Using index notation: 55The strong form residual \eqref{eq:strong} is expressed in index notation as
55 56
56\begin{equation} 57\begin{equation} \label{eq:strong-idx}
57 R(\phi) = a_i \phi,_i - \left(\kappa\phi,_i\right),_i 58 R(\phi) = a_i \phi,_i - \left(\kappa\phi,_i\right),_i
58\end{equation} 59\end{equation}
59 60
60Apply the method of weighted residuals and integration by parts to obtain the 61The solution can be obtained analytically for the 1D case using separation of
61weak form: 62variables:
62 63
63\begin{equation} 64\begin{equation}
64 \int_\Omega -w,_i a_i \phi + w,_i \kappa \phi,_i d\Omega = 0 65 \phi = \frac{\kappa}{a}e^{\frac{a}{k}x + c_1} + c_2
66\end{equation}
67
68Where \(c_1\) and \(c_2\) are solved based on the boundary conditions
69\((x_L,\phi_L)\) and \((x_R,\phi_R)\):
70
71\begin{equation}
72 c_1 = \ln\left(
73 \frac{a}{\kappa} \cdot
74 \frac{\phi_R - \phi_L}{e^{\frac{a}{\kappa}x_R} - e^{\frac{a}{\kappa}x_L}}
75 \right)
76 \quad
77 c_2 = \phi_L - \frac{\phi_R - \phi_L}{
78 e^{\frac{a}{\kappa}x_R} - e^{\frac{a}{\kappa}x_L}
79 }
65\end{equation} 80\end{equation}
66 81
67\subsection*{Stabilization} 82An analytical solution is shown in Figure \ref{fig:analytic}.
83
84\begin{figure}
85 \centering
86 \includegraphics[width=0.45\linewidth]{analytic-k1.png}
87 \caption{
88 Analytic solution with \(a_x = 1\), \(\kappa = 0.1\), and boundary
89 conditions \(\phi(0) = 0.2; \phi(1.6) = 1.4\)
90 }
91 \label{fig:analytic}
92\end{figure}
93
94The finite element method is typically used to solve cases in higher dimensions
95with general domains. The weak form is obtained from \eqref{eq:strong} by
96applying the method of weighted residuals and integration by parts:
97
98\begin{equation}
99 \int_\Omega -w,_i a_i \phi + w,_i \kappa \phi,_i d\Omega = 0
100\end{equation}
68 101
69Using the standard Galerkin approach in advection dominated cases results in an 102Then linear finite elements can be used. However, using the standard Galerkin
70ill-conditioned matrix. See Figure \ref{fig:fem-unstable} for an example of an 103approach in advection dominated cases results in an ill-conditioned matrix and
71unstable advection-dominated solution. 104numerical instability. See Figure \ref{fig:fem-unstable} for a comparison
105of a stable FEM solution and an unstable advection-dominated FEM solution.
72 106
73\begin{figure} 107\begin{figure}
74 \centering 108 \centering
75 \includegraphics[width=0.45\textwidth]{line-sol-k1e0.png} 109 \includegraphics[width=0.45\textwidth]{lecsoln-k1.png}
76 \includegraphics[width=0.45\textwidth]{line-sol-k1e-3.png} 110 \includegraphics[width=0.45\textwidth]{lecsoln-k2.png}
77 \caption{Stable solution (kappa=1) and unstable solution (kappa=1e-3)} 111 \caption{
112 Stable solution (kappa=0.1) and unstable solution (kappa=0.01) from a
113 reference FEM implementation with exact solution shown
114 }
78 \label{fig:fem-unstable} 115 \label{fig:fem-unstable}
79\end{figure} 116\end{figure}
80 117
81One approach to remedy this instability is to introduce a stabilization term 118One approach to remedy this instability is to introduce a stabilization term
82(artifical numerical diffusion). A simple formulation is called Streamlined- 119(artificial numerical diffusion). A simple formulation is called Streamlined-
83Upwind Petrov-Galerkin (SUPG). Here, an extra term is added to the weak form: 120Upwind Petrov-Galerkin (SUPG). Here, an extra term is added to the weak form:
84\(a({\pmb F}^\text{adv}(w), -\tau R(\phi))\). In the linear finite element 121\(a({\pmb F}^\text{adv}(w), -\tau R(\phi))\). In the linear finite element
85case, the diffusive term of the strong form residual can be dropped if care is 122case, the diffusive term of the strong form residual can be dropped if care is
@@ -96,23 +133,180 @@ form is:
96The stabilizing term depends on the residual so that it goes to zero when the 133The stabilizing term depends on the residual so that it goes to zero when the
97solution is achieved. The parameter \(\tau\) is of special importance, as too 134solution is achieved. The parameter \(\tau\) is of special importance, as too
98small or too large \(\tau\) can result in an ineffective method. Shakib and 135small or too large \(\tau\) can result in an ineffective method. Shakib and
99Hughes \cite{shakib_1991} identify an optimal value based on the cell Peclet 136Hughes \cite{shakib_1991} identify an optimal value in 1D based on the cell
100number. However, this value is computationally inefficient, so an approximation 137P\'{e}clet number.
101is also available: 138
139\begin{equation}
140 \tau_{skb} = \frac{h}{2|a_x|} \cdot \left(\coth(Pe) - \frac{q}{Pe}\right)
141 \quad
142 Pe = \frac{|a_x|h}{2\kappa}
143\end{equation}
144
145However, this value is computationally inefficient, so an approximation
146is also made available:
102 147
103\begin{equation} 148\begin{equation}
104 \tau_{skb} = \left[ 149 \tau_{skb,alg} = \left[
105 \left(\frac{2|a_x|}{h}\right)^2 150 \left(\frac{2|a_x|}{h}\right)^2
106 +\left(\frac{4\kappa}{h^2}\right)^2 151 +9\left(\frac{4\kappa}{h^2}\right)^2
107 \right]^{-1/2} 152 \right]^{-1/2}
108\end{equation} 153\end{equation}
109 154
110\begin{figure} 155An FEM solution with SUPG stabilization is shown in Figure \ref{fig:fem-supg}.
111 \includegraphics[width=\textwidth]{line-supg-sol-k1e-3.png} 156
157\begin{figure}[htp]
158 \centering
159 \includegraphics[width=0.45\textwidth]{lecsoln-k2-supg.png}
112 \caption{SUPG stabilized solution (kappa=1e-3)} 160 \caption{SUPG stabilized solution (kappa=1e-3)}
113 \label{fig:fem-supg} 161 \label{fig:fem-supg}
114\end{figure} 162\end{figure}
115 163
164In this project I use MFEM, a C++ framework for finite elements
165\cite{mfem-web}, to solve the advection-diffusion equation in an
166advection-dominated case. I compare my results to the exact solution and the
167reference FEM solution.
168
169\section{Methods}
170
171The MFEM library allows specification of the weak form using pre-defined
172\texttt{Integrator}s. Two such classes are readily available for solving
173the advection-diffusion equation: \texttt{ConservativeConvectionIntegrator} and
174\texttt{DiffusionIntegrator}. Implementing the SUPG term requires the addition
175of a custom integrator, \texttt{SUPGIntegrator}. Additionally, because the SUPG
176term includes the solution variable, it is implemented by extending
177\texttt{NonlinearFormIntegrator} instead of \texttt{BilinearFormIntegrator},
178which changes the problem setup for the stabilized case. See Listing
179\ref{inp:ex1} for the code for the nonlinear residual and Listing \ref{inp:ex2}
180for code for the nonlinear jacobian.
181
182\lstinputlisting[
183 basicstyle=\ttfamily\small,tabsize=2,frame=single,
184 caption={Key lines of code for the SUPG nonlinear residual},
185 label={inp:ex1}
186]{paper-excerpt1.cc}
187
188\lstinputlisting[
189 basicstyle=\ttfamily\small,tabsize=2,frame=single,
190 caption={Key lines of code for the SUPG nonlinear jacobian},
191 label={inp:ex2}
192]{paper-excerpt2.cc}
193
194\section{Results}
195
196The custom \texttt{SUPGIntegrator} provided stabilization and accurate results
197for advection-dominated cases, except when the left boundary condition was
198enforced -- note that \ref{tbl:k2} and the right of Figure \ref{fig:mfem-supg}
199start from \(\phi = 0.0\) whereas the left and \ref{tbl:k0} start from \(\phi =
2000.2\). The cause for this is unclear, as the implementation uses physical
201gradients and includes the inverse jacobian determinant.
202
203\begin{figure}[htp]
204 \centering
205 \includegraphics[width=0.45\textwidth]{line-sol-k0.png}
206 \includegraphics[width=0.45\textwidth]{line-supg-sol-k2.png}
207 \caption{
208 MFEM solution for \(a_x=1\), \(\kappa=1\) (left) and \(a_x=1\),
209 \(\kappa=0.01\) (right)
210 }
211 \label{fig:mfem-supg}
212\end{figure}
213
214\begin{table}
215 \centering
216 \begin{tabular}{c|c|c}
217 \small
218 Exact solution & Reference FEM solution & MFEM solution \\
219 \hline
220 0.2 & 0.2 & 0.2 \\
221 \hline
222 0.23192615 & 0.23192615 & 0.2318994842537078 \\
223 \hline
224 0.26721 & 0.26721 & 0.2671570027631416 \\
225 \hline
226 0.30620469 & 0.30620469 & 0.3061264579767903 \\
227 \hline
228 0.34930048 & 0.34930048 & 0.3491981952038976 \\
229 \hline
230 0.3969287 & 0.3969287 & 0.3968037571864139 \\
231 \hline
232 0.44956602 & 0.44956602 & 0.4494211044369776 \\
233 \hline
234 0.50773925 & 0.50773926 & 0.5075777552014797 \\
235 \hline
236 0.57203062 & 0.57203063 & 0.5718563242761415 \\
237 \hline
238 0.64308357 & 0.64308358 & 0.6429009576212408 \\
239 \hline
240 0.72160923 & 0.72160923 & 0.7214237583971538 \\
241 \hline
242 0.8083935 & 0.8083935 & 0.8082118551597843 \\
243 \hline
244 0.90430495 & 0.90430496 & 0.904135215032668 \\
245 \hline
246 1.0103035 & 1.0103035 & 1.010155960623283 \\
247 \hline
248 1.12745001 & 1.12745001 & 1.12733665457002 \\
249 \hline
250 1.25691693 & 1.25691693 & 1.256851800816963 \\
251 \hline
252 1.4 & 1.4 & 1.4
253 \end{tabular}
254 \caption{Comparison of nodal values for \(a_x=1\), \(\kappa=1\)}
255 \label{tbl:k0}
256\end{table}
257
258\begin{table}
259 \centering
260 \begin{tabular}{c|c|c}
261 \small
262 Exact solution & Reference FEM solution & MFEM solution \\
263 \hline
264 7.07789169e-85 & 0.00000000e+00 & 0 \\
265 \hline
266 1.00446783e-65 & 6.72915553e-24 & 1.344027471478775e-21 \\
267 \hline
268 2.21258808e-61 & 2.47544695e-22 & -3.440531560398167e-19 \\
269 \hline
270 4.87354958e-57 & 8.86558356e-21 & -5.957125219217317e-19 \\
271 \hline
272 1.07347073e-52 & 3.17278380e-19 & 5.144414882568559e-17 \\
273 \hline
274 2.36447663e-48 & 1.13544128e-17 & 1.095961397199189e-16 \\
275 \hline
276 5.20810637e-44 & 4.06339111e-16 & -5.302401810502381e-15 \\
277 \hline
278 1.14716177e-39 & 1.45416125e-14 & 4.901903445752921e-15 \\
279 \hline
280 2.52679194e-35 & 5.20399065e-13 & 1.007010439154497e-12 \\
281 \hline
282 5.56562963e-31 & 1.86234634e-11 & 1.920121752194572e-11 \\
283 \hline
284 1.22591151e-26 & 6.66475808e-10 & 6.356196583077191e-10 \\
285 \hline
286 2.70024979e-22 & 2.38510955e-08 & 2.383479327580857e-08 \\
287 \hline
288 5.94769596e-18 & 8.53556496e-07 & 8.549283844700147e-07 \\
289 \hline
290 1.31006722e-13 & 3.05461312e-05 & 3.054579043392884e-05 \\
291 \hline
292 2.88561507e-09 & 1.09315099e-03 & 0.001093115172881016 \\
293 \hline
294 6.35599017e-05 & 3.91204728e-02 & 0.03912052192397422 \\
295 \hline
296 1.40000000e+00 & 1.40000000e+00 & 1.4
297 \end{tabular}
298 \caption{Comparison of nodal values for \(a_x=1\), \(\kappa=0.01\)}
299 \label{tbl:k2}
300\end{table}
301
302\section{Lessons learned}
303
304Using MFEM turned out to be the most difficult part of the project. Initially,
3052D cases were also planned for, but had to be abandoned due to time
306constraints. It was unclear that a \texttt{NonlinearFormIntegrator} was
307required, and since the needs of this project differed from the provided
308examples, it was somewhat unclear what to do.
309
116Code is available at \url{https://git.aidenw.net/rpi/mfem-supg}. 310Code is available at \url{https://git.aidenw.net/rpi/mfem-supg}.
117 311
118\printbibliography 312\printbibliography
diff --git a/doc/sources.bib b/doc/sources.bib
index 84d577c..58efee9 100644
--- a/doc/sources.bib
+++ b/doc/sources.bib
@@ -1,3 +1,35 @@
1@article{mfem-2024,
2 title = {High-Performance Finite Elements with {MFEM}},
3 author = {J. Andrej and N. Atallah and J.-P. Bäcker and J.-S. Camier and
4 D. Copeland and V. Dobrev and Y. Dudouit and T. Duswald and
5 B. Keith and D. Kim and T. Kolev and B. Lazarov and K. Mittal and
6 W. Pazner and S. Petrides and S. Shiraiwa and M. Stowell and V. Tomov},
7 journal={The International Journal of High Performance Computing Applications},
8 volume={38},
9 number={5},
10 pages={447-467},
11 year={2024},
12 publisher={SAGE Publications Sage UK: London, England}
13}
14
15@article{mfem-2021,
16 title = {{MFEM}: A Modular Finite Element Methods Library},
17 author = {R. Anderson and J. Andrej and A. Barker and J. Bramwell and J.-S. Camier and
18 J. Cerveny and V. Dobrev and Y. Dudouit and A. Fisher and Tz. Kolev and W. Pazner and
19 M. Stowell and V. Tomov and I. Akkerman and J. Dahm and D. Medina and S. Zampini},
20 journal = {Computers \& Mathematics with Applications},
21 doi = {10.1016/j.camwa.2020.06.009},
22 volume = {81},
23 pages = {42-74},
24 year = {2021}
25}
26
27@misc{mfem-web,
28 key = {mfem},
29 title = {{MFEM}: Modular Finite Element Methods {[Software]}},
30 howpublished = {\url{mfem.org}},
31 doi = {10.11578/dc.20171025.1248}
32}
1 33
2@article{shakib_1991, 34@article{shakib_1991,
3 title = {A new finite element formulation for computational fluid dynamics: X. The compressible Euler and Navier-Stokes equations}, 35 title = {A new finite element formulation for computational fluid dynamics: X. The compressible Euler and Navier-Stokes equations},