Skip to content

Commit 9110b5a

Browse files
committed
When calculating error norms, skip points that are set by radial bc
For Dirichlet bc this probably does not matter (as the boundary points should have zero error anyway), but when using Neumann boundary conditions the radial boundaries may give the largest timestep errors even though they are not actually evolved values - ignore these to avoid unnecessarily restricting the adaptive timestep.
1 parent f0acc77 commit 9110b5a

4 files changed

Lines changed: 187 additions & 75 deletions

File tree

moment_kinetics/src/boundary_conditions.jl

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export enforce_neutral_boundary_conditions!
1010
using LinearAlgebra: dot
1111
using SpecialFunctions: erfc
1212

13-
using ..array_allocation: allocate_shared_float
13+
using ..array_allocation: allocate_shared_float, allocate_shared_bool
1414
using ..calculus: integral, reconcile_element_boundaries_MPI!
1515
using ..communication
1616
using ..coordinates: coordinate
@@ -219,8 +219,83 @@ function create_r_boundary_info(input_dict, pdf, moments, r, z, vperp, vpa, vzet
219219
end
220220
end
221221

222+
ion_error_norm_skip_inner = allocate_shared_bool(z.n)
223+
ion_error_norm_skip_outer = allocate_shared_bool(z.n)
224+
electron_error_norm_skip_inner = allocate_shared_bool(z.n)
225+
electron_error_norm_skip_outer = allocate_shared_bool(z.n)
226+
neutral_error_norm_skip_inner = allocate_shared_bool(z.n)
227+
neutral_error_norm_skip_outer = allocate_shared_bool(z.n)
228+
@begin_serial_region()
229+
@serial_region begin
230+
if r.irank == 0
231+
for s inner_sections
232+
if (isa(s.ion, ion_r_boundary_section_Neumann)
233+
|| isa(s.ion, ion_r_boundary_section_Dirichlet))
234+
235+
ion_error_norm_skip_inner[s.z_range] .= true
236+
else
237+
ion_error_norm_skip_inner[s.z_range] .= false
238+
end
239+
if (isa(s.electron, electron_r_boundary_section_Neumann)
240+
|| isa(s.electron, electron_r_boundary_section_Dirichlet))
241+
242+
electron_error_norm_skip_inner[s.z_range] .= true
243+
else
244+
electron_error_norm_skip_inner[s.z_range] .= false
245+
end
246+
if (isa(s.neutral, neutral_r_boundary_section_Neumann)
247+
|| isa(s.neutral, neutral_r_boundary_section_Dirichlet))
248+
249+
neutral_error_norm_skip_inner[s.z_range] .= true
250+
else
251+
neutral_error_norm_skip_inner[s.z_range] .= false
252+
end
253+
end
254+
else
255+
ion_error_norm_skip_inner .= false
256+
electron_error_norm_skip_inner .= false
257+
neutral_error_norm_skip_inner .= false
258+
end
259+
260+
if r.irank == r.nrank - 1
261+
for s outer_sections
262+
if (isa(s.ion, ion_r_boundary_section_Neumann)
263+
|| isa(s.ion, ion_r_boundary_section_Dirichlet))
264+
265+
ion_error_norm_skip_outer[s.z_range] .= true
266+
else
267+
ion_error_norm_skip_outer[s.z_range] .= false
268+
end
269+
if (isa(s.electron, electron_r_boundary_section_Neumann)
270+
|| isa(s.electron, electron_r_boundary_section_Dirichlet))
271+
272+
electron_error_norm_skip_outer[s.z_range] .= true
273+
else
274+
electron_error_norm_skip_outer[s.z_range] .= false
275+
end
276+
if (isa(s.neutral, neutral_r_boundary_section_Neumann)
277+
|| isa(s.neutral, neutral_r_boundary_section_Dirichlet))
278+
279+
neutral_error_norm_skip_outer[s.z_range] .= true
280+
else
281+
neutral_error_norm_skip_outer[s.z_range] .= false
282+
end
283+
end
284+
else
285+
ion_error_norm_skip_outer .= false
286+
electron_error_norm_skip_outer .= false
287+
neutral_error_norm_skip_outer .= false
288+
end
289+
end
290+
222291
r_boundaries = r_boundary_info(Tuple(s for s inner_sections if s !== nothing),
223-
Tuple(s for s outer_sections if s !== nothing))
292+
Tuple(s for s outer_sections if s !== nothing),
293+
ion_error_norm_skip_inner,
294+
electron_error_norm_skip_inner,
295+
neutral_error_norm_skip_inner,
296+
ion_error_norm_skip_outer,
297+
electron_error_norm_skip_outer,
298+
neutral_error_norm_skip_outer)
224299

225300
# Check that all boundary points are handled
226301
if r.irank == 0 && r.n > 1

moment_kinetics/src/moment_kinetics_structs.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,12 @@ struct r_boundary_info{Tinner <: NTuple{M,r_boundary_section} where M,
550550
Touter <: NTuple{N,r_boundary_section} where N}
551551
inner_sections::Tinner
552552
outer_sections::Touter
553+
ion_error_norm_skip_inner::MPISharedArray{Bool,1}
554+
ion_error_norm_skip_outer::MPISharedArray{Bool,1}
555+
electron_error_norm_skip_inner::MPISharedArray{Bool,1}
556+
electron_error_norm_skip_outer::MPISharedArray{Bool,1}
557+
neutral_error_norm_skip_inner::MPISharedArray{Bool,1}
558+
neutral_error_norm_skip_outer::MPISharedArray{Bool,1}
553559
end
554560

555561
struct z_boundary_info

moment_kinetics/src/runge_kutta.jl

Lines changed: 80 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -935,50 +935,56 @@ function local_error_norm end
935935

936936
function local_error_norm(f_loworder::MPISharedArray{mk_float,2},
937937
f::MPISharedArray{mk_float,2}, rtol, atol; method="Linf",
938-
skip_r_inner=false, skip_z_lower=false, error_sum_zero=0.0)
938+
skip_r_inner, skip_r_outer, skip_z_lower=false,
939+
error_sum_zero=0.0)
940+
nr = size(f, 2)
939941
if method == "Linf"
940942
f_max = -Inf
941943
@loop_r_z ir iz begin
944+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
945+
continue
946+
end
942947
error_norm = abs(f_loworder[iz,ir] - f[iz,ir]) / (rtol*abs(f[iz,ir]) + atol)
943948
f_max = max(f_max, error_norm)
944949
end
945950
return f_max
946951
elseif method == "L2"
947952
L2sum = error_sum_zero
948953
@loop_r_z ir iz begin
949-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
954+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
955+
(skip_z_lower && iz == 1)
950956
continue
951957
end
952958
error_norm = ((f_loworder[iz,ir] - f[iz,ir]) / (rtol*abs(f[iz,ir]) + atol))^2
953959
L2sum += error_norm
954960
end
955961
# Will sum results from different processes in shared memory block after returning
956962
# from this function.
957-
nz, nr = size(f_loworder)
958-
if skip_r_inner
959-
nr -= 1
960-
end
961-
if skip_z_lower
962-
nz -= 1
963-
end
964963
return L2sum
965964
else
966965
error("Unrecognized method '$method'")
967966
end
968967
end
969968
function local_error_norm(f_loworder::MPISharedArray{mk_float,3},
970969
f::MPISharedArray{mk_float,3}, rtol, atol, neutral=false;
971-
method="Linf", skip_r_inner=false, skip_z_lower=false,
970+
method="Linf", skip_r_inner, skip_r_outer, skip_z_lower=false,
972971
error_sum_zero=0.0)
972+
nr = size(f, 2)
973973
if method == "Linf"
974974
f_max = -Inf
975975
if neutral
976976
@loop_sn_r_z isn ir iz begin
977+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
978+
continue
979+
end
977980
error_norm = abs(f_loworder[iz,ir,isn] - f[iz,ir,isn]) / (rtol*abs(f[iz,ir,isn]) + atol)
978981
f_max = max(f_max, error_norm)
979982
end
980983
else
981984
@loop_s_r_z is ir iz begin
985+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
986+
continue
987+
end
982988
error_norm = abs(f_loworder[iz,ir,is] - f[iz,ir,is]) / (rtol*abs(f[iz,ir,is]) + atol)
983989
f_max = max(f_max, error_norm)
984990
end
@@ -988,15 +994,17 @@ function local_error_norm(f_loworder::MPISharedArray{mk_float,3},
988994
L2sum = error_sum_zero
989995
if neutral
990996
@loop_sn_r_z isn ir iz begin
991-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
997+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
998+
(skip_z_lower && iz == 1)
992999
continue
9931000
end
9941001
error_norm = ((f_loworder[iz,ir,isn] - f[iz,ir,isn]) / (rtol*abs(f[iz,ir,isn]) + atol))^2
9951002
L2sum += error_norm
9961003
end
9971004
else
9981005
@loop_s_r_z is ir iz begin
999-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
1006+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
1007+
(skip_z_lower && iz == 1)
10001008
continue
10011009
end
10021010
error_norm = ((f_loworder[iz,ir,is] - f[iz,ir,is]) / (rtol*abs(f[iz,ir,is]) + atol))^2
@@ -1005,108 +1013,117 @@ function local_error_norm(f_loworder::MPISharedArray{mk_float,3},
10051013
end
10061014
# Will sum results from different processes in shared memory block after returning
10071015
# from this function.
1008-
nz, nr, nspecies = size(f_loworder)
1009-
if skip_r_inner
1010-
nr -= 1
1011-
end
1012-
if skip_z_lower
1013-
nz -= 1
1014-
end
10151016
return L2sum
10161017
else
10171018
error("Unrecognized method '$method'")
10181019
end
10191020
end
10201021
function local_error_norm(f_loworder::MPISharedArray{mk_float,4},
10211022
f::MPISharedArray{mk_float,4}, rtol, atol; method="Linf",
1022-
skip_r_inner=false, skip_z_lower=false, error_sum_zero=0.0)
1023+
skip_r_inner, skip_r_outer, skip_z_lower=false,
1024+
error_sum_zero=0.0)
1025+
nr = size(f, 4)
10231026
if method == "Linf"
10241027
f_max = -Inf
1025-
@loop_r_z_vperp_vpa ir iz ivperp ivpa begin
1026-
error_norm = abs(f_loworder[ivpa,ivperp,iz,ir] - f[ivpa,ivperp,iz,ir]) /
1027-
(rtol*abs(f[ivpa,ivperp,iz,ir]) + atol)
1028-
f_max = max(f_max, error_norm)
1028+
@loop_r_z ir iz begin
1029+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
1030+
continue
1031+
end
1032+
@loop_vperp_vpa ivperp ivpa begin
1033+
error_norm = abs(f_loworder[ivpa,ivperp,iz,ir] - f[ivpa,ivperp,iz,ir]) /
1034+
(rtol*abs(f[ivpa,ivperp,iz,ir]) + atol)
1035+
f_max = max(f_max, error_norm)
1036+
end
10291037
end
10301038
return f_max
10311039
elseif method == "L2"
10321040
L2sum = error_sum_zero
1033-
@loop_r_z_vperp_vpa ir iz ivperp ivpa begin
1034-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
1041+
@loop_r_z ir iz begin
1042+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
1043+
(skip_z_lower && iz == 1)
10351044
continue
10361045
end
1037-
error_norm = ((f_loworder[ivpa,ivperp,iz,ir] - f[ivpa,ivperp,iz,ir]) /
1038-
(rtol*abs(f[ivpa,ivperp,iz,ir]) + atol))^2
1039-
L2sum += error_norm
1046+
@loop_vperp_vpa ivperp ivpa begin
1047+
error_norm = ((f_loworder[ivpa,ivperp,iz,ir] - f[ivpa,ivperp,iz,ir]) /
1048+
(rtol*abs(f[ivpa,ivperp,iz,ir]) + atol))^2
1049+
L2sum += error_norm
1050+
end
10401051
end
10411052
# Will sum results from different processes in shared memory block after returning
10421053
# from this function.
1043-
nvpa, nvperp, nz, nr = size(f_loworder)
1044-
if skip_r_inner
1045-
nr -= 1
1046-
end
1047-
if skip_z_lower
1048-
nz -= 1
1049-
end
10501054
return L2sum
10511055
else
10521056
error("Unrecognized method '$method'")
10531057
end
10541058
end
10551059
function local_error_norm(f_loworder::MPISharedArray{mk_float,5},
10561060
f::MPISharedArray{mk_float,5}, rtol, atol; method="Linf",
1057-
skip_r_inner=false, skip_z_lower=false, error_sum_zero=0.0)
1061+
skip_r_inner, skip_r_outer, skip_z_lower=false,
1062+
error_sum_zero=0.0)
1063+
nr = size(f, 4)
10581064
if method == "Linf"
10591065
f_max = -Inf
1060-
@loop_s_r_z_vperp_vpa is ir iz ivperp ivpa begin
1061-
error_norm = abs(f_loworder[ivpa,ivperp,iz,ir,is] - f[ivpa,ivperp,iz,ir,is]) /
1062-
(rtol*abs(f[ivpa,ivperp,iz,ir,is]) + atol)
1063-
f_max = max(f_max, error_norm)
1066+
@loop_s_r_z is ir iz begin
1067+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
1068+
continue
1069+
end
1070+
@loop_vperp_vpa ivperp ivpa begin
1071+
error_norm = abs(f_loworder[ivpa,ivperp,iz,ir,is] - f[ivpa,ivperp,iz,ir,is]) /
1072+
(rtol*abs(f[ivpa,ivperp,iz,ir,is]) + atol)
1073+
f_max = max(f_max, error_norm)
1074+
end
10641075
end
10651076
return f_max
10661077
elseif method == "L2"
10671078
L2sum = error_sum_zero
1068-
@loop_s_r_z_vperp_vpa is ir iz ivperp ivpa begin
1069-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
1079+
@loop_s_r_z is ir iz begin
1080+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
1081+
(skip_z_lower && iz == 1)
10701082
continue
10711083
end
1072-
error_norm = ((f_loworder[ivpa,ivperp,iz,ir,is] - f[ivpa,ivperp,iz,ir,is]) /
1073-
(rtol*abs(f[ivpa,ivperp,iz,ir,is]) + atol))^2
1074-
L2sum += error_norm
1084+
@loop_vperp_vpa ivperp ivpa begin
1085+
error_norm = ((f_loworder[ivpa,ivperp,iz,ir,is] - f[ivpa,ivperp,iz,ir,is]) /
1086+
(rtol*abs(f[ivpa,ivperp,iz,ir,is]) + atol))^2
1087+
L2sum += error_norm
1088+
end
10751089
end
10761090
# Will sum results from different processes in shared memory block after returning
10771091
# from this function.
1078-
nvpa, nvperp, nz, nr, nspecies = size(f_loworder)
1079-
if skip_r_inner
1080-
nr -= 1
1081-
end
1082-
if skip_z_lower
1083-
nz -= 1
1084-
end
10851092
return L2sum
10861093
else
10871094
error("Unrecognized method '$method'")
10881095
end
10891096
end
10901097
function local_error_norm(f_loworder::MPISharedArray{mk_float,6},
10911098
f::MPISharedArray{mk_float,6}, rtol, atol; method="Linf",
1092-
skip_r_inner=false, skip_z_lower=false, error_sum_zero=0.0)
1099+
skip_r_inner, skip_r_outer, skip_z_lower=false,
1100+
error_sum_zero=0.0)
1101+
nr = size(f, 5)
10931102
if method == "Linf"
10941103
f_max = -Inf
1095-
@loop_sn_r_z_vzeta_vr_vz isn ir iz ivzeta ivr ivz begin
1096-
error_norm = abs(f_loworder[ivz,ivr,ivzeta,iz,ir,isn] - f[ivz,ivr,ivzeta,iz,ir,isn]) /
1097-
(rtol*abs(f[ivz,ivr,ivzeta,iz,ir,isn]) + atol)
1098-
f_max = max(f_max, error_norm)
1104+
@loop_sn_r_z isn ir iz begin
1105+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr)
1106+
continue
1107+
end
1108+
@loop_vzeta_vr_vz ivzeta ivr ivz begin
1109+
error_norm = abs(f_loworder[ivz,ivr,ivzeta,iz,ir,isn] - f[ivz,ivr,ivzeta,iz,ir,isn]) /
1110+
(rtol*abs(f[ivz,ivr,ivzeta,iz,ir,isn]) + atol)
1111+
f_max = max(f_max, error_norm)
1112+
end
10991113
end
11001114
return f_max
11011115
elseif method == "L2"
11021116
L2sum = error_sum_zero
1103-
@loop_sn_r_z_vzeta_vr_vz isn ir iz ivzeta ivr ivz begin
1104-
if (skip_r_inner && ir == 1) || (skip_z_lower && iz == 1)
1117+
@loop_sn_r_z isn ir iz begin
1118+
if (skip_r_inner[iz] && ir == 1) || (skip_r_outer[iz] && ir == nr) ||
1119+
(skip_z_lower && iz == 1)
11051120
continue
11061121
end
1107-
error_norm = ((f_loworder[ivz,ivr,ivzeta,iz,ir,isn] - f_loworder[ivz,ivr,ivzeta,iz,ir,isn]) /
1108-
(rtol*abs(f[ivz,ivr,ivzeta,iz,ir,isn]) + atol))^2
1109-
L2sum += error_norm
1122+
@loop_vzeta_vr_vz ivzeta ivr ivz begin
1123+
error_norm = ((f_loworder[ivz,ivr,ivzeta,iz,ir,isn] - f_loworder[ivz,ivr,ivzeta,iz,ir,isn]) /
1124+
(rtol*abs(f[ivz,ivr,ivzeta,iz,ir,isn]) + atol))^2
1125+
L2sum += error_norm
1126+
end
11101127
end
11111128
# Will sum results from different processes in shared memory block after returning
11121129
# from this function.

0 commit comments

Comments
 (0)