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
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')
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
2088 allocate(
m(1:3,1:3))
2096 if (
present(n_mod))
then
2097 allocate(
f(1:n_mod,1:n_mod))
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))
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
2245 function derivs(order,dims)
result(res)
2247 integer,
intent(in) :: order
2248 integer,
intent(in),
optional :: dims
2249 integer,
allocatable :: res(:,:)
2252 call calc_derivs_of_order(res,order,dims)
2259 integer function check_deriv(deriv,max_deriv,sr_name)
result(ierr)
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))
2323 integer function calc_ext_var(ext_var,var,var_points,ext_point,deriv_in) &
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))
2695 subroutine shift_f(Al,Bl,Cl,A,B,C)
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)
2828 integer function calc_d2_smooth(fil_N,x,y,D2y,style)
result(ierr)
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)