-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start writing automated tests for MMS; renormalise manufactured distribution functions #64
Draft
johnomotani
wants to merge
30
commits into
radial-vperp-standard-DKE-with-neutrals
Choose a base branch
from
radial-vperp-standard-DKE-auto-MMS
base: radial-vperp-standard-DKE-with-neutrals
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
f10f8fd
Refactor loading of coordinates data
johnomotani ac40519
Start working on automated test for MMS
johnomotani 4de5828
Use absolute not relative errors
johnomotani 895a33b
Fix missing mk_float argument to ensure Chebyshev weights are mk_float
johnomotani 03b20ea
Use cos instead of sin so manufactured solution has perturbation at t=0
johnomotani 2efe60a
Functions to build manufactured RHS expression/function
johnomotani 1803b44
Bugfix - use begin_s_r_z_region() in ssp_rk!()
johnomotani 9c49fd5
Hacky function for evaluating df/dt
johnomotani 1e8a10c
Move advance_info definition to input_structs.jl
johnomotani a4ef258
Add vpa variation in manufactured solution for dfni
johnomotani 3ea98bd
Test case evaluating RHS with manufactured f
johnomotani 4d3d192
Parallelise loop initialising manufactured solutions
johnomotani 1ea92f2
Fix so "zero" bc works for vpa coordinate
johnomotani 1fd2e9d
MMS test: use "zero" bc for vpa, non-zero upar, correct f normalization
johnomotani 2e3e252
Remove points affected by bc in MMS test
johnomotani 27c7d42
Support neutrals when calculating rhs in manufactured_solns.jl
johnomotani 5693c4e
Support neutrals in test/manufactured_ddt_tests.jl
johnomotani 859c3c4
Make initial neutral density perturbation non-zero
johnomotani 49bfb9a
Fix dfnn normalisation, add odd components, rationalise argument orders
johnomotani b4fa510
Fix cartesian_dfni_sym(), gyroaveraged_dfnn_sym() to include norm
johnomotani 8d166a8
(Re-)add charge exchange term in manufactured rhs for ion equation
johnomotani db2cf67
Fix indexing typo in charge_exchange_collisions_3V!()
johnomotani ee465d7
Simplify declaration of netcdf_info struct
johnomotani f404095
Update load_coordinate_data() for refactored coordinates setup
johnomotani 7023930
Update sound wave tests for refactored coordinates setup
johnomotani 2fae0b8
Fix some accidental allocations
johnomotani 0917b14
Run cases without neutrals in manufactured_ddt_tests.jl
johnomotani d3b3d67
Use slightly lower v-space resolution for MMS tests
johnomotani 15a3b70
Parallelise manufactured_solutions_as_arrays(), manufactured_rhs_as_a…
johnomotani 3f63c75
More convenient choice of maximum n_element in manufactured_ddt_tests.jl
johnomotani File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
""" | ||
Test cases using the method of manufactured solutions (MMS) | ||
""" | ||
module ManufacturedSolutionsTests | ||
|
||
include("setup.jl") | ||
include("mms_utils.jl") | ||
|
||
using moment_kinetics.post_processing: L2_error_norm, L_infinity_error_norm | ||
using moment_kinetics.manufactured_solns | ||
using moment_kinetics.type_definitions | ||
|
||
# Create a temporary directory for test output | ||
test_output_directory = tempname() | ||
mkpath(test_output_directory) | ||
|
||
const input_sound_wave_periodic = Dict( | ||
"use_manufactured_solns" => true, | ||
"n_ion_species" => 1, | ||
"n_neutral_species" => 0, | ||
"boltzmann_electron_response" => true, | ||
"run_name" => "MMS-rperiodic", | ||
"base_directory" => test_output_directory, | ||
"evolve_moments_density" => false, | ||
"evolve_moments_parallel_flow" => false, | ||
"evolve_moments_parallel_pressure" => false, | ||
"evolve_moments_conservation" => false, | ||
"T_e" => 1.0, | ||
"rhostar" => 1.0, | ||
"initial_density1" => 0.5, | ||
"initial_temperature1" => 1.0, | ||
"initial_density2" => 0.5, | ||
"initial_temperature2" => 1.0, | ||
"z_IC_option1" => "sinusoid", | ||
"z_IC_density_amplitude1" => 0.001, | ||
"z_IC_density_phase1" => 0.0, | ||
"z_IC_upar_amplitude1" => 0.0, | ||
"z_IC_upar_phase1" => 0.0, | ||
"z_IC_temperature_amplitude1" => 0.0, | ||
"z_IC_temperature_phase1" => 0.0, | ||
"z_IC_option2" => "sinusoid", | ||
"z_IC_density_amplitude2" => 0.001, | ||
"z_IC_density_phase2" => 0.0, | ||
"z_IC_upar_amplitude2" => 0.0, | ||
"z_IC_upar_phase2" => 0.0, | ||
"z_IC_temperature_amplitude2" => 0.0, | ||
"z_IC_temperature_phase2" => 0.0, | ||
"charge_exchange_frequency" => 0.62831853071, | ||
"ionization_frequency" => 0.0, | ||
#"nstep" => 10, #1700, | ||
#"dt" => 0.002, | ||
#"nwrite" => 10, #1700, | ||
"nstep" => 1700, #1700, | ||
"dt" => 0.0002, #0.002, | ||
"nwrite" => 1700, #1700, | ||
"use_semi_lagrange" => false, | ||
"n_rk_stages" => 4, | ||
"split_operators" => false, | ||
"z_ngrid" => 4, | ||
"z_nelement" => 2, | ||
"z_bc" => "periodic", | ||
"z_discretization" => "chebyshev_pseudospectral", | ||
"r_ngrid" => 4, | ||
"r_nelement" => 2, | ||
"r_bc" => "periodic", | ||
"r_discretization" => "chebyshev_pseudospectral", | ||
"vpa_ngrid" => 4, | ||
"vpa_nelement" => 4, | ||
"vpa_L" => 8.0, | ||
"vpa_bc" => "periodic", | ||
"vpa_discretization" => "chebyshev_pseudospectral", | ||
"vperp_ngrid" => 4, | ||
"vperp_nelement" => 4, | ||
"vperp_L" => 8.0, | ||
"vperp_bc" => "periodic", | ||
"vperp_discretization" => "chebyshev_pseudospectral", | ||
) | ||
|
||
""" | ||
runcase(input::Dict) | ||
|
||
Run a simulation with parameters set by `input` using manufactured sources and return | ||
the errors in each variable compared to the manufactured solution. | ||
""" | ||
function runcase(input::Dict) | ||
quietoutput() do | ||
# run simulation | ||
run_moment_kinetics(input) | ||
end | ||
|
||
n_error_2 = nothing | ||
n_error_inf = nothing | ||
phi_error_2 = nothing | ||
phi_error_inf = nothing | ||
f_error_2 = nothing | ||
f_error_inf = nothing | ||
if global_rank[] == 0 | ||
output = load_test_output(input, (:phi, :moments, :f)) | ||
|
||
t = output["time"][end] | ||
n = output["density"][:,:,1,end] | ||
phi = output["phi"][:,:,end] | ||
f = output["f"][:,:,:,:,1,end] | ||
f0 = f[size(f,1)÷2, 1, :, :] | ||
|
||
n_manf, phi_manf, f_manf = manufactured_solutions_as_arrays(t, output["r"], | ||
output["z"], output["vperp"], output["vpa"]) | ||
f0_manf = f_manf[size(f,1)÷2, 1, :, :] | ||
|
||
n_error_2 = L2_error_norm(n, n_manf) | ||
n_error_inf = L_infinity_error_norm(n, n_manf) | ||
|
||
phi_error_2 = L2_error_norm(phi, phi_manf) | ||
phi_error_inf = L_infinity_error_norm(phi, phi_manf) | ||
|
||
f_error_2 = L2_error_norm(f, f_manf) | ||
f_error_inf = L_infinity_error_norm(f, f_manf) | ||
|
||
f0_error_2 = L2_error_norm(f0, f0_manf) | ||
f0_error_inf = L_infinity_error_norm(f0, f0_manf) | ||
|
||
println("n ", n_error_2, " ", n_error_inf) | ||
println("phi ", phi_error_2, " ", phi_error_inf) | ||
println("f ", f_error_2, " ", f_error_inf) | ||
println("f0 ", f0_error_2, " ", f0_error_inf) | ||
end | ||
|
||
return n_error_2, n_error_inf, phi_error_2, phi_error_inf, f_error_2, f_error_inf | ||
end | ||
|
||
""" | ||
testconvergence(input::Dict) | ||
|
||
Test convergence with spatial resolution | ||
|
||
The parameters for the run are given in `input::Dict`. | ||
""" | ||
function testconvergence(input::Dict) | ||
n_errors_2 = Vector{mk_float}(undef, 0) | ||
n_errors_inf = Vector{mk_float}(undef, 0) | ||
phi_errors_2 = Vector{mk_float}(undef, 0) | ||
phi_errors_inf = Vector{mk_float}(undef, 0) | ||
f_errors_2 = Vector{mk_float}(undef, 0) | ||
f_errors_inf = Vector{mk_float}(undef, 0) | ||
|
||
ngrid = get_and_check_ngrid(input) | ||
|
||
nelement_values = [2, 3, 4] | ||
for nelement ∈ nelement_values | ||
global_rank[] == 0 && println("testing nelement=$nelement") | ||
case_input = increase_resolution(input, nelement) | ||
|
||
n_error_2, n_error_inf, phi_error_2, phi_error_inf, f_error_2, | ||
f_error_inf = runcase(case_input) | ||
|
||
if global_rank[] == 0 | ||
push!(n_errors_2, n_error_2) | ||
push!(n_errors_inf, n_error_inf) | ||
push!(phi_errors_2, phi_error_2) | ||
push!(phi_errors_inf, phi_error_inf) | ||
push!(f_errors_2, f_error_2) | ||
push!(f_errors_inf, f_error_inf) | ||
end | ||
end | ||
|
||
if global_rank[] == 0 | ||
n_convergence_2 = n_errors_2[1] ./ n_errors_2[2:end] | ||
n_convergence_inf = n_errors_inf[1] ./ n_errors_inf[2:end] | ||
phi_convergence_2 = phi_errors_2[1] ./ phi_errors_2[2:end] | ||
phi_convergence_inf = phi_errors_inf[1] ./ phi_errors_inf[2:end] | ||
f_convergence_2 = f_errors_2[1] ./ f_errors_2[2:end] | ||
f_convergence_inf = f_errors_inf[1] ./ f_errors_inf[2:end] | ||
expected_convergence = @. (nelement_values[2:end] / nelement_values[1])^(ngrid - 1) | ||
println("n convergence") | ||
println(n_convergence_2) | ||
println(n_convergence_inf) | ||
println("phi convergence") | ||
println(phi_convergence_2) | ||
println(phi_convergence_inf) | ||
println("f convergence") | ||
println(f_convergence_2) | ||
println(f_convergence_inf) | ||
println("expected convergence") | ||
println(expected_convergence) | ||
end | ||
end | ||
|
||
function runtests() | ||
@testset "MMS" verbose=use_verbose begin | ||
global_rank[] == 0 && println("MMS tests") | ||
|
||
@testset "r-periodic, z-periodic" begin | ||
testconvergence(input_sound_wave_periodic) | ||
end | ||
end | ||
|
||
return nothing | ||
end | ||
|
||
end # ManufacturedSolutionsTests | ||
|
||
|
||
using .ManufacturedSolutionsTests | ||
|
||
ManufacturedSolutionsTests.runtests() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
""" | ||
Some shared functions used by MMS tests | ||
""" | ||
module MMSTestUtils | ||
|
||
export increase_resolution, get_and_check_ngrid, test_error_series | ||
|
||
using moment_kinetics.type_definitions | ||
|
||
""" | ||
increase_resolution(input::Dict, factor) | ||
|
||
Increase resolution of simulation by multiplying the numbers of elements `*_nelement` in | ||
the `input` settings by `factor`. | ||
""" | ||
function increase_resolution(input::Dict, nelement) | ||
result = copy(input) | ||
result["run_name"] = input["run_name"] * "_$nelement" | ||
for key ∈ keys(result) | ||
if occursin("_nelement", key) | ||
if occursin("v", key) | ||
result[key] = 4 * nelement | ||
else | ||
result[key] = nelement | ||
end | ||
end | ||
end | ||
|
||
return result | ||
end | ||
|
||
""" | ||
get_and_check_ngrid(input::Dict) | ||
|
||
Get value of `ngrid` and check that it is the same for all dimensions. `ngrid` needs to | ||
be the same as it sets the convergence order, and we want this to be the same for all | ||
operators. | ||
""" | ||
function get_and_check_ngrid(input::Dict)::mk_int | ||
ngrid = nothing | ||
|
||
for key ∈ keys(input) | ||
if occursin("_ngrid", key) | ||
if ngrid === nothing | ||
ngrid = input[key] | ||
else | ||
if ngrid != input[key] | ||
error("*_ngrid should all be the same, but $key=$(input[key]) when " | ||
* "we already found ngrid=$ngrid") | ||
end | ||
end | ||
end | ||
end | ||
|
||
return ngrid | ||
end | ||
|
||
""" | ||
test_error_series(errors::Vector{mk_float}, resolution_factors::Vector, | ||
expected_order, expected_lowest) | ||
|
||
Test whether the error norms in `errors` converge as expected with increases in | ||
resolution by `resolution_factors`. `expected_order` is the order p such that the error | ||
is expected to be proportional to h^p. `expected_lowest` is the expected value of the | ||
error at the lowest resolution (used as a regression test). | ||
|
||
Note the entries in `errors` and `resolution_factors` should be sorted in increasing | ||
order of `resolution_factors`. | ||
""" | ||
function test_error_series(errors::Vector{mk_float}, resolution_factors::Vector, | ||
expected_order, expected_lowest) | ||
error_factors = errors[1:end-1] ./ errors[2:end] | ||
expected_factors = resolution_factors[2:end].^expected_order | ||
end | ||
|
||
end # MMSTestUtils | ||
|
||
using .MMSTestUtils |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does a function like this make it possible to avoid passing the MMS functions around the main code?
If I not mistaken, there appears to be a speed cost associated with passing the runtimegenerated function -- it would be interesting to know if you notice a significant speedup by using this approach instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there would be, mostly because this function allocates new arrays for its output, then returns them. Also it's re-building the manufactured-solutions functions each time it's called.
It should be possible to set up a struct in a way that everything in the main time-loop is fully typed. I'll have a look now and check if there is some type instability...