From 489501df2ae199cf9a30a75cb13266c9f8f68659 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Mon, 10 Jul 2023 22:20:32 +1000 Subject: [PATCH 1/8] fix typo --- docs/src/timestepping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index 778a5782..8ac4aed3 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -32,7 +32,7 @@ The high-wavenumber filter used in the filtered timesteppers is: For fluid equations with quadratic non-linearities it makes sense to choose a cutoff wavenumber at 2/3 of the highest wavenumber resolved in our domain, ``k_{\textrm{cutoff}} = \tfrac{2}{3} k_{\textrm{max}}`` (see discussion in [Aliasing section](@ref aliasing)). -Given the order ``p``, we calculate the coefficient ``\alpha`` so that the the filter value +Given the order ``p``, we calculate the coefficient ``\alpha`` so that the filter value that corresponds to the highest allowed wavenumber in our domain is a small value, ``\delta``, taken to be close to machine precision. From c6951eb4cbdb68096ccc97c2426a50c3d87b8d30 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Mon, 10 Jul 2023 22:22:30 +1000 Subject: [PATCH 2/8] minor reword to avoid repetition --- docs/src/timestepping.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index 8ac4aed3..8cc564ee 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -33,8 +33,8 @@ For fluid equations with quadratic non-linearities it makes sense to choose a cu at 2/3 of the highest wavenumber resolved in our domain, ``k_{\textrm{cutoff}} = \tfrac{2}{3} k_{\textrm{max}}`` (see discussion in [Aliasing section](@ref aliasing)). Given the order ``p``, we calculate the coefficient ``\alpha`` so that the filter value -that corresponds to the highest allowed wavenumber in our domain is a small value, ``\delta``, -taken to be close to machine precision. +that corresponds to the highest allowed wavenumber in our domain is some small number, ``\delta``, +usually taken to be close to machine precision. That is: From 031682de521a303058408c12424e9401fdbbd928 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Tue, 11 Jul 2023 08:32:32 +1000 Subject: [PATCH 3/8] add comparison of different order filters + some rewording --- docs/src/timestepping.md | 58 ++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index 8cc564ee..72bce6da 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -16,37 +16,45 @@ For example, `"RK4"` for the Runge-Kutta 4th-order time stepper. Most of the time steppers also come with their `Filtered` equivalents: [`FilteredForwardEulerTimeStepper`](@ref), [`FilteredAB3TimeStepper`](@ref), [`FilteredRK4TimeStepper`](@ref), [`FilteredLSRK54TimeStepper`](@ref), and [`FilteredETDRK4TimeStepper`](@ref). The filtered time steppers apply a high-wavenumber filter to the solution at the end of each step. -The motivation behind filtering is to remove enstrophy accumulating at high wavenumbers and creating -noise at grid-scale level. +The motivation behind filtering is to preclude enstrophy from accumulating at high wavenumbers and +creating noise at grid-scale level. -The high-wavenumber filter used in the filtered timesteppers is: +The high-wavenumber filter used in the filtered time steppers is: ```math \mathrm{filter}(\boldsymbol{k}) = - \begin{cases} - 1 & \quad |\boldsymbol{k}| ≤ k_{\textrm{cutoff}} \, ,\\ - \exp{ \left [- \alpha (|\boldsymbol{k}| - k_{\textrm{cutoff}})^p \right]} & \quad |\boldsymbol{k}| > k_{\textrm{cutoff}} \, . - \end{cases} + \begin{cases} + 1 & \quad |\boldsymbol{k}| ≤ k_{\textrm{cutoff}} \, ,\\ + \exp{ \left [- \alpha (|\boldsymbol{k}| - k_{\textrm{cutoff}})^p \right]} & \quad |\boldsymbol{k}| > k_{\textrm{cutoff}} \, . + \end{cases} ``` -For fluid equations with quadratic non-linearities it makes sense to choose a cutoff wavenumber -at 2/3 of the highest wavenumber resolved in our domain, ``k_{\textrm{cutoff}} = \tfrac{2}{3} k_{\textrm{max}}`` (see discussion in [Aliasing section](@ref aliasing)). +For fluid equations with quadratic non-linearities it makes sense to choose a cut-off wavenumber +at 2/3 of the highest wavenumber that is resolved in our domain, +``k_{\textrm{cutoff}} = \tfrac{2}{3} k_{\textrm{max}}`` (see discussion in [Aliasing section](@ref aliasing)). -Given the order ``p``, we calculate the coefficient ``\alpha`` so that the filter value -that corresponds to the highest allowed wavenumber in our domain is some small number, ``\delta``, -usually taken to be close to machine precision. - -That is: +Given the order ``p``, we choose coefficient ``\alpha`` so that the filter value that corresponds +to the highest allowed wavenumber in our domain is a small number ``\delta``, usually taken to be +close to machine precision. That is: ```math \alpha = \frac{- \log\delta}{(k_{\textrm{max}} - k_{\textrm{cutoff}})^p} \ . ``` -The above filter originates from the book by [Canuto-etal-1987](@cite). In geophysical turbulence -applications it was used by [LaCasce-1996](@cite) and later by [Arbic-Flierl-2004](@cite). +The above-mentioned filter form originates from the book by [Canuto-etal-1987](@cite). +In fluid applications it was used by [LaCasce-1996](@cite) and later by [Arbic-Flierl-2004](@cite). + +!!! warning "Not too steep, not too shallow" + Care should be taken if one decides to fiddle with the filter parameters. Changing + the order ``p`` affects how steeply the filter falls off. Lower order values imply + that the filter might fall off too quickly and may lead to Gibbs artifacts; higher + order value implies that the filter might fall off too slow and won't suffice to + remove enstrophy accumulating at the grid scale. -Using the default parameters provided by the filtered time steppers (see -[`FourierFlows.makefilter`](@ref)), the filter has the following form: +The filter using the default parameters provided by the filtered time steppers (see +[`FourierFlows.makefilter`](@ref)) is depicted below. The same plot also compares how +the filter changes when we vary the order parameter ``p`` while keeping everything +else the same. ```@setup 1 using CairoMakie @@ -57,14 +65,18 @@ set_theme!(Theme(linewidth = 3, fontsize = 20)) ```@example 1 using FourierFlows, CairoMakie -K = 0:0.01:1 # non-dimensional wavenumber k * dx / π +K = 0:0.001:1 # non-dimensional wavenumber k * dx / π + +fig = Figure(resolution=(600, 350)) +ax = Axis(fig[1, 1], xlabel = "|𝐤| dx / π", ylabel = "filter", aspect=2.5, xticks=0:0.2:1) -filter = FourierFlows.makefilter(K) +vlines!(ax, 2/3, color = (:gray, 0.4), linewidth=6, label = "cutoff wavenumber") -fig = Figure() -ax = Axis(fig[1, 1], xlabel = "k dx / π", ylabel = "filter", aspect=2.5, xticks=0:0.2:1) +lines!(ax, K, FourierFlows.makefilter(K), linewidth=4, label = "order p=4 (default)") +lines!(ax, K, FourierFlows.makefilter(K, order = 1), linestyle = :dash, label = "order p=1") +lines!(ax, K, FourierFlows.makefilter(K, order = 10), linestyle = :dot, label = "order p=10") -lines!(ax, K, filter) +axislegend(position = :lb) current_figure() # hide ``` From 4090770ab3bf28a40c933de36b986a8eda6ec371 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Tue, 11 Jul 2023 08:33:59 +1000 Subject: [PATCH 4/8] don't fix the resolution --- docs/src/timestepping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index 72bce6da..d70305fb 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -67,7 +67,7 @@ using FourierFlows, CairoMakie K = 0:0.001:1 # non-dimensional wavenumber k * dx / π -fig = Figure(resolution=(600, 350)) +fig = Figure() ax = Axis(fig[1, 1], xlabel = "|𝐤| dx / π", ylabel = "filter", aspect=2.5, xticks=0:0.2:1) vlines!(ax, 2/3, color = (:gray, 0.4), linewidth=6, label = "cutoff wavenumber") From b96f940eeab38236a64ee2239b1aa797fb719be2 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Tue, 11 Jul 2023 08:35:08 +1000 Subject: [PATCH 5/8] add gfd clarification --- docs/src/timestepping.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index d70305fb..e67e4b76 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -42,7 +42,8 @@ close to machine precision. That is: ``` The above-mentioned filter form originates from the book by [Canuto-etal-1987](@cite). -In fluid applications it was used by [LaCasce-1996](@cite) and later by [Arbic-Flierl-2004](@cite). +In geophysical turbulence applications it was used by [LaCasce-1996](@cite) and later +by [Arbic-Flierl-2004](@cite). !!! warning "Not too steep, not too shallow" Care should be taken if one decides to fiddle with the filter parameters. Changing From f5ccaa034741e8fffd70e9b7b1c9ce5da5f55fe4 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Tue, 11 Jul 2023 08:49:54 +1000 Subject: [PATCH 6/8] add default cutoff wavenumber --- docs/src/timestepping.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index e67e4b76..8569cf93 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -64,18 +64,19 @@ set_theme!(Theme(linewidth = 3, fontsize = 20)) ``` ```@example 1 -using FourierFlows, CairoMakie +using CairoMakie +using FourierFlows: makefilter K = 0:0.001:1 # non-dimensional wavenumber k * dx / π fig = Figure() ax = Axis(fig[1, 1], xlabel = "|𝐤| dx / π", ylabel = "filter", aspect=2.5, xticks=0:0.2:1) -vlines!(ax, 2/3, color = (:gray, 0.4), linewidth=6, label = "cutoff wavenumber") +vlines!(ax, 2/3, color = (:gray, 0.4), linewidth = 6, label = "cutoff wavenumber |𝐤| dx / π = 2/3 (default)") -lines!(ax, K, FourierFlows.makefilter(K), linewidth=4, label = "order p=4 (default)") -lines!(ax, K, FourierFlows.makefilter(K, order = 1), linestyle = :dash, label = "order p=1") -lines!(ax, K, FourierFlows.makefilter(K, order = 10), linestyle = :dot, label = "order p=10") +lines!(ax, K, makefilter(K), linewidth = 4, label = "order 4 (default)") +lines!(ax, K, makefilter(K, order = 1), linestyle = :dash, label = "order 1") +lines!(ax, K, makefilter(K, order = 10), linestyle = :dot, label = "order 10") axislegend(position = :lb) From b8983b00639d7d6aa6fac44147afdded086c7b81 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Tue, 11 Jul 2023 08:53:53 +1000 Subject: [PATCH 7/8] better phrasing in makefilter docstring --- src/domains.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/domains.jl b/src/domains.jl index 9eb5f7ef..d367e58e 100644 --- a/src/domains.jl +++ b/src/domains.jl @@ -485,7 +485,7 @@ one-dimensional grid, the non-dimensional wavenumber `K` is K = k * dx / π ``` -and thus it takes values `K` ``∈ [-1, 1]``. +and thus take values in ``[-1, 1]``. For `K ≤ innerK` the filter is inactive, i.e., equal to 1. For `K > innerK`, the filter decays exponentially to remove high-wavenumber content from @@ -495,8 +495,9 @@ the solution, i.e., filter(K) = exp(- decay * (K - innerK)^order) ``` -For a given `order` and , the `decay` rate is determined so that the filter value at the -outer wavenumber `outerK` is `tol`, where `tol` is a small number, close to machine precision. +For a given `order`, the `decay` rate is determined so that the filter value at the +outer wavenumber `outerK` is `tol`, where `tol` is a small number, close to machine +precision. ```julia decay = - log(tol) / (outerK - innerK)^order From 2bb7ffdb571a6f1b8b9071d42352037fd34d6c54 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Wed, 12 Jul 2023 07:40:44 +1000 Subject: [PATCH 8/8] remove debuging show msg --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index ff759667..a37f9381 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -9,7 +9,7 @@ using ##### Generate examples ##### -@show bib_filepath = joinpath(@__DIR__, "src/references.bib") +bib_filepath = joinpath(@__DIR__, "src/references.bib") bib = CitationBibliography(bib_filepath) const EXAMPLES_DIR = joinpath(@__DIR__, "..", "examples")