5#include <PB3D_macros.h>
23 integer,
allocatable ::
d(:,:,:)
24 integer,
allocatable ::
m(:,:)
25 integer,
allocatable ::
f(:,:)
41 module procedure add_arr_mult_3_3
43 module procedure add_arr_mult_3_1
45 module procedure add_arr_mult_1_1
65 module procedure calc_det_0d
67 module procedure calc_det_3d
83 module procedure calc_inv_0d
85 module procedure calc_inv_3d
97 module procedure calc_mult_0d_real
99 module procedure calc_mult_3d_real
101 module procedure calc_mult_3d_complex
125 module procedure conv_mat_3d
127 module procedure conv_mat_3d_complex
129 module procedure conv_mat_0d
131 module procedure conv_mat_0d_complex
162 module procedure calc_int_eqd
164 module procedure calc_int_reg
171 module procedure round_with_tol_ind
173 module procedure round_with_tol_arr
190 module procedure con2dis_eqd
192 module procedure con2dis_reg
208 module procedure dis2con_eqd
210 module procedure dis2con_reg
223 module procedure con_3d
225 module procedure con_2d
227 module procedure con_1d
229 module procedure con_0d
239 module procedure bubble_sort_int
241 module procedure bubble_sort_real
250 module procedure order_per_fun_1
252 module procedure order_per_fun_2
278 module procedure spline_real
280 module procedure spline_complex
285 integer function calc_int_reg(var,x,var_int)
result(ierr)
286 character(*),
parameter :: rout_name =
'calc_int_reg'
289 real(
dp),
intent(inout) :: var_int(:)
290 real(
dp),
intent(in) :: var(:)
291 real(
dp),
intent(in) :: x(:)
296 character(len=max_str_ln) :: err_msg
305 if (
size(x).ne.n_max)
then
306 err_msg =
'The arrays of points and values are not of the same &
310 else if (n_max.lt.2)
then
311 err_msg =
'Asking to integrate with '//trim(
i2str(n_max))&
312 &//
' points. Need at least 2'
321 var_int(kd) = var_int(kd-1) + &
322 &(var(kd)+var(kd-1))/2 * (x(kd)-x(kd-1))
324 end function calc_int_reg
326 integer function calc_int_eqd(var,step_size,var_int)
result(ierr)
327 character(*),
parameter :: rout_name =
'calc_int_eqd'
330 real(
dp),
intent(inout) :: var_int(:)
331 real(
dp),
intent(in) :: var(:)
332 real(
dp),
intent(in) :: step_size
337 character(len=max_str_ln) :: err_msg
347 err_msg =
'Asking to integrate with '//trim(
i2str(n_max))&
348 &//
' points. Need at least 2'
357 var_int(kd) = var_int(kd-1) + (var(kd)+var(kd-1))/2 * step_size
359 end function calc_int_eqd
362 integer function add_arr_mult_3_3(arr_1,arr_2,arr_3,deriv)
result(ierr)
363 character(*),
parameter :: rout_name =
'add_arr_mult_3_3'
366 real(
dp),
intent(in) :: arr_1(1:,1:,1:,0:,0:,0:)
367 real(
dp),
intent(in) :: arr_2(1:,1:,1:,0:,0:,0:)
368 real(
dp),
intent(out) :: arr_3(1:,1:,1:)
369 integer,
intent(in) :: deriv(3)
372 real(
dp) :: bin_fac(3)
375 character(len=max_str_ln) :: err_msg
381 if (
size(arr_1,1).ne.
size(arr_2,1) .or.
size(arr_1,2).ne.
size(arr_2,2) &
382 &.or.
size(arr_1,3).ne.
size(arr_2,3))
then
383 err_msg =
'Arrays 1 and 2 need to have the same size'
387 if (
size(arr_1,1).ne.
size(arr_3,1) .or.
size(arr_1,2).ne.
size(arr_3,2) &
388 &.or.
size(arr_1,3).ne.
size(arr_3,3))
then
389 err_msg =
'Arrays 1 and 2 need to have the same size as the &
395 if (
size(arr_1,3+kd).lt.deriv(kd)+1 .or. &
396 &
size(arr_2,3+kd).lt.deriv(kd)+1)
then
397 err_msg =
'Arrays 1 and 2 do not provide deriv. orders for a &
398 &derivative of order ['//trim(
i2str(deriv(1)))//
','//&
399 &trim(
i2str(deriv(2)))//
','//trim(
i2str(deriv(3)))//
'&
400 &] in coordinate '//trim(
i2str(kd))
412 bin_fac(1) = bin_fac(1)*(deriv(1)-(r-1))/r
419 bin_fac(2) = bin_fac(2)*(deriv(2)-(
m-1))/
m
426 bin_fac(3) = bin_fac(3)*(deriv(3)-(n-1))/n
431 &bin_fac(1)*bin_fac(2)*bin_fac(3) &
432 &* arr_1(:,:,:,r,
m,n)&
433 &* arr_2(:,:,:,deriv(1)-r,deriv(2)-
m,deriv(3)-n)
437 end function add_arr_mult_3_3
440 integer function add_arr_mult_3_1(arr_1,arr_2,arr_3,deriv)
result(ierr)
441 character(*),
parameter :: rout_name =
'add_arr_mult_3_1'
444 real(
dp),
intent(in) :: arr_1(1:,1:,1:,0:,0:,0:)
445 real(
dp),
intent(in) :: arr_2(1:,0:)
446 real(
dp),
intent(out) :: arr_3(1:,1:,1:)
447 integer,
intent(in) :: deriv(3)
453 character(len=max_str_ln) :: err_msg
459 if (
size(arr_1,3).ne.
size(arr_2,1))
then
460 err_msg =
'Arrays 1 and 2 need to have the same size in the flux &
465 if (
size(arr_1,1).ne.
size(arr_3,1) .or.
size(arr_1,2).ne.
size(arr_3,2) &
466 &.or.
size(arr_1,3).ne.
size(arr_3,3))
then
467 err_msg =
'Array 1 needs to have the same size as the resulting &
480 bin_fac = bin_fac*(deriv(1)-(r-1))/r
484 do kd = 1,
size(arr_1,3)
485 arr_3(:,:,kd) = arr_3(:,:,kd) + bin_fac * &
486 &arr_1(:,:,kd,r,deriv(2),deriv(3))* arr_2(kd,deriv(1)-r)
489 end function add_arr_mult_3_1
491 integer function add_arr_mult_1_1(arr_1,arr_2,arr_3,deriv)
result(ierr)
492 character(*),
parameter :: rout_name =
'add_arr_mult_1_1'
495 real(
dp),
intent(in) :: arr_1(1:,0:)
496 real(
dp),
intent(in) :: arr_2(1:,0:)
497 real(
dp),
intent(out) :: arr_3(1:)
498 integer,
intent(in) :: deriv(3)
503 character(len=max_str_ln) :: err_msg
509 if (
size(arr_1,1).ne.
size(arr_2,1))
then
510 err_msg =
'Arrays 1 and 2 need to have the same size in the &
515 if (
size(arr_1,1).ne.
size(arr_3,1))
then
516 err_msg =
'Array 1 needs to have the same size as the resulting &
522 if (deriv(2).gt.0 .or. deriv(3).gt.0)
then
532 bin_fac = bin_fac*(deriv(1)-(r-1))/r
536 arr_3 = arr_3 + bin_fac * arr_1(:,r)* arr_2(:,deriv(1)-r)
539 end function add_arr_mult_1_1
542 integer recursive function calc_det_3d(deta,a,n) result (ierr)
543 character(*),
parameter :: rout_name =
'calc_det_3D'
546 real(
dp),
intent(inout) :: deta(:,:,:)
547 real(
dp),
intent(in) :: a(:,:,:,:)
548 integer,
intent(in) :: n
552 integer :: id, jd, kd
555 integer,
allocatable :: slct(:)
556 integer,
allocatable :: idx(:)
557 character(len=max_str_ln) :: err_msg
558 real(
dp),
allocatable :: work(:,:,:)
559 integer,
allocatable :: c_sub(:)
560 integer,
allocatable :: k_sub(:)
566 if (
size(deta,1).ne.
size(a,1) .or.
size(deta,2).ne.
size(a,2) .or. &
567 &
size(deta,3).ne.
size(a,3))
then
568 err_msg =
'The output and input matrix have to have the same sizes'
586 allocate (work(
size(a,1),
size(a,2),
size(a,3)))
591 deta = a(:,:,:,
c([1,1],sym,n))
592 else if (n.eq.2)
then
593 deta = a(:,:,:,
c([1,1],sym,n))*a(:,:,:,
c([2,2],sym,n))-&
594 &a(:,:,:,
c([1,2],sym,n))*a(:,:,:,
c([2,1],sym,n))
597 allocate(c_sub((n-1)**2))
598 allocate(k_sub(n**2)); k_sub = 0
604 k_sub = pack(idx,slct.gt.0)
607 c_sub((kd-1)*(n-1)+jd) =
c([jd+1,k_sub(kd)],sym,n)
610 ierr = calc_det_3d(work,a(:,:,:,c_sub),n-1)
612 deta = deta + a(:,:,:,
c([1,id],sym,n))*sgn*work
617 deallocate(c_sub,k_sub)
619 end function calc_det_3d
621 integer function calc_det_0d(det_0D,A)
result(ierr)
622 character(*),
parameter :: rout_name =
'calc_det_0D'
625 real(dp),
intent(inout) :: det_0d
626 real(dp),
intent(in) :: a(:,:)
632 integer,
allocatable :: ipiv(:)
633 character(len=max_str_ln) :: err_msg
634 real(dp),
allocatable :: a_loc(:,:)
640 if (
size(a,1).ne.
size(a,2))
then
641 err_msg =
'The matrix A has to be square'
655 call dgetrf(n,n,a_loc,n,ipiv,info)
659 det_0d = det_0d*a_loc(id,id)
664 if(ipiv(id).ne.id)
then
672 end function calc_det_0d
675 integer function calc_inv_3d(inv_3D,A,n)
result(ierr)
678 character(*),
parameter :: rout_name =
'calc_inv_3D'
681 real(
dp),
intent(inout) :: inv_3d(:,:,:,:)
682 real(
dp),
intent(in) :: a(:,:,:,:)
683 integer,
intent(in) :: n
687 real(
dp),
allocatable :: deta(:,:,:)
688 integer :: id, jd, kd, ld
690 integer,
allocatable :: slct(:,:)
691 integer,
allocatable :: idx(:)
692 character(len=max_str_ln) :: err_msg
693 integer,
allocatable :: c_sub(:)
694 integer,
allocatable :: l_sub(:), k_sub(:)
701 if (
size(inv_3d,1).ne.
size(a,1) .or.
size(inv_3d,2).ne.
size(a,2) .or. &
702 &
size(inv_3d,3).ne.
size(a,3) .or.
size(inv_3d,4).ne.
size(a,4))
then
703 err_msg =
'The output and input matrix have to have the same sizes'
720 allocate(deta(
size(a,1),
size(a,2),
size(a,3)))
724 allocate(c_sub((n-1)**2))
725 allocate(l_sub(n**2)); l_sub = 0
726 allocate(k_sub(n**2)); k_sub = 0
740 l_sub = pack(idx,slct(:,1).gt.0)
741 k_sub = pack(idx,slct(:,2).gt.0)
744 c_sub((jd-1)*(n-1)+id) =
c([l_sub(id),k_sub(jd)],sym,n)
747 ierr = calc_det_3d(deta,a(:,:,:,c_sub),n-1)
749 inv_3d(:,:,:,
c([kd,ld],sym,n)) = (-1.0_dp)**(kd+ld)*deta
756 deallocate(c_sub,l_sub,k_sub)
763 deta = sign(max(abs(deta),
tol_zero),deta)
767 inv_3d(:,:,:,kd) = inv_3d(:,:,:,kd) / deta
769 end function calc_inv_3d
771 integer function calc_inv_0d(inv_0D,A)
result(ierr)
772 character(*),
parameter :: rout_name =
'calc_inv_0D'
775 real(dp),
intent(inout) :: inv_0d(:,:)
776 real(dp),
intent(in) :: a(:,:)
780 integer,
allocatable :: ipiv(:)
781 real(dp),
allocatable :: w(:)
782 character(len=max_str_ln) :: err_msg
788 if (
size(a,1).ne.
size(a,1))
then
789 err_msg =
'The input matrix A has to be square'
793 if (
size(inv_0d,1).ne.
size(a,1) .or.
size(inv_0d,2).ne.
size(a,2))
then
794 err_msg =
'The output and input matrix have to have the same sizes'
807 call dgetrf(n,n,inv_0d,n,ipiv,ierr)
808 err_msg =
'Lapack couldn''t find the LU factorization'
811 call dgetri(n,inv_0d,n,ipiv,w,n,ierr)
812 chckerr(
'Lapack couldn''t compute the inverse')
813 end function calc_inv_0d
816 integer function calc_mult_3d_real(A,B,AB,n,transp)
result(ierr)
817 character(*),
parameter :: rout_name =
'calc_mult_3D_real'
820 real(dp),
intent(in) :: a(:,:,:,:)
821 real(dp),
intent(in) :: b(:,:,:,:)
822 real(dp),
intent(inout) :: ab(:,:,:,:)
823 integer,
intent(in) :: n
824 logical,
intent(in),
optional :: transp(2)
829 character(len=max_str_ln) :: err_msg
830 integer :: id, jd, kd
832 integer :: c1, c2, c3
834 logical :: transp_loc(2)
840 if (
size(a,1).ne.
size(b,1) .or.
size(a,2).ne.
size(b,2) .or. &
841 &
size(a,3).ne.
size(b,3) .or.
size(a,1).ne.
size(ab,1) .or. &
842 &
size(a,2).ne.
size(ab,2) .or.
size(a,3).ne.
size(ab,3))
then
843 err_msg =
'The output and input matrices have to defined on the &
851 if (
present(transp)) transp_loc = transp
860 ierr =
is_sym(n,nn(id),sym(id))
873 if (sym(3)) id_min = jd
877 c3 =
c(ind(:,3),sym(3),n)
878 if (transp_loc(1))
then
883 c1 =
c(ind(:,1),sym(1),n)
884 if (transp_loc(2))
then
889 c2 =
c(ind(:,2),sym(2),n)
890 ab(:,:,:,c3) = ab(:,:,:,c3) + &
891 &a(:,:,:,c1)*b(:,:,:,c2)
895 end function calc_mult_3d_real
897 integer function calc_mult_3d_complex(A,B,AB,n,transp)
result(ierr)
898 character(*),
parameter :: rout_name =
'calc_mult_3D_complex'
901 complex(dp),
intent(in) :: a(:,:,:,:)
902 complex(dp),
intent(in) :: b(:,:,:,:)
903 complex(dp),
intent(inout) :: ab(:,:,:,:)
904 integer,
intent(in) :: n
905 logical,
intent(in),
optional :: transp(2)
910 character(len=max_str_ln) :: err_msg
911 integer :: id, jd, kd
913 integer :: c1, c2, c3
914 logical :: transp_loc(2)
922 if (
size(a,1).ne.
size(b,1) .or.
size(a,2).ne.
size(b,2) .or. &
923 &
size(a,3).ne.
size(b,3) .or.
size(a,1).ne.
size(ab,1) .or. &
924 &
size(a,2).ne.
size(ab,2) .or.
size(a,3).ne.
size(ab,3))
then
925 err_msg =
'The output and input matrices have to defined on the &
933 if (
present(transp)) transp_loc = transp
936 d = [
size(a,1),
size(a,2),
size(a,3)]
945 ierr =
is_sym(n,nn(id),sym(id))
958 if (sym(3)) id_min = jd
962 c3 =
c(ind(:,3),sym(3),n)
963 if (transp_loc(1))
then
968 c1 =
c(ind(:,1),sym(1),n)
969 if (transp_loc(2))
then
974 c2 =
c(ind(:,2),sym(2),n)
975 ab(:,:,:,c3) = ab(:,:,:,c3) + &
976 &
con(a(:,:,:,c1),ind(:,1),sym(1),
d)*&
977 &
con(b(:,:,:,c2),ind(:,2),sym(2),
d)
981 end function calc_mult_3d_complex
983 integer function calc_mult_0d_real(A,B,AB,n,transp)
result(ierr)
984 character(*),
parameter :: rout_name =
'calc_mult_0D_real'
987 real(dp),
intent(in) :: a(:)
988 real(dp),
intent(in) :: b(:)
989 real(dp),
intent(inout) :: ab(:)
990 integer,
intent(in) :: n
991 logical,
intent(in),
optional :: transp(2)
994 real(dp),
allocatable :: loc_ab(:,:,:,:)
1000 allocate(loc_ab(1,1,1,
size(ab)))
1003 ierr = calc_mult_3d_real(reshape(a,[1,1,1,
size(a)]),&
1004 &reshape(b,[1,1,1,
size(b)]),loc_ab,n,transp)
1007 ab = loc_ab(1,1,1,:)
1011 end function calc_mult_0d_real
1014 integer function conv_mat_3d(A,B,n,transp)
result(ierr)
1015 character(*),
parameter :: rout_name =
'conv_mat_3D'
1018 real(dp),
intent(in) :: a(:,:,:,:)
1019 real(dp),
intent(inout) :: b(:,:,:,:)
1020 integer,
intent(in) :: n
1021 logical,
intent(in),
optional :: transp
1025 logical :: transp_loc
1030 real(dp),
allocatable :: a_loc(:,:,:,:)
1040 transp_loc = .false.
1041 if (
present(transp)) transp_loc = transp
1044 allocate(a_loc(
size(a,1),
size(a,2),
size(a,3),
size(a,4)))
1049 ierr =
is_sym(n,nn(id),sym(id))
1054 if (sym(1).and.sym(2) .or. &
1055 &.not.sym(1).and..not.sym(2).and..not.transp_loc)
then
1069 if (transp_loc)
then
1076 b(:,:,:,
c(ind(:,2),sym(2),n)) = &
1077 &a_loc(:,:,:,
c(ind(:,1),sym(1),n))
1081 end function conv_mat_3d
1083 integer function conv_mat_0d(A,B,n,transp)
result(ierr)
1084 character(*),
parameter :: rout_name =
'conv_mat_0D'
1087 real(dp),
intent(in) :: a(:)
1088 real(dp),
intent(inout) :: b(:)
1089 integer,
intent(in) :: n
1090 logical,
intent(in),
optional :: transp
1093 real(dp),
allocatable :: b_loc(:,:,:,:)
1099 allocate(b_loc(1,1,1,
size(b)))
1102 ierr = conv_mat_3d(reshape(a,[1,1,1,
size(a)]),b_loc,n,transp)
1107 end function conv_mat_0d
1109 integer function conv_mat_3d_complex(A,B,n,transp)
result(ierr)
1110 character(*),
parameter :: rout_name =
'conv_mat_3D_complex'
1113 complex(dp),
intent(in) :: a(:,:,:,:)
1114 complex(dp),
intent(inout) :: b(:,:,:,:)
1115 integer,
intent(in) :: n
1116 logical,
intent(in),
optional :: transp
1120 logical :: transp_loc
1125 complex(dp),
allocatable :: a_loc(:,:,:,:)
1135 transp_loc = .false.
1136 if (
present(transp)) transp_loc = transp
1139 allocate(a_loc(
size(a,1),
size(a,2),
size(a,3),
size(a,4)))
1144 ierr =
is_sym(n,nn(id),sym(id))
1149 if (sym(1).and.sym(2) .or. &
1150 &.not.sym(1).and..not.sym(2).and..not.transp_loc)
then
1164 if (transp_loc)
then
1171 b(:,:,:,
c(ind(:,2),sym(2),n)) = &
1172 &a_loc(:,:,:,
c(ind(:,1),sym(1),n))
1176 end function conv_mat_3d_complex
1178 integer function conv_mat_0d_complex(A,B,n,transp)
result(ierr)
1179 character(*),
parameter :: rout_name =
'conv_mat_0D_complex'
1182 complex(dp),
intent(in) :: a(:)
1183 complex(dp),
intent(inout) :: b(:)
1184 integer,
intent(in) :: n
1185 logical,
intent(in),
optional :: transp
1188 complex(dp),
allocatable :: b_loc(:,:,:,:)
1194 allocate(b_loc(1,1,1,
size(b)))
1197 ierr = conv_mat_3d_complex(reshape(a,[1,1,1,
size(a)]),b_loc,n,transp)
1202 end function conv_mat_0d_complex
1205 integer function con2dis_eqd(pt_c,pt_d,lim_c,lim_d)
result(ierr)
1209 real(dp),
intent(in) :: pt_c
1210 real(dp),
intent(inout) :: pt_d
1211 real(dp),
intent(in) :: lim_c(2)
1212 integer,
intent(in) :: lim_d(2)
1221 pt_d = lim_d(1) + (lim_d(2)-lim_d(1)) * (pt_c-lim_c(1)) / &
1222 &(lim_c(2)-lim_c(1))
1223 end function con2dis_eqd
1225 integer function con2dis_reg(pt_c,pt_d,var_c)
result(ierr)
1226 character(*),
parameter :: rout_name =
'con2dis_reg'
1229 real(dp),
intent(in) :: pt_c
1230 real(dp),
intent(inout) :: pt_d
1231 real(dp),
intent(in) :: var_c(:)
1234 real(dp),
allocatable :: var_c_loc(:)
1235 real(dp),
allocatable :: var_c_inv(:)
1237 integer :: ind_lo, ind_hi
1239 real(dp) :: pt_c_loc
1240 character(len=max_str_ln) :: err_msg
1241 real(dp),
parameter :: tol = 1.e-8_dp
1247 size_c =
size(var_c)
1251 &
call writo(
'finding the discrete index of '//trim(r2str(pt_c)))
1255 allocate(var_c_loc(size_c))
1256 if (var_c(1).lt.var_c(size_c))
then
1262 &
call writo(
'setting var_c_loc = - var_c and pt_c_loc = -pt_c')
1269 allocate(var_c_inv(size_c))
1270 var_c_inv = var_c_loc(size_c:1:-1)
1276 if (pt_c_loc+tol*abs(pt_c_loc) .ge. var_c_loc(id))
then
1280 &trim(i2str(id))//
'/'//trim(i2str(size_c))//
', '//&
1281 &trim(r2strt(pt_c_loc))//
' + '//trim(r2strt(tol))//&
1282 &
'*abs('//trim(r2strt(pt_c_loc))//
') >= '//&
1283 &trim(r2strt(var_c_loc(id)))//
' => ['//&
1284 &trim(i2str(ind_lo))//
','//trim(i2str(ind_hi))//
']')
1287 if (pt_c_loc-tol*abs(pt_c_loc) .le. var_c_inv(id))
then
1288 ind_hi = size_c+1-id
1291 &trim(i2str(id))//
'/'//trim(i2str(size_c))//
', '//&
1292 &trim(r2strt(pt_c_loc))//
' - '//trim(r2strt(tol))//&
1293 &
'*abs('//trim(r2strt(pt_c_loc))//
') < '//&
1294 &trim(r2strt(var_c_inv(id)))//
' => ['//&
1295 &trim(i2str(ind_lo))//
','//trim(i2str(ind_hi))//
']')
1301 call writo(
'final ind_lo = '//trim(i2str(ind_lo))//
', ind_hi = '//&
1302 &trim(i2str(ind_hi)))
1309 if (ind_lo.eq.0 .or. ind_hi.eq.size_c+1)
then
1312 err_msg =
'pt_c '//trim(r2str(pt_c))//
' not within range '//&
1313 &trim(r2str(minval(var_c)))//
'..'//trim(r2str(maxval(var_c)))
1318 if (ind_lo.lt.ind_hi)
then
1319 pt_d = ind_lo + (pt_c_loc-var_c_loc(ind_lo))/&
1320 &(var_c_loc(ind_hi)-var_c_loc(ind_lo))
1321 else if (ind_lo.eq.ind_hi)
then
1326 err_msg =
'ind_lo cannot be higher than ind_hi'
1331 deallocate(var_c_loc,var_c_inv)
1332 end function con2dis_reg
1335 integer function dis2con_eqd(pt_d,pt_c,lim_d,lim_c)
result(ierr)
1339 integer,
intent(in) :: pt_d
1340 real(dp),
intent(inout) :: pt_c
1341 integer,
intent(in) :: lim_d(2)
1342 real(dp),
intent(in) :: lim_c(2)
1351 pt_c = lim_c(1) + (lim_c(2)-lim_c(1)) * (pt_d-lim_d(1)) / &
1352 &(lim_d(2)-lim_d(1))
1353 end function dis2con_eqd
1355 integer function dis2con_reg(pt_d,pt_c,var_c)
result(ierr)
1356 character(*),
parameter :: rout_name =
'dis2con_reg'
1359 integer,
intent(in) :: pt_d
1360 real(dp),
intent(inout) :: pt_c
1361 real(dp),
intent(in) :: var_c(:)
1364 character(len=max_str_ln) :: err_msg
1370 if (pt_d.lt.1 .or. pt_d.gt.
size(var_c))
then
1373 err_msg =
'pt_c not within range'
1379 end function dis2con_reg
1382 integer function round_with_tol_arr(vals,lim_lo,lim_hi,tol)
result(ierr)
1383 character(*),
parameter :: rout_name =
'round_with_tol_arr'
1386 real(dp),
intent(inout) :: vals(:)
1387 real(dp),
intent(in) :: lim_lo
1388 real(dp),
intent(in) :: lim_hi
1389 real(dp),
intent(in),
optional :: tol
1393 character(len=max_str_ln) :: err_msg
1399 if (
present(tol))
then
1406 err_msg =
'value has to lie within 0..1'
1408 if (minval(vals-lim_lo+loc_tol).lt.0)
then
1411 else if (maxval(vals-lim_hi-loc_tol).gt.0)
then
1415 where (vals.lt.lim_lo) vals = lim_lo
1416 where (vals.gt.lim_hi) vals = lim_hi
1418 end function round_with_tol_arr
1420 integer function round_with_tol_ind(val,lim_lo,lim_hi,tol)
result(ierr)
1421 character(*),
parameter :: rout_name =
'round_with_tol_ind'
1424 real(dp),
intent(inout) :: val
1425 real(dp),
intent(in) :: lim_lo
1426 real(dp),
intent(in) :: lim_hi
1427 real(dp),
intent(in),
optional :: tol
1437 ierr = round_with_tol_arr(vals,lim_lo,lim_hi,tol)
1441 end function round_with_tol_ind
1444 function con_3d(A,c,sym,d)
result(B)
1445 complex(dp),
intent(in) :: a(:,:,:)
1446 integer,
intent(in) ::
c(2)
1447 logical,
intent(in) :: sym
1448 integer,
intent(in) ::
d(3)
1449 complex(dp) :: b(
d(1),
d(2),
d(3))
1452 if (
c(2).gt.
c(1) .and. sym)
then
1459 function con_2d(A,c,sym,d)
result(B)
1460 complex(dp),
intent(in) :: a(:,:)
1461 integer,
intent(in) ::
c(2)
1462 logical,
intent(in) :: sym
1463 integer,
intent(in) ::
d(2)
1464 complex(dp) :: b(
d(1),
d(2))
1467 if (
c(2).gt.
c(1) .and. sym)
then
1474 function con_1d(A,c,sym,d)
result(B)
1475 complex(dp),
intent(in) :: a(:)
1476 integer,
intent(in) ::
c(2)
1477 logical,
intent(in) :: sym
1478 integer,
intent(in) ::
d(1)
1479 complex(dp) :: b(
d(1))
1482 if (
c(2).gt.
c(1) .and. sym)
then
1489 function con_0d(A,c,sym)
result(B)
1490 complex(dp),
intent(in) :: a
1491 integer,
intent(in) ::
c(2)
1492 logical,
intent(in) :: sym
1496 if (
c(2).gt.
c(1) .and. sym)
then
1504 subroutine bubble_sort_real(a,piv)
1506 real(dp),
intent(inout) :: a(:)
1507 integer,
intent(inout),
optional :: piv(:)
1516 if (
present(piv))
then
1517 if (
size(piv).eq.
size(a))
then
1519 piv = [(jd,jd=1,
size(a))]
1523 do jd =
size(a)-1,1,-1
1526 if (a(id) .gt. a(id+1))
then
1530 piv(id:id+1) = piv(id+1:id:-1)
1534 if (.not. swapped)
exit
1536 end subroutine bubble_sort_real
1538 subroutine bubble_sort_int(a,piv)
1540 integer,
intent(inout) :: a(:)
1541 integer,
intent(inout),
optional :: piv(:)
1550 if (
present(piv))
then
1551 if (
size(piv).eq.
size(a))
then
1553 piv = [(jd,jd=1,
size(a))]
1557 do jd =
size(a)-1,1,-1
1560 if (a(id) .gt. a(id+1))
then
1564 if (
present(piv)) piv(id:id+1) = piv(id+1:id:-1)
1568 if (.not. swapped)
exit
1570 end subroutine bubble_sort_int
1573 integer function order_per_fun_1(x,y,x_out,y_out,overlap,tol)
result(ierr)
1576 character(*),
parameter :: rout_name =
'order_per_fun_1'
1579 real(
dp),
intent(in) :: x(:)
1580 real(
dp),
intent(in) :: y(:)
1581 real(
dp),
intent(inout),
allocatable :: x_out(:)
1582 real(
dp),
intent(inout),
allocatable :: y_out(:)
1583 integer,
intent(in) :: overlap
1584 real(
dp),
intent(in),
optional :: tol
1588 real(
dp),
allocatable :: x_fund(:)
1591 integer :: lim_loc(2)
1592 character(len=max_str_ln) :: err_msg
1599 if (
present(tol)) tol_loc = tol
1602 if (abs(cos(x(
size(x)))-cos(x(1))).lt.tol_loc .and. &
1603 &abs(sin(x(
size(x)))-sin(x(1))).lt.tol_loc)
then
1605 err_msg =
'First and last point cannot be identical. Remove one.'
1610 allocate(x_fund(
size(x)))
1611 x_fund = mod(x,2*
pi)
1612 where(x_fund.lt.0._dp) x_fund = x_fund+2*
pi
1613 ml_x = maxloc(x_fund,1)
1615 allocate(x_out(
size(x)+2*overlap))
1616 allocate(y_out(
size(x)+2*overlap))
1619 lim = [max(ml_x-overlap+1,1),ml_x]
1620 lim_loc = [overlap-lim(2)+lim(1),overlap]
1621 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))-2*
pi
1622 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1623 lim_loc = [1,lim_loc(1)-1]
1624 lim = [
size(x)-(lim_loc(2)-lim_loc(1)),
size(x)]
1625 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))-2*
pi
1626 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1629 lim = [ml_x+1,
size(x)]
1630 lim_loc = [overlap+1,overlap+lim(2)-lim(1)+1]
1631 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))
1632 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1634 lim_loc = lim_loc(2) + [1,lim(2)-lim(1)+1]
1635 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))
1636 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1639 lim = [ml_x+1,min(ml_x+overlap,
size(x))]
1640 lim_loc = lim_loc(2) + [1,lim(2)-lim(1)+1]
1641 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))+2*
pi
1642 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1643 lim_loc = [lim_loc(2)+1,
size(x)+2*overlap]
1644 lim = [1,lim_loc(2)-lim_loc(1)+1]
1645 x_out(lim_loc(1):lim_loc(2)) = x_fund(lim(1):lim(2))+2*
pi
1646 y_out(lim_loc(1):lim_loc(2)) = y(lim(1):lim(2))
1647 end function order_per_fun_1
1649 integer function order_per_fun_2(xy,xy_out,overlap,tol)
result(ierr)
1650 character(*),
parameter :: rout_name =
'order_per_fun_2'
1653 real(dp),
intent(in) :: xy(:,:)
1654 real(dp),
intent(inout),
allocatable :: xy_out(:,:)
1655 integer,
intent(in) :: overlap
1656 real(dp),
intent(in),
optional :: tol
1659 real(dp),
allocatable :: x_out(:)
1660 real(dp),
allocatable :: y_out(:)
1665 ierr = order_per_fun_1(xy(:,1),xy(:,2),x_out,y_out,overlap,tol)
1668 allocate(xy_out(
size(x_out),2))
1671 end function order_per_fun_2
1674 integer function spline_real(x,y,xnew,ynew,ord,deriv,bcs,bcs_val,extrap) &
1680 character(*),
parameter :: rout_name =
'spline_real'
1683 real(dp),
intent(in),
target :: x(:)
1684 real(dp),
intent(in) :: y(:)
1685 real(dp),
intent(in),
target :: xnew(:)
1686 real(dp),
intent(out) :: ynew(:)
1687 integer,
intent(in),
optional :: ord
1688 integer,
intent(in),
optional :: deriv
1689 integer,
intent(in),
optional :: bcs(2)
1690 real(dp),
intent(in),
optional :: bcs_val(2)
1691 logical,
intent(in),
optional :: extrap
1694 type(ezspline1_r8) :: f_spl
1696 integer :: deriv_loc
1697 integer :: bcs_loc(2)
1701 integer :: nnew_interp
1703 real(dp),
pointer :: x_loc(:)
1704 real(dp),
pointer :: xnew_loc(:)
1705 real(dp) :: bcs_val_loc(2)
1706 real(dp) :: lim_vals(0:3)
1707 real(dp),
allocatable :: xnew_ez(:)
1708 real(dp),
allocatable :: ynew_ez(:)
1709 character(len=max_str_ln) :: err_msg
1711 logical :: extrap_loc
1718 if (
present(ord)) ord_loc = ord
1720 if (
present(deriv)) deriv_loc = deriv
1722 if (
present(bcs)) bcs_loc = bcs
1723 if (
present(bcs_val)) bcs_val_loc = bcs_val
1724 extrap_loc = .false.
1725 if (
present(extrap)) extrap_loc = extrap
1732 flip_x = (x(2) .lt. x(1))
1735 allocate(xnew_loc(nnew))
1746 if (x_loc(kd).le.x_loc(kd-1))
then
1748 err_msg =
'|x| is not monotonously increasing'
1754 if (
size(y).ne.n)
then
1756 err_msg =
'x and y need to have the same size'
1759 if (
size(ynew).ne.nnew)
then
1761 err_msg =
'xnew and ynew need to have the same size'
1766 if (ord_loc.lt.1 .or. ord_loc.gt.3)
then
1768 err_msg =
'Only order 1 (linear), 2 (akima hermite) or 3 (cubic) &
1774 select case (deriv_loc)
1777 err_msg =
'only nonnegative degrees of derivative are possible'
1782 if (ord_loc.eq.1 .or. ord_loc.eq.2)
then
1784 err_msg =
'Derivative of degree '//trim(i2str(deriv_loc))//&
1785 &
' not possible for order '//trim(i2str(ord_loc))
1790 err_msg =
'maximum degree of derivative is 2 for order 4'
1795 select case (ord_loc)
1797 if (
present(bcs) .or.
present(bcs_val))
then
1798 call writo(
'for order 1, no boundary conditions can be &
1799 &prescribed',alert=.true.)
1804 if (bcs_loc(kd).lt.-1 .or. bcs_loc(kd).gt.ord_loc-1)
then
1806 err_msg =
'For order '//trim(i2str(ord_loc))//&
1807 &
' bcs has to be -1..'//trim(i2str(ord_loc-1))
1813 if ((any(bcs_loc.eq.1) .or. any(bcs_loc.eq.2)) &
1814 &.and. .not.
present(bcs_val))
then
1816 err_msg =
'When prescribing first or second derviatives, &
1817 &need to provide bcs_val'
1825 if (xnew_loc(kd).ge.x_loc(1))
exit
1829 if (xnew_loc(kd).le.x_loc(n))
exit
1832 nnew_interp = il(2)-il(1)+1
1835 if ((il(1).ne.1 .or. il(2).ne.nnew) .and. &
1836 &.not.extrap_loc)
then
1838 call writo(
'xnew = ['//trim(r2str(minval(xnew)))//
'..'//&
1839 &trim(r2str(maxval(xnew)))//
']')
1840 call writo(
'but x = ['//trim(r2str(minval(x)))//
'..'//&
1841 &trim(r2str(maxval(x)))//
']')
1842 err_msg =
'Extrapolation needed, but not allowed'
1847 if (ord_loc.eq.1)
then
1848 call ezlinear_init(f_spl,n,ierr)
1849 call ezspline_error(ierr)
1852 call ezspline_init(f_spl,n,bcs_loc,ierr)
1853 call ezspline_error(ierr)
1855 if (ord_loc.eq.2) f_spl%isHermite = 1
1862 if (
present(bcs_val))
then
1863 f_spl%bcval1min = bcs_val_loc(1)
1864 f_spl%bcval1max = bcs_val_loc(2)
1866 if (bcs_loc(1) .eq. 1) f_spl%bcval1min = -f_spl%bcval1min
1867 if (bcs_loc(2) .eq. 1) f_spl%bcval1max = -f_spl%bcval1max
1872 call ezspline_setup(f_spl,y,ierr,exact_dim=.true.)
1873 call ezspline_error(ierr)
1876 if (il(1).le.il(2))
then
1877 allocate(xnew_ez(nnew_interp))
1878 allocate(ynew_ez(nnew_interp))
1879 xnew_ez = xnew_loc(il(1):il(2))
1881 if (deriv_loc.eq.0)
then
1883 call ezspline_interp(f_spl,nnew_interp,xnew_ez,ynew_ez,ierr)
1884 call ezspline_error(ierr)
1887 call ezspline_derivative(f_spl,deriv_loc,nnew_interp,xnew_ez,&
1889 call ezspline_error(ierr)
1893 ynew(il(1):il(2)) = ynew_ez
1894 deallocate(xnew_ez,ynew_ez)
1898 if (extrap_loc)
then
1900 if (il(1).gt.1)
then
1906 call calc_extrap(xnew_loc(1:il(1)-1),x_loc(1),lim_vals,&
1911 if (il(2).lt.nnew)
then
1917 call calc_extrap(xnew_loc(il(2)+1:nnew),x_loc(n),lim_vals,&
1918 &ynew(il(2)+1:nnew))
1923 call ezspline_free(f_spl,ierr)
1925 call ezspline_error(ierr)
1929 deallocate(xnew_loc)
1938 character(*),
parameter :: rout_name =
'setup_lim_vals'
1941 real(dp),
intent(in) :: xb
1942 real(dp),
intent(out) :: lim_vals(0:3)
1946 integer :: max_deriv
1953 select case(ord_loc)
1961 call ezspline_interp(f_spl,xb,lim_vals(0),ierr)
1962 call ezspline_error(ierr)
1967 call ezspline_derivative(f_spl,kd,xb,lim_vals(kd),ierr)
1968 call ezspline_error(ierr)
1974 subroutine calc_extrap(xnew,xb,lim_vals,ynew)
1976 real(dp),
intent(in) :: xnew(:)
1977 real(dp),
intent(in) :: xb
1978 real(dp),
intent(in) :: lim_vals(0:2)
1979 real(dp),
intent(out) :: ynew(:)
1982 real(dp),
allocatable :: xdel(:)
1984 allocate(xdel(
size(xnew)))
1987 select case (deriv_loc)
1989 ynew = lim_vals(0) + &
1990 &lim_vals(1)*xdel + &
1991 &lim_vals(2)*xdel**2*0.5_dp
1993 ynew = lim_vals(1) + &
1998 end subroutine calc_extrap
1999 end function spline_real
2001 integer function spline_complex(x,y,xnew,ynew,ord,deriv,bcs,bcs_val,&
2002 &extrap)
result(ierr)
2007 character(*),
parameter :: rout_name =
'spline_complex'
2010 real(dp),
intent(in) :: x(:)
2011 complex(dp),
intent(in) :: y(:)
2012 real(dp),
intent(in) :: xnew(:)
2013 complex(dp),
intent(out) :: ynew(:)
2014 integer,
intent(in),
optional :: ord
2015 integer,
intent(in),
optional :: deriv
2016 integer,
intent(in),
optional :: bcs(2)
2017 complex(dp),
intent(in),
optional :: bcs_val(2)
2018 logical,
intent(in),
optional :: extrap
2021 real(dp),
allocatable :: ynew_loc(:,:)
2024 allocate(ynew_loc(
size(ynew),2))
2027 if (
present(bcs_val))
then
2028 ierr = spline_real(x,rp(y),xnew,ynew_loc(:,1),ord,deriv,bcs,&
2029 &bcs_val=rp(bcs_val),extrap=extrap)
2032 ierr = spline_real(x,rp(y),xnew,ynew_loc(:,1),ord,deriv,bcs,&
2038 if (
present(bcs_val))
then
2039 ierr = spline_real(x,ip(y),xnew,ynew_loc(:,2),ord,deriv,bcs,&
2040 &bcs_val=ip(bcs_val),extrap=extrap)
2043 ierr = spline_real(x,ip(y),xnew,ynew_loc(:,2),ord,deriv,bcs,&
2049 ynew = ynew_loc(:,1) + iu*ynew_loc(:,2)
2050 end function spline_complex
2066 integer,
intent(in),
optional :: n_mod
2069 integer :: id, jd, kd
2079 d(id,jd,kd) = calc_derivs_1d_id([id,jd,kd],3)
2088 allocate(
m(1:3,1:3))
2091 m(id,jd) = calc_derivs_1d_id([id,jd],2)
2096 if (
present(n_mod))
then
2097 allocate(
f(1:n_mod,1:n_mod))
2100 f(id,jd) = calc_derivs_1d_id([id,jd],2)
2145 integer function calc_derivs_1d_id(deriv,dims)
result(res)
2147 integer,
intent(in) :: deriv(:)
2148 integer,
intent(in) :: dims
2153 integer :: tot_deriv
2154 integer,
allocatable :: deriv_loc(:)
2157 allocate(deriv_loc(0:
size(deriv)))
2159 deriv_loc(1:
size(deriv)) = deriv
2162 tot_deriv = sum(deriv)
2169 if (tot_deriv.gt.0)
then
2172 do id = 1,
size(deriv)
2173 if (deriv(id).gt.0) id_max = id
2179 do id = 0,tot_deriv-sum(deriv_loc(0:jd))-1
2180 res = res +
fac(dims-jd+id-1)/(
fac(id)*
fac(dims-jd-1))
2184 end function calc_derivs_1d_id
2203 recursive subroutine calc_derivs_of_order(res,order,dims)
2205 integer,
intent(inout),
allocatable :: res(:,:)
2206 integer,
intent(in) :: order
2207 integer,
intent(in),
optional :: dims
2211 integer,
allocatable :: derivs_loc(:,:)
2217 if (
present(dims)) dims_loc = dims
2220 if (
allocated(res))
deallocate(res)
2222 &dims_loc,
fac(order+dims_loc-1)/(
fac(order)*
fac(dims_loc-1))))
2225 if (order.gt.0)
then
2230 if (dims_loc.gt.1)
then
2231 call calc_derivs_of_order(derivs_loc,order-id,dims_loc-1)
2232 res(1,id_tot+1:id_tot+
size(derivs_loc,2)) = id
2233 res(2:dims_loc,id_tot+1:id_tot+
size(derivs_loc,2)) &
2235 id_tot = id_tot+
size(derivs_loc,2)
2243 end subroutine calc_derivs_of_order
2247 integer,
intent(in) :: order
2248 integer,
intent(in),
optional :: dims
2249 integer,
allocatable :: res(:,:)
2252 call calc_derivs_of_order(res,order,dims)
2260 character(*),
parameter :: rout_name =
'check_deriv'
2263 integer,
intent(in) :: deriv(3)
2264 integer,
intent(in) :: max_deriv
2265 character(len=*),
intent(in) :: sr_name
2269 character(len=max_str_ln) :: err_msg
2276 if (deriv(id).gt.max_deriv)
then
2277 err_msg =
'Asking '//trim(sr_name)//
' for a derivative&
2278 & in the '//trim(i2str(id))//
'th dimension of order '&
2279 &//trim(i2str(deriv(id)))//
', while the maximum order is '&
2280 &//trim(i2str(max_deriv))
2325 character(*),
parameter :: rout_name =
'ext_var'
2328 real(dp),
intent(inout) :: ext_var
2329 real(dp),
intent(in) :: var(:)
2330 real(dp),
intent(in) :: var_points(:)
2331 real(dp),
intent(in) :: ext_point
2332 integer,
intent(in),
optional :: deriv_in
2339 real(dp),
allocatable :: a(:,:), lu(:,:)
2340 real(dp),
allocatable :: a_i(:)
2342 character(len=max_str_ln) :: err_msg
2351 if (
size(var).ne.
size(var_points))
then
2352 err_msg =
'The size of the arrays containing the variable and &
2353 &the points do not match'
2357 if (
present(deriv_in))
then
2359 if (deriv.ge.pol_deg)
then
2360 err_msg =
'Asking ext_var for '//trim(i2str(deriv_in))&
2361 &//
'th derivative, while using a polynomial of degree '&
2362 &//trim(i2str(pol_deg))
2365 else if (deriv.lt.0)
then
2366 err_msg =
'Asking ext_var for a derivative of order '&
2367 &//trim(i2str(deriv_in))
2376 allocate(a(pol_deg,pol_deg))
2377 allocate(lu(pol_deg,pol_deg))
2379 col:
do jd = 2, pol_deg
2380 row:
do id = 1, pol_deg
2381 a(id,jd) = var_points(id)**(jd-1)
2386 allocate(a_i(pol_deg))
2389 call dgesv( pol_deg, 1, lu, pol_deg, [(id,id=1,pol_deg)], &
2390 &a_i, pol_deg, istat)
2393 if (istat.ne.0)
then
2394 err_msg =
'The solution could not be found. Are the extrapolating &
2395 &points independent?'
2398 call writo(
'The matrix equation to be solved was Ax=b, A = ')
2400 call writo(
'and b = ')
2401 call print_ar_1(var)
2409 polynom:
do id = 1+deriv, pol_deg
2412 d_dx:
do jd = 1,deriv
2413 fact = fact * float((id-1)-(jd-1))
2416 ext_var = ext_var + fact*a_i(id)*ext_point**(id-1-deriv)
2449 character(*),
parameter :: rout_name =
'calc_coeff_fin_diff'
2452 integer,
intent(in) :: deriv
2453 integer,
intent(in) :: nr
2454 integer,
intent(in) :: ind
2455 real(dp),
intent(inout),
allocatable :: coeff(:)
2458 character(len=max_str_ln) :: err_msg
2459 real(dp),
allocatable :: mat_loc(:)
2460 real(dp),
allocatable :: rhs_loc(:)
2468 if (deriv.le.0)
then
2470 err_msg =
'The degree of the derivative has to be positive'
2475 err_msg =
'The number of points in the finite differences has to &
2479 if (ind.lt.1 .or. ind.gt.nr)
then
2481 err_msg =
'The position of the derivative is not in range.'
2486 if (deriv.gt.nr-1)
then
2488 err_msg =
'For derivatives of degree '//trim(i2str(deriv))//&
2489 &
' minimally '//trim(i2str(deriv+1))//
' points are necessary'
2494 if (
allocated(coeff))
deallocate(coeff)
2496 allocate(mat_loc(nr))
2497 allocate(rhs_loc(nr))
2501 mat_loc(id) = (id-ind)*1._dp
2504 rhs_loc(deriv+1) = 1._dp
2505 call solve_vand(nr,mat_loc,rhs_loc,coeff,transp=.true.)
2506 coeff = coeff*
fac(deriv)
2555 integer function c(ij,sym,n,lim_n)
2557 integer,
intent(in) :: ij(2)
2558 logical,
intent(in) :: sym
2559 integer,
intent(in),
optional :: n
2560 integer,
intent(in),
optional :: lim_n(2,2)
2565 integer :: ij_loc(2)
2570 if (
present(n)) n_loc = n
2576 if (
present(lim_n)) ij_loc = ij + lim_n(1,:) - 1
2579 if (ij_loc(2).gt.ij_loc(1))
then
2581 ij_loc(2) = ij_loc(1)
2586 c = nint((ij_loc(2)-1)*n_loc + ij_loc(1) - &
2587 &(ij_loc(2)-1)*ij_loc(2)*0.5)
2589 if (
present(lim_n))
then
2591 js = max(0,min(ij_loc(2)-lim_n(1,2)+1,lim_n(1,1)-lim_n(1,2)+1))
2592 c =
c - nint((lim_n(1,2)-1)*(n_loc+1-lim_n(1,2)*0.5) &
2593 &+js*(lim_n(1,1)-lim_n(1,2)+0.5-js*0.5) &
2594 &+(n_loc-lim_n(2,1))*(ij_loc(2)-lim_n(1,2)))
2597 if (
present(lim_n))
then
2599 c = (ij(2)-1)*(lim_n(2,1)-lim_n(1,1)+1) + ij(1)
2602 c = (ij(2)-1)*n_loc + ij(1)
2608 recursive function fac(n)
result(fact)
2610 integer,
intent(in) :: n
2625 integer function is_sym(n,nn,sym)
result(ierr)
2626 character(*),
parameter :: rout_name =
'is_sym'
2629 integer,
intent(in) :: n
2630 integer,
intent(in) :: nn
2631 logical,
intent(inout) :: sym
2634 character(len=max_str_ln) :: err_msg
2640 if (nn.eq.n**2)
then
2642 else if (nn.eq.n*(n+1)/2)
then
2646 err_msg =
'The matrix corresponds neither to a symmetric nor to a &
2656 recursive function lcm(u, v)
result(res)
2657 integer,
intent(in) :: u
2658 integer,
intent(in) :: v
2661 res = u*v /
gcd(u,v)
2668 recursive function gcd(u, v)
result(res)
2669 integer,
intent(in) :: u
2670 integer,
intent(in) :: v
2673 if (mod(u, v) /= 0)
then
2674 res =
gcd(v, mod(u, v))
2697 integer,
intent(in) :: al(2)
2698 integer,
intent(in) :: bl(2)
2699 integer,
intent(in) :: cl(2)
2700 real(dp),
intent(in) :: a(al(1):al(2),2)
2701 real(dp),
intent(in) :: b(bl(1):bl(2),2)
2702 real(dp),
intent(inout) ::
c(cl(1):cl(2),2)
2705 integer :: i_a, i_b, i_c
2711 do i_a = al(1),al(2)
2712 do i_b = bl(1),bl(2)
2716 if (i_c.ge.cl(1) .and. i_c.le.cl(2))
then
2717 c(i_c,1) =
c(i_c,1) + 0.5* a(i_a,1)*b(i_b,1)
2718 c(i_c,2) =
c(i_c,2) + 0.5* a(i_a,1)*b(i_b,2)
2719 c(i_c,2) =
c(i_c,2) + 0.5* a(i_a,2)*b(i_b,1)
2720 c(i_c,1) =
c(i_c,1) - 0.5* a(i_a,2)*b(i_b,2)
2726 if (i_c.ge.cl(1) .and. i_c.le.cl(2))
then
2727 c(i_c,1) =
c(i_c,1) + 0.5* a(i_a,1)*b(i_b,1)
2728 c(i_c,2) =
c(i_c,2) - 0.5* a(i_a,1)*b(i_b,2)
2729 c(i_c,2) =
c(i_c,2) + 0.5* a(i_a,2)*b(i_b,1)
2730 c(i_c,1) =
c(i_c,1) + 0.5* a(i_a,2)*b(i_b,2)
2752 integer,
intent(in) :: n
2753 real(dp),
intent(in) :: a(n)
2754 real(dp),
intent(in) :: b(n)
2755 real(dp),
intent(inout) :: x(n)
2756 logical,
intent(in),
optional :: transp
2760 logical :: transp_loc
2763 transp_loc = .false.
2764 if (
present(transp)) transp_loc = transp
2767 if (transp_loc)
then
2769 do jd = n, kd + 1, -1
2770 x(jd) = x(jd) - a(kd) * x(jd-1)
2774 do kd = n - 1, 1, -1
2776 x(jd) = x(jd) / ( a(jd) - a(jd-kd) )
2779 x(jd) = x(jd) - x(jd+1)
2784 do jd = n, kd + 1, -1
2785 x(jd) = ( x(jd) - x(jd-1) ) / ( a(jd) - a(jd-kd) )
2789 do kd = n - 1, 1, -1
2791 x(jd) = x(jd) - a(kd) * x(jd+1)
2829 character(*),
parameter :: rout_name =
'calc_D2_smooth'
2832 integer,
intent(in) :: fil_n
2833 real(dp),
intent(in) :: x(:)
2834 real(dp),
intent(in) :: y(:)
2835 real(dp),
intent(inout) :: d2y(:)
2836 integer,
intent(in) :: style
2842 real(dp),
allocatable :: s(:)
2843 real(dp),
allocatable :: ab(:)
2844 character(len=max_str_ln) :: err_msg
2850 if (fil_n.lt.5)
then
2852 err_msg =
'filter length must be at least 5'
2855 if (mod(fil_n,2).ne.1)
then
2857 err_msg =
'filter length must be odd'
2864 allocate(s(0:sym_m+1))
2870 do kd = sym_m-1,0,-1
2871 s(kd) = ((2*fil_n-10)*s(kd+1) - (fil_n+2*kd+3)*s(kd+2)) / &
2879 d2y(1:sym_m) = 0._dp
2880 d2y(n-sym_m+1:n) = 0._dp
2881 do id = sym_m+1,n-sym_m
2884 ab(kd) = 4*kd**2*s(kd)*(x(id+kd)-x(id-kd))**(-2)
2887 d2y(id) = sum(ab*(y(id+1:id+sym_m))) + &
2888 &sum(ab*y(id-1:id-sym_m:-1)) - &
2892 d2y(1:2*sym_m) = 0._dp
2896 ab(kd) = 4*kd**2*s(kd)*(x(id+kd-sym_m)-x(id-kd-sym_m))**(-2)
2899 d2y(id) = sum(ab*(y(id+1-sym_m:id))) + &
2900 &sum(ab*y(id-1-sym_m:id-2*sym_m:-1)) - &
2901 &2*y(id-sym_m)*sum(ab)
2904 err_msg =
'No style associated with '//trim(i2str(style))
2910 d2y = d2y * 2._dp**(3._dp-fil_n)
Add to an array (3) the product of arrays (1) and (2).
Sorting with the bubble sort routine.
Calculate determinant of a matrix.
Integrates a function using the trapezoidal rule.
Calculate inverse of square matrix A.
Calculate matrix multiplication of two square matrices .
Convert between points from a continuous grid to a discrete grid.
Either takes the complex conjugate of a square matrix element A, defined on a 3-D grid,...
Converts a (symmetric) matrix A with the storage convention described in eq_vars.eq_2_type.
Convert between points from a discrete grid to a continuous grid.
Order a periodic function to include and an overlap.
Rounds an arry of values to limits, with a tolerance that can optionally be modified.
Wrapper to the pspline library, making it easier to use for 1-D applications where speed is not the m...
Numerical utilities related to giving output.
integer function, public check_deriv(deriv, max_deriv, sr_name)
checks whether the derivatives requested for a certain subroutine are valid
integer function, public calc_ext_var(ext_var, var, var_points, ext_point, deriv_in)
Extrapolates a function.
recursive integer function, public lcm(u, v)
Returns common multiple using the Euclid's algorithm.
recursive integer function, public gcd(u, v)
Returns least denominator using the GCD.
recursive integer function, public fac(n)
Calculate factorial.
integer function, public calc_coeff_fin_diff(deriv, nr, ind, coeff)
Calculate the coefficients for finite differences.
integer function, public is_sym(n, nn, sym)
Determines whether a matrix making use of the storage convention in eq_vars.eq_2_type is symmetric or...
subroutine, public solve_vand(n, a, b, x, transp)
Solve a Vandermonde system .
integer function, public c(ij, sym, n, lim_n)
Convert 2-D coordinates (i,j) to the storage convention used in matrices.
integer, dimension(:,:,:), allocatable, public d
1-D array indices of derivatives
integer, dimension(:,:), allocatable, public f
1-D array indices of Fourier mode combination indices
integer function, public calc_d2_smooth(fil_n, x, y, d2y, style)
Calculate second derivative with smoothing formula by Holoborodko, holoborodko2008diff.
logical, public debug_con2dis_reg
plot debug information for con2dis_reg()
subroutine, public shift_f(al, bl, cl, a, b, c)
Calculate multiplication through shifting of fourier modes A and B into C.
integer function, dimension(:,:), allocatable, public derivs(order, dims)
Returns derivatives of certain order.
integer, dimension(:,:), allocatable, public m
1-D array indices of metric indices
logical, public debug_calc_coeff_fin_diff
plot debug information for calc_coeff_fin_diff()
subroutine, public calc_aux_utilities(n_mod)
Initialize utilities for fast future reference, depending on program style.
Numerical variables used by most other modules.
integer, parameter, public dp
double precision
real(dp), parameter, public pi
complex(dp), parameter, public iu
complex unit
integer, parameter, public max_str_ln
maximum length of strings
integer, parameter, public max_deriv
highest derivatives for metric factors in Flux coords.
real(dp), public tol_zero
tolerance for zeros
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
integer function setup_lim_vals(xb, lim_vals)
/private set up limit values