|
33 | 33 |
|
34 | 34 | \end{center}
|
35 | 35 |
|
36 |
| -The Advection Equation |
37 |
| -====================== |
38 |
| - |
39 |
| -We seek to solve the advection equation on a multi-level, adaptive grid structure: |
40 |
| - |
41 |
| -.. math:: \frac{\partial\phi}{\partial t} = -\nabla\cdot(\phi{\bf U}). |
42 |
| - |
43 |
| -The velocity field is a specified divergence-free (so the flow field is incompressible) |
44 |
| -function of space and time. The initial scalar field is a |
45 |
| -Gaussian profile. To integrate these equations on a given level, we use a simple conservative update, |
46 |
| - |
47 |
| -.. math:: \frac{\phi_{i,\,j}^{n+1}-\phi_{i,\,j}^n}{\Delta t} = \frac{(\phi u)_{i+^1\!/_2,\,j}^{n+^1\!/_2}-(\phi u)_{i-^1\!/_2,\,j}^{n+^1\!/_2}}{\Delta x} + \frac{(\phi v)_{i,\,j+^1\!/_2}^{n+^1\!/_2} - (\phi v)_{i,\,j-^1\!/_2}^{n+^1\!/_2}}{\Delta y}, |
48 |
| - |
49 |
| -where the velocities on faces are prescribed functions of space and time, and the scalars on faces |
50 |
| -are computed using a Godunov advection integration scheme. The fluxes in this case are the face-centered, |
51 |
| -time-centered “:math:`\phi u`” and “:math:`\phi v`” terms. |
52 |
| - |
53 |
| -We use a subcycling-in-time approach where finer levels are advanced with smaller |
54 |
| -time steps than coarser levels, and then synchronization is later performed between levels. |
55 |
| -More specifically, the multi-level procedure can most |
56 |
| -easily be thought of as a recursive algorithm in which, to advance level :math:`\ell`, |
57 |
| -:math:`0\le\ell\le\ell_{\rm max}`, the following steps are taken: |
58 |
| - |
59 |
| -- Advance level :math:`\ell` in time by one time step, :math:`\Delta t^{\ell}`, as if it is |
60 |
| - the only level. If :math:`\ell>0`, obtain boundary data (i.e. fill the level :math:`\ell` ghost cells) |
61 |
| - using space- and time-interpolated data from the grids at :math:`\ell-1` where appropriate. |
62 |
| - |
63 |
| -- If :math:`\ell<\ell_{\rm max}` |
64 |
| - |
65 |
| - - Advance level :math:`(\ell+1)` for :math:`r` time steps with :math:`\Delta t^{\ell+1} = \frac{1}{r}\Delta t^{\ell}`. |
66 |
| - |
67 |
| - - Synchronize the data between levels :math:`\ell` and :math:`\ell+1`. |
68 |
| - |
69 |
| -.. raw:: latex |
70 |
| - |
71 |
| - \begin{center} |
72 |
| - |
73 |
| -.. _fig:subcycling: |
74 |
| - |
75 |
| -.. figure:: ./AmrCore/figs/subcycling.png |
76 |
| - :width: 4in |
77 |
| - |
78 |
| - Schematic of subcycling-in-time algorithm. |
79 |
| - |
80 |
| -.. raw:: latex |
81 |
| - |
82 |
| - \end{center} |
83 |
| - |
84 |
| -Specifically, for a 3-level simulation, depicted graphically in the figure |
85 |
| -showing the :ref:`fig:subcycling` above: |
86 |
| - |
87 |
| -#. Integrate :math:`\ell=0` over :math:`\Delta t`. |
88 |
| - |
89 |
| -#. Integrate :math:`\ell=1` over :math:`\Delta t/2`. |
90 |
| - |
91 |
| -#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
92 |
| - |
93 |
| -#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
94 |
| - |
95 |
| -#. Synchronize levels :math:`\ell=1,2`. |
96 |
| - |
97 |
| -#. Integrate :math:`\ell=1` over :math:`\Delta t/2`. |
98 |
| - |
99 |
| -#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
100 |
| - |
101 |
| -#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
102 |
| - |
103 |
| -#. Synchronize levels :math:`\ell=1,2`. |
104 |
| - |
105 |
| -#. Synchronize levels :math:`\ell=0,1`. |
106 |
| - |
107 |
| - |
108 |
| - |
109 |
| -For the scalar field, we keep track volume and time-weighted fluxes at coarse-fine interfaces. |
110 |
| -We accumulate area and time-weighted fluxes in :cpp:`FluxRegister` objects, which can be |
111 |
| -thought of as special boundary FABsets associated with coarse-fine interfaces. |
112 |
| -Since the fluxes are area and time-weighted (and sign-weighted, depending on whether they |
113 |
| -come from the coarse or fine level), the flux registers essentially store the extent by |
114 |
| -which the solution does not maintain conservation. Conservation only happens if the |
115 |
| -sum of the (area and time-weighted) fine fluxes equals the coarse flux, which in general |
116 |
| -is not true. |
117 |
| - |
118 |
| -The idea behind the level :math:`\ell/(\ell+1)` synchronization step is to correct for sources of |
119 |
| -mismatch in the composite solution: |
120 |
| - |
121 |
| -#. The data at level :math:`\ell` that underlie the level :math:`\ell+1` data are not synchronized with the level :math:`\ell+1` data. |
122 |
| - This is simply corrected by overwriting covered coarse cells to be the average of the overlying fine cells. |
123 |
| - |
124 |
| -#. The area and time-weighted fluxes from the level :math:`\ell` faces and the level :math:`\ell+1` faces |
125 |
| - do not agree at the :math:`\ell/(\ell+1)` interface, resulting in a loss of conservation. |
126 |
| - The remedy is to modify the solution in the coarse cells immediately next to the coarse-fine interface |
127 |
| - to account for the mismatch stored in the flux register (computed by taking the coarse-level divergence of the |
128 |
| - flux register data). |
129 |
| - |
130 |
| - |
131 | 36 | .. _ss:amrcore:
|
132 | 37 |
|
133 |
| -AmrCore Source Code |
134 |
| -=================== |
| 38 | +AmrCore Source Code: Details |
| 39 | +============================ |
135 | 40 |
|
136 |
| -Here we provide a high-level overview of the source code in ``amrex/Src/AmrCore.`` |
| 41 | +Here we provide more information about the source code in ``amrex/Src/AmrCore.`` |
137 | 42 |
|
138 | 43 | AmrMesh and AmrCore
|
139 | 44 | -------------------
|
@@ -299,16 +204,22 @@ Note that at the coarsest level,
|
299 | 204 | the interior and domain boundary (which can be periodic or prescribed based on physical considerations)
|
300 | 205 | need to be filled. At the non-coarsest level, the ghost cells can also be interior or domain,
|
301 | 206 | but can also be at coarse-fine interfaces away from the domain boundary.
|
302 |
| -AMReX_FillPatchUtil.cpp/H contains two primary functions of interest. |
| 207 | +:cpp:`AMReX_FillPatchUtil.cpp/H` contains two primary functions of interest. |
303 | 208 |
|
304 | 209 | #. :cpp:`FillPatchSingleLevel()` fills a :cpp:`MultiFab` and its ghost region at a single level of
|
305 | 210 | refinement. The routine is flexible enough to interpolate in time between two MultiFabs
|
306 | 211 | associated with different times.
|
307 | 212 |
|
308 |
| -#. :cpp:`FillPatchTwoLevels()` fills a MultiFab and its ghost region at a single level of |
| 213 | +#. :cpp:`FillPatchTwoLevels()` fills a :cpp:`MultiFab` and its ghost region at a single level of |
309 | 214 | refinement, assuming there is an underlying coarse level. This routine is flexible enough to interpolate
|
310 | 215 | the coarser level in time first using :cpp:`FillPatchSingleLevel()`.
|
311 | 216 |
|
| 217 | +Note that :cpp:`FillPatchSingleLevel()` and :cpp:`FillPatchTwoLevels()` call the |
| 218 | +single-level routines :cpp:`MultiFab::FillBoundary` and :cpp:`FillDomainBoundary()` |
| 219 | +to fill interior, periodic, and physical boundary ghost cells. In principle, you can |
| 220 | +write a single-level application that calls :cpp:`FillPatchSingleLevel()` instead |
| 221 | +of using :cpp:`MultiFab::FillBoundary` and :cpp:`FillDomainBoundary()`. |
| 222 | + |
312 | 223 | A :cpp:`FillPatchUtil` uses an :cpp:`Interpolator`. This is largely hidden from application codes.
|
313 | 224 | AMReX_Interpolater.cpp/H contains the virtual base class :cpp:`Interpolater`, which provides
|
314 | 225 | an interface for coarse-to-fine spatial interpolation operators. The fillpatch routines described
|
@@ -390,6 +301,100 @@ the class :cpp:`ParGDBBase` (in ``amrex/Src/Particle/AMReX_ParGDB``).
|
390 | 301 | Example: Advection_AmrCore
|
391 | 302 | ==========================
|
392 | 303 |
|
| 304 | +The Advection Equation |
| 305 | +---------------------- |
| 306 | + |
| 307 | +We seek to solve the advection equation on a multi-level, adaptive grid structure: |
| 308 | + |
| 309 | +.. math:: \frac{\partial\phi}{\partial t} = -\nabla\cdot(\phi{\bf U}). |
| 310 | + |
| 311 | +The velocity field is a specified divergence-free (so the flow field is incompressible) |
| 312 | +function of space and time. The initial scalar field is a |
| 313 | +Gaussian profile. To integrate these equations on a given level, we use a simple conservative update, |
| 314 | + |
| 315 | +.. math:: \frac{\phi_{i,\,j}^{n+1}-\phi_{i,\,j}^n}{\Delta t} = \frac{(\phi u)_{i+^1\!/_2,\,j}^{n+^1\!/_2}-(\phi u)_{i-^1\!/_2,\,j}^{n+^1\!/_2}}{\Delta x} + \frac{(\phi v)_{i,\,j+^1\!/_2}^{n+^1\!/_2} - (\phi v)_{i,\,j-^1\!/_2}^{n+^1\!/_2}}{\Delta y}, |
| 316 | + |
| 317 | +where the velocities on faces are prescribed functions of space and time, and the scalars on faces |
| 318 | +are computed using a Godunov advection integration scheme. The fluxes in this case are the face-centered, |
| 319 | +time-centered “:math:`\phi u`” and “:math:`\phi v`” terms. |
| 320 | + |
| 321 | +We use a subcycling-in-time approach where finer levels are advanced with smaller |
| 322 | +time steps than coarser levels, and then synchronization is later performed between levels. |
| 323 | +More specifically, the multi-level procedure can most |
| 324 | +easily be thought of as a recursive algorithm in which, to advance level :math:`\ell`, |
| 325 | +:math:`0\le\ell\le\ell_{\rm max}`, the following steps are taken: |
| 326 | + |
| 327 | +- Advance level :math:`\ell` in time by one time step, :math:`\Delta t^{\ell}`, as if it is |
| 328 | + the only level. If :math:`\ell>0`, obtain boundary data (i.e. fill the level :math:`\ell` ghost cells) |
| 329 | + using space- and time-interpolated data from the grids at :math:`\ell-1` where appropriate. |
| 330 | + |
| 331 | +- If :math:`\ell<\ell_{\rm max}` |
| 332 | + |
| 333 | + - Advance level :math:`(\ell+1)` for :math:`r` time steps with :math:`\Delta t^{\ell+1} = \frac{1}{r}\Delta t^{\ell}`. |
| 334 | + |
| 335 | + - Synchronize the data between levels :math:`\ell` and :math:`\ell+1`. |
| 336 | + |
| 337 | +.. raw:: latex |
| 338 | + |
| 339 | + \begin{center} |
| 340 | + |
| 341 | +.. _fig:subcycling: |
| 342 | + |
| 343 | +.. figure:: ./AmrCore/figs/subcycling.png |
| 344 | + :width: 4in |
| 345 | + |
| 346 | + Schematic of subcycling-in-time algorithm. |
| 347 | + |
| 348 | +.. raw:: latex |
| 349 | + |
| 350 | + \end{center} |
| 351 | + |
| 352 | +Specifically, for a 3-level simulation, depicted graphically in the figure |
| 353 | +showing the :ref:`fig:subcycling` above: |
| 354 | + |
| 355 | +#. Integrate :math:`\ell=0` over :math:`\Delta t`. |
| 356 | + |
| 357 | +#. Integrate :math:`\ell=1` over :math:`\Delta t/2`. |
| 358 | + |
| 359 | +#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
| 360 | + |
| 361 | +#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
| 362 | + |
| 363 | +#. Synchronize levels :math:`\ell=1,2`. |
| 364 | + |
| 365 | +#. Integrate :math:`\ell=1` over :math:`\Delta t/2`. |
| 366 | + |
| 367 | +#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
| 368 | + |
| 369 | +#. Integrate :math:`\ell=2` over :math:`\Delta t/4`. |
| 370 | + |
| 371 | +#. Synchronize levels :math:`\ell=1,2`. |
| 372 | + |
| 373 | +#. Synchronize levels :math:`\ell=0,1`. |
| 374 | + |
| 375 | + |
| 376 | + |
| 377 | +For the scalar field, we keep track volume and time-weighted fluxes at coarse-fine interfaces. |
| 378 | +We accumulate area and time-weighted fluxes in :cpp:`FluxRegister` objects, which can be |
| 379 | +thought of as special boundary FABsets associated with coarse-fine interfaces. |
| 380 | +Since the fluxes are area and time-weighted (and sign-weighted, depending on whether they |
| 381 | +come from the coarse or fine level), the flux registers essentially store the extent by |
| 382 | +which the solution does not maintain conservation. Conservation only happens if the |
| 383 | +sum of the (area and time-weighted) fine fluxes equals the coarse flux, which in general |
| 384 | +is not true. |
| 385 | + |
| 386 | +The idea behind the level :math:`\ell/(\ell+1)` synchronization step is to correct for sources of |
| 387 | +mismatch in the composite solution: |
| 388 | + |
| 389 | +#. The data at level :math:`\ell` that underlie the level :math:`\ell+1` data are not synchronized with the level :math:`\ell+1` data. |
| 390 | + This is simply corrected by overwriting covered coarse cells to be the average of the overlying fine cells. |
| 391 | + |
| 392 | +#. The area and time-weighted fluxes from the level :math:`\ell` faces and the level :math:`\ell+1` faces |
| 393 | + do not agree at the :math:`\ell/(\ell+1)` interface, resulting in a loss of conservation. |
| 394 | + The remedy is to modify the solution in the coarse cells immediately next to the coarse-fine interface |
| 395 | + to account for the mismatch stored in the flux register (computed by taking the coarse-level divergence of the |
| 396 | + flux register data). |
| 397 | + |
393 | 398 | Code Structure
|
394 | 399 | --------------
|
395 | 400 |
|
|
0 commit comments