├── .github └── workflows │ └── build-book.yml ├── .gitignore ├── ADDITIONS ├── CompHydroTutorial.tex ├── Euler ├── Euler-methods.tex ├── Euler-theory.tex ├── README ├── advect_hydro1d.pdf ├── axisymmetry.odg ├── axisymmetry.pdf ├── hydro1d_god_double_rare.pdf ├── hydro1d_god_sod.pdf ├── hydro1d_plm_double_rare.pdf ├── hydro1d_plm_sod.pdf ├── hydro1d_ppm_double_rare.pdf ├── hydro1d_ppm_sod.pdf ├── hydro1d_sedov_1dsph.pdf ├── main.tex ├── multiple_interfaces.pdf ├── piecewise-constant.pdf ├── piecewise-linear.pdf ├── piecewise-parabolic.pdf ├── ppm-trace.pdf ├── quad.pdf ├── rarefaction_center.pdf ├── rarefaction_left.pdf ├── rarefaction_right.pdf ├── riemann-2shock-sod-phase.pdf ├── riemann-phase.pdf ├── riemann-sod.pdf ├── riemann-waves.pdf ├── riemann_comp.pdf ├── riemann_waves_ifc_L.pdf ├── riemann_waves_ifc_Lstar.pdf ├── riemann_waves_ifc_R.pdf ├── riemann_waves_ifc_Rstar.pdf ├── sedov_compare.pdf ├── sedov_pyro.pdf ├── slowshock.pdf └── states.pdf ├── GNUmakefile ├── LICENSE ├── NOTES ├── README.md ├── TODO ├── advection ├── 2dgrid-hat.pdf ├── 2dgrid-transverse.pdf ├── 2dgrid.pdf ├── advection-basics.tex ├── advection-characteristics.pdf ├── advection-higherorder.tex ├── domains_FTCS.pdf ├── domains_downwind.pdf ├── domains_upwind.pdf ├── fd_ghost.pdf ├── fdadvect-FTCS-C0_1.pdf ├── fdadvect-FTCS-C0_5.pdf ├── fdadvect-implicit.pdf ├── fdadvect-upwind.pdf ├── fv-advect.pdf ├── fv-gaussian-limiters.pdf ├── fv-tophat-limiters.pdf ├── fv_ghost.pdf ├── generalgrid.pdf ├── main.tex ├── old-scripts │ ├── fv.py │ ├── simplegrid.py │ └── simplegrid2.py ├── plm-converge.pdf ├── rea-evolve.pdf ├── rea-final.pdf ├── rea-nolimit-start_001.pdf ├── rea-nolimit-start_002.pdf ├── rea-nolimit-start_003.pdf ├── rea-nolimit-start_004.pdf ├── rea-nolimit-start_005.pdf ├── rea-nolimit-start_006.pdf ├── rea-nolimit-start_007.pdf ├── rea-nolimit-start_008.pdf ├── rea-reconstruction.pdf ├── rea-start.pdf ├── rea-start_001.pdf ├── rea-start_002.pdf ├── rea-start_003.pdf ├── rea-start_004.pdf ├── rea-start_005.pdf ├── rea-start_006.pdf ├── rea-start_007.pdf ├── rea-start_008.pdf ├── rea-trace.pdf ├── riemann-adv.pdf ├── riemann-bc.pdf ├── riemann-mol.pdf ├── smooth_final.pdf ├── smooth_init.pdf ├── tophat_final.pdf ├── tophat_init.pdf ├── tophat_rk4_cfl04.pdf └── tophat_rk4_cfl08.pdf ├── burgers ├── burgers-characteristics-rare.pdf ├── burgers-characteristics.pdf ├── burgers.tex ├── fv-burger-rarefaction.pdf ├── fv-burger-sine.pdf └── rh.pdf ├── codes └── intro │ └── sin-converge.py ├── diffusion ├── GNUmakefile ├── diff-explicit-64-bad.pdf ├── diff-explicit-64.pdf ├── diff-implicit-128-CFL_0_8.pdf ├── diff-implicit-128-CFL_8_0.pdf ├── diff-implicit-64-CFL_10_0.pdf ├── diffexplicit-converge-0_8.pdf ├── diffexplicit-res.pdf ├── diffimplicit-converge-0_8.pdf ├── diffimplicit-converge-8_0.pdf ├── diffusion.tex ├── gauss_diff_end.pdf ├── gauss_diff_start.pdf └── gauss_diffusion_compare.pdf ├── figures ├── Euler │ ├── multiple_interfaces.py │ ├── ppm-sequence.py │ ├── ppm-trace.py │ ├── ppm.py │ ├── rarefaction_cartoon.py │ ├── riemann-states-q.py │ ├── riemann-states.py │ ├── riemann-waves-jump.py │ ├── riemann-waves.py │ ├── riemann_cartoon.py │ ├── states.py │ └── update.sh ├── advection │ ├── 2dFD.py │ ├── 2dFV.py │ ├── 2dgrid.py │ ├── 2dgrid_hat.py │ ├── 2dgrid_transverse.py │ ├── characteristics.py │ ├── domains.py │ ├── domains_downwind.pdf │ ├── domains_upwind.pdf │ ├── fd_ghost.py │ ├── fv_ghost.py │ ├── generalgrid.py │ ├── rea-limitex.py │ ├── rea.py │ ├── riemann.py │ ├── riemann_bc.py │ ├── riemann_mol.py │ └── update.sh ├── burgers │ ├── characteristics.py │ ├── rh.py │ └── update.sh ├── finite-volume │ ├── ccfd.py │ ├── discretizations.odg │ ├── domain.py │ ├── fd.py │ ├── fv.py │ ├── simplegrid2.py │ ├── simplegrid_gc.py │ └── update.sh ├── gridFigs │ ├── fdrestrict.py │ ├── fvprolong.py │ ├── fvrestrict.py │ └── nested.py ├── incompressible │ ├── MAC-solve.py │ └── MAC.py ├── intro │ ├── fft_simple_examples.py │ ├── integrals.py │ ├── rk4_plot.py │ └── update.sh ├── multigrid │ ├── 2dgrid-mg.py │ ├── fv-fd_bnd.py │ ├── fvrestrict.py │ ├── laplacian.py │ ├── mgtower.py │ ├── red_black.py │ └── smooth-separate.py └── weno │ └── weno.py ├── finite-volume ├── ccfd_grid.pdf ├── discretizations.eps ├── domain.pdf ├── fd_grid.pdf ├── finite-volume.tex ├── fv_grid.pdf ├── main.tex ├── old-scripts │ ├── domain-1d.py │ └── simplegrid.py └── simplegrid_gc.pdf ├── gravity └── gravity.tex ├── higher-order ├── higher-order-burgers.tex ├── higher-order-euler.tex ├── weno-coefficients.ipynb ├── weno-converge-burgers.pdf ├── weno-converge-gaussian-rk4.pdf ├── weno-converge-gaussian.pdf ├── weno-convergence.pdf ├── weno-euler-r3.pdf ├── weno-euler-r5.pdf ├── weno-euler-rarefaction-r3.pdf ├── weno-vs-plm-burger.pdf └── weno-weights.pdf ├── hydro-test-problems └── hydro-test-problems.tex ├── hydro1d └── hydro1d.tex ├── hydro_examples └── hydro_examples.tex ├── images ├── advection.png ├── compressible.png ├── cover.png ├── crop_cover.png ├── diffusion.png ├── incompressible.png ├── lm_atm.png └── mg.png ├── incompressible ├── GNUmakefile ├── MAC.eps ├── MAC_solve.eps ├── incompressible.tex ├── main.tex └── project-u.pdf ├── instabilities └── instabilities.tex ├── intro ├── deriv_error.pdf ├── derivs.pdf ├── fft-sine-phase.pdf ├── fluid_scale.pdf ├── intro.tex ├── newton_00.pdf ├── newton_01.pdf ├── newton_02.pdf ├── newton_03.pdf ├── rectangle.pdf ├── rk4_final.pdf ├── rk4_k1.pdf ├── rk4_k2.pdf ├── rk4_k3.pdf ├── rk4_k4.pdf ├── simpsons.pdf └── trapezoid.pdf ├── low_mach ├── low_mach.tex ├── mg_vc_periodic_converge.eps └── mg_vc_periodic_test.eps ├── multigrid ├── 2dgrid-prolong.eps ├── GNUmakefile ├── fft-poisson-converge.pdf ├── fv-fd_grid_bc.pdf ├── fvrestrict.pdf ├── laplacian.pdf ├── main.tex ├── mg-converge.eps ├── mg_error_vs_cycle.eps ├── mgtower.pdf ├── multigrid.tex ├── poisson_fft.pdf ├── rb.eps ├── smooth-badBCs.pdf ├── smooth-error-norms.pdf ├── smooth-error.pdf └── smooth-multimode.pdf ├── multiphysics ├── burgersvisc.pdf ├── burgersvisc_converge.pdf ├── flame_seq.pdf └── multiphysics.tex ├── mysymbols.tex ├── pde-classes └── pde-classes.tex ├── preface └── preface.tex ├── public-codes └── NOTES ├── pyro └── pyro.tex ├── radiation ├── mg_general_inhomogeneous_converge.eps ├── mg_general_inhomogeneous_test.eps └── radiation.tex ├── reactive_flow ├── notes.txt └── reactive_flow.tex ├── refs.bib ├── simulations └── simulations.tex ├── software-engineering ├── software-engineering.tex └── topics.txt └── symbols └── symbols.tex /.github/workflows/build-book.yml: -------------------------------------------------------------------------------- 1 | name: build book 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | build-book: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Install dependencies 20 | run: | 21 | sudo apt-get update -y -qq 22 | sudo apt-get -qq -y install texlive texlive-latex-extra texlive-fonts-extra texlive-font-utils build-essential 23 | 24 | - name: Build 25 | run: | 26 | make 27 | mkdir out 28 | mv CompHydroTutorial.pdf out 29 | 30 | - name: Archive 31 | uses: actions/upload-artifact@v3 32 | with: 33 | name: book-pdf 34 | path: out/CompHydroTutorial.pdf 35 | 36 | - name: Deploy 37 | uses: peaceiris/actions-gh-pages@v3 38 | with: 39 | github_token: ${{ secrets.GITHUB_TOKEN }} 40 | publish_dir: ./out 41 | keep_files: true 42 | 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | \#* 4 | .\#* 5 | 6 | 7 | *.log 8 | *.aux 9 | *.dvi 10 | *.bbl 11 | *.blg 12 | *-converted-to.pdf 13 | *.lof 14 | *.exc 15 | *.toc 16 | *.png 17 | *.bcf 18 | *.brf 19 | CompHydroTutorial.out 20 | CompHydroTutorial.pdf 21 | 22 | figures/*/*.eps 23 | figures/*/*.pdf 24 | -------------------------------------------------------------------------------- /ADDITIONS: -------------------------------------------------------------------------------- 1 | * convergence testing via Richardson extrapolation 2 | 3 | -- always test the convergence of the initial conditions 4 | 5 | * PPM vis 6 | 7 | * well-balancing 8 | -------------------------------------------------------------------------------- /Euler/README: -------------------------------------------------------------------------------- 1 | sod.eps: made by hydro1d in the exact/ subdirector 2 | -------------------------------------------------------------------------------- /Euler/advect_hydro1d.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/advect_hydro1d.pdf -------------------------------------------------------------------------------- /Euler/axisymmetry.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/axisymmetry.odg -------------------------------------------------------------------------------- /Euler/axisymmetry.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/axisymmetry.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_god_double_rare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_god_double_rare.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_god_sod.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_god_sod.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_plm_double_rare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_plm_double_rare.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_plm_sod.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_plm_sod.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_ppm_double_rare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_ppm_double_rare.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_ppm_sod.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_ppm_sod.pdf -------------------------------------------------------------------------------- /Euler/hydro1d_sedov_1dsph.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/hydro1d_sedov_1dsph.pdf -------------------------------------------------------------------------------- /Euler/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | % margins 4 | \usepackage[margin=0.75in]{geometry} 5 | 6 | % 7 | \usepackage{amsmath} 8 | 9 | % figures 10 | \usepackage{graphicx} 11 | 12 | % font 13 | \usepackage{mathpazo} 14 | 15 | \usepackage{helvet} 16 | 17 | % coloring 18 | \usepackage{color} 19 | \definecolor{mygray}{gray}{0.5} 20 | 21 | % footer 22 | \usepackage{fancyhdr} 23 | \pagestyle{fancy} 24 | \fancyfoot[LO,LE]{\footnotesize \sffamily \color{mygray} M.\ Zingale---Notes on the Euler equations} 25 | \fancyfoot[RO,RE]{\footnotesize \sffamily \color{mygray} (\today)} 26 | \fancyfoot[CO,CE]{\thepage} 27 | \fancyhead{} 28 | \renewcommand{\headrulewidth}{0.0pt} 29 | \renewcommand{\footrulewidth}{0.0pt} 30 | 31 | % captions 32 | \usepackage{caption} 33 | \renewcommand{\captionfont}{\footnotesize} 34 | \renewcommand{\captionlabelfont}{\footnotesize} 35 | \setlength{\captionmargin}{5em} 36 | 37 | \newcommand{\evm}{{(-)}} 38 | \newcommand{\evz}{{(\circ)}} 39 | \newcommand{\evp}{{(+)}} 40 | \newcommand{\enu}{{(\nu)}} 41 | 42 | % for dotted lines in the matrics/arrays 43 | \usepackage{arydshln} 44 | 45 | \usepackage{sectsty} 46 | \allsectionsfont{\sffamily} 47 | 48 | \begin{document} 49 | 50 | \begin{center} 51 | {\LARGE \textsf{\textbf{ 52 | Notes on the Euler Equations}} 53 | } 54 | \end{center} 55 | 56 | \input Euler 57 | 58 | \bibliographystyle{plain} 59 | \bibliography{../refs} 60 | 61 | \end{document} 62 | -------------------------------------------------------------------------------- /Euler/multiple_interfaces.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/multiple_interfaces.pdf -------------------------------------------------------------------------------- /Euler/piecewise-constant.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/piecewise-constant.pdf -------------------------------------------------------------------------------- /Euler/piecewise-linear.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/piecewise-linear.pdf -------------------------------------------------------------------------------- /Euler/piecewise-parabolic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/piecewise-parabolic.pdf -------------------------------------------------------------------------------- /Euler/ppm-trace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/ppm-trace.pdf -------------------------------------------------------------------------------- /Euler/quad.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/quad.pdf -------------------------------------------------------------------------------- /Euler/rarefaction_center.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/rarefaction_center.pdf -------------------------------------------------------------------------------- /Euler/rarefaction_left.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/rarefaction_left.pdf -------------------------------------------------------------------------------- /Euler/rarefaction_right.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/rarefaction_right.pdf -------------------------------------------------------------------------------- /Euler/riemann-2shock-sod-phase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann-2shock-sod-phase.pdf -------------------------------------------------------------------------------- /Euler/riemann-phase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann-phase.pdf -------------------------------------------------------------------------------- /Euler/riemann-sod.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann-sod.pdf -------------------------------------------------------------------------------- /Euler/riemann-waves.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann-waves.pdf -------------------------------------------------------------------------------- /Euler/riemann_comp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann_comp.pdf -------------------------------------------------------------------------------- /Euler/riemann_waves_ifc_L.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann_waves_ifc_L.pdf -------------------------------------------------------------------------------- /Euler/riemann_waves_ifc_Lstar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann_waves_ifc_Lstar.pdf -------------------------------------------------------------------------------- /Euler/riemann_waves_ifc_R.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann_waves_ifc_R.pdf -------------------------------------------------------------------------------- /Euler/riemann_waves_ifc_Rstar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/riemann_waves_ifc_Rstar.pdf -------------------------------------------------------------------------------- /Euler/sedov_compare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/sedov_compare.pdf -------------------------------------------------------------------------------- /Euler/sedov_pyro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/sedov_pyro.pdf -------------------------------------------------------------------------------- /Euler/slowshock.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/slowshock.pdf -------------------------------------------------------------------------------- /Euler/states.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/Euler/states.pdf -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # by default, typing make will build the `production' version of the 2 | # Computational Hydrodynamics notes. 3 | # 4 | # if you instead for 'make DEBUG=t', then it will make the draft version. 5 | # this will enable margin comments and build in any chapters that are 6 | # not yet complete. 7 | 8 | ALL: CompHydroTutorial.pdf 9 | 10 | DEBUG := 11 | 12 | DIRS := preface \ 13 | intro \ 14 | pde-classes \ 15 | finite-volume \ 16 | advection \ 17 | burgers \ 18 | Euler \ 19 | hydro-test-problems \ 20 | multigrid \ 21 | diffusion \ 22 | multiphysics \ 23 | incompressible \ 24 | low_mach \ 25 | pyro \ 26 | hydro_examples \ 27 | software-engineering \ 28 | symbols \ 29 | radiation 30 | 31 | # dependencies 32 | TEXS := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.tex)) 33 | EPSS := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.eps)) 34 | 35 | # for PDFs, pdflatex will automagically convert file.eps to 36 | # file-converted-to.pdf at build time. These lines create 37 | # a variable, PDFS, that just contains the original PDF files 38 | # as dependencies 39 | tPDFS := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.pdf)) 40 | cPDFS := $(foreach dir, $(DIRS), $(wildcard $(dir)/*converted-to.pdf)) 41 | PDFS := $(filter-out $(cPDFS), $(tPDFS)) 42 | 43 | 44 | conditional.tex: 45 | ifdef DEBUG 46 | echo "\def\debugmode{}" > conditional.tex 47 | else 48 | echo "" > conditional.tex 49 | endif 50 | 51 | CompHydroTutorial.pdf: CompHydroTutorial.tex conditional.tex $(TEXS) $(EPSS) $(PDFS) refs.bib 52 | git rev-parse --short=12 HEAD > git_info.tex 53 | pdflatex CompHydroTutorial < /dev/null 54 | bibtex CompHydroTutorial.aux 55 | pdflatex CompHydroTutorial < /dev/null 56 | pdflatex CompHydroTutorial < /dev/null 57 | #pdflatex CompHydroTutorial < /dev/null 58 | $(RM) git_info.tex 59 | $(RM) conditional.tex 60 | 61 | 62 | clean: 63 | $(RM) *.aux *.log *.dvi *.bbl *.blg *.lof *.toc *.exc *.out *.brf 64 | $(RM) *~ conditional.tex 65 | 66 | realclean: clean 67 | $(RM) CompHydroTutorial.pdf 68 | find . -name "*-converted-to.pdf" -exec $(RM) {} \; 69 | 70 | .PHONY: clean 71 | 72 | 73 | print-%: ; @echo $* is $($*) 74 | -------------------------------------------------------------------------------- /NOTES: -------------------------------------------------------------------------------- 1 | -- add to Ch 1 a review of numerical methods: 2 | 3 | . truncation vs. roundoff error 4 | . numerical differentiation and integration 5 | . ODEs 6 | . linear algebra 7 | 8 | -- add section to each chapter: "Numerical Explorations" 9 | 10 | . create a separate, non-pyro git repo that has basic examples for all 11 | of the methods in 1-d also add discussions from pyro. 12 | . start with simple grid class and BC discussion 13 | . 1-d advection example 14 | 15 | 16 | -- preface: 17 | 18 | "Each of the main chapters has 2 sections at the end: "Numerical 19 | Explorations" and "Going further". The first guides the reader 20 | through some exercises using the codes in the git repo associated 21 | with these notes. The latter briefly discusses some of the popular 22 | extensions done to the core algorithms discussed here, with pointers 23 | to the relevant papers in the literature. 24 | 25 | -- burgers: 26 | 27 | http://onlinelibrary.wiley.com/doi/10.1002/fld.1650030302/abstract 28 | 29 | Generating exact solutions of the two-dimensional Burgers' equations 30 | Clive A. J. Fletcher 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computational Hydrodynamics for Astrophysics 2 | 3 | *part of the Open Astrophysics Bookshelf* 4 | 5 | Notes on numerical methods for computational astrophysical hydrodynamics. 6 | 7 | These notes describe the way I think about the numerical methods commonly 8 | used with grid-based codes in astrophysical hydrodynamics. The notes 9 | are written in LaTeX, and should build by typing 'make' in the main 10 | directory. 11 | 12 | Working implementations for all of the solvers are contained either in 13 | the main pyro code or in the set of hydro examples, both referenced 14 | below. 15 | 16 | ## Chapters 17 | 18 | The following chapters are mostly written: 19 | 20 | - Simulation Overview 21 | - Finite-Volume Grids 22 | - Advection 23 | - Burgers' Equation 24 | - Euler Equations: Theory 25 | - Euler Equations: Numerical Methods 26 | - Elliptic Equations and Multigrid 27 | - Diffusion 28 | - Model Multiphysics Problems 29 | - Reactive Flow 30 | - Planning a Simulation 31 | - Incompressible Flow and Projection Methods 32 | - Low Mach Number Methods 33 | 34 | The following are things I'd like to add in the next 1-2 years: 35 | 36 | - Fluid Instabilities 37 | - Rotation and Self-gravity 38 | - Radiation Hydrodynamics 39 | - MHD 40 | - AMR 41 | - Mapped Grids 42 | 43 | The following are things hopefully will eventually get written: 44 | 45 | - Relativisitc Flows 46 | - Higher-Order Methods 47 | - Implicit Hydrodynamics 48 | 49 | 50 | ## Getting PDFs and Source 51 | 52 | A PDF version of these notes is available at: 53 | 54 | http://open-astrophysics-bookshelf.github.io/numerical_exercises/ 55 | 56 | (this PDF is automatically generated by a Github action each time changes are pushed to `main`.) 57 | 58 | There are two sets of companion codes that go along with these notes: 59 | 60 | - *hydro_examples*: https://github.com/zingale/hydro_examples 61 | 62 | simple, standalone, 1-d solvers that illustrate the basic ideas. 63 | 64 | - *pyro*: https://github.com/python-hydro/pyro2 65 | 66 | pyro is a 2-d full simulation code designed with simplicity in 67 | mind that implements the core solvers described in these notes 68 | along with various test problems. 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Add implementation details throughout, explaining how to translate stuff into code 2 | -- maybe in the margins with the Tufte class? 3 | 4 | https://en.wikipedia.org/wiki/Shallow_water_equations#/media/File:Characteristics_saint-venant.svg 5 | 6 | new chapters: 7 | 8 | -- self-gravity 9 | 10 | -- radiation hydro 11 | 12 | -- AMR 13 | 14 | -- mapped grids 15 | 16 | * general quadralateral grids 17 | 18 | * moving grids 19 | 20 | - 1-d moving grid showing 21 | 22 | -- MHD 23 | 24 | -- relativisitc 25 | 26 | -- WENO 27 | 28 | -- higher-order 29 | 30 | o method of lines integration with RK3/4 and high-order reconstruction 31 | 32 | -- implicit hydro 33 | 34 | -- shallow water 35 | 36 | -- cosmological flows 37 | 38 | -- understanding simulations 39 | 40 | * convergence tests 41 | 42 | * sanity checks 43 | 44 | * parameter studies vs. hero calculations 45 | 46 | -- volume of fluid 47 | 48 | 49 | 50 | 51 | sample of public codes 52 | 53 | -- Athena 54 | -- Castro 55 | -- Enzo 56 | -- Flash 57 | -- Maestro 58 | -- Pluto 59 | -- Zeus 60 | 61 | 62 | ======================= 63 | 64 | Chapter 2: 65 | 66 | -- in "what is a simulation", add a discussion of DNS, LES, and ILES 67 | 68 | -- add BC and difference on a grid examples perhaps through a ipython 69 | notebook. 70 | 71 | 72 | 73 | ======================= 74 | 75 | Chapter 4: 76 | 77 | -- add a notebook showing FTCS and upwind on a simple FV grid 78 | 79 | pyro exercises: 80 | 81 | -- try out different limiters 82 | 83 | 84 | ======================= 85 | 86 | Chapter 5: 87 | 88 | 89 | -- exercise: notebook showing burgers' solution 90 | 91 | 92 | ======================= 93 | 94 | Chapter 6/7: 95 | 96 | -- add a figure for section 5.2.1, showing piecewise constant 97 | reconstruction 98 | 99 | -- add a discussion (interlude) motivating how limiters are derived 100 | 101 | -- bulletted list on different Riemann solvers 102 | 103 | -- derive the jump conditions and the entropy conditions for the 104 | Riemann problem and show the function we zero. 105 | 106 | -- implementation detail: for Riemann solvers, usually the godunov 107 | velocity is set to 0 at symmetry boundaries 108 | 109 | -- it is important to odd-reflect the gravitational acceleration 110 | at reflecting boundaries 111 | 112 | examples: 113 | 114 | -- 1-d Riemann solver 115 | -- 1-d Godunov 116 | 117 | pyro... 118 | 119 | 120 | ======================= 121 | 122 | Multigrid chapter: 123 | 124 | examples: 125 | 126 | -- 1-d relaxation 127 | -- 1-d MG 128 | 129 | 130 | ======================= 131 | 132 | Diffusion chapter: 133 | 134 | 135 | examples: 136 | 137 | -- 1-d diffusion solver 138 | 139 | pyro 140 | 141 | 142 | ---- 143 | 144 | reference for the choice of epsilon in numerical derivatives as 145 | \sqrt{machine epsilon} -- this gives some suggestions: 146 | http://mathoverflow.net/questions/28463/optimum-small-number-for-numerical-differentiation 147 | 148 | 149 | ---- 150 | 151 | tcolorbox for exercises: 152 | 153 | http://tex.stackexchange.com/questions/172475/how-can-i-define-a-custom-tcolorbox-environment-with-color-as-a-parameter 154 | 155 | 156 | http://www.scriptscoop2.com/t/e6de0140d668/counters-for-chapter-and-section-environments-when-using-tcolorbox-for.html 157 | 158 | 159 | http://tex.stackexchange.com/questions/254401/use-the-exercise-environment-from-legrand-book-template 160 | 161 | http://www.latextemplates.com/template/the-legrand-orange-book 162 | 163 | -------------------------------------------------------------------------------- /advection/2dgrid-hat.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/2dgrid-hat.pdf -------------------------------------------------------------------------------- /advection/2dgrid-transverse.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/2dgrid-transverse.pdf -------------------------------------------------------------------------------- /advection/2dgrid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/2dgrid.pdf -------------------------------------------------------------------------------- /advection/advection-characteristics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/advection-characteristics.pdf -------------------------------------------------------------------------------- /advection/domains_FTCS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/domains_FTCS.pdf -------------------------------------------------------------------------------- /advection/domains_downwind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/domains_downwind.pdf -------------------------------------------------------------------------------- /advection/domains_upwind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/domains_upwind.pdf -------------------------------------------------------------------------------- /advection/fd_ghost.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fd_ghost.pdf -------------------------------------------------------------------------------- /advection/fdadvect-FTCS-C0_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fdadvect-FTCS-C0_1.pdf -------------------------------------------------------------------------------- /advection/fdadvect-FTCS-C0_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fdadvect-FTCS-C0_5.pdf -------------------------------------------------------------------------------- /advection/fdadvect-implicit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fdadvect-implicit.pdf -------------------------------------------------------------------------------- /advection/fdadvect-upwind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fdadvect-upwind.pdf -------------------------------------------------------------------------------- /advection/fv-advect.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fv-advect.pdf -------------------------------------------------------------------------------- /advection/fv-gaussian-limiters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fv-gaussian-limiters.pdf -------------------------------------------------------------------------------- /advection/fv-tophat-limiters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fv-tophat-limiters.pdf -------------------------------------------------------------------------------- /advection/fv_ghost.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/fv_ghost.pdf -------------------------------------------------------------------------------- /advection/generalgrid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/generalgrid.pdf -------------------------------------------------------------------------------- /advection/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | % margins 4 | \usepackage[margin=0.75in]{geometry} 5 | 6 | % figures 7 | \usepackage{graphicx} 8 | 9 | % font 10 | \usepackage{mathpazo} 11 | 12 | \usepackage{helvet} 13 | 14 | % coloring 15 | \usepackage{color} 16 | \definecolor{mygray}{gray}{0.5} 17 | 18 | % footer 19 | \usepackage{fancyhdr} 20 | \pagestyle{fancy} 21 | \fancyfoot[LO,LE]{\footnotesize \sffamily \color{mygray} M.\ Zingale---Notes on Advection} 22 | \fancyfoot[RO,RE]{\footnotesize \sffamily \color{mygray} (\today)} 23 | \fancyfoot[CO,CE]{\thepage} 24 | \fancyhead{} 25 | \renewcommand{\headrulewidth}{0.0pt} 26 | \renewcommand{\footrulewidth}{0.0pt} 27 | 28 | % captions 29 | \usepackage{caption} 30 | \renewcommand{\captionfont}{\footnotesize} 31 | \renewcommand{\captionlabelfont}{\footnotesize} 32 | \setlength{\captionmargin}{5em} 33 | 34 | 35 | \usepackage{sectsty} 36 | \allsectionsfont{\sffamily} 37 | 38 | \usepackage{amsmath} 39 | 40 | \newcounter{exercise} 41 | \usepackage{changepage} 42 | 43 | \newenvironment{exercise}% environment name 44 | {% begin code 45 | \begin{adjustwidth}{1.0cm}{0.5cm} 46 | \par\vspace{\baselineskip}\noindent 47 | \refstepcounter{exercise}% 48 | \textbf{Exercise \theexercise\ }\begin{itshape}% 49 | %\par\vspace{\baselineskip}\noindent\ignorespaces 50 | }% 51 | {% end code 52 | \end{itshape}\end{adjustwidth}\vspace{\baselineskip}\ignorespacesafterend 53 | } 54 | 55 | \begin{document} 56 | 57 | \begin{center} 58 | {\LARGE \textsf{\textbf{ 59 | Notes on Advection}} 60 | } 61 | \end{center} 62 | 63 | 64 | \input advection 65 | 66 | \bibliographystyle{plain} 67 | \bibliography{../refs} 68 | 69 | \end{document} 70 | -------------------------------------------------------------------------------- /advection/old-scripts/fv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import pylab 4 | import grid_plot_util as gpu 5 | 6 | 7 | nzones = 5 8 | 9 | # data that lives on the grid 10 | a = numpy.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5]) 11 | 12 | gr = gpu.grid(nzones) 13 | 14 | 15 | gpu.drawGrid(gr) 16 | 17 | gpu.labelCenter(gr, nzones/2, r"$x_i$") 18 | gpu.labelAvg(gr, nzones/2, a[nzones/2], r"$\langle f\rangle_i$") 19 | 20 | gpu.labelCenter(gr, nzones/2-1, r"$x_{i-1}$") 21 | gpu.labelCenter(gr, nzones/2+1, r"$x_{i+1}$") 22 | gpu.labelCenter(gr, nzones/2-2, r"$x_{i-2}$") 23 | gpu.labelCenter(gr, nzones/2+2, r"$x_{i+2}$") 24 | 25 | gpu.labelEdge(gr, nzones/2, r"$x_{i-1/2}$") 26 | gpu.labelEdge(gr, nzones/2+1, r"$x_{i+1/2}$") 27 | 28 | n = 0 29 | while (n < nzones): 30 | gpu.drawCellAvg(gr, n, a[n]) 31 | n += 1 32 | 33 | 34 | pylab.axis([gr.xmin-0.5*gr.dx,gr.xmax+0.5*gr.dx, -0.25, 1.2]) 35 | pylab.axis("off") 36 | 37 | pylab.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 38 | 39 | f = pylab.gcf() 40 | f.set_size_inches(8.0,2.0) 41 | 42 | 43 | pylab.savefig("fv.png", dpi=200) 44 | pylab.savefig("fv.eps") 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /advection/old-scripts/simplegrid.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import pylab 4 | 5 | def simplegrid(): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 7 12 | ng = 1 13 | 14 | dx = (xmax - xmin)/float(nzones) 15 | 16 | xl = (numpy.arange(2*ng+nzones) - ng)*dx 17 | xr = (numpy.arange(2*ng+nzones)+1 - ng)*dx 18 | 19 | xc = 0.5*(xl + xr) 20 | 21 | 22 | #------------------------------------------------------------------------ 23 | # plot a domain without ghostcells 24 | pylab.plot([xmin,xmax], [0,0], color="k", lw=2) 25 | 26 | # domain left edge 27 | pylab.plot([xl[ng], xl[ng]], [0, 0.5], color="k", lw=4) 28 | 29 | n = ng 30 | while (n < ng+nzones): 31 | 32 | # draw right edge 33 | pylab.plot([xr[n], xr[n]], [0, 0.5], color="k", lw=2) 34 | 35 | # draw center marker 36 | pylab.plot([xc[n], xc[n]], [-0.05, 0], color="k") 37 | n += 1 38 | 39 | # domain right edge 40 | pylab.plot([xl[ng+nzones], xl[ng+nzones]], [0, 0.5], color="k", lw=4) 41 | 42 | 43 | # label a few 44 | pylab.text(xc[ng+nzones/2], -0.1, r"$i$", 45 | horizontalalignment='center', verticalalignment='top') 46 | 47 | pylab.text(xc[ng+nzones/2-1], -0.1, r"$i-1$", 48 | horizontalalignment='center', verticalalignment='top') 49 | 50 | pylab.text(xc[ng+nzones/2+1], -0.1, r"$i+1$", 51 | horizontalalignment='center', verticalalignment='top') 52 | 53 | pylab.xlim(xl[0]-0.5*dx,xr[2*ng+nzones-1]+0.5*dx) 54 | pylab.ylim(-0.25, 0.6) 55 | pylab.axis("off") 56 | 57 | pylab.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 58 | 59 | f = pylab.gcf() 60 | f.set_size_inches(8.0,2.0) 61 | 62 | 63 | pylab.savefig("simplegrid.png") 64 | pylab.savefig("simplegrid.eps") 65 | 66 | 67 | 68 | #------------------------------------------------------------------------ 69 | # now draw one with ghostcells 70 | pylab.plot([xmin-ng*dx,xmax+ng*dx], [0,0], color="k", lw=2) 71 | 72 | 73 | # domain (w/ ghostcells) left edge 74 | pylab.plot([xl[0], xl[0]], [0, 0.5], color="k", lw=2) 75 | 76 | n = 0 77 | while (n < 2*ng+nzones): 78 | 79 | # draw right edge 80 | pylab.plot([xr[n], xr[n]], [0, 0.5], color="k", lw=2) 81 | 82 | # draw center marker 83 | pylab.plot([xc[n], xc[n]], [-0.05, 0], color="k") 84 | n += 1 85 | 86 | 87 | # domain left edge 88 | pylab.plot([xl[ng], xl[ng]], [0, 0.5], color="k", lw=4) 89 | 90 | # domain right edge 91 | pylab.plot([xl[ng+nzones], xl[ng+nzones]], [0, 0.5], color="k", lw=4) 92 | 93 | 94 | # label a few 95 | pylab.text(xc[ng+nzones/2], -0.1, r"$i$", 96 | horizontalalignment='center', verticalalignment='top') 97 | 98 | pylab.text(xc[ng+nzones/2-1], -0.1, r"$i-1$", 99 | horizontalalignment='center', verticalalignment='top') 100 | 101 | pylab.text(xc[ng+nzones/2+1], -0.1, r"$i+1$", 102 | horizontalalignment='center', verticalalignment='top') 103 | 104 | pylab.text(xc[ng-1], -0.1, r"$-1$", 105 | horizontalalignment='center', verticalalignment='top') 106 | 107 | pylab.text(xc[ng], -0.1, r"$0$", 108 | horizontalalignment='center', verticalalignment='top') 109 | 110 | pylab.text(xc[ng+nzones-1], -0.1, r"$N-1$", 111 | horizontalalignment='center', verticalalignment='top') 112 | 113 | pylab.text(xc[ng+nzones], -0.1, r"$N$", 114 | horizontalalignment='center', verticalalignment='top') 115 | 116 | pylab.xlim(xl[0]-0.5*dx,xr[2*ng+nzones-1]+0.5*dx) 117 | pylab.ylim(-0.25, 0.6) 118 | pylab.axis("off") 119 | 120 | pylab.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 121 | 122 | f = pylab.gcf() 123 | f.set_size_inches(8.0,2.0) 124 | 125 | 126 | pylab.savefig("simplegrid_gc.png") 127 | pylab.savefig("simplegrid_gc.eps") 128 | 129 | 130 | 131 | 132 | if __name__== "__main__": 133 | simplegrid() 134 | -------------------------------------------------------------------------------- /advection/old-scripts/simplegrid2.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import pylab 4 | 5 | def simplegrid(): 6 | 7 | xmin = 0.0 8 | xmax = 1.0 9 | 10 | nzones = 7 11 | 12 | dx = (xmax - xmin)/float(nzones) 13 | 14 | xl = numpy.arange(nzones)*dx 15 | xr = (numpy.arange(nzones)+1)*dx 16 | 17 | xc = 0.5*(xl + xr) 18 | 19 | pylab.plot([xmin-0.5*dx,xmax+0.5*dx], [0,0], color="k", lw=2) 20 | 21 | pylab.plot([xl[0], xl[0]], [0, 0.5], color="k", lw=2) 22 | n = 0 23 | while (n < nzones): 24 | 25 | # draw right edge 26 | pylab.plot([xr[n], xr[n]], [0, 0.5], color="k", lw=2) 27 | 28 | # draw center marker 29 | pylab.plot([xc[n], xc[n]], [-0.05, 0], color="k") 30 | 31 | # draw edge marker 32 | if (n == 0): 33 | pylab.plot([xl[0], xl[0]], [-0.05, 0], color="k") 34 | 35 | pylab.plot([xr[n], xr[n]], [-0.05, 0], color="k") 36 | 37 | n += 1 38 | 39 | 40 | # label a few cell-centers 41 | pylab.text(xc[nzones/2], -0.1, r"$i$", 42 | horizontalalignment='center', verticalalignment='top', 43 | fontsize="small") 44 | 45 | pylab.text(xc[nzones/2-1], -0.1, r"$i-1$", 46 | horizontalalignment='center', verticalalignment='top', 47 | fontsize="small") 48 | 49 | pylab.text(xc[nzones/2+1], -0.1, r"$i+1$", 50 | horizontalalignment='center', verticalalignment='top', 51 | fontsize="small") 52 | 53 | 54 | # label a few edges 55 | pylab.text(xl[nzones/2], -0.075, r"$i-1/2$", 56 | horizontalalignment='center', verticalalignment='top', 57 | fontsize="small") 58 | 59 | pylab.text(xr[nzones/2], -0.075, r"$i+1/2$", 60 | horizontalalignment='center', verticalalignment='top', 61 | fontsize="small") 62 | 63 | 64 | 65 | pylab.axis([xmin-0.5*dx,xmax+0.5*dx, -0.25, 0.6]) 66 | pylab.axis("off") 67 | 68 | pylab.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 69 | 70 | f = pylab.gcf() 71 | f.set_size_inches(8.0,2.0) 72 | 73 | 74 | pylab.savefig("simplegrid2.png") 75 | pylab.savefig("simplegrid2.eps") 76 | 77 | 78 | 79 | if __name__== "__main__": 80 | simplegrid() 81 | -------------------------------------------------------------------------------- /advection/plm-converge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/plm-converge.pdf -------------------------------------------------------------------------------- /advection/rea-evolve.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-evolve.pdf -------------------------------------------------------------------------------- /advection/rea-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-final.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_001.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_001.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_002.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_003.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_003.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_004.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_004.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_005.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_005.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_006.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_006.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_007.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_007.pdf -------------------------------------------------------------------------------- /advection/rea-nolimit-start_008.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-nolimit-start_008.pdf -------------------------------------------------------------------------------- /advection/rea-reconstruction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-reconstruction.pdf -------------------------------------------------------------------------------- /advection/rea-start.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start.pdf -------------------------------------------------------------------------------- /advection/rea-start_001.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_001.pdf -------------------------------------------------------------------------------- /advection/rea-start_002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_002.pdf -------------------------------------------------------------------------------- /advection/rea-start_003.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_003.pdf -------------------------------------------------------------------------------- /advection/rea-start_004.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_004.pdf -------------------------------------------------------------------------------- /advection/rea-start_005.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_005.pdf -------------------------------------------------------------------------------- /advection/rea-start_006.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_006.pdf -------------------------------------------------------------------------------- /advection/rea-start_007.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_007.pdf -------------------------------------------------------------------------------- /advection/rea-start_008.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-start_008.pdf -------------------------------------------------------------------------------- /advection/rea-trace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/rea-trace.pdf -------------------------------------------------------------------------------- /advection/riemann-adv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/riemann-adv.pdf -------------------------------------------------------------------------------- /advection/riemann-bc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/riemann-bc.pdf -------------------------------------------------------------------------------- /advection/riemann-mol.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/riemann-mol.pdf -------------------------------------------------------------------------------- /advection/smooth_final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/smooth_final.pdf -------------------------------------------------------------------------------- /advection/smooth_init.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/smooth_init.pdf -------------------------------------------------------------------------------- /advection/tophat_final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/tophat_final.pdf -------------------------------------------------------------------------------- /advection/tophat_init.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/tophat_init.pdf -------------------------------------------------------------------------------- /advection/tophat_rk4_cfl04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/tophat_rk4_cfl04.pdf -------------------------------------------------------------------------------- /advection/tophat_rk4_cfl08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/advection/tophat_rk4_cfl08.pdf -------------------------------------------------------------------------------- /burgers/burgers-characteristics-rare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/burgers/burgers-characteristics-rare.pdf -------------------------------------------------------------------------------- /burgers/burgers-characteristics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/burgers/burgers-characteristics.pdf -------------------------------------------------------------------------------- /burgers/fv-burger-rarefaction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/burgers/fv-burger-rarefaction.pdf -------------------------------------------------------------------------------- /burgers/fv-burger-sine.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/burgers/fv-burger-sine.pdf -------------------------------------------------------------------------------- /burgers/rh.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/burgers/rh.pdf -------------------------------------------------------------------------------- /codes/intro/sin-converge.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | X = [0.5, 0.25, 0.125, 0.0625] 4 | 5 | for x in X: 6 | print x, math.sin(x) - (x - x**3/6.0) 7 | 8 | -------------------------------------------------------------------------------- /diffusion/GNUmakefile: -------------------------------------------------------------------------------- 1 | EPStoPDF = epstopdf 2 | 3 | ALL: diffusion.pdf 4 | 5 | 6 | diffusion.pdf: main.tex diffusion.tex 7 | pdflatex -jobname=diffusion main.tex < /dev/null 8 | bibtex diffusion.aux 9 | pdflatex -jobname=diffusion main.tex < /dev/null 10 | pdflatex -jobname=diffusion main.tex < /dev/null 11 | 12 | 13 | clean: 14 | $(RM) *.aux *.log *.dvi *.bbl *.blg 15 | $(RM) *~ 16 | 17 | .PHONY: clean 18 | -------------------------------------------------------------------------------- /diffusion/diff-explicit-64-bad.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diff-explicit-64-bad.pdf -------------------------------------------------------------------------------- /diffusion/diff-explicit-64.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diff-explicit-64.pdf -------------------------------------------------------------------------------- /diffusion/diff-implicit-128-CFL_0_8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diff-implicit-128-CFL_0_8.pdf -------------------------------------------------------------------------------- /diffusion/diff-implicit-128-CFL_8_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diff-implicit-128-CFL_8_0.pdf -------------------------------------------------------------------------------- /diffusion/diff-implicit-64-CFL_10_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diff-implicit-64-CFL_10_0.pdf -------------------------------------------------------------------------------- /diffusion/diffexplicit-converge-0_8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diffexplicit-converge-0_8.pdf -------------------------------------------------------------------------------- /diffusion/diffexplicit-res.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diffexplicit-res.pdf -------------------------------------------------------------------------------- /diffusion/diffimplicit-converge-0_8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diffimplicit-converge-0_8.pdf -------------------------------------------------------------------------------- /diffusion/diffimplicit-converge-8_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/diffimplicit-converge-8_0.pdf -------------------------------------------------------------------------------- /diffusion/gauss_diff_end.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/gauss_diff_end.pdf -------------------------------------------------------------------------------- /diffusion/gauss_diff_start.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/gauss_diff_start.pdf -------------------------------------------------------------------------------- /diffusion/gauss_diffusion_compare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/diffusion/gauss_diffusion_compare.pdf -------------------------------------------------------------------------------- /figures/Euler/multiple_interfaces.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import matplotlib as mpl 4 | import random 5 | 6 | import grid_plot as gp 7 | 8 | mpl.rcParams['mathtext.fontset'] = 'cm' 9 | mpl.rcParams['mathtext.rm'] = 'serif' 10 | 11 | # font sizes 12 | mpl.rcParams['font.size'] = 12 13 | mpl.rcParams['legend.fontsize'] = 'large' 14 | mpl.rcParams['figure.titlesize'] = 'medium' 15 | 16 | 17 | class RiemannWaves(object): 18 | """draw a diagram with a the three waves """ 19 | 20 | def __init__(self, x0, dx): 21 | """ create a random collection of Riemann waves """ 22 | 23 | states = ["shock", "rarefaction"] 24 | 25 | self.x0 = x0 26 | self.dx = dx 27 | 28 | # first pick if the angle of the contact, from a normalize distribution centered on 0 29 | _a = np.degrees(0.4*np.random.randn()) 30 | while _a > 45: 31 | _a = np.degrees(0.4*np.random.randn()) 32 | self.contact_pos = _a 33 | print(_a) 34 | 35 | # now the left state -- first set how far it is from the contact 36 | _a = np.degrees(0.4*np.random.randn()) 37 | while _a > 45: 38 | _a = np.degrees(0.4*np.random.randn()) 39 | print(_a) 40 | self.left_pos = self.contact_pos - np.abs(_a) 41 | self.left_type = random.choice(states) 42 | 43 | # and the right 44 | _a = np.degrees(0.4*np.random.randn()) 45 | while _a > 45: 46 | _a = np.degrees(0.4*np.random.randn()) 47 | print(_a) 48 | self.right_pos = self.contact_pos + np.abs(_a) 49 | self.right_type = random.choice(states) 50 | 51 | def draw(self, output="plot.png", label=None): 52 | """ draw the wave structure """ 53 | 54 | print(self.left_pos, self.contact_pos, self.right_pos) 55 | 56 | # each wave has a point on the origin. The maximum height we 57 | # want to draw to is self.dx -- we'll do the center and right 58 | x1 = self.x0 + self.dx * np.tan(np.radians(self.left_pos)) 59 | xc = self.x0 + self.dx * np.tan(np.radians(self.contact_pos)) 60 | x3 = self.x0 + self.dx * np.tan(np.radians(self.right_pos)) 61 | 62 | # draw the waves 63 | if self.left_type == "shock": 64 | plt.plot([self.x0, x1], [0, self.dx], color="C0", lw=3) 65 | else: 66 | for n in range(5): 67 | x1 = self.x0 + self.dx * np.tan(np.radians(self.left_pos - 2*n)) 68 | plt.plot([self.x0, x1], [0, self.dx], color="C0", lw=1) 69 | 70 | plt.plot([self.x0, xc], [0, self.dx], color="C1") 71 | 72 | if self.right_type == "shock": 73 | plt.plot([self.x0, x3], [0, self.dx], color="C0", lw=3) 74 | else: 75 | for n in range(5): 76 | x3 = self.x0 + self.dx * np.tan(np.radians(self.right_pos + 2*n)) 77 | plt.plot([self.x0, x3], [0, self.dx], color="C0", lw=1) 78 | 79 | 80 | if __name__ == "__main__": 81 | 82 | 83 | xmin = 0.0 84 | xmax = 8.0 85 | 86 | nzones = 4 87 | ng = 0 88 | 89 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 90 | 91 | gr.draw_grid() 92 | 93 | gr.label_edge(0, r"$i-\mythreehalf$", fontsize="medium") 94 | gr.label_edge(1, r"$i-\myhalf$", fontsize="medium") 95 | gr.label_edge(2, r"$i+\myhalf$", fontsize="medium") 96 | gr.label_edge(3, r"$i+\mythreehalf$", fontsize="medium") 97 | gr.label_edge(3, r"$i+\myfivehalf$", fontsize="medium", right_edge=True) 98 | 99 | gr.label_center(0, r"$i-1$", fontsize="medium") 100 | gr.label_center(1, r"$i$", fontsize="medium") 101 | gr.label_center(2, r"$i+1$", fontsize="medium") 102 | gr.label_center(3, r"$i+2$", fontsize="medium") 103 | 104 | riemann = [] 105 | for n in range(nzones): 106 | riemann.append(RiemannWaves(gr.xl[n], 0.5*gr.dx)) 107 | riemann.append(RiemannWaves(gr.xr[nzones-1], 0.5*gr.dx)) 108 | 109 | # draw 110 | for r in riemann: 111 | r.draw() 112 | 113 | gr.clean_axes() 114 | 115 | f = plt.gcf() 116 | f.set_size_inches(8.0, 2.5) 117 | 118 | plt.tight_layout() 119 | 120 | plt.savefig("multiple_interfaces.pdf", dpi=150) 121 | -------------------------------------------------------------------------------- /figures/Euler/ppm-sequence.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | import riemann 6 | 7 | class RiemannProblem(object): 8 | def __init__(self, q_l, q_r, gamma=5./3., N=3): 9 | 10 | self.q_l = q_l 11 | self.q_r = q_r 12 | self.nx = 2*N 13 | 14 | self.gr = gp. FVGrid(self.nx) 15 | 16 | # allocate space -- we just care about N zones to the left and 17 | # right of the interface 18 | self.vars = {} 19 | 20 | rho = self.gr.scratch_array() 21 | rho[0:N] = q_l.rho 22 | rho[N:2**N] = q_r.rho 23 | 24 | u = self.gr.scratch_array() 25 | u[0:N] = q_l.u 26 | u[N:2*N] = q_r.u 27 | 28 | p = self.gr.scratch_array() 29 | p[0:N] = q_l.p 30 | p[N:2*N] = q_r.p 31 | 32 | rscale = max(q_l.rho, q_r.rho) 33 | uscale = max(q_l.u, q_r.u) 34 | pscale = max(q_l.p, q_r.p) 35 | 36 | # do the ppm reconstruction on all of these variables 37 | self.vars["rho"] = gp.PiecewiseParabolic(self.gr, rho, scale=rscale) 38 | self.vars["u"] = gp.PiecewiseParabolic(self.gr, u, scale=uscale) 39 | self.vars["p"] = gp.PiecewiseParabolic(self.gr, p, scale=pscale) 40 | 41 | def draw_cubic_points(self, var, color="r"): 42 | # these are defined on the i+1/2 interface 43 | # note that we require 2 zones on either side of the interface, so 44 | # we cannot draw points for the first 2 or last 2 zones 45 | aint = self.vars[var].aint 46 | plt.scatter(self.gr.xr[1:-2], aint[1:-2], marker="x", s=40, color=color, zorder=10) 47 | 48 | def draw_parabola(self, var): 49 | ap, am = self.vars[var].ap, self.vars[var].am 50 | for n in range(2,self.nx-2): 51 | self.vars[var].draw_parabola(n) 52 | 53 | def draw_grid(self): 54 | self.gr.draw_grid() 55 | 56 | self.gr.label_center(self.nx/2, r"$i$") 57 | self.gr.label_center(self.nx/2-1, r"$i-1$") 58 | self.gr.label_center(self.nx/2+1, r"$i+1$") 59 | self.gr.label_center(self.nx/2-2, r"$i-2$") 60 | self.gr.label_center(self.nx/2+2, r"$i+2$") 61 | 62 | def draw_var_avg(self, var, scale=1.0): 63 | for n in range(self.gr.nx): 64 | self.vars[var].draw_cell_avg(n, color="r") 65 | 66 | 67 | #----------------------------------------------------------------------------- 68 | 69 | 70 | 71 | # multipage PDF 72 | # http://matplotlib.org/examples/pylab_examples/multipage_pdf.html 73 | 74 | 75 | # left state 76 | q_l = riemann.State(rho=1.0, u=0.0, p=1.0) 77 | 78 | # right state 79 | q_r = riemann.State(rho=0.125, u=0.0, p=0.1) 80 | 81 | r = RiemannProblem(q_l, q_r) 82 | 83 | 84 | subidx = [311, 312, 313] 85 | states = ["rho", "u", "p"] 86 | state_labels = [r"$\rho$", r"$u$", r"$p$"] 87 | 88 | 89 | #----------------------------------------------------------------------------- 90 | # plot 1: initial state 91 | plt.clf() 92 | 93 | for n, s in enumerate(states): 94 | 95 | plt.subplot(subidx[n]) 96 | r.draw_grid() 97 | r.draw_var_avg(s) 98 | r.gr.clean_axes() 99 | 100 | plt.title(state_labels[n]) 101 | 102 | f = plt.gcf() 103 | f.set_size_inches(8.0,7.0) 104 | plt.tight_layout() 105 | 106 | plt.savefig("ppm-seq-1.png") 107 | 108 | 109 | #----------------------------------------------------------------------------- 110 | # plot 2: cubic points (three vertical) 111 | plt.clf() 112 | 113 | for n, s in enumerate(states): 114 | 115 | plt.subplot(subidx[n]) 116 | r.draw_grid() 117 | r.draw_var_avg(s) 118 | r.draw_cubic_points(s) 119 | 120 | r.gr.clean_axes() 121 | 122 | plt.title(state_labels[n]) 123 | 124 | f = plt.gcf() 125 | f.set_size_inches(8.0,7.0) 126 | plt.tight_layout() 127 | 128 | plt.savefig("ppm-seq-2.png") 129 | 130 | 131 | #----------------------------------------------------------------------------- 132 | # plot 3: parabola (three vertical) 133 | plt.clf() 134 | 135 | for n, s in enumerate(states): 136 | 137 | plt.subplot(subidx[n]) 138 | r.draw_grid() 139 | r.draw_var_avg(s) 140 | r.draw_cubic_points(s) 141 | r.draw_parabola(s) 142 | r.gr.clean_axes() 143 | 144 | plt.title(state_labels[n]) 145 | 146 | f = plt.gcf() 147 | f.set_size_inches(8.0,7.0) 148 | plt.tight_layout() 149 | 150 | plt.savefig("ppm-seq-3.png") 151 | 152 | 153 | 154 | #----------------------------------------------------------------------------- 155 | # plot 4: cell-center Riemann waves to show what hits the interface 156 | 157 | 158 | #----------------------------------------------------------------------------- 159 | # plot 5: tracing (zoom in, 3 horizontal) 160 | 161 | 162 | 163 | #----------------------------------------------------------------------------- 164 | # plot 6: final interface state (zoom in, 3 horizontal) 165 | 166 | 167 | 168 | #----------------------------------------------------------------------------- 169 | # plot 7: Riemann phase 170 | 171 | 172 | 173 | #----------------------------------------------------------------------------- 174 | # plot 8: Riemann solution 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /figures/Euler/ppm-trace.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | 6 | #----------------------------------------------------------------------------- 7 | 8 | nzones = 8 9 | 10 | # data that lives on the grid 11 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 12 | a = np.array([0.3, 1.0, 1.0, 0.8, 0.2, 0.15, 0.5, 0.55]) 13 | 14 | gr = gp.FVGrid(nzones) 15 | 16 | 17 | plt.clf() 18 | 19 | gr.draw_grid(center_only=1) 20 | 21 | gr.label_center(nzones//2-1, r"$i$") 22 | gr.label_center(nzones//2, r"$i+1$") 23 | 24 | 25 | ppm = gp.PiecewiseParabolic(gr, a) 26 | 27 | for n in range(gr.nx//2-1, gr.nx//2+1): 28 | ppm.draw_parabola(n, color="r") 29 | 30 | nn = gr.nx//2-1 31 | sigma = 0.6 32 | ppm.ppm_trace_left(nn, sigma, color="0.75") 33 | 34 | plt.plot([gr.xr[gr.nx//2-1]-sigma*gr.dx, 35 | gr.xr[gr.nx//2-1]], [1.2, 1.2], color="k") 36 | plt.plot([gr.xr[gr.nx//2-1]-sigma*gr.dx, 37 | gr.xr[gr.nx//2-1]-sigma*gr.dx], [1.15, 1.25], color="k") 38 | plt.plot([gr.xr[gr.nx//2-1], 39 | gr.xr[gr.nx//2-1]], [1.15, 1.25], color="k") 40 | 41 | plt.text(gr.xr[gr.nx//2-1]-0.5*sigma*gr.dx, 1.3, 42 | r"$\sigma_{i}^{(\nu)} \Delta x$", 43 | horizontalalignment="center") 44 | 45 | plt.text(gr.xr[gr.nx//2-1]-0.5*sigma*gr.dx, 0.4, 46 | r"$\mathcal{I}_+^{(\nu)}$", 47 | color="r", horizontalalignment="center") 48 | 49 | plt.axis([gr.xl[gr.nx//2-1]-0.5*gr.dx,gr.xr[gr.nx//2]+0.5*gr.dx, -0.25, 1.4]) 50 | plt.axis("off") 51 | 52 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 53 | 54 | f = plt.gcf() 55 | f.set_size_inches(3.0,2.0) 56 | 57 | plt.savefig("ppm-trace.pdf") 58 | plt.savefig("ppm-trace.png") 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /figures/Euler/ppm.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | 7 | #----------------------------------------------------------------------------- 8 | 9 | nzones = 8 10 | 11 | # data that lives on the grid 12 | a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 13 | 14 | gr = gp.FVGrid(nzones) 15 | 16 | plt.clf() 17 | 18 | gr.draw_grid() 19 | 20 | gr.label_center(nzones//2, r"$i$") 21 | gr.label_center(nzones//2-1, r"$i-1$") 22 | gr.label_center(nzones//2+1, r"$i+1$") 23 | gr.label_center(nzones//2-2, r"$i-2$") 24 | gr.label_center(nzones//2+2, r"$i+2$") 25 | 26 | 27 | pc = gp.PiecewiseConstant(gr, a) 28 | 29 | for n in range(nzones): 30 | pc.draw_cell_avg(n, color="r") 31 | 32 | 33 | gr.clean_axes() 34 | plt.ylim(-0.25, 1.2) 35 | 36 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 37 | 38 | f = plt.gcf() 39 | f.set_size_inches(8.0,2.0) 40 | 41 | plt.savefig("piecewise-constant.pdf") 42 | plt.savefig("piecewise-constant.png") 43 | 44 | 45 | #------------- PLM ------------- 46 | plt.clf() 47 | 48 | gr.draw_grid() 49 | 50 | gr.label_center(nzones//2, r"$i$") 51 | gr.label_center(nzones//2-1, r"$i-1$") 52 | gr.label_center(nzones//2+1, r"$i+1$") 53 | gr.label_center(nzones//2-2, r"$i-2$") 54 | gr.label_center(nzones//2+2, r"$i+2$") 55 | 56 | 57 | # not limited and limited 58 | pl_n = gp.PiecewiseLinear(gr, a, nolimit=1) 59 | pl_y = gp.PiecewiseLinear(gr, a) 60 | 61 | for n in range(nzones): 62 | pc.draw_cell_avg(n, color="0.5") 63 | 64 | for n in range(2, nzones-2): 65 | pl_n.draw_slope(n, color="r", ls=":") 66 | pl_y.draw_slope(n, color="r") 67 | 68 | 69 | gr.clean_axes() 70 | plt.ylim(-0.25, 1.2) 71 | 72 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 73 | 74 | f = plt.gcf() 75 | f.set_size_inches(8.0,2.0) 76 | 77 | plt.savefig("piecewise-linear.pdf") 78 | plt.savefig("piecewise-linear.png") 79 | 80 | 81 | #------------- PPM ------------- 82 | plt.clf() 83 | 84 | gr.draw_grid() 85 | 86 | gr.label_center(nzones//2, r"$i$") 87 | gr.label_center(nzones//2-1, r"$i-1$") 88 | gr.label_center(nzones//2+1, r"$i+1$") 89 | gr.label_center(nzones//2-2, r"$i-2$") 90 | gr.label_center(nzones//2+2, r"$i+2$") 91 | 92 | for n in range(nzones): 93 | pc.draw_cell_avg(n, color="0.5") 94 | 95 | 96 | # compute the parabolic coefficients -- limited and not limited 97 | pm_n = gp.PiecewiseParabolic(gr, a, nolimit=1) 98 | pm_y = gp.PiecewiseParabolic(gr, a) 99 | 100 | for n in range(2, nzones-2): 101 | pm_n.draw_parabola(n, color="r", ls=":") 102 | pm_y.draw_parabola(n, color="r") 103 | 104 | 105 | gr.clean_axes() 106 | plt.ylim(-0.25, 1.2) 107 | 108 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 109 | 110 | f = plt.gcf() 111 | f.set_size_inches(8.0,2.0) 112 | 113 | 114 | plt.savefig("piecewise-parabolic.pdf") 115 | plt.savefig("piecewise-parabolic.png") 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /figures/Euler/rarefaction_cartoon.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import matplotlib as mpl 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | # font sizes 9 | mpl.rcParams['font.size'] = 12 10 | mpl.rcParams['legend.fontsize'] = 'large' 11 | mpl.rcParams['figure.titlesize'] = 'medium' 12 | 13 | 14 | class RiemannWaves(object): 15 | """draw a diagram with a left rarefaction and 2 other waves """ 16 | 17 | def __init__(self, rpos=-1): 18 | """rpos is position of rarefaction, -1 is left of the interface, +1 is 19 | right of the interface 20 | 21 | """ 22 | 23 | self.rpos = rpos 24 | 25 | # these control the spacing of the waves in the figure 26 | self.h = 1.0 27 | 28 | # this controls the spacing of the structure in the rarefaction 29 | self.rare_theta = np.radians(2.5) 30 | 31 | if rpos < 0: 32 | self.head = np.radians(-45) 33 | self.center = np.radians(5) 34 | self.right = np.radians(40) 35 | elif rpos == 0: 36 | self.head = 0 - 2.5*self.rare_theta 37 | self.center = np.radians(30) 38 | self.right = np.radians(45) 39 | else: 40 | self.head = np.radians(5) 41 | self.center = np.radians(35) 42 | self.right = np.radians(50) 43 | 44 | self.tail = self.head + 5*self.rare_theta 45 | 46 | def draw(self, output="plot.png", label=None): 47 | """ draw the wave structure """ 48 | 49 | # each wave has a point on the origin. The maximum height we 50 | # want to draw to is self.h -- we'll do the center and right 51 | xc = self.h*np.tan(self.center) 52 | x3 = self.h*np.tan(self.right) 53 | 54 | plt.clf() 55 | 56 | # draw the waves 57 | plt.plot([0, xc], [0, self.h], color="C0") 58 | plt.plot([0, x3], [0, self.h], color="C0") 59 | 60 | # rarefaction 61 | for t in np.arange(self.head, self.tail+self.rare_theta, 62 | self.rare_theta): 63 | xr = self.h*np.tan(t) 64 | plt.plot([0, xr], [0, self.h], color="C0") 65 | 66 | xhead = self.h*np.tan(self.head) 67 | xtail = self.h*np.tan(self.tail) #+self.rare_theta) 68 | 69 | # draw the grid 70 | L = 1.1*max(abs(xhead), abs(x3)) 71 | 72 | plt.plot([-L, L], [0, 0], color="k", zorder=-100) 73 | plt.plot([0, 0], [0, 1.2*self.h], color="k", zorder=-100) 74 | 75 | plt.text(xhead, self.h, r"$\lambda_\mathrm{head}$", 76 | horizontalalignment="right", color="C0") 77 | 78 | plt.text(xtail, self.h, r"$\lambda_\mathrm{tail}$", 79 | horizontalalignment="left", color="C0") 80 | 81 | 82 | dx = abs(0.75*self.h*np.tan(0.5*(self.head + self.tail))) 83 | 84 | if self.rpos == -1: 85 | fac = 0.4 86 | elif self.rpos == 0: 87 | fac = 1.0 88 | else: 89 | fac = 1.0 90 | 91 | xh = 0.75*self.h*np.tan(self.head) 92 | xt = 0.75*self.h*np.tan(self.tail) 93 | xc = 0.75*self.h*np.tan(self.center) 94 | xr = 0.75*self.h*np.tan(self.right) 95 | 96 | if dx == 0: 97 | dx = abs(xh) 98 | 99 | xL = xh - fac*dx 100 | xLstar = 0.5*(xt + xc) 101 | xRstar = 0.5*(xc + xr) 102 | xR = xr + fac*dx 103 | 104 | plt.text(xL, 0.65*self.h, r"$L$", horizontalalignment="right", color="C0") 105 | plt.text(xLstar, 0.75*self.h, r"$L_\star$", horizontalalignment="center", color="C0") 106 | plt.text(xRstar, 0.75*self.h, r"$R_\star$", horizontalalignment="center", color="C0") 107 | plt.text(xR, 0.65*self.h, r"$R$", horizontalalignment="left", color="C0") 108 | 109 | 110 | f = plt.gcf() 111 | 112 | # label? 113 | if label is not None: 114 | plt.text(0.1, 0.9, label, transform=f.transFigure) 115 | 116 | plt.axis("off") 117 | plt.subplots_adjust(left=0.02, right=0.95, bottom=0.05, top=0.95) 118 | 119 | f.set_size_inches(5.0, 3.5) 120 | 121 | plt.tight_layout() 122 | plt.savefig(output, bbox_inches="tight", pad_inches=0) 123 | 124 | 125 | if __name__ == "__main__": 126 | 127 | rw = RiemannWaves(rpos=-1) 128 | rw.draw("rarefaction_left.pdf", label="(a)") 129 | 130 | rw = RiemannWaves(rpos=0) 131 | rw.draw("rarefaction_center.pdf", label="(b)") 132 | 133 | rw = RiemannWaves(rpos=1) 134 | rw.draw("rarefaction_right.pdf", label="(c)") 135 | -------------------------------------------------------------------------------- /figures/Euler/riemann-states-q.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def riemann(with_time=True): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 2 12 | ng = 0 13 | 14 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 15 | 16 | plt.clf() 17 | 18 | #------------------------------------------------------------------------ 19 | # plot a domain without ghostcells 20 | gr.draw_grid(emphasize_end=True) 21 | 22 | # label a few 23 | gr.label_center(0, r"$i$", fontsize="medium") 24 | gr.label_center(1, r"$i+1$", fontsize="medium") 25 | gr.label_edge(1, r"$i+1/2$", fontsize="medium") 26 | 27 | if with_time: 28 | gr.mark_cell_left_state(1, r"$q_{i+1/2,R}^{n+1/2}$", fontsize="large", 29 | color="b") 30 | gr.mark_cell_right_state(0, r"$q_{i+1/2,L}^{n+1/2}$", fontsize="large", 31 | color="b") 32 | else: 33 | gr.mark_cell_left_state(1, r"$q_{i+1/2,R}$", fontsize="large", 34 | color="b") 35 | gr.mark_cell_right_state(0, r"$q_{i+1/2,L}$", fontsize="large", 36 | color="b") 37 | 38 | gr.label_cell_center(0, r"$q_i$") 39 | gr.label_cell_center(1, r"$q_{i+1}$") 40 | 41 | 42 | 43 | # flux 44 | plt.arrow(gr.xl[ng+nzones//2]-0.25*gr.dx, 1.05, 0.5*gr.dx, 0, 45 | shape='full', head_width=0.075, head_length=0.05, 46 | lw=1, width=0.03, 47 | edgecolor="none", facecolor="red", 48 | length_includes_head=True, zorder=100) 49 | 50 | if with_time: 51 | plt.text(gr.xl[ng+nzones//2], 1.15, r"$F(U(q_{i+1/2}^{n+1/2}))$", color="red", 52 | horizontalalignment="center") 53 | else: 54 | plt.text(gr.xl[ng+nzones//2], 1.15, r"$F(U(q_{i+1/2}))$", color="red", 55 | horizontalalignment="center") 56 | 57 | gr.clean_axes(padding=False) 58 | plt.ylim(-0.25, 1.25) 59 | 60 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 61 | 62 | f = plt.gcf() 63 | f.set_size_inches(6.0,2.25) 64 | 65 | 66 | plt.tight_layout() 67 | 68 | if with_time: 69 | plt.savefig("riemann_comp_q.pdf") 70 | else: 71 | plt.savefig("riemann_comp_q_mol.pdf") 72 | 73 | if __name__== "__main__": 74 | riemann() 75 | riemann(with_time=False) 76 | 77 | -------------------------------------------------------------------------------- /figures/Euler/riemann-states.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def riemann(with_time=True): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 2 12 | ng = 0 13 | 14 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 15 | 16 | plt.clf() 17 | 18 | #------------------------------------------------------------------------ 19 | # plot a domain without ghostcells 20 | gr.draw_grid(emphasize_end=True) 21 | 22 | # label a few 23 | gr.label_center(0, r"$i$", fontsize="medium") 24 | gr.label_center(1, r"$i+1$", fontsize="medium") 25 | gr.label_edge(1, r"$i+\myhalf$", fontsize="medium") 26 | 27 | if with_time: 28 | gr.mark_cell_left_state(1, r"$U_{i+\myhalf,R}^{n+\myhalf}$", fontsize="large", 29 | color="b") 30 | gr.mark_cell_right_state(0, r"$U_{i+\myhalf,L}^{n+\myhalf}$", fontsize="large", 31 | color="b") 32 | else: 33 | gr.mark_cell_left_state(1, r"$U_{i+\myhalf,R}$", fontsize="large", 34 | color="b") 35 | gr.mark_cell_right_state(0, r"$U_{i+\myhalf,L}$", fontsize="large", 36 | color="b") 37 | 38 | gr.label_cell_center(0, r"$U_i$") 39 | gr.label_cell_center(1, r"$U_{i+1}$") 40 | 41 | 42 | 43 | # flux 44 | plt.arrow(gr.xl[ng+nzones//2]-0.25*gr.dx, 1.05, 0.5*gr.dx, 0, 45 | shape='full', head_width=0.075, head_length=0.05, 46 | lw=1, width=0.03, 47 | edgecolor="none", facecolor="red", 48 | length_includes_head=True, zorder=100) 49 | 50 | if with_time: 51 | plt.text(gr.xl[ng+nzones//2], 1.15, r"$F(U_{i+\myhalf}^{n+\myhalf})$", color="red", 52 | horizontalalignment="center") 53 | else: 54 | plt.text(gr.xl[ng+nzones//2], 1.15, r"$F(U_{i+\myhalf})$", color="red", 55 | horizontalalignment="center") 56 | 57 | gr.clean_axes(padding=False) 58 | plt.ylim(-0.25, 1.25) 59 | 60 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 61 | 62 | f = plt.gcf() 63 | f.set_size_inches(6.0,2.25) 64 | 65 | plt.tight_layout() 66 | 67 | if with_time: 68 | plt.savefig("riemann_comp.pdf") 69 | else: 70 | plt.savefig("riemann_comp_mol.pdf") 71 | 72 | if __name__== "__main__": 73 | riemann() 74 | riemann(with_time=False) 75 | -------------------------------------------------------------------------------- /figures/Euler/riemann-waves-jump.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import grid_plot as gp 3 | 4 | def simplegrid(): 5 | 6 | # grid info 7 | xmin = 0.0 8 | xmax = 1.0 9 | 10 | nzones = 2 11 | ng = 0 12 | 13 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 14 | 15 | 16 | #------------------------------------------------------------------------ 17 | # plot a domain without ghostcells 18 | gr.draw_grid(draw_end=False, edge_ticks=False) 19 | 20 | gr.label_center(0, r"$i$") 21 | gr.label_center(1, r"$i+1$") 22 | 23 | gr.label_edge(1, r"$q_{i+\myhalf}$") 24 | 25 | 26 | # draw waves 27 | # u - c 28 | plt.plot([gr.xr[0], gr.xr[0]-0.75*gr.dx], [0,1.0], color="C0", ls="-") 29 | plt.text(gr.xr[0]-0.75*gr.dx, 1.0+0.05, "$\lambda^{(-)} =\, u - c$", 30 | horizontalalignment="center") 31 | 32 | # u 33 | plt.plot([gr.xr[0], gr.xr[0]-0.2*gr.dx], [0,1.0], color="C0", ls="-") 34 | plt.text(gr.xr[0]-0.2*gr.dx, 1.0+0.05, "$\lambda^{(\circ)} =\, u$", 35 | horizontalalignment="center") 36 | 37 | # u + c 38 | plt.plot([gr.xr[0], gr.xr[0]+0.4*gr.dx], [0,1.0], color="C0", ls="-") 39 | plt.text(gr.xr[0]+0.4*gr.dx, 1.0+0.05, "$\lambda^{(+)} =\, u + c$", 40 | horizontalalignment="center") 41 | 42 | 43 | plt.plot([gr.xl[0], gr.xr[0]], [0.3, 0.3], color="C1", linewidth=2) 44 | plt.text(gr.xc[0], 0.33, r"$\langle q \rangle_i$", color="C1") 45 | 46 | plt.plot([gr.xl[1], gr.xr[1]], [0.6, 0.6], color="C1", linewidth=2) 47 | plt.text(gr.xc[1], 0.63, r"$\langle q \rangle_{i+1}$", color="C1") 48 | 49 | gr.clean_axes(padding=False) 50 | plt.ylim(-0.2,1.2) 51 | 52 | plt.tight_layout() 53 | 54 | f = plt.gcf() 55 | f.set_size_inches(6, 3.5) 56 | 57 | 58 | plt.savefig("riemann-waves-jump.png", dpi=150) 59 | 60 | if __name__== "__main__": 61 | simplegrid() 62 | -------------------------------------------------------------------------------- /figures/Euler/riemann-waves.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import grid_plot as gp 3 | 4 | def simplegrid(): 5 | 6 | # grid info 7 | xmin = 0.0 8 | xmax = 1.0 9 | 10 | nzones = 2 11 | ng = 0 12 | 13 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 14 | 15 | 16 | #------------------------------------------------------------------------ 17 | # plot a domain without ghostcells 18 | gr.draw_grid(draw_end=False, edge_ticks=False) 19 | 20 | gr.label_center(0, r"$i$") 21 | gr.label_center(1, r"$i+1$") 22 | 23 | gr.label_edge(1, r"$q_{i+\myhalf}$") 24 | 25 | 26 | # draw waves 27 | # u - c 28 | plt.plot([gr.xr[0], gr.xr[0]-0.75*gr.dx], [0,1.0], color="C0", ls="-") 29 | plt.text(gr.xr[0]-0.75*gr.dx, 1.0+0.05, "$\lambda^{(-)} =\, u - c$", 30 | horizontalalignment="center") 31 | 32 | # u 33 | plt.plot([gr.xr[0], gr.xr[0]-0.2*gr.dx], [0,1.0], color="C0", ls="-") 34 | plt.text(gr.xr[0]-0.2*gr.dx, 1.0+0.05, "$\lambda^{(\circ)} =\, u$", 35 | horizontalalignment="center") 36 | 37 | # u + c 38 | plt.plot([gr.xr[0], gr.xr[0]+0.4*gr.dx], [0,1.0], color="C0", ls="-") 39 | plt.text(gr.xr[0]+0.4*gr.dx, 1.0+0.05, "$\lambda^{(+)} =\, u + c$", 40 | horizontalalignment="center") 41 | 42 | # label regions 43 | plt.text(gr.xr[0]-0.5*gr.dx, 0.3, r"$L$", horizontalalignment="center", color="C1") 44 | plt.text(gr.xr[0]-0.5*gr.dx, 0.22, r"$(\rho_L, u_L, p_L)$", 45 | horizontalalignment="center", color="C1", fontsize="small") 46 | 47 | plt.text(gr.xr[0]-0.33*gr.dx, 0.75, r"$L_*$", 48 | horizontalalignment="center", color="C1") 49 | plt.text(gr.xr[0]-0.33*gr.dx, 0.67, r"$(\rho_{\star L}, u_\star, p_\star)$", 50 | horizontalalignment="center", color="C1", fontsize="small") 51 | 52 | plt.text(gr.xr[0]+0.1*gr.dx, 0.75, r"$R_*$", horizontalalignment="center", color="C1") 53 | plt.text(gr.xr[0]+0.1*gr.dx, 0.67, r"$(\rho_{\star R}, u_\star, p_\star)$", 54 | horizontalalignment="center", color="C1", fontsize="small", zorder=1000) 55 | 56 | plt.text(gr.xr[0]+0.3*gr.dx, 0.3, r"$R$", horizontalalignment="center", color="C1") 57 | plt.text(gr.xr[0]+0.3*gr.dx, 0.22, r"$(\rho_R, u_R, p_R)$", 58 | horizontalalignment="center", color="C1", fontsize="small") 59 | 60 | 61 | 62 | gr.clean_axes(padding=False) 63 | plt.ylim(-0.2,1.2) 64 | 65 | plt.tight_layout() 66 | 67 | f = plt.gcf() 68 | f.set_size_inches(6,3.5) 69 | 70 | 71 | plt.savefig("riemann-waves.pdf") 72 | 73 | if __name__== "__main__": 74 | simplegrid() 75 | -------------------------------------------------------------------------------- /figures/Euler/riemann_cartoon.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import matplotlib as mpl 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | # font sizes 9 | mpl.rcParams['font.size'] = 12 10 | mpl.rcParams['legend.fontsize'] = 'large' 11 | mpl.rcParams['figure.titlesize'] = 'medium' 12 | 13 | 14 | class RiemannWaves(object): 15 | """draw a diagram with the 3 waves for the Euler Riemann problem""" 16 | 17 | def __init__(self, left=-1, contact=-1, right=1): 18 | """for each of the waves, -1 is left of the interface, +1 is right of 19 | the interface""" 20 | 21 | self.left = left 22 | self.contact = contact 23 | self.right = right 24 | 25 | # these control the spacing of the waves in the figure 26 | self.theta = np.radians(25) 27 | self.h = 1.0 28 | 29 | def draw(self, output="plot.png", label=None): 30 | """ draw the wave structure """ 31 | 32 | # by default, we'll make the waves theta degrees apart 33 | if self.right < 0: 34 | angle3 = -0.75*self.theta 35 | elif self.right > 0 and self.contact < 0: 36 | angle3 = 0.534*self.theta 37 | elif self.right > 0 and self.contact > 0 and self.left < 0: 38 | angle3 = 0.966*self.theta 39 | else: 40 | angle3 = 2.25*self.theta 41 | 42 | anglec = angle3 - 0.75*self.theta 43 | angle1 = anglec - 0.75*self.theta 44 | 45 | print(np.degrees(angle1), np.degrees(anglec), np.degrees(angle3)) 46 | 47 | # each wave has a point on the origin. The maximum height we want to draw to is self.h 48 | x1 = self.h*np.tan(angle1) 49 | xc = self.h*np.tan(anglec) 50 | x3 = self.h*np.tan(angle3) 51 | 52 | print(x1, xc, x3) 53 | 54 | plt.clf() 55 | 56 | # draw the waves 57 | plt.plot([0, x1], [0, self.h], color="C0") 58 | plt.plot([0, xc], [0, self.h], color="C0") 59 | plt.plot([0, x3], [0, self.h], color="C0") 60 | 61 | # label regions 62 | x1h = 0.75*self.h*np.tan(angle1) 63 | xch = 0.75*self.h*np.tan(anglec) 64 | x3h = 0.75*self.h*np.tan(angle3) 65 | 66 | dx = max(xch - x1h, x3h - xch) 67 | xL = x1h - 0.6*dx 68 | xLstar = 0.5*(x1h + xch) 69 | xRstar = 0.5*(xch + x3h) 70 | xR = x3h + 0.6*dx 71 | 72 | plt.text(xL, 0.65*self.h, r"$L$", horizontalalignment="right", color="C0") 73 | plt.text(xLstar, 0.75*self.h, r"$L_\star$", horizontalalignment="center", color="C0") 74 | plt.text(xRstar, 0.75*self.h, r"$R_\star$", horizontalalignment="center", color="C0") 75 | plt.text(xR, 0.65*self.h, r"$R$", horizontalalignment="left", color="C0") 76 | 77 | # draw the grid 78 | L = 1.1*max(abs(x1), abs(x3)) 79 | 80 | plt.plot([-L, L], [0, 0], color="k") 81 | plt.plot([0, 0], [0, 1.2*self.h], color="k") 82 | 83 | f = plt.gcf() 84 | 85 | # label? 86 | if label is not None: 87 | plt.text(0.1, 0.9, label, transform=f.transFigure) 88 | 89 | plt.axis("off") 90 | plt.subplots_adjust(left=0.02, right=0.95, bottom=0.05, top=0.95) 91 | 92 | 93 | f.set_size_inches(5.0, 3.5) 94 | 95 | plt.tight_layout() 96 | plt.savefig(output, bbox_inches="tight", pad_inches=0) 97 | 98 | 99 | if __name__ == "__main__": 100 | 101 | rw = RiemannWaves(left=-1, contact=-1, right=-1) 102 | rw.draw("riemann_waves_ifc_R.pdf", label="(a)") 103 | 104 | rw = RiemannWaves(left=-1, contact=-1, right=1) 105 | rw.draw("riemann_waves_ifc_Rstar.pdf", label="(b)") 106 | 107 | rw = RiemannWaves(left=-1, contact=1, right=1) 108 | rw.draw("riemann_waves_ifc_Lstar.pdf", label="(c)") 109 | 110 | rw = RiemannWaves(left=1, contact=1, right=1) 111 | rw.draw("riemann_waves_ifc_L.pdf", label="(d)") 112 | -------------------------------------------------------------------------------- /figures/Euler/states.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | def riemann(): 7 | 8 | # grid info 9 | xmin = 0.0 10 | xmax = 1.0 11 | 12 | nzones = 1 13 | ng = 0 14 | 15 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 16 | 17 | 18 | #------------------------------------------------------------------------ 19 | # plot a domain without ghostcells 20 | gr.draw_grid() 21 | 22 | gr.label_center(0, r"$i$") 23 | 24 | gr.label_cell_center(0, r"$q_i$") 25 | 26 | gr.mark_cell_left_state(0, r"$q_{i-1/2,R}^{n+1/2}$", color="r") 27 | gr.mark_cell_right_state(0, r"$q_{i+1/2,L}^{n+1/2}$", color="r") 28 | 29 | 30 | plt.arrow(gr.xc[0]-0.05*gr.dx, 0.5, -0.13*gr.dx, 0, 31 | shape='full', head_width=0.075, head_length=0.05, 32 | lw=1, width=0.01, 33 | edgecolor="none", facecolor="r", 34 | length_includes_head=True, zorder=100) 35 | 36 | plt.arrow(gr.xc[0]+0.05*gr.dx, 0.5, 0.13*gr.dx, 0, 37 | shape='full', head_width=0.075, head_length=0.05, 38 | lw=1, width=0.01, 39 | edgecolor="none", facecolor="r", 40 | length_includes_head=True, zorder=100) 41 | 42 | 43 | plt.xlim(gr.xl[0]-0.25*gr.dx,gr.xr[2*ng+nzones-1]+0.25*gr.dx) 44 | # plt.ylim(-0.25, 0.75) 45 | plt.axis("off") 46 | 47 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 48 | 49 | f = plt.gcf() 50 | f.set_size_inches(4.0,2.5) 51 | 52 | 53 | plt.savefig("states.png") 54 | plt.savefig("states.pdf") 55 | 56 | 57 | if __name__== "__main__": 58 | riemann() 59 | -------------------------------------------------------------------------------- /figures/Euler/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEST=../../Euler 4 | 5 | # riemann-states.py makes riemann_comp.pdf 6 | python3 riemann-states.py 7 | cp -f riemann_comp.pdf ${DEST} 8 | 9 | 10 | # ppm.py makes piecewise-constant.pdf piecewise-linear.pdf piecewise-parabolic.pdf 11 | python3 ppm.py 12 | cp -f piecewise-constant.pdf piecewise-linear.pdf piecewise-parabolic.pdf ${DEST} 13 | 14 | 15 | # states.py makes states.pdf 16 | python3 states.py 17 | cp -f states.pdf ${DEST} 18 | 19 | 20 | -------------------------------------------------------------------------------- /figures/advection/2dFD.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | def simplegrid(): 7 | 8 | nzones = 5 9 | gr = gp.FDGrid2d(nzones, nzones, ng=0) 10 | 11 | # plot a domain without ghostcells 12 | gr.draw_grid() 13 | 14 | #------------------------------------------------------------------------ 15 | # label 16 | gr.label_cell_center(nzones/2, nzones/2, r"$a_{i,j}$", 17 | fontsize="x-large", color="r") 18 | 19 | # grid labels 20 | gr.label_center_x(nzones/2-2, r"$i-2$") 21 | gr.label_center_x(nzones/2-1, r"$i-1$") 22 | gr.label_center_x(nzones/2, r"$i$") 23 | gr.label_center_x(nzones/2+1, r"$i+1$") 24 | gr.label_center_x(nzones/2+2, r"$i+2$") 25 | 26 | gr.label_center_y(nzones/2-2, r"$j-2$") 27 | gr.label_center_y(nzones/2-1, r"$j-1$") 28 | gr.label_center_y(nzones/2, r"$j$") 29 | gr.label_center_y(nzones/2+1, r"$j+1$") 30 | gr.label_center_y(nzones/2+2, r"$j+2$") 31 | 32 | # axes 33 | gr.clean_axes() 34 | plt.subplots_adjust(left=0.025,right=0.98,bottom=0.1,top=0.98) 35 | 36 | f = plt.gcf() 37 | f.set_size_inches(7.0,7.0) 38 | 39 | plt.savefig("2dFD.png") 40 | 41 | if __name__== "__main__": 42 | simplegrid() 43 | -------------------------------------------------------------------------------- /figures/advection/2dFV.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | def simplegrid(): 7 | 8 | nzones = 5 9 | gr = gp.FVGrid2d(nzones, nzones, ng=0) 10 | 11 | # plot a domain without ghostcells 12 | gr.draw_grid() 13 | 14 | #------------------------------------------------------------------------ 15 | # label 16 | gr.label_cell_center(nzones/2, nzones/2, r"$a_{i,j}$", 17 | fontsize="x-large", color="r") 18 | gr.shade_cell(nzones/2, nzones/2) 19 | 20 | # grid labels 21 | gr.label_center_x(nzones/2-2, r"$i-2$") 22 | gr.label_center_x(nzones/2-1, r"$i-1$") 23 | gr.label_center_x(nzones/2, r"$i$") 24 | gr.label_center_x(nzones/2+1, r"$i+1$") 25 | gr.label_center_x(nzones/2+2, r"$i+2$") 26 | 27 | gr.label_center_y(nzones/2-2, r"$j-2$") 28 | gr.label_center_y(nzones/2-1, r"$j-1$") 29 | gr.label_center_y(nzones/2, r"$j$") 30 | gr.label_center_y(nzones/2+1, r"$j+1$") 31 | gr.label_center_y(nzones/2+2, r"$j+2$") 32 | 33 | # axes 34 | gr.clean_axes() 35 | plt.subplots_adjust(left=0.025,right=0.98,bottom=0.1,top=0.98) 36 | 37 | f = plt.gcf() 38 | f.set_size_inches(7.0,7.0) 39 | 40 | plt.savefig("2dFV.png") 41 | 42 | if __name__== "__main__": 43 | simplegrid() 44 | -------------------------------------------------------------------------------- /figures/advection/2dgrid.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def simplegrid(): 6 | 7 | nzones = 3 8 | gr = gp.FVGrid2d(nzones, nzones, ng=0) 9 | 10 | # plot a domain without ghostcells 11 | gr.draw_grid() 12 | 13 | 14 | #------------------------------------------------------------------------ 15 | # label 16 | gr.label_cell_center(nzones//2, nzones//2, r"$a_{i,j}$", fontsize="large") 17 | gr.label_cell_center(nzones//2+1, nzones//2, r"$a_{i+1,j}$", fontsize="large") 18 | gr.label_cell_center(nzones//2, nzones//2+1, r"$a_{i,j+1}$", fontsize="large") 19 | 20 | # i+1/2,j interface 21 | gr.mark_cell_left_state_x(nzones//2, nzones//2, r"$a^{n+\myhalf}_{i+\myhalf,j,L}$", 22 | color="b") 23 | gr.mark_cell_right_state_x(nzones//2+1, nzones//2, r"$a^{n+\myhalf}_{i+\myhalf,j,R}$", 24 | color="b") 25 | 26 | 27 | # i,j+1/2 interface 28 | gr.mark_cell_left_state_y(nzones//2, nzones//2, r"$a^{n+\myhalf}_{i,j+\myhalf,L}$", 29 | color="b") 30 | gr.mark_cell_right_state_y(nzones//2, nzones//2+1, r"$a^{n+\myhalf}_{i,j+\myhalf,R}$", 31 | color="b") 32 | 33 | # grid labels 34 | gr.label_center_x(nzones//2-1, r"$i-1$") 35 | gr.label_center_x(nzones//2, r"$i$") 36 | gr.label_center_x(nzones//2+1, r"$i+1$") 37 | 38 | gr.label_center_y(nzones//2-1, r"$j-1$") 39 | gr.label_center_y(nzones//2, r"$j$") 40 | gr.label_center_y(nzones//2+1, r"$j+1$") 41 | 42 | 43 | # axes 44 | gr.clean_axes() 45 | plt.subplots_adjust(left=0.02,right=0.98,bottom=0.02,top=0.98) 46 | 47 | f = plt.gcf() 48 | f.set_size_inches(7.0,7.0) 49 | 50 | plt.savefig("2dgrid.pdf") 51 | 52 | if __name__== "__main__": 53 | simplegrid() 54 | -------------------------------------------------------------------------------- /figures/advection/2dgrid_hat.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def simplegrid(): 6 | 7 | nzones = 3 8 | gr = gp.FVGrid2d(nzones, nzones, ng=0) 9 | 10 | 11 | # plot a domain without ghostcells 12 | gr.draw_grid() 13 | 14 | 15 | #------------------------------------------------------------------------ 16 | # label 17 | gr.label_cell_center(nzones//2, nzones//2, r"$a_{i,j}$", fontsize="large") 18 | gr.label_cell_center(nzones//2+1, nzones//2, r"$a_{i+1,j}$", fontsize="large") 19 | gr.label_cell_center(nzones//2, nzones//2+1, r"$a_{i,j+1}$", fontsize="large") 20 | gr.label_cell_center(nzones//2, nzones//2-1, r"$a_{i,j-1}$", fontsize="large") 21 | 22 | # i+1/2,j interface 23 | gr.mark_cell_left_state_x(nzones//2, nzones//2, r"$\hat{a}^{n+\myhalf}_{i+\myhalf,j,L}$", color="b") 24 | 25 | # i,j+1/2 interface 26 | gr.mark_cell_left_state_y(nzones//2, nzones//2, r"$\hat{a}^{n+\myhalf}_{i,j+\myhalf,L}$", color="b") 27 | gr.mark_cell_right_state_y(nzones//2, nzones//2+1, r"$\hat{a}^{n+\myhalf}_{i,j+\myhalf,R}$", color="b") 28 | 29 | # i,j-1/2 interface 30 | gr.mark_cell_left_state_y(nzones//2, nzones//2-1, r"$\hat{a}^{n+\myhalf}_{i,j-\myhalf,L}$", color="b") 31 | gr.mark_cell_right_state_y(nzones//2, nzones//2, r"$\hat{a}^{n+\myhalf}_{i,j-\myhalf,R}$", color="b") 32 | 33 | # grid labels 34 | gr.label_center_x(nzones//2-1, r"$i-1$") 35 | gr.label_center_x(nzones//2, r"$i$") 36 | gr.label_center_x(nzones//2+1, r"$i+1$") 37 | 38 | gr.label_center_y(nzones//2-1, r"$j-1$") 39 | gr.label_center_y(nzones//2, r"$j$") 40 | gr.label_center_y(nzones//2+1, r"$j+1$") 41 | 42 | # axes 43 | gr.clean_axes() 44 | plt.subplots_adjust(left=0.02,right=0.98,bottom=0.02,top=0.98) 45 | 46 | f = plt.gcf() 47 | f.set_size_inches(7.0,7.0) 48 | 49 | plt.savefig("2dgrid-hat.pdf") 50 | 51 | if __name__== "__main__": 52 | simplegrid() 53 | -------------------------------------------------------------------------------- /figures/advection/2dgrid_transverse.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | def simplegrid(): 7 | 8 | nzones = 3 9 | gr = gp.FVGrid2d(nzones, nzones, ng=0) 10 | 11 | 12 | # plot a domain without ghostcells 13 | gr.draw_grid() 14 | 15 | #------------------------------------------------------------------------ 16 | # label 17 | gr.label_cell_center(nzones//2, nzones//2, r"$a_{i,j}$", fontsize="large") 18 | gr.label_cell_center(nzones//2+1, nzones//2, r"$a_{i+1,j}$", fontsize="large") 19 | gr.label_cell_center(nzones//2, nzones//2+1, r"$a_{i,j+1}$", fontsize="large") 20 | gr.label_cell_center(nzones//2, nzones//2-1, r"$a_{i,j-1}$", fontsize="large") 21 | 22 | # i+1/2,j interface 23 | gr.mark_cell_left_state_x(nzones//2, nzones//2, r"$\hat{a}^{n+\myhalf}_{i+\myhalf,j,L}$", color="b") 24 | 25 | # i,j+1/2 interface 26 | gr.mark_cell_state_y(nzones//2, nzones//2, r"${a}^T_{i,j+\myhalf}$") 27 | 28 | # i,j-1/2 interface 29 | gr.mark_cell_state_y(nzones//2, nzones//2-1, r"${a}^T_{i,j-\myhalf}$", off_sign=-1) 30 | 31 | # helpful line showing the transverse bits 32 | plt.plot([gr.xc[nzones//2], gr.xc[nzones//2]], 33 | [gr.yl[nzones//2]+0.025*gr.dy, gr.yr[nzones//2]-0.025*gr.dy], linestyle=":", 34 | color="0.5", zorder=1000) 35 | 36 | plt.plot([gr.xc[nzones//2], gr.xr[nzones//2]-0.26*gr.dx], 37 | [gr.yc[nzones//2], gr.yc[nzones//2]], linestyle=":", 38 | color="0.5", zorder=1000) 39 | 40 | plt.plot([gr.xr[nzones//2]-0.34*gr.dx, gr.xr[nzones//2]-0.26*gr.dx], 41 | [gr.yc[nzones//2]+0.04*gr.dy, gr.yc[nzones//2]], linestyle=":", 42 | color="0.5", zorder=1000) 43 | 44 | plt.plot([gr.xr[nzones//2]-0.34*gr.dx, gr.xr[nzones//2]-0.26*gr.dx], 45 | [gr.yc[nzones//2]-0.04*gr.dy, gr.yc[nzones//2]], linestyle=":", 46 | color="0.5", zorder=1000) 47 | 48 | 49 | # grid labels 50 | gr.label_center_x(nzones//2-1, r"$i-1$") 51 | gr.label_center_x(nzones//2, r"$i$") 52 | gr.label_center_x(nzones//2+1, r"$i+1$") 53 | 54 | gr.label_center_y(nzones//2-1, r"$j-1$") 55 | gr.label_center_y(nzones//2, r"$j$") 56 | gr.label_center_y(nzones//2+1, r"$j+1$") 57 | 58 | 59 | # axes 60 | gr.clean_axes() 61 | 62 | plt.subplots_adjust(left=0.02,right=0.98,bottom=0.02,top=0.98) 63 | 64 | f = plt.gcf() 65 | f.set_size_inches(7.0,7.0) 66 | 67 | plt.savefig("2dgrid-transverse.pdf") 68 | 69 | 70 | if __name__== "__main__": 71 | simplegrid() 72 | -------------------------------------------------------------------------------- /figures/advection/characteristics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib as mpl 3 | import matplotlib.pyplot as plt 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | 9 | def fun(x): 10 | state = np.zeros_like(xplot) 11 | state[x < 0.5] = 1.0 12 | return state 13 | 14 | def funs(x): 15 | state = 0.5 + 0.25*np.sin(2.0*np.pi*x) 16 | return state 17 | 18 | npts_plot = 1000 19 | xplot = np.linspace(0.0, 1.0, npts_plot) 20 | 21 | nchar = 20 22 | xchar = np.linspace(0.0, 1.0, nchar) 23 | 24 | state = funs(xplot) 25 | print(type(state)) 26 | 27 | plt.subplot(211) 28 | 29 | plt.plot(xplot, state, lw=2) 30 | 31 | 32 | ax = plt.gca() 33 | ax.spines['right'].set_visible(False) 34 | ax.spines['top'].set_visible(False) 35 | ax.spines['right'].set_visible(False) 36 | ax.spines['top'].set_visible(False) 37 | ax.spines['right'].set_visible(False) 38 | ax.spines['top'].set_visible(False) 39 | ax.xaxis.set_ticks_position('bottom') 40 | ax.yaxis.set_ticks_position('left') 41 | 42 | plt.ylim(-0.1, 1.1) 43 | 44 | plt.xlabel(r"$x$", fontsize="large") 45 | plt.ylabel(r"$a$", fontsize="large") 46 | 47 | 48 | 49 | plt.subplot(212) 50 | 51 | uchar = 1.0 52 | t = np.linspace(0.0, 1.0, 100) 53 | for n in range(nchar): 54 | xc = xchar[n] + uchar*t 55 | plt.plot(xc, t, color="0.5") 56 | 57 | ax = plt.gca() 58 | ax.spines['right'].set_visible(False) 59 | ax.spines['top'].set_visible(False) 60 | ax.spines['right'].set_visible(False) 61 | ax.spines['top'].set_visible(False) 62 | ax.spines['right'].set_visible(False) 63 | ax.spines['top'].set_visible(False) 64 | ax.xaxis.set_ticks_position('bottom') 65 | ax.yaxis.set_ticks_position('left') 66 | 67 | plt.xlabel(r"$x$", fontsize="large") 68 | plt.ylabel(r"$t$", fontsize="large") 69 | 70 | plt.xlim(0.0, 1.0) 71 | plt.ylim(0.0, 1.1) 72 | 73 | f = plt.gcf() 74 | f.set_size_inches(6.0, 8.0) 75 | 76 | plt.tight_layout() 77 | 78 | plt.savefig("advection-characteristics.png") 79 | 80 | -------------------------------------------------------------------------------- /figures/advection/domains.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pylab as plt 3 | import matplotlib as mpl 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | mpl.rcParams['font.size'] = 12 9 | mpl.rcParams['legend.fontsize'] = 'large' 10 | mpl.rcParams['figure.titlesize'] = 'medium' 11 | 12 | def domains(method="FTCS"): 13 | 14 | # grid info 15 | xl = 0.0 16 | xc = 1.0 17 | xr = 2.0 18 | 19 | dx = xr - xc 20 | 21 | t0 = 0.0 22 | t1 = 1.0 23 | 24 | dt = t1 - t0 25 | 26 | C = 0.6 27 | xp = xc - C*dx 28 | 29 | plt.clf() 30 | 31 | # plot a square representing [x, x+dx] x [t, t+dt] 32 | 33 | # x-axis 34 | plt.arrow(0, 0, 2.5*dx, 0, 35 | shape="full", head_width=0.04, head_length=0.06, 36 | lw=1, width=0.005, 37 | facecolor="k", 38 | length_includes_head=True, zorder=100) 39 | 40 | plt.text(2.55*dx, 0, r"$x$", fontsize=16, verticalalignment="center") 41 | 42 | # x points labeled 43 | for p, l in [((xc, 0), r"$x_i$"), ((xl, 0), r"$x_{i-1}$"), ((xr, 0), r"$x_{i+1}$")]: 44 | plt.text(p[0], p[1]-0.07, l, fontsize=16, 45 | horizontalalignment="center", verticalalignment="top") 46 | plt.plot([p[0], p[0]], [p[1], p[1]-0.04], color="k") 47 | 48 | plt.text(xp, -0.07, r"$x_i - C \Delta x$", fontsize=16, 49 | horizontalalignment="center", verticalalignment="top") 50 | plt.plot([xp, xp], [0, -0.04], color="k") 51 | 52 | # points 53 | plt.scatter([xl, xc, xr, xc], [0, 0, 0, dt], color="C3", 54 | marker="o", s=40, zorder=1000, alpha=1.0) 55 | 56 | # data points 57 | eps = 0.02*dx 58 | for p, l in [((xl, 0), r"$a_{i-1}^n$"), ((xc, 0), r"$a_{i}^n$"), 59 | ((xr, 0), r"$a_{i+1}^n$"), ((xc, dt), r"$a_{i}^{n+1}$")]: 60 | plt.text(p[0]+eps, p[1]+eps, l, 61 | horizontalalignment="left", verticalalignment="bottom", 62 | fontsize=16, color="C3", zorder=1000) 63 | 64 | # time axis 65 | plt.arrow(0, 0, 0, 1.3*dt, 66 | shape="full", head_width=0.04, head_length=0.06, 67 | lw=1, width=0.005, 68 | facecolor="k", 69 | length_includes_head=True, zorder=100) 70 | 71 | plt.text(0, 1.35*dt, r"$t$", fontsize=16, horizontalalignment="center") 72 | 73 | plt.text(-0.25, dt, r"$t^{n+1}$", fontsize=16) 74 | plt.plot([-0.04, 0], [dt, dt], color="k") 75 | 76 | plt.text(-0.25, 0, r"$t^n$", fontsize=16) 77 | plt.plot([-0.04, 0], [0, 0], color="k") 78 | 79 | plt.plot([0, 2.0*dx], [dt, dt], ls=":", color="0.5") 80 | plt.plot([dx, dx], [0, dt], ls=":", color="0.5") 81 | plt.plot([2.0*dx, 2.0*dx], [0, dt], ls=":", color="0.5") 82 | 83 | # domain of dependence 84 | if method == "upwind": 85 | plt.fill([0, xc, xc, 0], [0, dt, 0, 0], color="C0", lw=2, alpha=0.5) 86 | elif method == "FTCS": 87 | plt.fill([0, xc, xr, 0], [0, dt, 0, 0], color="C0", lw=2, alpha=0.5) 88 | elif method == "downwind": 89 | plt.fill([xc, xc, xr, 0], [0, dt, 0, 0], color="C0", lw=2, alpha=0.5) 90 | 91 | # true domain of dependence 92 | plt.fill([xp, xc, xc, 0], [0, dt, 0, 0], color="C1", lw=2, alpha=0.5) 93 | 94 | 95 | # label 96 | plt.text(xr+0.1*dx, 0.5*dt, method, fontsize=16, 97 | horizontalalignment="left") 98 | 99 | plt.axis("off") 100 | 101 | plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) 102 | 103 | plt.xlim(-0.4,2.8*dx) 104 | plt.ylim(-0.1,1.4*dx) 105 | 106 | f = plt.gcf() 107 | f.set_size_inches(9.0,5.0) 108 | 109 | plt.tight_layout() 110 | plt.savefig(f"domains_{method}.pdf", bbox_inches="tight") 111 | 112 | 113 | if __name__== "__main__": 114 | domains(method="upwind") 115 | domains(method="FTCS") 116 | domains(method="downwind") 117 | -------------------------------------------------------------------------------- /figures/advection/domains_downwind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/figures/advection/domains_downwind.pdf -------------------------------------------------------------------------------- /figures/advection/domains_upwind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/figures/advection/domains_upwind.pdf -------------------------------------------------------------------------------- /figures/advection/fd_ghost.py: -------------------------------------------------------------------------------- 1 | import grid_plot as gp 2 | import numpy as np 3 | 4 | # plot a simple finite-difference grid 5 | 6 | #----------------------------------------------------------------------------- 7 | 8 | nzones = 9 9 | 10 | # data that lives on the grid 11 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 12 | a = np.array([0.55, 0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 13 | 14 | gr = gp.FDGrid(nzones, ng=1) 15 | 16 | gr.draw_grid(draw_ghost=1) 17 | 18 | labels = ["-1", "0", "1", "", "i-1", "i", "i+1", "", "N-2", "N-1", "N"] 19 | 20 | for i in range(gr.ilo-gr.ng, gr.ng+gr.nx+1): 21 | if not labels[i] == "": 22 | gr.label_node(i, r"$%s$" % (labels[i]), fontsize="medium") 23 | 24 | # draw the data 25 | for i in range(gr.ilo, gr.ihi+1): 26 | gr.draw_data(i, a[i-gr.ng], color="r") 27 | 28 | 29 | gr.label_value(gr.ilo+4, a[gr.ilo+4-gr.ng], r"$a_i$", color="r") 30 | 31 | # label dx 32 | gr.label_dx(gr.ng+nzones//2) 33 | 34 | gr.clean_axes(pad_fac=0.1, show_ghost=True, ylim=(-0.5, 1.3)) 35 | 36 | fig = gr.fig 37 | fig.set_size_inches(10.0,3.0) 38 | 39 | 40 | fig.savefig("fd_ghost.pdf") 41 | -------------------------------------------------------------------------------- /figures/advection/fv_ghost.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | # plot a simple finite-difference grid 6 | 7 | #----------------------------------------------------------------------------- 8 | 9 | nzones = 7 10 | ng = 2 11 | 12 | # data that lives on the grid 13 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 14 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 15 | a = np.array([1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 16 | 17 | gr = gp.FVGrid(nzones, ng) 18 | 19 | aa = gr.scratch_array() 20 | aa[gr.ilo:gr.ihi+1] = a 21 | 22 | cc = gp.PiecewiseConstant(gr, aa) 23 | 24 | plt.clf() 25 | 26 | gr.draw_grid(draw_ghost=1, emphasize_end=1) 27 | 28 | gr.label_center(ng+nzones//2, r"$i$") 29 | gr.label_center(ng+nzones//2-1, r"$i-1$") 30 | gr.label_center(ng+nzones//2+1, r"$i+1$") 31 | 32 | gr.label_center(gr.ilo, r"$\mathrm{lo}$") 33 | gr.label_center(gr.ilo-1, r"$\mathrm{lo-1}$") 34 | gr.label_center(gr.ilo-2, r"$\mathrm{lo-2}$") 35 | 36 | gr.label_center(gr.ihi, r"$\mathrm{hi}$") 37 | gr.label_center(gr.ihi+1, r"$\mathrm{hi+1}$") 38 | gr.label_center(gr.ihi+2, r"$\mathrm{hi+2}$") 39 | 40 | gr.label_edge(ng+nzones//2, r"$i-\sfrac{1}{2}$") 41 | gr.label_edge(ng+nzones//2+1, r"$i+\sfrac{1}{2}$") 42 | 43 | # draw the data 44 | for i in range(nzones): 45 | cc.draw_cell_avg(ng+i, color="r") 46 | 47 | cc.label_cell_avg(ng+nzones//2, r"$\langle a\rangle_i$", color="r") 48 | 49 | # label dx 50 | gr.label_dx(gr.ng+nzones//2) 51 | 52 | gr.clean_axes(show_ghost=True, pad_fac=0.02, ylim=(-0.5, 1.6)) 53 | 54 | f = plt.gcf() 55 | f.set_size_inches(10.0,2.5) 56 | 57 | plt.savefig("fv_ghost.pdf") 58 | -------------------------------------------------------------------------------- /figures/advection/generalgrid.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | 7 | nzones = 7 8 | 9 | # data that lives on the grid 10 | ainit = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5]) 11 | 12 | gr = gp.FVGrid(nzones) 13 | a = gr.scratch_array() 14 | a[gr.ilo:gr.ihi+1] = ainit[:] 15 | 16 | pl_nolim = gp.PiecewiseLinear(gr, a, nolimit=1) 17 | pl = gp.PiecewiseLinear(gr, a) 18 | 19 | gr.draw_grid() 20 | 21 | gr.label_center(nzones//2, r"$i$") 22 | gr.label_center(nzones//2-1, r"$i-1$") 23 | gr.label_center(nzones//2+1, r"$i+1$") 24 | gr.label_center(nzones//2-2, r"$i-2$") 25 | gr.label_center(nzones//2+2, r"$i+2$") 26 | 27 | #labelEdge(gr, nzones//2, r"$i-1/2$") 28 | #labelEdge(gr, nzones//2+1, r"$i+1/2$") 29 | 30 | for n in range(nzones): 31 | pl.draw_cell_avg(n, ls=":", color="0.5") 32 | pl_nolim.draw_slope(n, color="0.5") 33 | pl.draw_slope(n, color="r") 34 | 35 | gr.clean_axes(ylim=(-0.25, 1.2)) 36 | 37 | f = plt.gcf() 38 | f.set_size_inches(8.0,2.0) 39 | 40 | plt.savefig("generalgrid.pdf") 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /figures/advection/rea.py: -------------------------------------------------------------------------------- 1 | # reconstruct - evolve - average 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | import grid_plot as gp 6 | 7 | 8 | #----------------------------------------------------------------------------- 9 | 10 | atemp = np.array([1.0, 1.0, 0.9, 0.8, 0.25, 0.1, 0.1, 0.1]) 11 | nzones = len(atemp) 12 | 13 | # CFL number 14 | C = 0.6 15 | 16 | 17 | gr = gp.FVGrid(nzones, ng=4) 18 | 19 | a = gr.scratch_array() 20 | a[gr.ilo:gr.ihi+1] = atemp[:] 21 | 22 | pl = gp.PiecewiseLinear(gr, a) 23 | pl.fill_zero_gradient() 24 | 25 | 26 | #----------------------------------------------------------------------------- 27 | # first frame -- the original cell-averages 28 | 29 | plt.clf() 30 | 31 | gr.draw_grid() 32 | 33 | labels = ["$i-2$", "$i-1$", "$i$", "$i+1$", "$i+2$"] 34 | indices = [gr.ng+nzones//2-2, gr.ng+nzones//2-1, 35 | gr.ng+nzones//2, gr.ng+nzones//2+1, gr.ng+nzones//2+2] 36 | 37 | for i, l in zip(indices, labels): 38 | gr.label_center(i, l) 39 | 40 | # draw cell averages 41 | for n in range(gr.ilo, gr.ihi+1): 42 | pl.draw_cell_avg(n, color="r") 43 | 44 | gr.clean_axes(ylim=(-0.25, 1.2)) 45 | 46 | f = plt.gcf() 47 | f.set_size_inches(8.0,2.0) 48 | 49 | plt.savefig("rea-start.pdf") 50 | 51 | 52 | #----------------------------------------------------------------------------- 53 | # second frame -- reconstruction 54 | 55 | plt.clf() 56 | 57 | gr.draw_grid() 58 | 59 | for i, l in zip(indices, labels): 60 | gr.label_center(i, l) 61 | 62 | # draw cell averages and slopes 63 | for n in range(gr.ilo, gr.ihi+1): 64 | pl.draw_cell_avg(n, color="0.5", ls=":") 65 | pl.draw_slope(n, color="r") 66 | 67 | 68 | gr.clean_axes(ylim=(-0.25, 1.2)) 69 | 70 | f = plt.gcf() 71 | f.set_size_inches(8.0,2.0) 72 | 73 | plt.savefig("rea-reconstruction.pdf") 74 | 75 | 76 | #----------------------------------------------------------------------------- 77 | # third frame -- shade the portion that will come into the cell 78 | 79 | plt.clf() 80 | 81 | gr.draw_grid() 82 | 83 | for i, l in zip(indices, labels): 84 | gr.label_center(i, l) 85 | 86 | # draw cell averages and slopes 87 | for n in range(gr.ilo, gr.ihi+1): 88 | pl.draw_slope(n, color="r") 89 | 90 | 91 | # shade regions 92 | ii = gr.ng + nzones//2-1 93 | pl.slope_trace_left(ii, C, color="0.75") 94 | pl.slope_trace_right(ii+1, 1.0-C, color="0.75") 95 | 96 | gr.clean_axes(ylim=(-0.25, 1.2)) 97 | 98 | f = plt.gcf() 99 | f.set_size_inches(8.0,2.0) 100 | 101 | plt.savefig("rea-trace.pdf") 102 | 103 | 104 | #----------------------------------------------------------------------------- 105 | # fourth frame -- evolve 106 | 107 | plt.clf() 108 | 109 | gr.draw_grid() 110 | 111 | for i, l in zip(indices, labels): 112 | gr.label_center(i, l) 113 | 114 | # draw cell averages and slopes 115 | for n in range(gr.ilo, gr.ihi+1): 116 | pl.draw_slope(n, color="0.75", ls=":") 117 | pl.evolve_to_right(n, C, color="r") 118 | 119 | gr.clean_axes(ylim=(-0.25, 1.2)) 120 | 121 | f = plt.gcf() 122 | f.set_size_inches(8.0,2.0) 123 | 124 | plt.savefig("rea-evolve.pdf") 125 | 126 | 127 | #----------------------------------------------------------------------------- 128 | # fifth frame -- re-average 129 | 130 | # left states (we don't need the right state when u > 0) 131 | al = np.zeros(2*gr.ng + gr.nx, dtype=np.float64) 132 | 133 | for n in range(gr.ilo, gr.ihi+2): 134 | al[n] = a[n-1] + 0.5*(1 - C)*pl.slope[n-1] 135 | 136 | # the Riemann problem just picks the right state. Do a conservative 137 | # update 138 | anew = gr.scratch_array() 139 | 140 | anew[gr.ilo:gr.ihi+1] = a[gr.ilo:gr.ihi+1] + \ 141 | C*(al[gr.ilo:gr.ihi+1] - al[gr.ilo+1:gr.ihi+2]) 142 | 143 | 144 | plt.clf() 145 | 146 | gr.draw_grid() 147 | 148 | for i, l in zip(indices, labels): 149 | gr.label_center(i, l) 150 | 151 | 152 | # show the evolved profiles from the old time 153 | for n in range(gr.ilo, gr.ihi+1): 154 | pl.evolve_to_right(n, C, color="0.5", ls=":") 155 | 156 | 157 | pl.a[:] = anew[:] 158 | pl.fill_zero_gradient() 159 | pl.calculate_slopes() 160 | 161 | for n in range(pl.gr.ilo, pl.gr.ihi+1): 162 | pl.draw_cell_avg(n, color="r") 163 | 164 | 165 | gr.clean_axes(ylim=(-0.25, 1.2)) 166 | 167 | f = plt.gcf() 168 | f.set_size_inches(8.0,2.0) 169 | 170 | plt.savefig("rea-final.pdf") 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /figures/advection/riemann.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pylab as plt 3 | import grid_plot as gp 4 | 5 | def riemann(with_time=True): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 2 12 | ng = 0 13 | 14 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 15 | 16 | plt.clf() 17 | 18 | #------------------------------------------------------------------------ 19 | # plot a domain without ghostcells 20 | gr.draw_grid() 21 | 22 | gr.label_center(0, r"$i$", fontsize="medium") 23 | gr.label_center(1, r"$i+1$", fontsize="medium") 24 | 25 | gr.label_edge(1, r"$i+\myhalf$", fontsize="medium") 26 | 27 | 28 | plt.arrow(gr.xc[0]+0.05*gr.dx, 0.5, 0.12*gr.dx, 0, 29 | shape='full', head_width=0.05, head_length=0.025, 30 | lw=1, width=0.02, 31 | edgecolor="none", facecolor="r", 32 | length_includes_head=True, zorder=100) 33 | 34 | plt.arrow(gr.xc[1]-0.1*gr.dx, 0.5, -0.12*gr.dx, 0, 35 | shape='full', head_width=0.05, head_length=0.025, 36 | lw=1, width=0.02, 37 | edgecolor="none", facecolor="r", 38 | length_includes_head=True, zorder=100) 39 | 40 | if with_time: 41 | gr.mark_cell_left_state(1, r"$a_{i+\myhalf,R}^{n+\myhalf}$", fontsize="large", 42 | color="b") 43 | gr.mark_cell_right_state(0, r"$a_{i+\myhalf,L}^{n+\myhalf}$", fontsize="large", 44 | color="b") 45 | else: 46 | gr.mark_cell_left_state(1, r"$a_{i+\myhalf,R}$", fontsize="large", 47 | color="b") 48 | gr.mark_cell_right_state(0, r"$a_{i+\myhalf,L}$", fontsize="large", 49 | color="b") 50 | 51 | gr.label_cell_center(0, r"$a_i$") 52 | gr.label_cell_center(1, r"$a_{i+1}$") 53 | 54 | 55 | gr.clean_axes(pad_fac=0.125, ylim=(-0.25, 1.0)) 56 | 57 | f = plt.gcf() 58 | f.set_size_inches(7.0,2.0) 59 | 60 | plt.tight_layout() 61 | 62 | if with_time: 63 | plt.savefig("riemann-adv.pdf") 64 | else: 65 | plt.savefig("riemann-adv-mol.pdf") 66 | 67 | if __name__== "__main__": 68 | riemann() 69 | riemann(with_time=False) 70 | -------------------------------------------------------------------------------- /figures/advection/riemann_bc.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def riemann(): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 4 12 | ng = 2 13 | 14 | gr = gp.FVGrid(nzones, ng=ng, xmin=xmin, xmax=xmax) 15 | 16 | # interior and ghost cell initialization 17 | a = gr.scratch_array() 18 | 19 | a[gr.ilo:gr.ihi+1] = np.array([0.8, 0.4, 0.3, 0.5]) 20 | a[0:gr.ilo] = a[gr.ihi-1:gr.ihi+1] 21 | a[gr.ihi:2*gr.ng+gr.nx] = a[gr.ihi] 22 | 23 | pc = gp.PiecewiseConstant(gr, a) 24 | pl = gp.PiecewiseLinear(gr, a, nolimit=1) 25 | 26 | 27 | 28 | #------------------------------------------------------------------------ 29 | # plot a domain without ghostcells 30 | gr.draw_grid(draw_ghost=1, emphasize_end=1) 31 | 32 | gr.label_center(gr.ng-2, r"$\mathrm{lo-2}$", fontsize="medium") 33 | gr.label_center(gr.ng-1, r"$\mathrm{lo-1}$", fontsize="medium") 34 | gr.label_center(gr.ng, r"$\mathrm{lo}$", fontsize="medium") 35 | gr.label_center(gr.ng+1, r"$\mathrm{lo+1}$", fontsize="medium") 36 | 37 | gr.label_edge(gr.ng, r"$\mathrm{lo}-\myhalf$", fontsize="medium") 38 | 39 | # draw cell averages 40 | for n in range(0, gr.ng+gr.nx-1): 41 | pc.draw_cell_avg(n, color="0.5", ls=":") 42 | 43 | 44 | # draw slopes 45 | for n in range(gr.ilo-1, gr.ihi): 46 | pl.draw_slope(n, color="r") 47 | 48 | 49 | # compute the states to the left and right of lo-1/2 50 | C = 0.5 # CFL 51 | print(a) 52 | print(pl.slope) 53 | al = a[gr.ilo-1] + 0.5*(1.0 - C)*pl.slope[gr.ilo-1] 54 | ar = a[gr.ilo] - 0.5*(1.0 + C)*pl.slope[gr.ilo] 55 | 56 | # L 57 | gr.mark_cell_right_state(ng-1, r"$a_{\mathrm{lo}-\myhalf,L}^{n+\myhalf}$", 58 | value=al, vertical="center", color="b") 59 | 60 | # R 61 | gr.mark_cell_left_state(ng, r"$a_{\mathrm{lo}-\myhalf,R}^{n+\myhalf}$", 62 | value=ar, vertical="top", color="b") 63 | 64 | 65 | plt.xlim(gr.xl[0]-0.025*gr.dx,gr.xr[ng+1]+0.15*gr.dx) 66 | plt.ylim(-0.25, 1.1) 67 | plt.axis("off") 68 | 69 | plt.subplots_adjust(left=0.025,right=0.95,bottom=0.05,top=0.95) 70 | 71 | f = plt.gcf() 72 | f.set_size_inches(8.0,2.0) 73 | 74 | plt.tight_layout() 75 | 76 | plt.savefig("riemann-bc.pdf") 77 | 78 | if __name__== "__main__": 79 | riemann() 80 | -------------------------------------------------------------------------------- /figures/advection/riemann_mol.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def riemann(): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 4 12 | ng = 2 13 | 14 | gr = gp.FVGrid(nzones, ng=ng, xmin=xmin, xmax=xmax) 15 | 16 | # interior and ghost cell initialization 17 | a = gr.scratch_array() 18 | 19 | a[gr.ilo:gr.ihi+1] = np.array([0.8, 0.7, 0.4, 0.5]) 20 | a[0:gr.ilo] = a[gr.ihi-1:gr.ihi+1] 21 | a[gr.ihi:2*gr.ng+gr.nx] = a[gr.ihi] 22 | 23 | pc = gp.PiecewiseConstant(gr, a) 24 | pl = gp.PiecewiseLinear(gr, a, nolimit=1) 25 | 26 | 27 | 28 | #------------------------------------------------------------------------ 29 | # plot a domain without ghostcells 30 | gr.draw_grid(draw_ghost=0, emphasize_end=0) 31 | 32 | zi = gr.ilo+1 33 | 34 | gr.label_center(zi-1, r"${i-1}$", fontsize="medium") 35 | gr.label_center(zi, r"${i}$", fontsize="medium") 36 | gr.label_center(zi+1, r"${i+1}$", fontsize="medium") 37 | 38 | gr.label_edge(zi+1, r"${i}+\myhalf$", fontsize="medium") 39 | 40 | # draw cell averages 41 | for n in range(gr.ilo, gr.ihi+1): 42 | pc.draw_cell_avg(n, color="0.5", ls=":") 43 | 44 | 45 | # draw slopes 46 | for n in range(gr.ilo, gr.ihi+1): 47 | pl.draw_slope(n, color="r") 48 | 49 | # compute the states to the left and right of lo-1/2 50 | al = a[zi] + 0.5*pl.slope[zi] 51 | ar = a[zi+1] - 0.5*pl.slope[zi+1] 52 | 53 | # L 54 | gr.mark_cell_right_state(zi, r"$q_{i+\myhalf,L}$", 55 | value=al, vertical="top", color="b", zorder=100) 56 | 57 | # R 58 | gr.mark_cell_left_state(zi+1, r"$q_{i+\myhalf,R}$", 59 | value=ar, vertical="top", color="b", zorder=100) 60 | 61 | 62 | plt.xlim(gr.xl[gr.ilo]-0.025*gr.dx, gr.xr[gr.ihi]+0.15*gr.dx) 63 | plt.ylim(-0.25, 1.1) 64 | plt.axis("off") 65 | 66 | plt.subplots_adjust(left=0.025,right=0.95,bottom=0.05,top=0.95) 67 | 68 | f = plt.gcf() 69 | f.set_size_inches(8.0,2.0) 70 | 71 | plt.tight_layout() 72 | 73 | plt.savefig("riemann-mol.pdf") 74 | 75 | if __name__== "__main__": 76 | riemann() 77 | -------------------------------------------------------------------------------- /figures/advection/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEST=../../advection 4 | 5 | # characteristics.py makes advection-characteristics.pdf 6 | python3 characteristics.py 7 | cp -f advection-characteristics.pdf ${DEST} 8 | 9 | # fd_ghost.py makes fd_ghost.pdf 10 | python3 fd_ghost.py 11 | cp -f fd_ghost.pdf ${DEST} 12 | 13 | # hydro_examples: fdadvect.py makes fdadvect-upwind.pdf 14 | 15 | 16 | # hydro_examples: fdadvect.py makes fdadvect-FTCS-C0_1.pdf, fdadvect-FTCS-C0_5.pdf 17 | 18 | 19 | # hydro_examples: fdadvect_implicit.py makes fdadvect-implicit.pdf 20 | 21 | 22 | # fv_ghost.py makes fv_ghost.pdf 23 | python3 fv_ghost.py 24 | cp -f fv_ghost.pdf ${DEST} 25 | 26 | # riemann.py makes riemann-adv.pdf 27 | python3 riemann.py 28 | cp -f riemann-adv.pdf ${DEST} 29 | 30 | # riemann_bc.py makes riemamm-bc.pdf 31 | python3 riemann_bc.py 32 | cp -f riemann-bc.pdf ${DEST} 33 | 34 | # hydro_examples: fv-advection.py makes fv-advect.pdf 35 | 36 | 37 | # rea-limitex.py makes rea*.pdf 38 | python3 rea-limitex.py 39 | cp -f rea*start_???.pdf ${DEST} 40 | 41 | # generalgrid.py makes generalgrid.pdf 42 | python3 generalgrid.py 43 | cp -f generalgrid.pdf ${DEST} 44 | 45 | # rea.py makes rea-*.pdf 46 | python3 rea.py 47 | cp -f rea-final.pdf rea-evolve.pdf rea-trace.pdf rea-reconstruction.pdf rea-start.pdf ${DEST} 48 | 49 | # hydro_examples: advection.py makes plm-converge.pdf, fv-gaussian-limiters.pdf fv-tophat-limiters.pdf 50 | 51 | 52 | # 2dgrid.py makes 2dgrid.pdf 53 | python3 2dgrid.py 54 | cp -f 2dgrid.pdf ${DEST} 55 | 56 | # 2dgrid_hat.py makes 2dgrid-hat.pdf 57 | python3 2dgrid_hat.py 58 | cp -f 2dgrid-hat.pdf ${DEST} 59 | 60 | # 2dgrid_transverse.py makes 2dgrid-transverse.pdf 61 | python3 2dgrid_transverse.py 62 | cp -f 2dgrid-transverse.pdf ${DEST} 63 | 64 | # pyro makes smooth_init.pdf smooth_final.pdf tophat_init.pdf tophat_final.pdf 65 | # tophat_rk4_cfl*.pdf 66 | 67 | -------------------------------------------------------------------------------- /figures/burgers/characteristics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib as mpl 3 | import matplotlib.pyplot as plt 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | 9 | def fun(x): 10 | state = np.zeros_like(x) 11 | state[x < 0.5] = 1.0 12 | return state 13 | 14 | def funs(x): 15 | state = 0.5 + 0.25*np.sin(2.0*np.pi*x) 16 | return state 17 | 18 | def funr(x): 19 | state = np.ones_like(x) 20 | state[x < 0.5] = 0.2 21 | return state 22 | 23 | def make_plot(icfun=None, label=""): 24 | 25 | npts_plot = 1000 26 | xplot = np.linspace(0.0, 1.0, npts_plot) 27 | 28 | nchar = 20 29 | xchar = np.linspace(0.0, 1.0, nchar) 30 | 31 | state = icfun(xplot) 32 | print(type(state)) 33 | 34 | plt.clf() 35 | 36 | plt.subplot(211) 37 | 38 | plt.plot(xplot, state, lw=2) 39 | 40 | 41 | ax = plt.gca() 42 | ax.spines['right'].set_visible(False) 43 | ax.spines['top'].set_visible(False) 44 | ax.spines['right'].set_visible(False) 45 | ax.spines['top'].set_visible(False) 46 | ax.spines['right'].set_visible(False) 47 | ax.spines['top'].set_visible(False) 48 | ax.xaxis.set_ticks_position('bottom') 49 | ax.yaxis.set_ticks_position('left') 50 | 51 | plt.ylim(-0.1, 1.1) 52 | 53 | plt.xlabel(r"$x$", fontsize="large") 54 | plt.ylabel(r"$u$", fontsize="large") 55 | 56 | 57 | 58 | plt.subplot(212) 59 | 60 | uchar = icfun(xchar) 61 | t = np.linspace(0.0, 1.0, 100) 62 | for n in range(nchar): 63 | xc = xchar[n] + uchar[n]*t 64 | plt.plot(xc, t, color="0.5") 65 | 66 | ax = plt.gca() 67 | ax.spines['right'].set_visible(False) 68 | ax.spines['top'].set_visible(False) 69 | ax.spines['right'].set_visible(False) 70 | ax.spines['top'].set_visible(False) 71 | ax.spines['right'].set_visible(False) 72 | ax.spines['top'].set_visible(False) 73 | ax.xaxis.set_ticks_position('bottom') 74 | ax.yaxis.set_ticks_position('left') 75 | 76 | plt.xlabel(r"$x$", fontsize="large") 77 | plt.ylabel(r"$t$", fontsize="large") 78 | 79 | plt.xlim(0.0, 1.0) 80 | plt.ylim(0.0, 1.1) 81 | 82 | f = plt.gcf() 83 | f.set_size_inches(6.0, 8.0) 84 | 85 | plt.tight_layout() 86 | 87 | plt.savefig(f"burgers-characteristics-{label}.png") 88 | 89 | if __name__ == "__main__": 90 | 91 | make_plot(funr, "rare") 92 | make_plot(funs, "shock") 93 | -------------------------------------------------------------------------------- /figures/burgers/rh.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pylab as plt 3 | import matplotlib as mpl 4 | 5 | mpl.rcParams['mathtext.fontset'] = 'cm' 6 | mpl.rcParams['mathtext.rm'] = 'serif' 7 | 8 | mpl.rcParams['font.size'] = 12 9 | mpl.rcParams['legend.fontsize'] = 'large' 10 | mpl.rcParams['figure.titlesize'] = 'medium' 11 | 12 | def rh(): 13 | 14 | # grid info 15 | xl = 0.0 16 | xr = 1.0 17 | 18 | dx = xr - xl 19 | 20 | xc = 0.5*(xl + xr) 21 | 22 | t0 = 0.0 23 | t1 = 1.0 24 | 25 | dt = t1 - t0 26 | 27 | # plot a square representing [x, x+dx] x [t, t+dt] 28 | 29 | # x-axis 30 | plt.arrow(0, 0, 1.3*dx, 0, 31 | shape="full", head_width=0.04, head_length=0.06, 32 | lw=1, width=0.005, 33 | facecolor="k", 34 | length_includes_head=True, zorder=100) 35 | 36 | plt.text(1.35*dx, 0, r"$x$", fontsize=20, verticalalignment="center") 37 | 38 | plt.text(dx, -0.1, r"$x_r$", fontsize=20) 39 | plt.text(0, -0.1, r"$x_l$", fontsize=20) 40 | 41 | # time axis 42 | plt.arrow(0, 0, 0, 1.3*dt, 43 | shape="full", head_width=0.04, head_length=0.06, 44 | lw=1, width=0.005, 45 | facecolor="k", 46 | length_includes_head=True, zorder=100) 47 | 48 | plt.text(0, 1.35*dt, r"$t$", fontsize=20, horizontalalignment="center") 49 | 50 | plt.text(-0.17, dt, r"$t^{n+1}$", fontsize=20) 51 | plt.text(-0.17, 0, r"$t^n$", fontsize=20) 52 | 53 | 54 | # space-time volume 55 | plt.plot([dx,dx], [0,dt], ls="--", color="0.5", lw=2) 56 | plt.plot([0,dx], [dt,dt], ls="--", color="0.5", lw=2) 57 | 58 | 59 | # diagonal representing S 60 | plt.plot([0,dx], [0,dt], color="k", lw=5, solid_capstyle="butt") 61 | 62 | plt.annotate(r"shock: $S = \Delta x / \Delta t$", xy=(0.74*dx,0.76*dt), 63 | xytext=(0.2*dx, 1.2*dt), textcoords="data", 64 | fontsize=18, 65 | arrowprops=dict(arrowstyle="->", 66 | connectionstyle="arc3,rad=.2")) 67 | 68 | # states 69 | plt.text(0.66*dx, 0.33*dt, r"$u_r$", color="k", fontsize=20) 70 | plt.text(0.33*dx, 0.66*dt, r"$u_l$", color="k", fontsize=20) 71 | 72 | 73 | # fluxes 74 | plt.arrow(-0.1*dx, 0.5*dt, 0.2*dx, 0, 75 | shape="full", head_width=0.04, head_length=0.06, 76 | lw=1, width=0.005, 77 | edgecolor="r", facecolor="r", 78 | length_includes_head=True, zorder=100) 79 | 80 | plt.text(-0.12*dx, 0.5*dt, r"$f = f(u_l)$", 81 | horizontalalignment="right", 82 | verticalalignment="center", color="r", fontsize=18) 83 | 84 | plt.arrow(0.9*dx, 0.5*dt, 0.2*dx, 0, 85 | shape="full", head_width=0.04, head_length=0.06, 86 | lw=1, width=0.005, 87 | edgecolor="r", facecolor="r", 88 | length_includes_head=True, zorder=100) 89 | 90 | plt.text(1.12*dx, 0.5*dt, r"$f = f(u_r)$", 91 | horizontalalignment="left", 92 | verticalalignment="center", color="r", fontsize=18) 93 | 94 | 95 | plt.axis("off") 96 | 97 | plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) 98 | 99 | plt.xlim(-0.4,1.4*dx) 100 | plt.ylim(-0.1,1.4*dx) 101 | 102 | f = plt.gcf() 103 | f.set_size_inches(7.0,6.0) 104 | 105 | plt.savefig("rh.pdf") 106 | 107 | 108 | if __name__== "__main__": 109 | rh() 110 | -------------------------------------------------------------------------------- /figures/burgers/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEST=../../burgers 4 | 5 | # characteristics.py makes burgers-characteristics.pdf 6 | python3 characteristics.py 7 | cp -f burgers-characteristics.pdf ${DEST} 8 | 9 | # rh.py makes rh.pdf 10 | python3 rh.py 11 | cp -f rh.pdf ${DEST} 12 | 13 | # hydro_examples: burgers.py makes fv-burger-rarefaction.pdf fv-burger-sine.pdf 14 | 15 | -------------------------------------------------------------------------------- /figures/finite-volume/ccfd.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import grid_plot as gp 5 | 6 | # plot a simple finite-difference grid 7 | 8 | #----------------------------------------------------------------------------- 9 | 10 | nzones = 8 11 | 12 | # data that lives on the grid 13 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 14 | a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 15 | 16 | gr = gp.FVGrid(nzones) 17 | 18 | 19 | plt.clf() 20 | 21 | gr.draw_grid() 22 | 23 | gr.label_center(nzones//2, r"$i$", fontsize="medium") 24 | gr.label_center(nzones//2-1, r"$i-1$", fontsize="medium") 25 | gr.label_center(nzones//2+1, r"$i+1$", fontsize="medium") 26 | gr.label_center(nzones//2-2, r"$i-2$", fontsize="medium") 27 | gr.label_center(nzones//2+2, r"$i+2$", fontsize="medium") 28 | 29 | 30 | cc = gp.CellCentered(gr, a) 31 | 32 | # draw the data 33 | for i in range(nzones): 34 | cc.draw_data_point(i, color="r") 35 | 36 | 37 | cc.label_data_point(nzones//2, r"$f_i$", color="r") 38 | 39 | # label dx 40 | gr.label_center_dx(gr.ng+nzones//2) 41 | 42 | gr.clean_axes(ylim=(-0.5, 1.2)) 43 | 44 | f = plt.gcf() 45 | f.set_size_inches(10.0,3.0) 46 | 47 | plt.savefig("ccfd_grid.pdf") 48 | -------------------------------------------------------------------------------- /figures/finite-volume/discretizations.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/figures/finite-volume/discretizations.odg -------------------------------------------------------------------------------- /figures/finite-volume/domain.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | 3 | def draw_box(ll, uu, nx, ny, gridColor="0.5", ng=0): 4 | 5 | # draw the frame 6 | plt.plot([ll[0], ll[0], uu[0], uu[0], ll[0]], 7 | [ll[1], uu[1], uu[1], ll[1], ll[1]], color="k", lw=2) 8 | 9 | # draw the x grid lines 10 | dx = (uu[0] - ll[0])/nx 11 | for n in range(1, nx): 12 | plt.plot([ll[0]+n*dx, ll[0]+n*dx], 13 | [ll[1], uu[1]], color=gridColor, ls=":", lw=1) 14 | 15 | # draw the y grid lines 16 | dy = (uu[1] - ll[1])/ny 17 | for n in range(1, ny): 18 | plt.plot([ll[0], uu[0]], 19 | [ll[1]+n*dy, ll[1]+n*dy], color=gridColor, ls=":", lw=1) 20 | 21 | # ghostcells? 22 | if ng > 0: 23 | xmin = ll[0]-ng*dx 24 | xmax = uu[0]+ng*dx 25 | ymin = ll[1]-ng*dy 26 | ymax = uu[1]+ng*dy 27 | plt.plot([xmin, xmin, xmax, xmax, xmin], 28 | [ymin, ymax, ymax, ymin, ymin], 29 | ls="--", color="r") 30 | 31 | 32 | plt.clf() 33 | 34 | draw_box([0., 0.], [1., 1.], 5, 5, ng=1) 35 | draw_box([1., 0.], [2., 1.], 5, 5) 36 | draw_box([2., 0.], [3., 1.], 5, 5) 37 | 38 | draw_box([0., 1.], [1., 2.], 5, 5) 39 | draw_box([1., 1.], [2., 2.], 5, 5) 40 | draw_box([2., 1.], [3., 2.], 5, 5) 41 | 42 | plt.xlim(-0.25,3.25) 43 | plt.ylim(-0.25,2.25) 44 | 45 | a = plt.gca() 46 | a.set_aspect("equal", "datalim") 47 | plt.axis("off") 48 | 49 | f = plt.gcf() 50 | f.set_size_inches(7.0,4.25) 51 | 52 | 53 | plt.savefig("domain.pdf", bbox_inches="tight") 54 | 55 | 56 | -------------------------------------------------------------------------------- /figures/finite-volume/fd.py: -------------------------------------------------------------------------------- 1 | 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import grid_plot as gp 5 | 6 | # plot a simple finite-difference grid 7 | 8 | #----------------------------------------------------------------------------- 9 | 10 | nzones = 8 11 | 12 | # data that lives on the grid 13 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 14 | a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 15 | 16 | gr = gp.FDGrid(nzones) 17 | 18 | 19 | plt.clf() 20 | 21 | gr.draw_grid() 22 | 23 | gr.label_node(nzones//2, r"$i$", fontsize="medium") 24 | gr.label_node(nzones//2-1, r"$i-1$", fontsize="medium") 25 | gr.label_node(nzones//2+1, r"$i+1$", fontsize="medium") 26 | gr.label_node(nzones//2-2, r"$i-2$", fontsize="medium") 27 | gr.label_node(nzones//2+2, r"$i+2$", fontsize="medium") 28 | 29 | 30 | # draw the data 31 | for i in range(nzones): 32 | gr.draw_data(i, a[i], color="r") 33 | 34 | 35 | gr.label_value(nzones//2, a[nzones//2], r"$f_i$", color="r") 36 | 37 | # label dx 38 | gr.label_dx(gr.ng+nzones//2) 39 | 40 | gr.clean_axes(ylim=(-0.5, 1.2)) 41 | 42 | f = plt.gcf() 43 | f.set_size_inches(10.0,3.0) 44 | 45 | plt.savefig("fd_grid.pdf") 46 | -------------------------------------------------------------------------------- /figures/finite-volume/fv.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | 6 | 7 | # plot a simple finite-difference grid 8 | 9 | #----------------------------------------------------------------------------- 10 | 11 | nzones = 8 12 | 13 | # data that lives on the grid 14 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 15 | a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.5, 0.55]) 16 | 17 | gr = gp.FVGrid(nzones) 18 | 19 | pc = gp.PiecewiseConstant(gr, a) 20 | 21 | plt.clf() 22 | 23 | gr.draw_grid() 24 | 25 | gr.label_center(nzones//2, r"$i$", fontsize="medium") 26 | gr.label_center(nzones//2-1, r"$i-1$", fontsize="medium") 27 | gr.label_center(nzones//2+1, r"$i+1$", fontsize="medium") 28 | gr.label_center(nzones//2-2, r"$i-2$", fontsize="medium") 29 | gr.label_center(nzones//2+2, r"$i+2$", fontsize="medium") 30 | 31 | gr.label_edge(nzones//2, r"$i-\sfrac{1}{2}$", fontsize="small") 32 | gr.label_edge(nzones//2+1, r"$i+\sfrac{1}{2}$", fontsize="small") 33 | 34 | # draw the data 35 | for i in range(nzones): 36 | pc.draw_cell_avg(i, color="r", filled=True) 37 | 38 | pc.label_cell_avg(nzones//2, r"$\langle f\rangle_i$", color="r") 39 | 40 | # label dx 41 | gr.label_dx(gr.ng+nzones//2) 42 | 43 | gr.clean_axes(ylim=(-0.5, 1.2)) 44 | 45 | f = plt.gcf() 46 | f.set_size_inches(10.0,3.0) 47 | 48 | plt.savefig("fv_grid.pdf") 49 | -------------------------------------------------------------------------------- /figures/finite-volume/simplegrid2.py: -------------------------------------------------------------------------------- 1 | import math 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import grid_plot as gp 5 | 6 | def simplegrid(): 7 | 8 | nzones = 7 9 | 10 | gr = gp.FVGrid(nzones, xmin=0, xmax=1) 11 | 12 | gr.draw_grid(edge_ticks=0) 13 | 14 | # label a few cell-centers 15 | gr.label_center(nzones/2, r"$i$") 16 | gr.label_center(nzones/2-1, r"$i-1$") 17 | gr.label_center(nzones/2+1, r"$i+1$") 18 | 19 | # label a few edges 20 | gr.label_edge(nzones/2, r"$i-1/2$") 21 | gr.label_edge(nzones/2+1, r"$i+1/2$") 22 | 23 | # sample data 24 | A = 0.4 25 | a = A*np.ones(nzones, dtype=np.float64) 26 | 27 | pc = gp.PiecewiseConstant(gr, a) 28 | 29 | # draw an average quantity 30 | pc.draw_cell_avg(nzones/2, color="r") 31 | pc.label_cell_avg(nzones/2, r"$\,\langle a \rangle_i$", color="r") 32 | 33 | gr.clean_axes() 34 | plt.ylim(-0.25, 1.5) 35 | 36 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 37 | 38 | f = plt.gcf() 39 | f.set_size_inches(10.0,2.5) 40 | 41 | plt.savefig("simplegrid2.png") 42 | plt.savefig("simplegrid2.pdf") 43 | 44 | if __name__== "__main__": 45 | simplegrid() 46 | -------------------------------------------------------------------------------- /figures/finite-volume/simplegrid_gc.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def simplegrid(): 6 | 7 | # grid info 8 | nzones = 7 9 | ng = 1 10 | 11 | gr = gp.FVGrid(nzones, ng, xmin=0.0, xmax=1.0) 12 | 13 | gr.draw_grid(emphasize_end=1, edge_ticks=0, draw_ghost=1) 14 | 15 | # label a few 16 | gr.label_center(ng+nzones//2, r"$i$", fontsize="medium") 17 | gr.label_center(ng+nzones//2-1, r"$i-1$", fontsize="medium") 18 | gr.label_center(ng+nzones//2+1, r"$i+1$", fontsize="medium") 19 | 20 | gr.label_center(ng-1, r"$\mathrm{lo}-1$", fontsize="medium") 21 | gr.label_center(ng, r"$\mathrm{lo}$", fontsize="medium") 22 | gr.label_center(ng+nzones-1, r"$\mathrm{hi}$", fontsize="medium") 23 | gr.label_center(ng+nzones, r"$\mathrm{hi+1}$", fontsize="medium") 24 | 25 | 26 | # label dx 27 | gr.label_dx(ng+nzones//2-2) 28 | 29 | 30 | gr.clean_axes(show_ghost=True, ylim=(-0.5, 1.5), padding=True, pad_fac=0.05) 31 | #plt.xlim(gr.xl[0]-0.05*gr.dx,gr.xr[2*ng+nzones-1]+0.25*gr.dx) 32 | #plt.ylim(-0.5, 1.5) 33 | #plt.axis("off") 34 | 35 | #plt.subplots_adjust(left=0.025,right=0.95,bottom=0.05,top=0.95) 36 | 37 | f = plt.gcf() 38 | f.set_size_inches(10.0,2.5) 39 | 40 | plt.tight_layout() 41 | 42 | plt.savefig("simplegrid_gc.pdf", bbox_inches="tight") 43 | 44 | 45 | if __name__== "__main__": 46 | simplegrid() 47 | -------------------------------------------------------------------------------- /figures/finite-volume/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # fd.py creates fd_grid.pdf 4 | python3 fd.py 5 | cp -f fd_grid.pdf ../../finite-volume/ 6 | 7 | # ccfd.py creates ccfd_grid.pdf 8 | python3 ccfd.py 9 | cp -f ccfd_grid.pdf ../../finite-volume/ 10 | 11 | # fv.py creates fv_grid.pdf 12 | python3 fv.py 13 | cp -f fv_grid.pdf ../../finite-volume/ 14 | 15 | # simplegrid_gc.py creates simplegrid_gc.pdf 16 | python3 simplegrid_gc.py 17 | cp -f simplegrid_gc.pdf ../../finite-volume/ 18 | 19 | # domain.py creates domain.pdf 20 | python3 domain.py 21 | cp -r domain.pdf ../../finite-volume/ 22 | -------------------------------------------------------------------------------- /figures/gridFigs/fdrestrict.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | # plot two stacked fv grids of different (2x) resolution to show prolongation 6 | 7 | #----------------------------------------------------------------------------- 8 | 9 | nf = 5 10 | nc = 3 11 | 12 | grf = gp.FDGrid(nf, voff=2.0) 13 | grc = gp.FDGrid(nc) 14 | 15 | plt.clf() 16 | 17 | grf.draw_grid() 18 | grc.draw_grid() 19 | 20 | grf.label_node(nf/2-2, r"$i-2$") 21 | grf.label_node(nf/2-1, r"$i-1$") 22 | grf.label_node(nf/2, r"$i$") 23 | grf.label_node(nf/2+1, r"$i+1$") 24 | grf.label_node(nf/2+2, r"$i+2$") 25 | 26 | 27 | grc.label_node(nc/2-1, r"$j-1$") 28 | grc.label_node(nc/2, r"$j$") 29 | grc.label_node(nc/2+1, r"$j+1$") 30 | 31 | grf.label_node_data(nf/2-2, r"$\phi_{i-2}^h$") 32 | grf.label_node_data(nf/2-1, r"$\phi_{i-1}^h$") 33 | grf.label_node_data(nf/2, r"$\phi_i^h$") 34 | grf.label_node_data(nf/2+1, r"$\phi_{i+1}^h$") 35 | grf.label_node_data(nf/2+2, r"$\phi_{i+2}^h$") 36 | 37 | grc.label_node_data(nc/2-1, r"$\phi_{j-1}^{2h}$") 38 | grc.label_node_data(nc/2, r"$\phi_{j}^{2h}$") 39 | grc.label_node_data(nc/2+1, r"$\phi_{j+1}^{2h}$") 40 | 41 | 42 | # connect the dots... 43 | 44 | plt.plot([grf.xc[nf/2-2], grf.xc[nf/2-2]], [-0.25, 3.25], ":", color="0.5") 45 | plt.plot([grf.xc[nf/2], grf.xc[nf/2]], [-0.25, 3.25], ":", color="0.5") 46 | plt.plot([grf.xc[nf/2+2], grf.xc[nf/2+2]], [-0.25, 3.25], ":", color="0.5") 47 | 48 | 49 | plt.axis([grf.xmin-0.5*grf.dx,grf.xmax+0.5*grf.dx, -0.5, 3.5]) 50 | plt.axis("off") 51 | 52 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 53 | 54 | f = plt.gcf() 55 | f.set_size_inches(6.0,5.0) 56 | 57 | plt.savefig("fdrestrict.pdf") 58 | 59 | 60 | -------------------------------------------------------------------------------- /figures/gridFigs/fvprolong.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import grid_plot as gp 3 | 4 | # plot two stacked fv grids of different (2x) resolution to show prolongation 5 | 6 | #----------------------------------------------------------------------------- 7 | 8 | nf = 4 9 | nc = nf/2 10 | 11 | grf = gp.FVGrid(nf) 12 | grc = gp.FVGrid(nc, voff=2.0) 13 | 14 | 15 | plt.clf() 16 | 17 | grf.draw_grid() 18 | grc.draw_grid() 19 | 20 | grf.label_center(nf/2-2, r"$i-2$") 21 | grf.label_center(nf/2-1, r"$i-1$") 22 | grf.label_center(nf/2, r"$i$") 23 | grf.label_center(nf/2+1, r"$i+1$") 24 | 25 | grc.label_center(nc/2-1, r"$j-1$") 26 | grc.label_center(nc/2, r"$j$") 27 | 28 | grf.label_cell_center(nf/2-2, r"$\phi_{i-2}^h$") 29 | grf.label_cell_center(nf/2-1, r"$\phi_{i-1}^h$") 30 | grf.label_cell_center(nf/2, r"$\phi_i^h$") 31 | grf.label_cell_center(nf/2+1, r"$\phi_{i+1}^h$") 32 | 33 | grc.label_cell_center(nc/2-1, r"$\phi_{j-1}^{2h}$") 34 | grc.label_cell_center(nc/2, r"$\phi_{j}^{2h}$") 35 | 36 | 37 | # connect the dots... 38 | 39 | plt.plot([grf.xl[nf/2-2], grf.xl[nf/2-2]], [-0.25, 3.25], ":", color="0.5") 40 | plt.plot([grf.xl[nf/2], grf.xl[nf/2]], [-0.25, 3.25], ":", color="0.5") 41 | plt.plot([grf.xr[nf/2+1], grf.xr[nf/2+1]], [-0.25, 3.25], ":", color="0.5") 42 | 43 | 44 | plt.axis([grf.xmin-0.5*grf.dx,grf.xmax+0.5*grf.dx, -0.5, 3.5]) 45 | plt.axis("off") 46 | 47 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 48 | 49 | f = plt.gcf() 50 | f.set_size_inches(6.0,5.0) 51 | 52 | plt.savefig("fvprolong.pdf") 53 | 54 | -------------------------------------------------------------------------------- /figures/gridFigs/fvrestrict.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | # plot two stacked fv grids of different (2x) resolution to show prolongation 6 | 7 | #----------------------------------------------------------------------------- 8 | 9 | nf = 4 10 | nc = nf/2 11 | 12 | grf = gp.FVGrid(nf, voff=2.0) 13 | grc = gp.FVGrid(nc) 14 | 15 | 16 | plt.clf() 17 | 18 | grf.draw_grid() 19 | grc.draw_grid() 20 | 21 | grf.label_center(nf/2-2, r"$i-2$") 22 | grf.label_center(nf/2-1, r"$i-1$") 23 | grf.label_center(nf/2, r"$i$") 24 | grf.label_center(nf/2+1, r"$i+1$") 25 | 26 | grc.label_center(nc/2-1, r"$j-1$") 27 | grc.label_center(nc/2, r"$j$") 28 | 29 | grf.label_cell_center(nf/2-2, r"$\phi_{i-2}^h$") 30 | grf.label_cell_center(nf/2-1, r"$\phi_{i-1}^h$") 31 | grf.label_cell_center(nf/2, r"$\phi_i^h$") 32 | grf.label_cell_center(nf/2+1, r"$\phi_{i+1}^h$") 33 | 34 | grc.label_cell_center(nc/2-1, r"$\phi_{j-1}^{2h}$") 35 | grc.label_cell_center(nc/2, r"$\phi_{j}^{2h}$") 36 | 37 | 38 | # connect the dots... 39 | 40 | plt.plot([grf.xl[nf/2-2], grf.xl[nf/2-2]], [-0.25, 3.25], ":", color="0.5") 41 | plt.plot([grf.xl[nf/2], grf.xl[nf/2]], [-0.25, 3.25], ":", color="0.5") 42 | plt.plot([grf.xr[nf/2+1], grf.xr[nf/2+1]], [-0.25, 3.25], ":", color="0.5") 43 | 44 | 45 | plt.axis([grf.xmin-0.5*grf.dx,grf.xmax+0.5*grf.dx, -0.5, 3.5]) 46 | plt.axis("off") 47 | 48 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 49 | 50 | f = plt.gcf() 51 | f.set_size_inches(6.0,5.0) 52 | 53 | plt.savefig("fvrestrict.pdf") 54 | 55 | -------------------------------------------------------------------------------- /figures/gridFigs/nested.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import grid_plot as gp 3 | 4 | # plot two stacked fv grids of different (2x) resolution to show prolongation 5 | 6 | #----------------------------------------------------------------------------- 7 | 8 | gr = [] 9 | 10 | nf = 8 11 | gr.append(gp.FVGrid(nf, ng=1, voff=0.0)) 12 | gr.append(gp.FVGrid(nf, ng=1, voff=0.0, xmin=0.25, xmax=0.75)) 13 | 14 | 15 | plt.clf() 16 | 17 | gr[0].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0, color="0.75") 18 | gr[1].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 19 | 20 | f = plt.gcf() 21 | f.set_size_inches(7.0,1.0) 22 | 23 | 24 | grf = gr[0] 25 | plt.xlim(grf.xmin-0.75*grf.dx,grf.xmax+0.25*grf.dx) 26 | 27 | plt.axis("off") 28 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 29 | 30 | plt.savefig("nested1.pdf") 31 | 32 | #----------------------------------------------------------------------------- 33 | 34 | plt.clf() 35 | 36 | gr = [] 37 | gr.append(gp.FVGrid(nf, ng=1, voff=0.0)) 38 | gr.append(gp.FVGrid(nf, ng=1, voff=4.0)) 39 | 40 | gr[0].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 41 | gr[1].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 42 | 43 | 44 | # labels 45 | plt.text(gr[0].xmin-0.7*gr[0].dx, gr[0].voff+0.5, r"$\phi^{c,n}$", fontsize="medium") 46 | plt.text(gr[1].xmin-0.7*gr[1].dx, gr[1].voff+0.5, r"$\phi^{c,n+1}$", fontsize="medium") 47 | 48 | plt.arrow(gr[0].xmin-0.5*gr[0].dx, 0.5+3.0*gr[0].dx, 0.001, gr[1].voff-4.0*gr[0].dx, 49 | shape='full', head_width=0.025, head_length=0.25, 50 | lw=1, width=0.01, 51 | edgecolor="none", facecolor="r", 52 | length_includes_head=True, zorder=100) 53 | 54 | 55 | f = plt.gcf() 56 | f.set_size_inches(7.0,5.0) 57 | 58 | 59 | grf = gr[0] 60 | plt.xlim(grf.xmin-0.75*grf.dx,grf.xmax+0.25*grf.dx) 61 | 62 | plt.axis("off") 63 | 64 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 65 | 66 | plt.savefig("nested2.pdf") 67 | 68 | 69 | #----------------------------------------------------------------------------- 70 | 71 | plt.clf() 72 | 73 | gr1 = [] 74 | gr1.append(gp.FVGrid(nf, ng=1, voff=0.0)) 75 | gr1.append(gp.FVGrid(nf, ng=1, voff=0.0, xmin=0.25, xmax=0.75)) 76 | 77 | gr2 = [] 78 | gr2.append(gp.FVGrid(nf, ng=1, voff=2.0)) 79 | gr2.append(gp.FVGrid(nf, ng=1, voff=2.0, xmin=0.25, xmax=0.75)) 80 | 81 | gr3 = [] 82 | gr3.append(gp.FVGrid(nf, ng=1, voff=4.0)) 83 | gr3.append(gp.FVGrid(nf, ng=1, voff=4.0, xmin=0.25, xmax=0.75)) 84 | 85 | 86 | gr1[0].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0, color="0.75") 87 | gr1[1].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 88 | 89 | gr2[0].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0, color="0.75") 90 | gr2[1].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 91 | 92 | gr3[0].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0, color="0.75") 93 | gr3[1].draw_grid(emphasize_end=1, draw_ghost=0, edge_ticks=0) 94 | 95 | plt.text(gr1[1].xmin-0.95*gr1[0].dx, gr1[1].voff+0.5, r"$\phi^{f,n}$", 96 | fontsize="11", horizontalalignment="left") 97 | plt.text(gr2[1].xmin-0.95*gr2[0].dx, gr2[1].voff+0.5, r"$\phi^{f,n+1/2}$", 98 | fontsize="11", horizontalalignment="left") 99 | plt.text(gr3[1].xmin-0.95*gr3[0].dx, gr3[1].voff+0.5, r"$\phi^{f,n+1}$", 100 | fontsize="11", horizontalalignment="left") 101 | 102 | 103 | plt.annotate(r"Dirichlet BCs $\phi^{c,n}$", xy=(gr1[1].xmin, gr1[1].voff), xycoords='data', 104 | xytext=(30,-25), textcoords="offset points", 105 | arrowprops=dict(arrowstyle="->", 106 | connectionstyle="angle,angleA=180,angleB=-90,rad=10", 107 | ec="0.5"), 108 | fontsize="small",color="0.5") 109 | 110 | plt.annotate(r"Dirichlet BCs $(\phi^{c,n} + \phi^{c,n+1})/2$", xy=(gr2[1].xmin, gr2[1].voff), xycoords='data', 111 | xytext=(30,-25), textcoords="offset points", 112 | arrowprops=dict(arrowstyle="->", 113 | connectionstyle="angle,angleA=180,angleB=-90,rad=10", 114 | ec="0.5"), 115 | fontsize="small",color="0.5") 116 | 117 | plt.annotate(r"Dirichlet BCs $\phi^{c,n+1}$", xy=(gr3[1].xmin, gr3[1].voff), xycoords='data', 118 | xytext=(30,-25), textcoords="offset points", 119 | arrowprops=dict(arrowstyle="->", 120 | connectionstyle="angle,angleA=180,angleB=-90,rad=10", 121 | ec="0.5"), 122 | fontsize="small",color="0.5") 123 | 124 | 125 | plt.arrow(gr1[1].xmin-0.75*gr1[0].dx, 0.5+3.0*gr1[0].dx, 0.001, gr2[0].voff-4.0*gr2[0].dx, 126 | shape='full', head_width=0.025, head_length=0.25, 127 | lw=1, width=0.01, 128 | edgecolor="none", facecolor="r", 129 | length_includes_head=True, zorder=100) 130 | 131 | plt.arrow(gr2[1].xmin-0.75*gr2[0].dx, gr2[1].voff+0.5+3.0*gr2[0].dx, 0.001, gr3[1].voff-gr2[1].voff-4.0*gr3[0].dx, 132 | shape='full', head_width=0.025, head_length=0.25, 133 | lw=1, width=0.01, 134 | edgecolor="none", facecolor="r", 135 | length_includes_head=True, zorder=100) 136 | 137 | f = plt.gcf() 138 | f.set_size_inches(7.0,5.0) 139 | 140 | 141 | grf = gr[0] 142 | plt.xlim(grf.xmin-0.75*grf.dx,grf.xmax+0.25*grf.dx) 143 | 144 | plt.axis("off") 145 | 146 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 147 | 148 | plt.savefig("nested3.pdf") 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /figures/intro/fft_simple_examples.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import matplotlib.pyplot as plt 4 | import matplotlib as mpl 5 | import numpy as np 6 | import math 7 | 8 | mpl.rcParams['mathtext.fontset'] = 'cm' 9 | mpl.rcParams['mathtext.rm'] = 'serif' 10 | 11 | 12 | # see: http://glowingpython.blogspot.com/2011/08/how-to-plot-frequency-spectrum-with.html 13 | # and 14 | # http://docs.scipy.org/doc/numpy/reference/routines.fft.html 15 | 16 | # Since our input data is real, the negative frequency components 17 | # don't include any new information, and are not interesting to us. 18 | # The rfft routines understand this, and rfft takes n real points and 19 | # returns n/2+1 complex output points. The corresponding inverse 20 | # knows this, and acts accordingly. 21 | # 22 | # these are the routines we want for real valued data 23 | # 24 | # note that the scipy version of rfft returns that data differently 25 | # 26 | # M. Zingale (2013-03-03) 27 | 28 | 29 | def single_freq_sine(npts, xmax, f_0): 30 | 31 | # a pure sine with no phase shift will result in pure imaginary 32 | # signal 33 | 34 | xx = np.linspace(0.0, xmax, npts, endpoint=False) 35 | return xx, np.sin(2.0*math.pi*f_0*xx) 36 | 37 | def single_freq_sine_plus_shift(npts, xmax, f_0): 38 | 39 | # a pure sine with no phase shift will result in pure imaginary 40 | # signal 41 | xx = np.linspace(0.0, xmax, npts, endpoint=False) 42 | return xx, np.sin(2.0*math.pi*f_0*xx + math.pi/4) 43 | 44 | def two_freq_sine(npts, xmax, f_0, f_1): 45 | 46 | # a pure sine with no phase shift will result in pure imaginary 47 | # signal 48 | xx = np.linspace(0.0, xmax, npts, endpoint=False) 49 | f = 0.5*(np.sin(2.0*math.pi*f_0*xx) + np.sin(2.0*math.pi*f_1*xx)) 50 | return xx, f 51 | 52 | def single_freq_cosine(npts, xmax, f_0): 53 | 54 | # a pure cosine with no phase shift will result in pure real 55 | # signal 56 | xx = np.linspace(0.0, xmax, npts, endpoint=False) 57 | f = np.cos(2.0*math.pi*f_0*xx) 58 | return xx, f 59 | 60 | def plot_FFT(xx, xmax, f, outfile): 61 | 62 | plt.clf() 63 | 64 | plt.rc("font", size=10) 65 | 66 | npts = len(xx) 67 | 68 | # Forward transform: f(x) -> F(k) 69 | fk = np.fft.rfft(f) 70 | 71 | # Normalization -- the '2' here comes from the fact that we are 72 | # neglecting the negative portion of the frequency space, since 73 | # the FFT of a real function contains redundant information, so 74 | # we are only dealing with 1/2 of the frequency space. 75 | # 76 | # technically, we should only scale the 0 bin by N, since k=0 is 77 | # not duplicated -- we won't worry about that for these plots 78 | norm = 2.0/npts 79 | 80 | fk = fk*norm 81 | 82 | fk_r = fk.real 83 | fk_i = fk.imag 84 | 85 | # the fftfreq returns the postive and negative (and 0) frequencies 86 | # the newer versions of numpy (>=1.8) have an rfftfreq() function 87 | # that really does what we want -- we'll use that here. 88 | k = np.fft.rfftfreq(npts) 89 | 90 | # to make these dimensional, we need to divide by dx. Note that 91 | # max(xx) is not the true length, since we didn't have a point 92 | # at the endpoint of the domain. 93 | kfreq = k*npts/(max(xx) + xx[1]) 94 | 95 | # Inverse transform: F(k) -> f(x) -- without the normalization 96 | fkinv = np.fft.irfft(fk/norm) 97 | 98 | plt.subplot(411) 99 | 100 | plt.plot(xx, f) 101 | plt.xlabel("x") 102 | plt.ylabel("$f(x)$") 103 | 104 | plt.xlim(0, xmax) 105 | 106 | plt.subplot(412) 107 | 108 | plt.plot(kfreq, fk_r, label=r"Re($\mathcal{F}$)") 109 | plt.plot(kfreq, fk_i, ls=":", label=r"Im($\mathcal{F}$)") 110 | plt.xlabel(r"$k$") 111 | plt.ylabel("$\mathcal{F}_k$") 112 | 113 | plt.legend(fontsize="small", frameon=False, ncol=2, loc="upper right") 114 | 115 | plt.subplot(413) 116 | 117 | plt.plot(kfreq, np.abs(fk)) 118 | plt.xlabel(r"$k$") 119 | plt.ylabel(r"$|\mathcal{F}_k|$") 120 | 121 | 122 | plt.subplot(414) 123 | 124 | plt.plot(xx, fkinv.real) 125 | plt.xlabel(r"$x$") 126 | plt.ylabel(r"$\mathcal{F}^{-1}(\mathcal{F}_k)$") 127 | 128 | plt.xlim(0, xmax) 129 | 130 | plt.tight_layout() 131 | 132 | plt.savefig(outfile) 133 | 134 | 135 | 136 | #----------------------------------------------------------------------------- 137 | 138 | npts = 256 #64 #256 139 | 140 | f_0 = 0.2 141 | 142 | xmax = 10.0/f_0 143 | 144 | # FFT of sine 145 | xx, f = single_freq_sine(npts, xmax, f_0) 146 | plot_FFT(xx, xmax, f, "fft-sine.pdf") 147 | 148 | 149 | # FFT of cosine 150 | xx, f = single_freq_cosine(npts, xmax, f_0) 151 | plot_FFT(xx, xmax, f, "fft-cosine.pdf") 152 | 153 | # FFT of sine with pi/4 phase 154 | xx, f = single_freq_sine_plus_shift(npts, xmax, f_0) 155 | plot_FFT(xx, xmax, f, "fft-sine-phase.pdf") 156 | 157 | # FFT of two sines 158 | f_1 = 0.5 159 | xx, f = two_freq_sine(npts, xmax, f_0, f_1) 160 | plot_FFT(xx, xmax, f, "fft-two-sines.pdf") 161 | 162 | -------------------------------------------------------------------------------- /figures/intro/integrals.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib as mpl 3 | import matplotlib.pyplot as plt 4 | from matplotlib.patches import Polygon 5 | 6 | mpl.rcParams['mathtext.fontset'] = 'cm' 7 | mpl.rcParams['mathtext.rm'] = 'serif' 8 | 9 | 10 | def f(x): 11 | """ the function we are integrating """ 12 | #return 1.0 + x*0.25*np.sin(np.pi*x) 13 | return (1.0 + x*0.25*np.sin(5*np.pi*x)) * np.exp(-(x - 1.0)**2/0.5) 14 | 15 | 16 | plt.rcParams.update({'xtick.labelsize': 18, 17 | 'ytick.labelsize': 18, 18 | 'font.size': 18}) 19 | 20 | 21 | 22 | def plot_base(xp, fp, xfine, a, b, label_mid=False): 23 | 24 | fmax = fp.max() 25 | 26 | for xl in xp: 27 | plt.plot([xl,xl], [0.0, 1.2*fmax], ls="--", color="0.5", zorder=-1) 28 | 29 | plt.scatter(xp, fp, marker="o", color="r", zorder=100) 30 | 31 | plt.figtext(0.9, 0.05, '$x$', fontsize=20) 32 | plt.figtext(0.1, 0.9, '$y$', fontsize=20) 33 | 34 | ax = plt.gca() 35 | 36 | ax.spines['right'].set_visible(False) 37 | ax.spines['top'].set_visible(False) 38 | ax.xaxis.set_ticks_position('bottom') 39 | 40 | if label_mid: 41 | ax.set_xticks((a, (a+b)/2, b)) 42 | ax.set_xticklabels(('$a$', r'$\frac{(a+b)}{2}$', '$b$')) 43 | else: 44 | ax.set_xticks((a, b)) 45 | ax.set_xticklabels(('$a$', '$b$')) 46 | 47 | ax.set_yticks([]) 48 | 49 | plt.plot(xfine, f(xfine), "r", linewidth=2) 50 | 51 | plt.xlim(np.min(xfine), 1.05*np.max(xfine)) 52 | plt.ylim(ymin = 0) 53 | 54 | 55 | 56 | def rectangle(xp, fp, a, b): 57 | 58 | ax = plt.gca() 59 | 60 | integral = 0.0 61 | 62 | for n in range(len(xp)-1): 63 | 64 | xl = xp[n] 65 | xr = xp[n+1] 66 | 67 | fl = fp[n] 68 | 69 | # shade region 70 | verts = [(xl, 0), (xl, fl), (xr, fl), (xr, 0)] 71 | ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k")) 72 | 73 | # and bonus! actually compute the integral in this approximation 74 | integral += (xr - xl) * fl 75 | 76 | return integral 77 | 78 | 79 | def trapezoid(xp, fp, a, b): 80 | 81 | ax = plt.gca() 82 | 83 | integral = 0.0 84 | 85 | for n in range(len(xp)-1): 86 | 87 | xl = xp[n] 88 | xr = xp[n+1] 89 | 90 | # shade region 91 | fl = f(xl) 92 | fr = f(xr) 93 | 94 | verts = [(xl, 0), (xl, fl), (xr, fr), (xr, 0)] 95 | ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k")) 96 | 97 | integral += 0.5 * (xr - xl) * (fl + fr) 98 | 99 | return integral 100 | 101 | def simpsons(xp, fp, a, b): 102 | 103 | ax = plt.gca() 104 | 105 | integral = 0.0 106 | 107 | for n in range(0, len(xp)-1, 2): 108 | 109 | # we need to handle the 1 bin case specially 110 | 111 | if len(xp) == 2: 112 | 113 | xl = xp[0] 114 | xr = xp[1] 115 | xm = 0.5 * (xl + xr) 116 | 117 | f0 = f(xl) 118 | f1 = f(xm) 119 | f2 = f(xr) 120 | 121 | else: 122 | f0 = fp[n] 123 | f1 = fp[n+1] 124 | f2 = fp[n+2] 125 | 126 | xl = xp[n] 127 | xr = xp[n+2] 128 | 129 | delta = 0.5*(xr - xl) 130 | 131 | A = (f0 - 2*f1 + f2)/(2*delta**2) 132 | B = -(f2 - 4*f1 + 3*f0)/(2*delta) 133 | C = f0 134 | 135 | xsimp = np.linspace(xl, xr, 100) 136 | fsimp = A * (xsimp - xl)**2 + B * (xsimp - xl) + C 137 | 138 | simpvert = list(zip(xsimp, fsimp)) 139 | 140 | verts = [(xl, 0)] + simpvert + [(xr, 0)] 141 | ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k")) 142 | 143 | integral += (xr - xl) / 6.0 * (f0 + 4 * f1 + f2) 144 | 145 | return integral 146 | 147 | def main(): 148 | 149 | N_fine = 200 150 | 151 | # the number of bins to divide [a, b] 152 | N_bins = 16 153 | 154 | xmin = 0.5 155 | xmax = 1.5 156 | 157 | dx_extra = 0.5 158 | 159 | # add a bin on each end of the domain outside of the integral 160 | xmin_plot = xmin - dx_extra 161 | xmax_plot = xmax + dx_extra 162 | 163 | xfine = np.linspace(xmin_plot, xmax_plot, N_fine+2) 164 | 165 | xp = np.linspace(xmin, xmax, N_bins+1) 166 | 167 | # integral range 168 | a = xmin 169 | b = xmax 170 | 171 | # function points 172 | fp = f(xp) 173 | 174 | 175 | # rectangle method 176 | 177 | plt.clf() 178 | 179 | plot_base(xp, fp, xfine, a, b) 180 | I_r = rectangle(xp, fp, a, b) 181 | 182 | plt.savefig(f"rectangle_N{N_bins}.png", bbox_inches="tight") 183 | 184 | # trapezoid method 185 | 186 | plt.clf() 187 | 188 | plot_base(xp, fp, xfine, a, b) 189 | I_t = trapezoid(xp, fp, a, b) 190 | 191 | plt.savefig(f"trapezoid_N{N_bins}.png", bbox_inches="tight") 192 | 193 | 194 | # simpsons method 195 | 196 | plt.clf() 197 | 198 | xp_tmp = list(xp) 199 | fp_tmp = list(fp) 200 | label_mid = False 201 | 202 | # if N_bins is 1, we need an extra point for Simpsons 203 | if N_bins == 1: 204 | xp_tmp.append((a + b)/2) 205 | fp_tmp.append(f((a + b)/2)) 206 | label_mid = True 207 | 208 | plot_base(np.array(xp_tmp), np.array(fp_tmp), xfine, a, b, 209 | label_mid=label_mid) 210 | 211 | 212 | I_s = simpsons(xp, fp, a, b) 213 | 214 | plt.savefig(f"simpsons_N{N_bins}.png", bbox_inches="tight") 215 | 216 | print(f"integral approximations: {I_r}, {I_t}, {I_s}") 217 | 218 | if __name__ == "__main__": 219 | main() 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /figures/intro/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # integrals.py creates rectange.pdf trapezoid.pdf simpsons.pdf 4 | python3 integrals.py 5 | cp -f rectangle.pdf trapezoid.pdf simpsons.pdf ../../intro/ 6 | 7 | # rk4_plot.py creates rk4_k[1-4].pdf, rk4_final.pdf 8 | python3 rk4_plot.py 9 | cp -f rk4_k[1-4].pdf rk4_final.pdf ../../intro 10 | 11 | -------------------------------------------------------------------------------- /figures/multigrid/fv-fd_bnd.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import grid_plot as gp 4 | 5 | # plot a simple finite-difference grid showing the boundary data 6 | # and a finite-volume grid with the same data, showing it's boundary 7 | 8 | #----------------------------------------------------------------------------- 9 | 10 | 11 | # finite-difference 12 | 13 | # data that lives on the grid 14 | #a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.15, 0.5, 0.55]) 15 | a = np.array([0.3, 1.0, 0.9, 0.8, 0.25, 0.1, 0.2, 0.5, 0.55]) 16 | nzones = len(a) 17 | 18 | voff = 2.0 19 | gr = gp.FDGrid(nzones, voff=voff) 20 | 21 | gr.draw_grid(emphasize_end=True) 22 | 23 | gr.label_node(nzones/2, r"$i$", fontsize="large") 24 | gr.label_node(nzones/2-1, r"$i-1$", fontsize="large") 25 | gr.label_node(nzones/2+1, r"$i+1$", fontsize="large") 26 | gr.label_node(nzones/2-2, r"$i-2$", fontsize="large") 27 | gr.label_node(nzones/2+2, r"$i+2$", fontsize="large") 28 | 29 | # draw the data 30 | for i in range(nzones): 31 | gr.draw_data(i, a[i], color="r") 32 | 33 | 34 | gr.label_value(nzones/2, a[nzones/2], r"$f_i$", color="r") 35 | 36 | # label dx 37 | plt.plot([gr.xc[gr.ng+nzones/2-1], gr.xc[gr.ng+nzones/2-1]], [-0.35+voff,-0.25+voff], color="k") 38 | plt.plot([gr.xc[gr.ng+nzones/2], gr.xc[gr.ng+nzones/2]], [-0.35+voff,-0.25+voff], color="k") 39 | plt.plot([gr.xc[gr.ng+nzones/2-1], gr.xc[gr.ng+nzones/2]], [-0.3+voff,-0.3+voff], color="k") 40 | plt.text(0.5*(gr.xc[gr.ng+nzones/2-1] + gr.xc[gr.ng+nzones/2]), -0.45+voff, r"$\Delta x$", 41 | horizontalalignment="center") 42 | 43 | 44 | 45 | # finite-volume 46 | av = 0.5*(a[0:nzones-1] + a[1:]) 47 | nzones = len(av) 48 | ng = 1 49 | 50 | gr = gp.FVGrid(nzones, ng=1) 51 | 52 | gr.draw_grid(emphasize_end=True, draw_ghost=True) 53 | 54 | gr.label_center(ng+nzones/2, r"$i$", fontsize="large") 55 | gr.label_center(ng+nzones/2-1, r"$i-1$", fontsize="large") 56 | gr.label_center(ng+nzones/2+1, r"$i+1$", fontsize="large") 57 | 58 | gr.label_center(ng+nzones-1, r"$\mathrm{hi}$", fontsize="large") 59 | gr.label_center(ng+nzones, r"$\mathrm{hi+1}$", fontsize="large") 60 | 61 | gr.label_center(gr.ilo, r"$\mathrm{lo}$", fontsize="large") 62 | gr.label_center(gr.ilo-1, r"$\mathrm{lo-1}$", fontsize="large") 63 | 64 | a = gr.scratch_array() 65 | a[gr.ilo:gr.ihi+1] = av 66 | 67 | cc = gp.CellCentered(gr, a) 68 | 69 | # draw the data 70 | for i in range(gr.ilo, gr.ihi+1): 71 | cc.draw_data_point(i, color="r") 72 | 73 | cc.label_data_point(ng+nzones/2, r"$f_i$", color="r") 74 | 75 | # label dx 76 | plt.plot([gr.xl[gr.ng+nzones/2], gr.xl[gr.ng+nzones/2]], [-0.35,-0.25], color="k") 77 | plt.plot([gr.xr[gr.ng+nzones/2], gr.xr[gr.ng+nzones/2]], [-0.35,-0.25], color="k") 78 | plt.plot([gr.xl[gr.ng+nzones/2], gr.xr[gr.ng+nzones/2]], [-0.3,-0.3], color="k") 79 | plt.text(gr.xc[gr.ng+nzones/2], -0.45, r"$\Delta x$", 80 | horizontalalignment="center") 81 | 82 | 83 | 84 | # illustrate the boundaries 85 | plt.plot([gr.xl[gr.ilo], gr.xl[gr.ilo]], [-0.5, 2.0], ls=":", color="0.5") 86 | plt.plot([gr.xr[gr.ihi], gr.xr[gr.ihi]], [-0.5, 2.0], ls=":", color="0.5") 87 | 88 | plt.text(gr.xl[gr.ilo], -0.5, "left BC", horizontalalignment="center", 89 | verticalalignment="top") 90 | 91 | plt.text(gr.xr[gr.ihi], -0.5, "right BC", horizontalalignment="center", 92 | verticalalignment="top") 93 | 94 | plt.axis([gr.xmin-gr.dx,gr.xmax+gr.dx, -0.5, 3.2]) 95 | plt.axis("off") 96 | 97 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 98 | 99 | f = plt.gcf() 100 | f.set_size_inches(10.0,6.0) 101 | 102 | plt.savefig("fv-fd_grid_bc.pdf") 103 | -------------------------------------------------------------------------------- /figures/multigrid/fvrestrict.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | # plot two stacked fv grids of different (2x) resolution to show prolongation 6 | 7 | #----------------------------------------------------------------------------- 8 | 9 | nf = 4 10 | nc = nf//2 11 | 12 | grf = gp.FVGrid(nf, voff=2.0) 13 | grc = gp.FVGrid(nc) 14 | 15 | 16 | plt.clf() 17 | 18 | grf.draw_grid() 19 | grc.draw_grid() 20 | 21 | grf.label_center(nf//2-2, r"$i-2$") 22 | grf.label_center(nf//2-1, r"$i-1$") 23 | grf.label_center(nf//2, r"$i$") 24 | grf.label_center(nf//2+1, r"$i+1$") 25 | 26 | grc.label_center(nc//2-1, r"$j-1$") 27 | grc.label_center(nc//2, r"$j$") 28 | 29 | grf.label_cell_center(nf//2-2, r"$\phi_{i-2}^f$") 30 | grf.label_cell_center(nf//2-1, r"$\phi_{i-1}^f$") 31 | grf.label_cell_center(nf//2, r"$\phi_i^f$") 32 | grf.label_cell_center(nf//2+1, r"$\phi_{i+1}^f$") 33 | 34 | grc.label_cell_center(nc//2-1, r"$\phi_{j-1}^{c}$") 35 | grc.label_cell_center(nc//2, r"$\phi_{j}^{c}$") 36 | 37 | 38 | # connect the dots... 39 | 40 | plt.plot([grf.xl[nf//2-2], grf.xl[nf//2-2]], [-0.25, 3.25], ":", color="0.5") 41 | plt.plot([grf.xl[nf//2], grf.xl[nf//2]], [-0.25, 3.25], ":", color="0.5") 42 | plt.plot([grf.xr[nf//2+1], grf.xr[nf//2+1]], [-0.25, 3.25], ":", color="0.5") 43 | 44 | 45 | plt.axis([grf.xmin-0.5*grf.dx,grf.xmax+0.5*grf.dx, -0.5, 3.5]) 46 | plt.axis("off") 47 | 48 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 49 | 50 | f = plt.gcf() 51 | f.set_size_inches(6.0,5.0) 52 | 53 | plt.savefig("fvrestrict.pdf") 54 | 55 | -------------------------------------------------------------------------------- /figures/multigrid/laplacian.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import grid_plot as gp 4 | 5 | def laplace(): 6 | 7 | # grid info 8 | xmin = 0.0 9 | xmax = 1.0 10 | 11 | nzones = 3 12 | ng = 0 13 | 14 | gr = gp.FVGrid(nzones, xmin=xmin, xmax=xmax) 15 | 16 | 17 | #------------------------------------------------------------------------ 18 | # plot a domain without ghostcells 19 | gr.draw_grid(emphasize_end=True) 20 | 21 | # label a few 22 | gr.label_center(0, r"$i-1$", fontsize="medium") 23 | gr.label_center(1, r"$i$", fontsize="medium") 24 | gr.label_center(2, r"$i+1$", fontsize="medium") 25 | gr.label_edge(1, r"$i-\myhalf$", fontsize="medium") 26 | gr.label_edge(2, r"$i+\myhalf$", fontsize="medium") 27 | 28 | gr.label_cell_center(0, r"$\phi_{i-1}$") 29 | gr.label_cell_center(1, r"$\phi_{i}$", value=0.7) 30 | gr.label_cell_center(2, r"$\phi_{i+1}$") 31 | 32 | gr.mark_cell_edge(1, r"$\left .\frac{d\phi}{dx} \right |_{i-\myhalf}$", color="C0") 33 | gr.mark_cell_edge(2, r"$\left .\frac{d\phi}{dx} \right |_{i+\myhalf}$", color="C0") 34 | 35 | gr.label_cell_center(1, r"$\left .\frac{d^2\phi}{dx^2} \right |_{i}$", 36 | value=0.3, color="C1") 37 | 38 | gr.clean_axes(padding=False) 39 | plt.ylim(-0.25, 1.25) 40 | 41 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 42 | 43 | f = plt.gcf() 44 | f.set_size_inches(6.0,2.25) 45 | 46 | 47 | plt.tight_layout() 48 | 49 | plt.savefig("laplacian.pdf") 50 | 51 | 52 | if __name__== "__main__": 53 | laplace() 54 | -------------------------------------------------------------------------------- /figures/multigrid/mgtower.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import grid_plot as gp 3 | 4 | # plot two stacked fv grids of different (2x) resolution to show prolongation 5 | 6 | #----------------------------------------------------------------------------- 7 | 8 | gr = [] 9 | 10 | nzones = [2, 4, 8, 16] 11 | for nf in nzones: 12 | gr.append(gp.FVGrid(nf, ng=1, voff=2.0*len(gr))) 13 | 14 | 15 | plt.clf() 16 | 17 | for g in gr: 18 | g.draw_grid(emphasize_end=1, draw_ghost=1, edge_ticks=0) 19 | 20 | f = plt.gcf() 21 | f.set_size_inches(7.0,5.0) 22 | 23 | grf = gr[0] 24 | plt.xlim(grf.xmin-1.1*grf.dx,grf.xmax+1.1*grf.dx) 25 | 26 | plt.axis("off") 27 | 28 | plt.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 29 | 30 | plt.savefig("mgtower.pdf") 31 | 32 | -------------------------------------------------------------------------------- /figures/multigrid/red_black.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import pylab 4 | import random 5 | 6 | # red black gauss seidel pattern 7 | 8 | class marker: 9 | 10 | def __init__(self, xc, yc, color): 11 | 12 | # a marker is indicated by its center (xc,yc). 13 | self.xc = xc 14 | self.yc = yc 15 | 16 | # keep track of the color 17 | self.color = color 18 | 19 | 20 | def RB(): 21 | 22 | # define the number of markers in x and y 23 | nx = 10 24 | ny = 10 25 | 26 | # define the length of a marker side 27 | L = 0.8 28 | 29 | # create a list of marker objects, one at each grid location 30 | markers = [] 31 | 32 | 33 | color = 0 34 | while (color <= 1): 35 | 36 | j = 0 37 | while (j < ny): 38 | 39 | if (color == 0): 40 | ioff = j % 2 41 | else: 42 | ioff = 1 - (j % 2) 43 | 44 | i = ioff 45 | while (i < nx): 46 | markers.append(marker(i, j, color)) 47 | i += 2 48 | 49 | j += 1 50 | 51 | color += 1 52 | 53 | 54 | pylab.clf() 55 | 56 | # the margins are funny -- we pick them to ensure that the 57 | # plot size is an integer multiple of the number of markers in 58 | # each dimension 59 | pylab.subplots_adjust(left=0.1, right=0.9, 60 | bottom=0.1,top=0.9) 61 | 62 | # draw the current state 63 | n = 0 64 | while (n < len(markers)): 65 | 66 | if (markers[n].color == 1): 67 | c = "r" 68 | else: 69 | c = "k" 70 | 71 | pylab.fill([markers[n].xc-L/2, markers[n].xc-L/2, 72 | markers[n].xc+L/2, markers[n].xc+L/2, 73 | markers[n].xc-L/2], 74 | [markers[n].yc-L/2, markers[n].yc+L/2, 75 | markers[n].yc+L/2, markers[n].yc-L/2, 76 | markers[n].yc-L/2], 77 | c) 78 | 79 | n += 1 80 | 81 | 82 | ax = pylab.axis([-0.5,nx+0.5,-0.5,ny+0.5]) 83 | pylab.axis("off") 84 | 85 | f = pylab.gcf() 86 | f.set_size_inches(6.0,6.0) 87 | 88 | pylab.tight_layout() 89 | 90 | pylab.savefig("rb.png") 91 | pylab.savefig("rb.eps", bbox_inches="tight", pad_inches=0) 92 | 93 | 94 | if __name__== "__main__": 95 | RB() 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /figures/multigrid/smooth-separate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | 5 | an example of solving Poisson's equation via smoothing only. Here, we 6 | solve 7 | 8 | u_xx = sin(x) 9 | u = 0 on the boundary [0,1] 10 | 11 | The analytic solution is u(x) = -sin(x) + x sin(1) 12 | 13 | This version (separate) differs from smooth.py in that we implement the 14 | smoothing here directly, instead of using the MG solver. 15 | 16 | M. Zingale (2013-03-31) 17 | 18 | """ 19 | #from io import * 20 | import numpy as np 21 | import matplotlib.pyplot as plt 22 | import sys 23 | 24 | def true(x): 25 | # the analytic solution 26 | return -np.sin(x) + x*np.sin(1.0) 27 | 28 | 29 | def error(ilo, ihi, dx, r): 30 | # L2 norm of elements in r, multiplied by dx to normalize 31 | return np.sqrt(dx*np.sum((r[ilo:ihi+1]**2))) 32 | 33 | 34 | def f(x): 35 | # the righthand side 36 | return np.sin(x) 37 | 38 | 39 | def compute_residual(ilo, ihi, dx, phi, frhs): 40 | # compute r = f - L phi 41 | r = np.zeros(len(phi)) 42 | r[ilo:ihi+1] = frhs[ilo:ihi+1] - \ 43 | (phi[ilo+1:ihi+2] - 2.0*phi[ilo:ihi+1] + phi[ilo-1:ihi])/dx**2 44 | return r 45 | 46 | 47 | def smooth_run(nx, method="GS"): 48 | 49 | xmin = 0.0 50 | xmax = 1.0 51 | 52 | ng = 1 53 | 54 | # initialize the solution to zero. Put one ghost cell on either end 55 | phi = np.zeros(nx + 2*ng, dtype=np.float64) 56 | phinew = np.zeros_like(phi) 57 | 58 | ilo = ng 59 | ihi = ng + nx - 1 60 | 61 | # coordinates of centers 62 | dx = (xmax - xmin)/nx 63 | x = (np.arange(nx+2*ng) - ng + 0.5)*dx + xmin 64 | 65 | # initialize the RHS using the function f 66 | frhs = f(x) 67 | 68 | # smooth 69 | n = np.arange(20000) + 1 70 | e = [] 71 | r = [] 72 | 73 | print("source norm: ", error(ilo, ihi, dx, frhs)) 74 | print(np.sum(frhs[ilo:ihi+1])) 75 | 76 | for i in n: 77 | 78 | # fill the ghost cells 79 | phi[ilo-1] = -phi[ilo] 80 | phi[ihi+1] = -phi[ihi] 81 | 82 | if method == "Jacobi": 83 | phinew[ilo:ihi+1] = \ 84 | (-dx*dx*frhs[ilo:ihi+1] + phi[ilo+1:ihi+2] + phi[ilo-1:ihi])/2.0 85 | phi[:] = phinew[:] 86 | 87 | elif method == "GS": 88 | 89 | # red-black Gauss-Seidel -- first do the odd, then even points 90 | phi[ilo:ihi+1:2] = \ 91 | 0.5*(-dx*dx*frhs[ilo:ihi+1:2] + 92 | phi[ilo+1:ihi+2:2] + phi[ilo-1:ihi:2]) 93 | 94 | # fill the ghost cells between red and black 95 | phi[ilo-1] = -phi[ilo] 96 | phi[ihi+1] = -phi[ihi] 97 | 98 | phi[ilo+1:ihi+1:2] = \ 99 | 0.5*(-dx*dx*frhs[ilo+1:ihi+1:2] + \ 100 | phi[ilo+2:ihi+2:2] + phi[ilo:ihi:2]) 101 | 102 | else: 103 | sys.exit("invalid method") 104 | 105 | # compute the true error (wrt the analytic solution) and residual 106 | e.append(error(ilo, ihi, dx, phi - true(x))) 107 | 108 | # compute the residual 109 | resid = compute_residual(ilo, ihi, dx, phi, frhs) 110 | r.append(error(ilo, ihi, dx, resid)) 111 | 112 | return n, np.array(r), np.array(e) 113 | 114 | 115 | # test the multigrid solver 116 | N = [16, 32, 64] 117 | 118 | c = ["r", "g", "b"] 119 | 120 | for nx in N: 121 | 122 | n, r, e = smooth_run(nx) 123 | color = c.pop() 124 | plt.plot(n, e, color=color, label = str(nx)) 125 | plt.plot(n, r, color=color, ls=":") 126 | 127 | ax = plt.gca() 128 | ax.set_xscale('log') 129 | ax.set_yscale('log') 130 | 131 | plt.xlabel("# of iterations") 132 | plt.ylabel("L2 norm of true error (solid) and residual (dotted)") 133 | plt.legend(frameon=False, fontsize="small") 134 | 135 | plt.savefig("smooth-error.png") 136 | 137 | 138 | -------------------------------------------------------------------------------- /finite-volume/ccfd_grid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/finite-volume/ccfd_grid.pdf -------------------------------------------------------------------------------- /finite-volume/domain.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/finite-volume/domain.pdf -------------------------------------------------------------------------------- /finite-volume/fd_grid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/finite-volume/fd_grid.pdf -------------------------------------------------------------------------------- /finite-volume/fv_grid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/finite-volume/fv_grid.pdf -------------------------------------------------------------------------------- /finite-volume/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | % margins 4 | \usepackage[margin=0.75in]{geometry} 5 | 6 | % figures 7 | \usepackage{graphicx} 8 | 9 | % font 10 | \usepackage{mathpazo} 11 | 12 | \usepackage{helvet} 13 | 14 | % coloring 15 | \usepackage{color} 16 | \definecolor{mygray}{gray}{0.5} 17 | 18 | % footer 19 | \usepackage{fancyhdr} 20 | \pagestyle{fancy} 21 | \fancyfoot[LO,LE]{\footnotesize\sffamily \color{mygray} M.\ Zingale---Notes on Grids} 22 | \fancyfoot[RO,RE]{\footnotesize \sffamily \color{mygray} (\today)} 23 | \fancyfoot[CO,CE]{\thepage} 24 | \fancyhead{} 25 | \renewcommand{\headrulewidth}{0.0pt} 26 | \renewcommand{\footrulewidth}{0.0pt} 27 | 28 | % captions 29 | \usepackage{caption} 30 | \renewcommand{\captionfont}{\footnotesize} 31 | \renewcommand{\captionlabelfont}{\footnotesize} 32 | \setlength{\captionmargin}{5em} 33 | 34 | 35 | \usepackage{sectsty} 36 | \allsectionsfont{\sffamily} 37 | 38 | \newcounter{exercise} 39 | \usepackage{changepage} 40 | 41 | \newenvironment{exercise}% environment name 42 | {% begin code 43 | \begin{adjustwidth}{1.0cm}{0.5cm} 44 | \par\vspace{\baselineskip}\noindent 45 | \refstepcounter{exercise}% 46 | \textbf{Exercise \theexercise\ }\begin{itshape}% 47 | %\par\vspace{\baselineskip}\noindent\ignorespaces 48 | }% 49 | {% end code 50 | \end{itshape}\end{adjustwidth}\vspace{\baselineskip}\ignorespacesafterend 51 | } 52 | 53 | \begin{document} 54 | 55 | \begin{center} 56 | {\LARGE \textsf{\textbf{ 57 | Notes on Grids}} 58 | } 59 | \end{center} 60 | 61 | \input finite-volume 62 | 63 | \bibliographystyle{plain} 64 | \bibliography{../refs} 65 | 66 | \end{document} 67 | -------------------------------------------------------------------------------- /finite-volume/old-scripts/domain-1d.py: -------------------------------------------------------------------------------- 1 | import pylab 2 | import numpy 3 | 4 | 5 | def drawBox(ll, uu, nx, ny, gridColor="0.5", ng=0): 6 | 7 | # draw the frame 8 | pylab.plot([ll[0], ll[0], uu[0], uu[0], ll[0]], 9 | [ll[1], uu[1], uu[1], ll[1], ll[1]], color="k", lw=2) 10 | 11 | # draw the x grid lines 12 | dx = (uu[0] - ll[0])/nx 13 | n = 1 14 | while (n < nx): 15 | pylab.plot([ll[0]+n*dx, ll[0]+n*dx], 16 | [ll[1], uu[1]], color=gridColor, ls=":") 17 | 18 | n += 1 19 | 20 | # draw the y grid lines 21 | dy = (uu[1] - ll[1])/ny 22 | n = 1 23 | while (n < ny): 24 | pylab.plot([ll[0], uu[0]], 25 | [ll[1]+n*dy, ll[1]+n*dy], color=gridColor, ls=":") 26 | 27 | n += 1 28 | 29 | # ghostcells? 30 | if (ng > 0): 31 | print "here" 32 | xmin = ll[0]-ng*dx 33 | xmax = uu[0]+ng*dx 34 | ymin = ll[1]-ng*dy 35 | ymax = uu[1]+ng*dy 36 | pylab.plot([xmin, xmin, xmax, xmax, xmin], 37 | [ymin, ymax, ymax, ymin, ymin], 38 | ls="--", color="r") 39 | 40 | 41 | pylab.clf() 42 | 43 | drawBox([0., 0.], [1., 6.], 5, 30) 44 | drawBox([1., 0.], [2., 6.], 5, 30) 45 | drawBox([2., 0.], [3., 6.], 5, 30) 46 | drawBox([3., 0.], [4., 6.], 5, 30, ng=1) 47 | drawBox([4., 0.], [5., 6.], 5, 30) 48 | drawBox([5., 0.], [6., 6.], 5, 30) 49 | 50 | pylab.xlim(-0.25,6.25) 51 | pylab.ylim(-0.25,6.25) 52 | 53 | a = pylab.gca() 54 | a.set_aspect("equal", "datalim") 55 | pylab.axis("off") 56 | 57 | f = pylab.gcf() 58 | f.set_size_inches(7.0,7.0) 59 | 60 | pylab.tight_layout() 61 | 62 | pylab.savefig("domain_1d.png") 63 | pylab.savefig("domain_1d.eps", bbox_inches="tight") 64 | 65 | -------------------------------------------------------------------------------- /finite-volume/old-scripts/simplegrid.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy 3 | import pylab 4 | import grid_plot_util as gpu 5 | 6 | def simplegrid(): 7 | 8 | # grid info 9 | nzones = 7 10 | ng = 1 11 | 12 | gr = gpu.grid(nzones, ng, xmin=0.0, xmax=1.0) 13 | 14 | 15 | #------------------------------------------------------------------------ 16 | gpu.drawGrid(gr, emphasizeEnd=1, edgeTicks=0) 17 | 18 | 19 | # label a few 20 | gpu.labelCenter(gr, ng+nzones/2, r"$i$") 21 | gpu.labelCenter(gr, ng+nzones/2-1, r"$i-1$") 22 | gpu.labelCenter(gr, ng+nzones/2+1, r"$i+1$") 23 | 24 | 25 | pylab.xlim(gr.xl[0]-0.5*gr.dx,gr.xr[2*ng+nzones-1]+0.5*gr.dx) 26 | 27 | # label dx 28 | pylab.plot([gr.xl[ng+nzones/2-2], gr.xl[ng+nzones/2-2]], 29 | [-0.35,-0.25], color="k") 30 | 31 | pylab.plot([gr.xr[ng+nzones/2-2], gr.xr[ng+nzones/2-2]], 32 | [-0.35,-0.25], color="k") 33 | 34 | pylab.plot([gr.xl[ng+nzones/2-2], gr.xr[ng+nzones/2-2]], 35 | [-0.3,-0.3], color="k") 36 | 37 | pylab.text(gr.xc[ng+nzones/2-2], -0.5, r"$\Delta x$", 38 | horizontalalignment="center") 39 | 40 | pylab.subplots_adjust(left=0.05,right=0.95,bottom=0.05,top=0.95) 41 | 42 | pylab.ylim(-0.5, 1.5) 43 | pylab.axis("off") 44 | 45 | 46 | f = pylab.gcf() 47 | f.set_size_inches(10.0,2.5) 48 | 49 | 50 | pylab.savefig("simplegrid.png") 51 | pylab.savefig("simplegrid.eps") 52 | 53 | if __name__== "__main__": 54 | simplegrid() 55 | -------------------------------------------------------------------------------- /finite-volume/simplegrid_gc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/finite-volume/simplegrid_gc.pdf -------------------------------------------------------------------------------- /gravity/gravity.tex: -------------------------------------------------------------------------------- 1 | \section{Self-gravity and hydrodynamics} 2 | 3 | \section{Monopole approximation} 4 | 5 | -- radial sampling 6 | -- time-centering 7 | -- predictor 8 | -- RK formalism (solve each stage) 9 | -- what to use as center? 10 | 11 | \section{Multipole expansions} 12 | 13 | 14 | \section{Full Poisson gravity} 15 | 16 | -- isolated boundaries 17 | 18 | \subsection{Special case: triply periodic and FFTs} 19 | 20 | 21 | \section{Conservative formulations} 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /higher-order/weno-converge-burgers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-converge-burgers.pdf -------------------------------------------------------------------------------- /higher-order/weno-converge-gaussian-rk4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-converge-gaussian-rk4.pdf -------------------------------------------------------------------------------- /higher-order/weno-converge-gaussian.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-converge-gaussian.pdf -------------------------------------------------------------------------------- /higher-order/weno-convergence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-convergence.pdf -------------------------------------------------------------------------------- /higher-order/weno-euler-r3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-euler-r3.pdf -------------------------------------------------------------------------------- /higher-order/weno-euler-r5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-euler-r5.pdf -------------------------------------------------------------------------------- /higher-order/weno-euler-rarefaction-r3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-euler-rarefaction-r3.pdf -------------------------------------------------------------------------------- /higher-order/weno-vs-plm-burger.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-vs-plm-burger.pdf -------------------------------------------------------------------------------- /higher-order/weno-weights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/higher-order/weno-weights.pdf -------------------------------------------------------------------------------- /hydro-test-problems/hydro-test-problems.tex: -------------------------------------------------------------------------------- 1 | \section{Testing} 2 | 3 | There are a large number of standard hydrodynamics test problems that 4 | should be run on any implementation of an algorithm. These problems 5 | uncover strengths and weaknesses in your choice of algorithm and also 6 | simple coding bugs. 7 | 8 | An ideal test problem has an analytic solution that can be compared to 9 | directly. 10 | 11 | Convergence of your results is also an important test. 12 | 13 | Recall that for a finite-volume discretization, to second-order, the 14 | value of a function evaluated at the cell-center is the same as the 15 | average of that function over the zone. Usually this means that you 16 | can simply initialize your test problem using cell-center coordinates. 17 | But for problems that are not well aligned with your grid, e.g., a 18 | spherical initial function mapped onto your Cartesian grid, it is 19 | beneficial to try to initialize the average value in the zone. A 20 | common way to do this is to sub-divide a zone into a number of 21 | sub-zones, initialize each of the sub-zones, and then average the 22 | sub-zones back to the original zone. \MarginPar{show figure} 23 | 24 | 25 | \section{Shock tube problems} 26 | 27 | 28 | These tests are one-dimensional, and as such, they can provide good 29 | tests of symmetry in your code. Run the shock tube in the $x$, $y$, 30 | and $z$ directions separately and then compare the profiles---they 31 | should be identical (atleast to machine precision). If not, there may 32 | be a simple indexing bug, or something like that in your code. 33 | 34 | Since these tests start out with a discontinuity, they are not the 35 | best tests to use for convergence testing. Wherever there is an 36 | initiali discontinuity, the limiters will kick in and drop your 37 | method to first-order accurate. 38 | 39 | 40 | \subsection{Slow moving shock} 41 | 42 | 43 | \section{Advection} 44 | 45 | 46 | \section{Sedov} 47 | 48 | 49 | 50 | \section{Gresho vortex} 51 | 52 | The Gresho vortex is a vortex in with a stabilizing pressure gradient 53 | designed such that the overall structure is unchanging in time. It 54 | has a nice feature in that it allows you to set the Mach number of 55 | the flow as one of the parameters. 56 | 57 | 58 | \section{Odd-even decompiling} 59 | 60 | 61 | \section{Hydrostatic equilibrium} 62 | 63 | -------------------------------------------------------------------------------- /hydro1d/hydro1d.tex: -------------------------------------------------------------------------------- 1 | \label{app:hydro1d} 2 | 3 | %% \begin{center} 4 | %% \includegraphics[width=0.125\linewidth]{pyro-sm} 5 | %% \end{center} 6 | 7 | \section{Introduction} 8 | 9 | \hydrooned\ is a one-dimensional compressible hydrodynamics code written 10 | in modern Fortran. In particular, it implements the piecewise parabolic 11 | method described in \S~\ref{sec:hydro:ppm}, in both Cartesian and spherical 12 | geometries. It assumes a gamma-law equation of state and supports gravity. 13 | 14 | 15 | \section{Getting \hydrooned} 16 | 17 | \hydrooned\ can be downloaded from its github repository, \url{https://github.com/zingale/hydro1d} as: 18 | \begin{verbatim} 19 | git clone https://github.com/zingale/hydro1d 20 | \end{verbatim} 21 | 22 | Some details on the code can be found on its webpage: 23 | \url{http://zingale.github.io/hydro1d/}\, . As with the other codes detailed here, 24 | if you wish to contribute, fix bugs, etc., you can create issues or pull requests 25 | through the code's github page. 26 | 27 | 28 | 29 | \section{\hydrooned 's structure} 30 | 31 | There a few major data structures in \hydrooned, defined in the {\tt 32 | grid.f90} file: 33 | 34 | \begin{itemize} 35 | \item {\tt grid\_t} : this holds the grid information, with fields for 36 | the low and high indicies of the valid domain, and coordinate 37 | information (including interface areas and volumes, to support 38 | spherical geometry). 39 | 40 | \item {\tt gridvar\_t} : data that lives on a grid. This holds both 41 | a {\tt data} array and the {\tt grid\_t} that it is defined on. 42 | 43 | \item {\tt gridedgevar\_t} : like {\tt gridvar\_t}, but for data 44 | defined at the interfaces between zones. 45 | 46 | \end{itemize} 47 | 48 | The integer keys defined in the {\tt variables\_module} allow you 49 | to index the difference state fields in the data arrays of the 50 | grid variables. 51 | 52 | 53 | \section{Running \hydrooned} 54 | 55 | Each problem is in it's own directory, and the code is built and run 56 | there. For example, to run the Sod shock tube problem, do: 57 | \begin{verbatim} 58 | cd hydro1d/sod 59 | make 60 | ./hydro1d inputs-sod-xp 61 | \end{verbatim} 62 | 63 | As the code is built, object files and modules will be output into the 64 | {\tt \_build} subdirectory. {\tt make realclean} will clean up the 65 | objects. Things are setup for {\tt gfortran} by default---you will 66 | need to edit the {\tt Ghydro.mak} with different options for different 67 | compilers. Some bits of Fortran 2003 and 2008 are used, so an 68 | up-to-date compiler is needed. 69 | 70 | A number of runtime options can be set---these are listed in {\tt 71 | params.f90} and {\tt probparams.f90} (the latter is problem-specific 72 | parameters). 73 | 74 | 75 | \section{Problem setups} 76 | 77 | The following problem setups are provided: 78 | \begin{itemize} 79 | \item {\tt advect} : a simple advection test where a density profile 80 | is advected through periodic boundaries, in a uniform pressure 81 | medium (to suppress dynamics) 82 | 83 | \item {\tt hse} : a simple 1-d atmosphere in hydrostatic equilibrium. 84 | This test works to see if the atmosphere stays in HSE. 85 | 86 | \item {\tt sedov} : a 1-d spherical Sedov explosion. 87 | 88 | \item {\tt sod} : a shock tube setup for testing against exact Riemann 89 | solvers. 90 | \end{itemize} 91 | 92 | 93 | -------------------------------------------------------------------------------- /images/advection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/advection.png -------------------------------------------------------------------------------- /images/compressible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/compressible.png -------------------------------------------------------------------------------- /images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/cover.png -------------------------------------------------------------------------------- /images/crop_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/crop_cover.png -------------------------------------------------------------------------------- /images/diffusion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/diffusion.png -------------------------------------------------------------------------------- /images/incompressible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/incompressible.png -------------------------------------------------------------------------------- /images/lm_atm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/lm_atm.png -------------------------------------------------------------------------------- /images/mg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/images/mg.png -------------------------------------------------------------------------------- /incompressible/GNUmakefile: -------------------------------------------------------------------------------- 1 | EPStoPDF = epstopdf 2 | 3 | ALL: incompressible.pdf 4 | 5 | 6 | incompressible.pdf: main.tex incompressible.tex 7 | pdflatex -jobname=incompressible main.tex < /dev/null 8 | bibtex incompressible.aux 9 | pdflatex -jobname=incompressible main.tex < /dev/null 10 | pdflatex -jobname=incompressible main.tex < /dev/null 11 | 12 | 13 | clean: 14 | $(RM) *.aux *.log *.dvi *.bbl *.blg 15 | $(RM) *~ 16 | 17 | .PHONY: clean 18 | -------------------------------------------------------------------------------- /incompressible/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | % margins 4 | \usepackage[margin=0.75in]{geometry} 5 | 6 | % figures 7 | \usepackage{graphicx} 8 | 9 | % font 10 | \usepackage{mathpazo} 11 | 12 | \usepackage{helvet} 13 | 14 | % coloring 15 | \usepackage{color} 16 | \definecolor{mygray}{gray}{0.5} 17 | 18 | % footer 19 | \usepackage{fancyhdr} 20 | \pagestyle{fancy} 21 | \fancyfoot[LO,LE]{\footnotesize\sffamily \color{mygray} M.\ Zingale---Notes on incompressible solvers} 22 | \fancyfoot[RO,RE]{\footnotesize \sffamily \color{mygray} (\today)} 23 | \fancyfoot[CO,CE]{\thepage} 24 | \fancyhead{} 25 | \renewcommand{\headrulewidth}{0.0pt} 26 | \renewcommand{\footrulewidth}{0.0pt} 27 | 28 | % captions 29 | \usepackage{caption} 30 | \renewcommand{\captionfont}{\footnotesize} 31 | \renewcommand{\captionlabelfont}{\footnotesize} 32 | \setlength{\captionmargin}{5em} 33 | 34 | \usepackage{sectsty} 35 | \allsectionsfont{\sffamily} 36 | 37 | % shortcuts 38 | \newcommand{\Dux}{\overline{\Delta u}^{(x)}} 39 | \newcommand{\Duy}{\overline{\Delta u}^{(y)}} 40 | 41 | \newcommand{\Dvx}{\overline{\Delta v}^{(x)}} 42 | \newcommand{\Dvy}{\overline{\Delta v}^{(y)}} 43 | 44 | \setlength{\marginparwidth}{0.75in} 45 | \newcommand{\MarginPar}[1]{\marginpar{\vskip-\baselineskip\raggedright\tiny\sffamily\hrule\smallskip{\color{red}#1}\par\smallskip\hrule}} 46 | 47 | 48 | 49 | 50 | \begin{document} 51 | 52 | \begin{center} 53 | {\LARGE \textsf{\textbf{ 54 | Notes on incompressible solvers}} 55 | } 56 | \end{center} 57 | 58 | \begin{quote} 59 | \noindent {\em These summarize methods for solving the incompressible 60 | hydrodynamics equations using an cell-centered approximate 61 | projection method.} 62 | \end{quote} 63 | 64 | \input incompressible 65 | 66 | \bibliographystyle{plain} 67 | \bibliography{../refs} 68 | 69 | 70 | \end{document} 71 | -------------------------------------------------------------------------------- /incompressible/project-u.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/incompressible/project-u.pdf -------------------------------------------------------------------------------- /instabilities/instabilities.tex: -------------------------------------------------------------------------------- 1 | \section{Dimensionless numbers} 2 | 3 | 4 | Re 5 | 6 | Ra 7 | 8 | M 9 | 10 | Pr 11 | 12 | Rossby 13 | 14 | Taylor 15 | 16 | Atwood 17 | 18 | 19 | Turbulence and instabilities are ubitiquous in astrophysical flows. 20 | A proper treatment of them requires resolving the important lengthscales 21 | Furthermore, it is three-dimensional 22 | 23 | 24 | \section{Turbulence} 25 | 26 | Astrophysical flows are characterized by large Reynolds numbers. 27 | 28 | Turbulent eddies cascade between scales, owing to the nonlinear advective 29 | term in the momentum equation: $\mathbf{U} \cdot \nabla \mathbf{U}$. 30 | 31 | Burgers' turbulence? 32 | 33 | integral scale and intensity 34 | 35 | difference between 2- and 3-d 36 | 37 | subgrid scale modeling / bottleneck 38 | ILES / LES / DNS 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | \section{Convection} 48 | 49 | MLT 50 | 51 | Ledoux 52 | 53 | internally driven vs. plates 54 | 55 | 56 | 57 | 58 | 59 | \section{Rayleigh-Taylor} 60 | 61 | linear growth eate 62 | 63 | alpha 64 | 65 | incompressible vs. compressible 66 | 67 | 68 | 69 | \section{Kelvin-Helmholtz} 70 | 71 | 72 | Galilean invariance 73 | 74 | 75 | 76 | \section{Reacting flow} 77 | 78 | LD 79 | 80 | fire-polishing length 81 | 82 | 83 | -------------------------------------------------------------------------------- /intro/deriv_error.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/deriv_error.pdf -------------------------------------------------------------------------------- /intro/derivs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/derivs.pdf -------------------------------------------------------------------------------- /intro/fft-sine-phase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/fft-sine-phase.pdf -------------------------------------------------------------------------------- /intro/fluid_scale.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/fluid_scale.pdf -------------------------------------------------------------------------------- /intro/newton_00.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/newton_00.pdf -------------------------------------------------------------------------------- /intro/newton_01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/newton_01.pdf -------------------------------------------------------------------------------- /intro/newton_02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/newton_02.pdf -------------------------------------------------------------------------------- /intro/newton_03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/newton_03.pdf -------------------------------------------------------------------------------- /intro/rectangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rectangle.pdf -------------------------------------------------------------------------------- /intro/rk4_final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rk4_final.pdf -------------------------------------------------------------------------------- /intro/rk4_k1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rk4_k1.pdf -------------------------------------------------------------------------------- /intro/rk4_k2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rk4_k2.pdf -------------------------------------------------------------------------------- /intro/rk4_k3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rk4_k3.pdf -------------------------------------------------------------------------------- /intro/rk4_k4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/rk4_k4.pdf -------------------------------------------------------------------------------- /intro/simpsons.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/simpsons.pdf -------------------------------------------------------------------------------- /intro/trapezoid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/intro/trapezoid.pdf -------------------------------------------------------------------------------- /multigrid/GNUmakefile: -------------------------------------------------------------------------------- 1 | EPStoPDF = epstopdf 2 | 3 | ALL: multigrid.pdf 4 | 5 | 6 | multigrid.pdf: main.tex multigrid.tex 7 | pdflatex -jobname=multigrid main.tex < /dev/null 8 | bibtex multigrid.aux 9 | pdflatex -jobname=multigrid main.tex < /dev/null 10 | pdflatex -jobname=multigrid main.tex < /dev/null 11 | 12 | 13 | clean: 14 | $(RM) *.aux *.log *.dvi *.bbl *.blg 15 | $(RM) *~ 16 | 17 | .PHONY: clean 18 | -------------------------------------------------------------------------------- /multigrid/fft-poisson-converge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/fft-poisson-converge.pdf -------------------------------------------------------------------------------- /multigrid/fv-fd_grid_bc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/fv-fd_grid_bc.pdf -------------------------------------------------------------------------------- /multigrid/fvrestrict.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/fvrestrict.pdf -------------------------------------------------------------------------------- /multigrid/laplacian.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/laplacian.pdf -------------------------------------------------------------------------------- /multigrid/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | % margins 4 | \usepackage[margin=0.75in]{geometry} 5 | 6 | % figures 7 | \usepackage{graphicx} 8 | 9 | % font 10 | \usepackage{mathpazo} 11 | 12 | \usepackage{helvet} 13 | 14 | % coloring 15 | \usepackage{color} 16 | \definecolor{mygray}{gray}{0.5} 17 | 18 | % footer 19 | \usepackage{fancyhdr} 20 | \pagestyle{fancy} 21 | \fancyfoot[LO,LE]{\footnotesize \sffamily \color{mygray} M.\ Zingale---Notes on multigrid} 22 | \fancyfoot[RO,RE]{\footnotesize \sffamily \color{mygray} (\today)} 23 | \fancyfoot[CO,CE]{\thepage} 24 | \fancyhead{} 25 | \renewcommand{\headrulewidth}{0.0pt} 26 | \renewcommand{\footrulewidth}{0.0pt} 27 | 28 | % captions 29 | \usepackage{caption} 30 | \renewcommand{\captionfont}{\footnotesize} 31 | \renewcommand{\captionlabelfont}{\footnotesize} 32 | \setlength{\captionmargin}{5em} 33 | 34 | 35 | \usepackage{sectsty} 36 | \allsectionsfont{\sffamily} 37 | 38 | 39 | \begin{document} 40 | 41 | \begin{center} 42 | {\LARGE \textsf{\textbf{ 43 | Notes on multigrid}} 44 | } 45 | \end{center} 46 | 47 | \input multigrid 48 | 49 | \bibliographystyle{plain} 50 | \bibliography{../refs} 51 | 52 | 53 | \end{document} 54 | -------------------------------------------------------------------------------- /multigrid/mgtower.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/mgtower.pdf -------------------------------------------------------------------------------- /multigrid/poisson_fft.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/poisson_fft.pdf -------------------------------------------------------------------------------- /multigrid/smooth-badBCs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/smooth-badBCs.pdf -------------------------------------------------------------------------------- /multigrid/smooth-error-norms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/smooth-error-norms.pdf -------------------------------------------------------------------------------- /multigrid/smooth-error.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/smooth-error.pdf -------------------------------------------------------------------------------- /multigrid/smooth-multimode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multigrid/smooth-multimode.pdf -------------------------------------------------------------------------------- /multiphysics/burgersvisc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multiphysics/burgersvisc.pdf -------------------------------------------------------------------------------- /multiphysics/burgersvisc_converge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multiphysics/burgersvisc_converge.pdf -------------------------------------------------------------------------------- /multiphysics/flame_seq.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Astrophysics-Bookshelf/numerical_exercises/2d001455106e3f74393bbacdd984157c19a16810/multiphysics/flame_seq.pdf -------------------------------------------------------------------------------- /mysymbols.tex: -------------------------------------------------------------------------------- 1 | \newcommand{\cfl}{{\mathcal{C}}} 2 | 3 | % velocity 4 | \newcommand{\Ub}{{\bf U}} 5 | \newcommand{\gb}{{\bf g}} 6 | \newcommand{\Gb}{{\bf G}} 7 | \newcommand{\Hb}{{\bf H}} 8 | 9 | % systems 10 | \newcommand{\Ab}{{\bf A}} 11 | \newcommand{\Uc}{{\,\boldsymbol{\mathcal{U}}}} 12 | \newcommand{\Rc}{{\,\boldsymbol{\mathcal{R}}}} 13 | \newcommand{\Fb}{{\bf F}} 14 | \newcommand{\qb}{{\bf q}} 15 | 16 | % reactions 17 | \newcommand{\omegadot}{{\dot{\omega}}} 18 | \newcommand{\Hnuc}{{H_\mathrm{nuc}}} 19 | 20 | % diffusion 21 | \newcommand{\kth}{{k_\mathrm{th}}} 22 | 23 | % eigenvectors 24 | \newcommand{\evm}{{(-)}} 25 | \newcommand{\evz}{{(\circ)}} 26 | \newcommand{\evzs}[1]{{(\circ,#1)}} 27 | \newcommand{\evp}{{(+)}} 28 | \newcommand{\enu}{{(\nu)}} 29 | 30 | \newcommand{\lb}{{\bf l}} 31 | \newcommand{\rb}{{\bf r}} 32 | \newcommand{\Lb}{{\bf L}} 33 | \newcommand{\Rb}{{\bf R}} 34 | \newcommand{\Lambdab}{{\boldsymbol{\Lambda}}} 35 | 36 | \newcommand{\wb}{{\bf w}} 37 | 38 | % directional exponents 39 | \newcommand{\exx}{{(x)}} 40 | \newcommand{\eyy}{{(y)}} 41 | 42 | % Riemann and compressible 43 | \newcommand{\riemann}{{\mathcal{R}}} 44 | \newcommand{\Ic}{{\mathcal{I}}} 45 | 46 | % derivative shortcuts 47 | \newcommand{\ddx}[1]{{\frac{{\partial#1}}{\partial x}}} 48 | \newcommand{\ddy}[1]{{\frac{{\partial#1}}{\partial y}}} 49 | \newcommand{\ddz}[1]{{\frac{{\partial#1}}{\partial z}}} 50 | \newcommand{\ddr}[1]{{\frac{{\partial#1}}{\partial r}}} 51 | \newcommand{\ddt}[1]{{\frac{{\partial#1}}{\partial t}}} 52 | \newcommand{\DDt}[1]{{\frac{{D#1}}{D t}}} 53 | 54 | % F-V shortcuts 55 | \newcommand{\favg}[1]{{\langle #1\rangle}} 56 | 57 | \newcommand{\dx}{\Delta x} 58 | \newcommand{\dy}{\Delta y} 59 | \newcommand{\dt}{\Delta t} 60 | 61 | % limited slopes 62 | \newcommand{\Dux}{\overline{\Delta u}^{(x)}} 63 | \newcommand{\Duy}{\overline{\Delta u}^{(y)}} 64 | 65 | \newcommand{\Dvx}{\overline{\Delta v}^{(x)}} 66 | \newcommand{\Dvy}{\overline{\Delta v}^{(y)}} 67 | 68 | 69 | \newcommand{\imag}{I} 70 | -------------------------------------------------------------------------------- /pde-classes/pde-classes.tex: -------------------------------------------------------------------------------- 1 | \section{Introduction} 2 | 3 | Partial differential equations (PDEs) are usually grouped into one of 4 | three different classes: {\em hyperbolic}, {\em parabolic}, or {\em 5 | elliptic}. You can find the precise mathematical definition of 6 | these classifications in most books on PDEs, but this formal 7 | definition is not very intuitive or useful. Instead, it is helpful to 8 | look at some prototypical examples of each type of PDE. 9 | 10 | When we are solving multiphysics problems, we will see that our 11 | system of PDEs spans these different types. Nevertheless, we will 12 | look at solutions methods for each type separately first, and then 13 | use what we learn to solve more complex systems of equations. 14 | 15 | \section{Hyperbolic PDEs} 16 | 17 | The canonical hyperbolic PDE is the wave equation: 18 | \begin{equation} 19 | \frac{\partial^2 \phi}{\partial t^2} = c^2 \frac{\partial^2 \phi}{\partial x^2} 20 | \end{equation} 21 | The general solution to this is traveling waves in either direction: 22 | \begin{equation} 23 | \label{eq:pde:wavesol} 24 | \phi(x,t) = \alpha f_0(x - ct) + \beta g_0(x + ct) 25 | \end{equation} 26 | Here $f_0$ and $g_0$ are set by the initial 27 | conditions, and the solution propagates $f_0$ to the right and $g_0$ to 28 | the left at a speed $c$. 29 | 30 | \begin{exercise}[Wave equation] 31 | {Show by substitution that Eq.~\ref{eq:pde:wavesol} is a solution 32 | to the wave equation} 33 | \end{exercise} 34 | 35 | A simple first-order hyperbolic PDE is the linear advection equation: 36 | \begin{equation} 37 | a_t + u a_x = 0 38 | \end{equation} 39 | This simply propagates any initial profile to the right at the speed 40 | $u$. We will use linear advection as our model equation for numerical 41 | methods for hyperbolic PDEs. 42 | 43 | A system of first-order hyperbolic PDEs takes the form: 44 | \begin{equation} 45 | {\bf a}_t + \Ab {\bf a}_x = 0 46 | \end{equation} 47 | where ${\bf a} = (a_0, a_1, \ldots a_{N-1})^\intercal$ and $\Ab$ is a matrix. 48 | This system is hyperbolic if the eigenvalues of $A$ are real (see 49 | \cite{leveque:2002} for an excellent introduction). 50 | 51 | An important concept for hyperbolic PDEs are {\em 52 | characteristics}---these are curves in a space-time diagram along 53 | which the solution is constant. Associated with these curves is a 54 | speed---this is the wave speed at which information on how the 55 | solution changes is communicated. For a linear PDE (or system of 56 | PDEs), these will tell you everything you need to know about the 57 | solution. 58 | 59 | 60 | \section{Elliptic PDEs} 61 | 62 | The canonical elliptic PDE is the Poisson equation: 63 | \begin{equation} 64 | \nabla^2 \phi = f 65 | \end{equation} 66 | Note that there is no time-variable here. This is a pure boundary 67 | value problem. The solution, $\phi$ is determined completely by the 68 | source, $f$, and the boundary conditions. 69 | 70 | In contrast to the hyperbolic case, there is no propagation of 71 | information here. The potential, $\phi$, is known instantaneously 72 | everywhere in the domain. For astrophysical flows, this commonly 73 | arises as the Poisson equation describing the gravitational potential. 74 | 75 | 76 | 77 | \section{Parabolic PDEs} 78 | 79 | The canonical parabolic PDE is the heat equation: 80 | \begin{equation} 81 | \label{eq:pde:heat} 82 | \frac{\partial \phi}{\partial t} = k \frac{\partial^2 f}{\partial x^2} 83 | \end{equation} 84 | This has aspects of both hyperbolic and elliptic PDEs. 85 | 86 | The heat equation represents diffusion---an initially sharp feature 87 | will spread out into a smoother profile on a timescale that depends on 88 | the coefficient $k$. We'll encounter parabolic equations for thermal 89 | diffusion and other types of diffusion (like species, mass), and with 90 | viscosity. 91 | 92 | 93 | \begin{exercise}[Diffusion timescale] 94 | {Using dimensional analysis, estimate the characteristic timescale for 95 | diffusion from Eq.~\ref{eq:pde:heat}.} 96 | \end{exercise} 97 | -------------------------------------------------------------------------------- /preface/preface.tex: -------------------------------------------------------------------------------- 1 | 2 | This text started as a set of notes to help new students at Stony 3 | Brook University working on projects in computational astrophysics. 4 | They focus on the common methods used in computational hydrodynamics 5 | for astrophysical flows and are written at a level appropriate for 6 | upper-level undergraduates. Problems integrated in the text help 7 | demonstrate the core ideas. An underlying principle is that source 8 | code is provided for all the methods described here (including all the 9 | figures). This allows the reader to explore the routines themselves. 10 | 11 | These notes are very much a work in progress, and new chapters will be 12 | added with time. The page size is formatted for easy reading 13 | on a tablet or for 2-up printing in a landscape orientation on 14 | letter-sized paper. 15 | 16 | This text is part of the Open Astrophysics Bookshelf. 17 | Contributions to these notes are welcomed. The \LaTeX\ source 18 | for these notes is available online on github at: \\[0.25em] 19 | % 20 | \url{https://github.com/Open-Astrophysics-Bookshelf/numerical_exercises} \\[0.25em] 21 | % 22 | Simply fork the notes, hack away, and submit a pull-request to add 23 | your contributions. All contributions will be acknowledged in the text. 24 | 25 | 26 | A PDF version of the notes is always available 27 | at: \\[0.25em] 28 | % 29 | \url{https://open-astrophysics-bookshelf.github.io/numerical_exercises/CompHydroTutorial.pdf} \\[0.25em] 30 | % 31 | These notes are updated at irregular intervals, usually when I have a 32 | new student working with me, or if I am using them for a course. 33 | 34 | The source (usually python) for all the figures is also contained in 35 | the main git repo. The line drawings of the grids are done using the 36 | classes in 37 | \href{https://github.com/Open-Astrophysics-Bookshelf/numerical_exercises/blob/master/grid_plot.py}{{\tt 38 | grid\_plot.py}}. This needs to be in your {\tt PYTHONPATH} if you 39 | wish to run the scripts. 40 | 41 | The best way to understand the methods described here is to run 42 | them for yourself. There are several sets of example codes that 43 | go along with these notes: 44 | 45 | \begin{enumerate} 46 | \item \hydroex\ is a set of simple 1-d, standalone python scripts 47 | that illustrate some of the basic solvers. Many of the figures 48 | in these notes were created using these codes---the relevant 49 | script will be noted in the figure caption. 50 | 51 | You can get this set of scripts from github at:\\ 52 | \url{https://github.com/zingale/hydro_examples/} 53 | 54 | References to the scripts in \hydroex\ are shown throughout 55 | the text as: \\[0.5em] 56 | \hydroexdoit{scriptname} \\[0.5em] 57 | Clicking on the name of the script will bring up the source code 58 | to the script (on github) in your web browser. 59 | 60 | More details on the codes available in \hydroex\ are described 61 | in Appendix~\ref{app:hydroex}. 62 | 63 | \item 64 | The \pyro\ code~\cite{pyro} is a 2-d simulation code with 65 | solvers for advection, diffusion, compressible and incompressible 66 | hydrodynamics, as well as multigrid. A gray flux-limited diffusion 67 | radiation hydrodynamics solver is 68 | in development. \pyro\ is designed with clarity in mind and to make 69 | experimentation easy. 70 | 71 | You can download \pyro\ at: \\ 72 | \url{https://github.com/python-hydro/pyro2/} 73 | 74 | A brief overview of \pyro\ is given in Appendix~\ref{app:pyro}, 75 | and more information can be found at: \\ 76 | \url{http://python-hydro.github.io/pyro2/} 77 | 78 | \item \hydrooned\ is a simple one-dimensional compressible 79 | hydrodynamics code that implements the piecewise parabolic method 80 | from Chapter~\ref{ch:compressible}. It can be obtained from 81 | github at:\\ 82 | \url{https://github.com/zingale/hydro1d/} 83 | 84 | Details on it are given in 85 | Appendix~\ref{app:hydro1d}. 86 | \end{enumerate} 87 | 88 | Wherever possible we try to use standardized notation for physical 89 | quantities, as listed in Table~\ref{table:sym}. 90 | 91 | These notes benefited {\em immensely} from numerous conversations and 92 | an ongoing collaboration with Ann Almgren, John Bell, Andy Nonaka, \& 93 | Weiqun Zhang---pretty much everything I know about projection methods 94 | comes from working with them. Discussions with Alan Calder, Sean 95 | Couch, Max Katz, Chris Malone, and Doug Swesty have also been 96 | influential in the presentation of these notes. 97 | 98 | If you find errors, please e-mail me at michael.zingale@stonybrook.edu, 99 | or issue a pull request to the git repo noted above. 100 | 101 | 102 | 103 | \begin{flushright} 104 | Michael Zingale \\ 105 | Stony Brook University 106 | \end{flushright} 107 | 108 | \clearpage 109 | 110 | \input symbols/symbols 111 | 112 | \clearpage 113 | 114 | \section*{Authorship} 115 | 116 | \subsection*{Primary Author} 117 | 118 | Michael Zingale (Stony Brook) 119 | 120 | 121 | \subsection*{Contributions} 122 | 123 | Thank you to the 124 | following people for pointing out typos or confusing remarks in the text: 125 | \begin{itemize} 126 | \item Chen-Hung 127 | \item Rixin Li (Arizona) 128 | \item Zhi Li (Shanghai Astronomical Observatory) 129 | \item Chris Malone 130 | \item Sai Praneeth (Waterloo) 131 | \item Donald Willcox (Stony Brook) 132 | \end{itemize} 133 | 134 | Material on WENO schemes was contributed by Ian Hawke (Southampton). 135 | 136 | See the git log for full details on contributions. All contributions 137 | via pull-requests will be acknowledged here. 138 | -------------------------------------------------------------------------------- /public-codes/NOTES: -------------------------------------------------------------------------------- 1 | Describe the features of public codes: 2 | 3 | 4 | Athena 5 | 6 | Castro 7 | 8 | Enzo 9 | 10 | Flash 11 | 12 | Maestro 13 | 14 | pyro 15 | 16 | pluto 17 | 18 | 19 | 20 | 21 | give details on: 22 | 23 | -- solver 24 | -- griding (including subcycling?) 25 | -- language 26 | -- EOS 27 | -- other physics 28 | -- species 29 | -- particles 30 | -- visualization tools 31 | -- gravity 32 | -- other details 33 | -- diffusion 34 | -- radiation 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /reactive_flow/notes.txt: -------------------------------------------------------------------------------- 1 | -- mass fractions, partial density 2 | 3 | -- ODEs for reaction network 4 | 5 | -- number density 6 | 7 | -- coupling (Strang splitting vs. SDC) 8 | 9 | -- flames 10 | 11 | -- detonations 12 | 13 | 14 | -------------------------------------------------------------------------------- /software-engineering/software-engineering.tex: -------------------------------------------------------------------------------- 1 | \section{Version control} 2 | 3 | Version control gives you the ability to keep track of changes to your 4 | source, interact with other developers on the same project, and to 5 | roll back changes when bugs are introduced. It is easy to get started 6 | and is perhaps the single most important part of code development for 7 | everyone. 8 | 9 | There are several choices for version control, split loosely between 10 | centralized systems and distributed version control systems. In the 11 | former category are CVS and subversion---these have been around for a long 12 | time and are still in wide use, but not recommedned for starting a new project. 13 | Mercurial and git are the two most popular distributed version control 14 | systems, each actively used. There are some subtle differences between 15 | the two, but generally the workflow in each system follows the same ideas. 16 | 17 | Diagram showing a distributed workflow. 18 | 19 | We generally want to pull 20 | 21 | bitbucket and github 22 | 23 | 24 | 25 | 26 | \section{Testing} 27 | 28 | There are several types of testing that are important in computational 29 | hydrodynamics. When concerning source code quality, {\em unit testing} 30 | and {\em regression testing} are invaluable in making sure that your 31 | code works as designed and that you don't change the results as you 32 | continue to develop. 33 | 34 | \section{Reproducibility} 35 | 36 | -------------------------------------------------------------------------------- /software-engineering/topics.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | -- git & github 4 | 5 | -- diff 6 | 7 | -- gnuplot 8 | 9 | -- awk 10 | 11 | -- grep / ack 12 | 13 | -- basic scripting (for i in ... [ seq, *.png ] 14 | 15 | . basename 16 | 17 | 18 | -- screen 19 | -------------------------------------------------------------------------------- /symbols/symbols.tex: -------------------------------------------------------------------------------- 1 | 2 | \renewcommand{\arraystretch}{1.5} 3 | % 4 | \begin{center} 5 | \begin{longtable}{|l|p{3.25in}|l|} 6 | \caption[Definition of symbols.]{Definition of symbols.} \label{table:sym} \\ 7 | % 8 | \hline \multicolumn{1}{|c|}{\textbf{symbol}} & 9 | \multicolumn{1}{ c|}{\textbf{meaning}} & 10 | \multicolumn{1}{ c|}{\textbf{units}} \\ \hline 11 | \endfirsthead 12 | 13 | \multicolumn{3}{c}% 14 | {{\tablename\ \thetable{}---continued}} \\ 15 | \hline \multicolumn{1}{|c|}{\textbf{symbol}} & 16 | \multicolumn{1}{ c|}{\textbf{meaning}} & 17 | \multicolumn{1}{ c|}{\textbf{units}} \\ \hline 18 | \endhead 19 | 20 | \multicolumn{3}{|r|}{{\em continued on next page}} \\ \hline 21 | \endfoot 22 | 23 | \hline 24 | \endlastfoot 25 | $\Ab$ & Jacobian matrix & N/A \\ 26 | % 27 | $C$ & Lagrangian sound speed, $C = \sqrt{\Gamma_1 p \rho}$ & g~m$^{-2}$~s$^{-1}$\\ 28 | % 29 | $\cfl$ & CFL number & --\\ 30 | % 31 | $c$ & sound speed, $c = \sqrt{\Gamma_1 p/\rho}$ & m~s$^{-1}$ \\ 32 | % 33 | $c_p$ & specific heat at constant pressure 34 | ($c_p \equiv \left . \partial h / \partial T \right |_{p,X_k}$) 35 | & erg~g$^{-1}$~K$^{-1}$ \\ 36 | % 37 | $c_v$ & specific heat at constant density 38 | ($c_v \equiv \left . \partial e / \partial T \right |_{\rho,X_k}$) 39 | & erg~g$^{-1}$~K$^{-1}$ \\ 40 | % 41 | $E$ & specific total energy & erg~g$^{-1}$ \\ 42 | % 43 | $e$ & specific internal energy & erg~g$^{-1}$ \\ 44 | % 45 | $\Fb$ & flux vector & N/A \\ 46 | % 47 | $\gb$ & gravitational acceleration & cm~s$^{-2}$ \\ 48 | % 49 | $\Gamma_1$ & first adiabatic exponent ($\Gamma_1 \equiv \left . d \log p/d \log \rho \right |_s$) & -- \\ 50 | % 51 | $\gamma$ & ratio of specific heats, $\gamma = c_p/c_v$ & -- \\ 52 | % 53 | $\gamma_e$ & the quantity $p/(\rho e) + 1$ & -- \\ 54 | % 55 | $H$ & heat sources & erg~g$^{-1}$~s$^{-1}$ \\ 56 | % 57 | $\Hnuc$ & nuclear energy source & erg~g$^{-1}$~s$^{-1}$ \\ 58 | % 59 | $h$ & specific enthalpy & erg~g$^{-1}$ \\ 60 | % 61 | $\Ic$ & integral under a (piecewise) parabolic polynomial reconstruction & N/A \\ 62 | % 63 | $\kth$ & thermal conductivity & erg~cm$^{-1}$~s$^{-1}$~K$^-1$ \\ 64 | % 65 | ${\bf L}$ & matrix of left eigenvectors & -- \\ 66 | % 67 | ${\boldsymbol{\Lambda}}$ & diagonal matrix of eigenvalue & -- \\ 68 | % 69 | $\lb$ & left eigenvector & N/A \\ 70 | % 71 | $\lambda$ & eigenvalue & N/A \\ 72 | % 73 | $M$ & Mach number, $M = |\Ub|/c$ & -- \\ 74 | % 75 | $\omegadot_k$ & species creation rate & s$^{-1}$ \\ 76 | % 77 | $p$ & pressure & erg~cm$^{-3}$ \\ 78 | % 79 | $\qb$ & primitive variable vector & N/A \\ 80 | % 81 | ${\bf R}$ & matrix of right eigenvectors & -- \\ 82 | % 83 | $\riemann(q_L, q_R)$ & Riemann problem between states $q_L$ and $q_R$ & N/A \\ 84 | % 85 | $\rb$ & right eigenvector & N/A \\ 86 | % 87 | $\rho$ & mass density & g~cm$^{-3}$ \\ 88 | % 89 | $S$ & source term to the divergence constraint & s$^{-1}$ \\ 90 | % 91 | $s$ & specific entropy & erg~g$^{-1}$~K$^{-1}$ \\ 92 | % 93 | $T$ & temperature & K \\ 94 | % 95 | $t$ & time & s \\ 96 | % 97 | $\tau$ & specific volume ($\tau = 1/\rho$) & cm$^3$~g$^{-1}$ \\ 98 | % 99 | $\Ub$ & total velocity vector, $\Ub = (u, v)^\intercal$ in 2-d & cm~s$^{-1}$ \\ 100 | % 101 | $\Uc$ & conserved variable vector & N/A \\ 102 | % 103 | $u$ & x-velocity & cm~s$^{-1}$ \\ 104 | % 105 | $v$ & y-velocity & cm~s$^{-1}$ \\ 106 | % 107 | $\wb$ & characteristic variables vector & N/A \\ 108 | % 109 | $X_k$ & mass fraction of the species ($\sum_k X_k = 1$) & -- \\ 110 | \end{longtable} 111 | \end{center} 112 | \renewcommand{\arraystretch}{1.0} 113 | 114 | 115 | --------------------------------------------------------------------------------