32 INTEGER,
PARAMETER :: rprec = selected_real_kind(12,100)
33 INTEGER,
PARAMETER :: iprec = selected_int_kind(8)
34 INTEGER,
PARAMETER :: cprec = kind((1.0_rprec,1.0_rprec))
35 REAL(rprec),
PARAMETER :: pi=3.14159265358979323846264338328_rprec
36 REAL(rprec),
PARAMETER :: twopi=6.28318530717958647692528677_rprec
37 REAL(rprec),
PARAMETER :: one = 1.0_rprec
38 REAL(rprec),
PARAMETER :: zero = 0.0_rprec
39 INTEGER :: mpi_err, myrank=0
43 PRIVATE rprec, iprec, cprec, pi, twopi, one, zero, mpi_err
56 MODULE PROCEDURE assert1,assert2,assert3,assert4,assert_v
63 MODULE PROCEDURE assert_eq2,assert_eq3,assert_eq4,assert_eqn
85 SUBROUTINE assert1(n1,string,err_class)
87 CHARACTER(LEN=*),
INTENT(IN) :: string
88 LOGICAL,
INTENT(IN) :: n1
89 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
92 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
93 CHARACTER(LEN=1) :: first_char
96 CALL mpi_comm_rank(mpi_comm_world, myrank, mpi_err)
101 WRITE (*,fmt)
'error: an assertion failed with this tag:',
103 WRITE(*,*)
' n1 = ',n1
107 IF (
PRESENT(err_class))
THEN
108 first_char = err_class(1:1)
109 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
114 CALL mpi_abort(mpi_comm_world, 1, mpi_err)
116 stop
'program terminated by assert1'
120 &
WRITE(*,*)
' end of warning error message from assert1'
123 END SUBROUTINE assert1
128 SUBROUTINE assert2(n1,n2,string,err_class)
130 CHARACTER(LEN=*),
INTENT(IN) :: string
131 LOGICAL,
INTENT(IN) :: n1, n2
132 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
135 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
136 CHARACTER(LEN=1) :: first_char
139 CALL mpi_comm_rank(mpi_comm_world, myrank, mpi_err)
143 IF (.not.(n1 .and. n2))
THEN
144 IF (myrank .eq. 0)
THEN
145 WRITE (*,fmt)
'error: an assertion failed with this tag:',
147 WRITE(*,*)
' n1, n2 = ',n1, n2
151 IF (
PRESENT(err_class))
THEN
152 first_char = err_class(1:1)
153 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
158 CALL mpi_abort(mpi_comm_world, 1, mpi_err)
160 stop
'program terminated by assert2'
164 &
WRITE(*,*)
' end of warning error message from assert2'
167 END SUBROUTINE assert2
172 SUBROUTINE assert3(n1,n2,n3,string,err_class)
174 CHARACTER(LEN=*),
INTENT(IN) :: string
175 LOGICAL,
INTENT(IN) :: n1,n2,n3
176 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
179 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
180 CHARACTER(LEN=1) :: first_char
183 CALL mpi_comm_rank(mpi_comm_world, myrank, mpi_err)
187 IF (.not.(n1 .and. n2 .and. n3))
THEN
188 IF (myrank .eq. 0)
THEN
189 WRITE (*,fmt)
'error: an assertion failed with this tag:',
191 WRITE(*,*)
' n1, n2, n3 = ',n1, n2, n3
195 IF (
PRESENT(err_class))
THEN
196 first_char = err_class(1:1)
197 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
202 CALL mpi_abort(mpi_comm_world, 1, mpi_err)
204 stop
'program terminated by assert3'
208 &
WRITE(*,*)
' end of warning error message from assert3'
211 END SUBROUTINE assert3
216 SUBROUTINE assert4(n1,n2,n3,n4,string,err_class)
218 CHARACTER(LEN=*),
INTENT(IN) :: string
219 LOGICAL,
INTENT(IN) :: n1,n2,n3,n4
220 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
223 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
224 CHARACTER(LEN=1) :: first_char
227 CALL mpi_comm_rank(mpi_comm_world, myrank, mpi_err)
231 IF (.not. (n1 .and. n2 .and. n3 .and. n4))
THEN
232 IF (myrank .eq. 0)
THEN
233 WRITE (*,fmt)
'error: an assertion failed with this tag:',
235 WRITE(*,*)
' n1, n2, n3, n4 = ',n1, n2, n3, n4
239 IF (
PRESENT(err_class))
THEN
240 first_char = err_class(1:1)
241 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
246 CALL mpi_abort(mpi_comm_world, 1, mpi_err)
248 stop
'program terminated by assert4'
252 &
WRITE(*,*)
' end of warning error message from assert4'
255 END SUBROUTINE assert4
260 SUBROUTINE assert_v(n,string,err_class)
262 CHARACTER(LEN=*),
INTENT(IN) :: string
263 LOGICAL,
DIMENSION(:),
INTENT(IN) :: n
264 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
267 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
268 INTEGER(iprec) :: ntot, nfalse, ifirst, i
269 CHARACTER(LEN=1) :: first_char
272 CALL mpi_comm_rank(mpi_comm_world, myrank, mpi_err)
276 IF (.not.all(n))
THEN
277 IF (myrank .eq. 0)
THEN
278 WRITE (*,fmt)
'error: an assertion failed with this tag:',
281 WRITE (*,*) ntot,
' logicals in array. indices of .F. are:'
289 WRITE (*,*) nfalse,
' logicals are false'
293 IF (
PRESENT(err_class))
THEN
294 first_char = err_class(1:1)
295 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
300 CALL mpi_abort(mpi_comm_world, 1, mpi_err)
302 stop
'program terminated by assert_v'
306 &
WRITE(*,*)
' end of warning error message from assert_v'
309 END SUBROUTINE assert_v
325 SUBROUTINE assert_eq2(n1,n2,string,err_class)
327 CHARACTER(LEN=*),
INTENT(IN) :: string
328 INTEGER,
INTENT(IN) :: n1,n2
329 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
332 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
333 CHARACTER(LEN=1) :: first_char
337 IF (.not.(n1 == n2))
THEN
338 WRITE (*,fmt)
'error: an assert_eq failed with this tag:',
340 WRITE (*,*)
' n1, n2 = ',n1, n2
343 IF (
PRESENT(err_class))
THEN
344 first_char = err_class(1:1)
345 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
349 stop
'program terminated by assert_eq2'
351 WRITE(*,*)
' end of warning error message from assert_eq2'
354 END SUBROUTINE assert_eq2
359 SUBROUTINE assert_eq3(n1,n2,n3,string,err_class)
361 CHARACTER(LEN=*),
INTENT(IN) :: string
362 INTEGER,
INTENT(IN) :: n1,n2,n3
363 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
366 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
367 CHARACTER(LEN=1) :: first_char
371 IF (.not.(n1 == n2 .and. n2 == n3))
THEN
372 WRITE (*,fmt)
'error: an assert_eq failed with this tag:',
374 WRITE (*,*)
' n1, n2, n3 = ',n1, n2, n3
377 IF (
PRESENT(err_class))
THEN
378 first_char = err_class(1:1)
379 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
383 stop
'program terminated by assert_eq3'
385 WRITE(*,*)
' end of warning error message from assert_eq3'
388 END SUBROUTINE assert_eq3
393 SUBROUTINE assert_eq4(n1,n2,n3,n4,string,err_class)
395 CHARACTER(LEN=*),
INTENT(IN) :: string
396 INTEGER,
INTENT(IN) :: n1,n2,n3,n4
397 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
400 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
401 CHARACTER(LEN=1) :: first_char
405 IF (.not.(n1 == n2 .and. n2 == n3 .and. n3 == n4))
THEN
406 WRITE (*,fmt)
'error: an assert_eq failed with this tag:',
408 WRITE (*,*)
' n1, n2, n3, n4 = ',n1, n2, n3, n4
411 IF (
PRESENT(err_class))
THEN
412 first_char = err_class(1:1)
413 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
417 stop
'program terminated by assert_eq4'
419 WRITE(*,*)
' end of warning error message from assert_eq4'
422 END SUBROUTINE assert_eq4
427 SUBROUTINE assert_eqn(nn,string,err_class)
429 CHARACTER(LEN=*),
INTENT(IN) :: string
430 INTEGER,
DIMENSION(:),
INTENT(IN) :: nn
431 INTEGER :: ntot, nne, i
432 CHARACTER(LEN=*),
INTENT(IN),
OPTIONAL :: err_class
435 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
436 CHARACTER(LEN=1) :: first_char
440 IF (.not.(all(nn(2:) == nn(1))))
THEN
441 WRITE (*,fmt)
'error: an assert_eq failed with this tag:',
444 WRITE (*,*) ntot,
' integers in the array.'
445 WRITE (*,*) nn(1),
' is the first value in the array'
446 WRITE(*,*) .ne.
' index value (of those to first)'
449 IF (nn(i) .ne. nn(1))
THEN
454 WRITE (*,*)
' There are ',nne, .ne.
' integers to first'
457 IF (
PRESENT(err_class))
THEN
458 first_char = err_class(1:1)
459 IF ((first_char .eq.
'w') .or. (first_char .eq.
'W'))
463 stop
'program terminated by assert_eqn'
465 WRITE(*,*)
' end of warning error message from assert_eqn'
468 END SUBROUTINE assert_eqn
480 SUBROUTINE err_fatal(string, char, real1, int, log)
482 CHARACTER(LEN=*),
INTENT(IN) :: string
483 CHARACTER(LEN=*),
OPTIONAL,
INTENT(IN) :: char
484 REAL(rprec),
OPTIONAL,
INTENT(IN) :: real1
485 INTEGER,
OPTIONAL,
INTENT(IN) :: int
486 LOGICAL,
OPTIONAL,
INTENT(IN) :: log
489 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
492 WRITE (*,fmt)
'FATAL ERROR: ',string
494 IF(
PRESENT(char))
THEN
495 WRITE (*,*)
' char argument = ', char
498 IF(
PRESENT(real1))
THEN
499 WRITE (*,*)
' real argument = ', real1
502 IF(
PRESENT(int))
THEN
503 WRITE (*,*)
' integer argument = ', int
506 IF(
PRESENT(log))
THEN
507 WRITE (*,*)
' logical argument = ', log
510 stop
'program terminated by err_fatal'
511 END SUBROUTINE err_fatal
526 SUBROUTINE err_warn(string, char, real, int, log)
528 CHARACTER(LEN=*),
INTENT(IN) :: string
529 CHARACTER(LEN=*),
OPTIONAL,
INTENT(IN) :: char
530 REAL(rprec),
OPTIONAL,
INTENT(IN) :: real
531 INTEGER,
OPTIONAL,
INTENT(IN) :: int
532 LOGICAL,
OPTIONAL,
INTENT(IN) :: log
535 CHARACTER(LEN=*),
PARAMETER :: fmt=
'(1x,a,/,1x,a)'
538 WRITE (*,fmt)
'WARNING ERROR: ',string
540 IF(
PRESENT(char))
THEN
541 WRITE (*,*)
' char argument = ', char
544 IF(
PRESENT(real))
THEN
545 WRITE (*,*)
' real argument = ', real
548 IF(
PRESENT(int))
THEN
549 WRITE (*,*)
' integer argument = ', int
552 IF(
PRESENT(log))
THEN
553 WRITE (*,*)
' logical argument = ', log
557 END SUBROUTINE err_warn
565 SUBROUTINE svdproducts(b,svprod,numzeros)
604 REAL(rprec),
DIMENSION(:,:),
INTENT(inout) :: b
605 REAL(rprec),
DIMENSION(:),
INTENT(inout) :: svprod
606 INTEGER,
DIMENSION(:),
INTENT(inout) :: numzeros
609 INTEGER,
DIMENSION(2) :: dimlens
610 INTEGER :: nrowb, ncolb, nrow, ncol, minrowcol, l_work_svd, ier1
611 INTEGER :: jelim, info_svd
613 REAL(rprec),
DIMENSION(:,:),
ALLOCATABLE :: c
614 REAL(rprec),
PARAMETER :: tiny = 1.e-14_rprec
615 REAL(rprec),
PARAMETER :: verytiny = 1.e-28_rprec
616 REAL(rprec),
DIMENSION(:),
ALLOCATABLE :: work_svd, svec
617 CHARACTER(len=*),
PARAMETER :: sub_name = &
626 CALL assert(nrowb .ge. 2,sub_name //
'nrowb too small')
627 CALL assert(ncolb .ge. 2,sub_name //
'ncolb too small')
628 CALL assert_eq(ncolb,
SIZE(svprod),sub_name //
'svprod wrong size')
629 CALL assert_eq(ncolb,
SIZE(numzeros),sub_name //
630 &
'numzeros wrong size')
635 minrowcol = min(nrow,ncol)
636 l_work_svd = 5 * max(nrow,ncol)
637 ALLOCATE(work_svd(l_work_svd), stat = ier1)
638 CALL assert_eq(0,ier1,sub_name //
'Allocate work_svd')
639 ALLOCATE(c(nrow,ncol), stat = ier1)
640 CALL assert_eq(0,ier1,sub_name //
'Allocate c')
641 ALLOCATE(svec(minrowcol), stat = ier1)
642 CALL assert_eq(0,ier1,sub_name //
'Allocate svec')
646 c(1:nrow,1:jelim-1) = b(1:nrow,1:jelim-1)
647 c(1:nrow,jelim:ncolb-1) = b(1:nrow,jelim+1:ncolb)
649 CALL dgesvd(
'None',
'None',nrow,ncol,c,nrow,
650 & svec,c,nrow,c,ncol,work_svd,l_work_svd,info_svd)
651 CALL assert_eq(0,info_svd,sub_name //
'dgesvd problem')
653 numzeros(jelim) = count(svec < tiny)
657 END SUBROUTINE svdproducts
661 SUBROUTINE most_redundant(a,ncol_array,svprod_array,j_col_elim)
686 REAL(rprec),
DIMENSION(:,:),
INTENT(inout) :: a
687 REAL(rprec),
DIMENSION(:),
INTENT(inout) :: svprod_array
688 INTEGER,
DIMENSION(:),
INTENT(inout) :: ncol_array, j_col_elim
693 REAL(rprec),
PARAMETER :: tiny = 1.e-14_rprec
694 REAL(rprec),
PARAMETER :: verytiny = 1.e-28_rprec
696 INTEGER,
DIMENSION(2) :: dimlens
697 INTEGER :: nrowa, ncola, nrow, ncol, minrowcol, ier1, ncolb
698 INTEGER :: i, ncolelim, minnz, k, kk
700 REAL(rprec),
DIMENSION(:),
ALLOCATABLE :: work_svd, svec
701 INTEGER :: l_work_svd, info_svd
703 REAL(rprec),
DIMENSION(:,:),
ALLOCATABLE :: atemp, b
704 REAL(rprec),
DIMENSION(:),
ALLOCATABLE :: svprod
705 INTEGER,
DIMENSION(:),
ALLOCATABLE :: numzeros
707 INTEGER,
DIMENSION(1) :: k_minnz_a, k_maxprod_a
708 INTEGER,
DIMENSION(:),
ALLOCATABLE :: j_now
710 REAL(rprec) :: maxprod
712 CHARACTER(len=*),
PARAMETER :: sub_name = &
723 CALL assert(nrowa .ge. 2,sub_name //
'nrowa too small')
724 CALL assert(ncola .ge. 2,sub_name //
'ncola too small')
725 CALL assert_eq(ncola,
SIZE(ncol_array),sub_name //
726 &
'ncol_array wrong size')
727 CALL assert_eq(ncola,
SIZE(svprod_array),sub_name //
728 &
'svprod_array wrong size')
729 CALL assert_eq(ncola,
SIZE(j_col_elim),sub_name //
730 &
'j_col_elim wrong size')
735 minrowcol = min(nrow,ncol)
736 l_work_svd = 5 * max(nrow,ncol)
737 ALLOCATE(work_svd(l_work_svd), stat = ier1)
738 CALL assert_eq(0,ier1,sub_name //
'Allocate work_svd')
739 ALLOCATE(atemp(nrow,ncol),b(nrow,ncol), stat = ier1)
740 CALL assert_eq(0,ier1,sub_name //
'Allocate atemp, b')
741 ALLOCATE(svec(minrowcol), stat = ier1)
742 CALL assert_eq(0,ier1,sub_name //
'Allocate svec')
743 ALLOCATE(svprod(ncola), stat = ier1)
744 CALL assert_eq(0,ier1,sub_name //
'Allocate svprod')
745 ALLOCATE(numzeros(ncola), stat = ier1)
746 CALL assert_eq(0,ier1,sub_name //
'Allocate numzeros')
747 ALLOCATE(j_now(ncola), stat = ier1)
748 CALL assert_eq(0,ier1,sub_name //
'Allocate j_now')
752 CALL dgesvd(
'None',
'None',nrow,ncol,b,nrow,
753 & svec,b,nrow,b,ncol,work_svd,l_work_svd,info_svd)
754 CALL assert_eq(0,info_svd,sub_name //
'dgesvd problem')
756 ncol_array(1) = ncola
757 svprod_array(1) = product(svec)
769 DO ncolelim = 1,ncola-2
770 ncolb = ncola + 1 - ncolelim
771 b(1:nrow,1:ncolb) = atemp(1:nrow,1:ncolb)
772 CALL svdproducts(b(1:nrow,1:ncolb),svprod(1:ncolb),
774 minnz = minval(numzeros(1:ncolb))
775 k_minnz_a = minloc(numzeros(1:ncolb))
776 maxprod = maxval(svprod(1:ncolb))
777 k_maxprod_a = maxloc(svprod(1:ncolb))
778 IF (minnz .gt. 0)
THEN
785 ncol_array(ncolelim + 1) = ncola - ncolelim
786 svprod_array(ncolelim + 1) = maxprod
787 j_col_elim(ncolelim + 1) = j_now(k)
788 DO kk = k,ncola - ncolelim + 1
789 j_now(kk) = j_now(kk + 1)
790 atemp(1:nrow,kk) = atemp(1:nrow,kk + 1)
797 ncol_array(ncola) = 1
798 svprod_array(ncola) = j_now(2)
799 j_col_elim(ncola) = j_now(1)
802 END SUBROUTINE most_redundant
812 FUNCTION to_integer(real_value)
814 use,
INTRINSIC :: iso_c_binding
819 INTEGER (C_INT64_T) :: to_integer
820 REAL (dp),
INTENT(in) :: real_value
823 REAL (dp) :: as_double
824 INTEGER (C_INT64_T) :: as_int
826 equivalence(as_double, as_int)
829 as_double = real_value
834 END MODULE v3_utilities