From 07ce23e2427e4c1561a8bc6896f8879e0aaada89 Mon Sep 17 00:00:00 2001
From: ESCOBAR Juan <escj@nuwa>
Date: Thu, 10 Mar 2022 15:47:24 +0100
Subject: [PATCH] Juan 10/03/2022:ZSOLVER/mode_mppdb.f90, add
 MPPDB_CHECK3D_REAL_MG for multigrid check

---
 src/ZSOLVER/mode_mppdb.f90 | 226 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 225 insertions(+), 1 deletion(-)

diff --git a/src/ZSOLVER/mode_mppdb.f90 b/src/ZSOLVER/mode_mppdb.f90
index 3fb6e1542..185fb4acb 100644
--- a/src/ZSOLVER/mode_mppdb.f90
+++ b/src/ZSOLVER/mode_mppdb.f90
@@ -22,6 +22,7 @@ MODULE MODE_MPPDB
 !  P. Wautelet 10/04/2019: replace ABORT and STOP calls by Print_msg
 !  P. Wautelet 26/04/2019: use modd_precision parameters for datatypes of MPI communications
 !  J. Escobar  09/07/2019: bug, in MPPDB_CHECK_SURFEX3D, recompute IKSIZE_ll for local 0 size array
+!  J. Escobar  10/10/2022: add MPPDB_CHECK3D_REAL_MG , for MultiGrid check  
 !-----------------------------------------------------------------
 !
   use ISO_FORTRAN_ENV, only: OUTPUT_UNIT
@@ -84,6 +85,16 @@ MODULE MODE_MPPDB
     module procedure mppdb_check4d_real
   end interface
 
+  INTERFACE
+     SUBROUTINE MPPDB_CHECK3D_REAL_MG(PTAB,MESSAGE,PPRECISION)
+       IMPLICIT NONE
+       !
+       REAL,DIMENSION(:,:,:),INTENT(IN) :: PTAB
+       CHARACTER(LEN=*), INTENT(IN) :: MESSAGE
+       REAL,OPTIONAL,    INTENT(IN) :: PPRECISION
+     END SUBROUTINE MPPDB_CHECK3D_REAL_MG
+  END INTERFACE
+  
   CONTAINS
 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -875,7 +886,7 @@ MODULE MODE_MPPDB
     END IF
 #endif
   END SUBROUTINE MPPDB_CHECK1D_REAL
-
+  
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -2269,3 +2280,216 @@ MODULE MODE_MPPDB
   END SUBROUTINE CHECK_ISXYSIZE
   !
 END MODULE MODE_MPPDB
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+  SUBROUTINE MPPDB_CHECK3D_REAL_MG(PTAB,MESSAGE,PPRECISION)
+    !
+    USE MODD_MPIF,      ONLY: MPI_CHARACTER, MPI_STATUS_IGNORE, MPI_SUM, MPI_MAX
+    use modd_precision, only: MNHINT_MPI, MNHREAL_MPI
+    !
+    USE MODE_DEVICE
+    !
+    USE MODE_MPPDB, ONLY: NMAXMSGLEN,NMAXPAS,NTAG
+    USE MODE_MPPDB, ONLY: mppdb_initialized,mppdb_actived,xprecision
+    USE MODE_MPPDB, ONLY: mppdb_inter_comm,mppdb_nbproc_intra,mppdb_intra_comm
+    USE MODE_MPPDB, ONLY: mppdb_father_world,mppdb_irank_world,mppdb_nbproc_world
+    USE MODE_MPPDB, ONLY: mppdb_barrier
+    USE mode_msg
+    use modi_tools_c
+    use ISO_FORTRAN_ENV, only: OUTPUT_UNIT
+    !
+    IMPLICIT NONE
+    !
+    REAL,DIMENSION(:,:,:),INTENT(IN) :: PTAB
+    CHARACTER(LEN=*), INTENT(IN) :: MESSAGE
+    REAL,OPTIONAL,    INTENT(IN) :: PPRECISION
+    !
+    CHARACTER(len=40)                                  :: YMSG
+    CHARACTER(len=NMAXMSGLEN)                          :: MSG
+    CHARACTER(len=NMAXMSGLEN),DIMENSION(:),ALLOCATABLE :: ALLMSG
+    INTEGER                                            :: IINFO_ll
+    INTEGER                                            :: I_FIRST_FATHER, I_FIRST_SON
+    INTEGER                                            :: IPAS,NPAS,NPAS_ll
+    INTEGER                                            :: IGLBSIZEPTAB
+    INTEGER                                            :: ISIZEOTHER
+    LOGICAL                                            :: G_PTAB_ON_DEVICE
+    LOGICAL,DIMENSION(NMAXPAS)                         :: OK
+    REAL                                               :: ZDIV
+    REAL                                               :: ZPRECISION
+    REAL,DIMENSION(NMAXPAS)                            :: MAX_DIFF , MAX_VAL
+    REAL, DIMENSION(SIZE(PTAB,1),SIZE(PTAB,2),SIZE(PTAB,3)) :: ZTAB_SON
+    REAL, DIMENSION(SIZE(PTAB,1),SIZE(PTAB,2),SIZE(PTAB,3),2) :: ZTAB_DIFF
+    !
+    REAL, ALLOCATABLE , DIMENSION(:,:,:) :: ZTAB
+    !
+#ifdef MNH_SP4
+    !pas de mpi_spawn sur IBM-SP ni MPI_ARGV_NULL etc ...
+    RETURN
+#else
+    IF ( ( .NOT. MPPDB_INITIALIZED ) .OR. ( .NOT. MPPDB_ACTIVED ) ) RETURN
+    !
+    IF ( PRESENT(PPRECISION) ) THEN
+      ZPRECISION = PPRECISION
+    ELSE
+      ZPRECISION = XPRECISION
+    END IF
+    !
+    !get the global size of PTAB
+    CALL MPI_ALLREDUCE(SIZE(PTAB), IGLBSIZEPTAB, 1,MNHINT_MPI, MPI_SUM, MPPDB_INTER_COMM, IINFO_ll)
+    IF ( IGLBSIZEPTAB == 0 ) RETURN
+    !
+    ALLOCATE(ZTAB(SIZE(PTAB,1),SIZE(PTAB,2),SIZE(PTAB,3)))
+    !
+    CALL MPPDB_BARRIER()
+    !
+    !
+    ALLOCATE(ALLMSG(MPPDB_NBPROC_INTRA))
+    MSG = MESSAGE
+    CALL MPI_ALLGATHER(MSG,LEN(MSG),MPI_CHARACTER,ALLMSG,LEN(MSG),MPI_CHARACTER,MPPDB_INTRA_COMM,IINFO_ll)
+    DO IPAS = 1, MPPDB_NBPROC_INTRA
+      IF ( ALLMSG(IPAS) /= MSG ) &
+        CALL PRINT_MSG(NVERB_FATAL,'GEN','MPPDB_CHECK3D_REAL_MG','message not similar on all processes (' &
+                       //TRIM(ALLMSG(IPAS))//' vs '//TRIM(MSG)//')')
+    END DO
+    DEALLOCATE(ALLMSG)
+    !
+    !implemented for only 1 process on each side
+    IF (MPPDB_NBPROC_INTRA>2) THEN
+      IF (MPPDB_FATHER_WORLD .AND. MPPDB_IRANK_WORLD.EQ.0) &
+        CALL PRINT_MSG(NVERB_WARNING,'GEN','MPPDB_CHECK3D_REAL_MG','only works with 1 process on each side')
+      RETURN
+    END IF
+    !
+    CALL GET_FROM_DEVICE(PTAB,ZTAB,G_PTAB_ON_DEVICE)
+    !
+    NPAS = 1
+    IF (G_PTAB_ON_DEVICE) NPAS=2
+    CALL MPI_ALLREDUCE(NPAS,NPAS_ll,1,MNHINT_MPI,MPI_MAX,MPPDB_INTRA_COMM,IINFO_ll)
+    !
+    IF (NPAS_ll>NMAXPAS) THEN
+      NPAS_ll = NMAXPAS
+      CALL PRINT_MSG(NVERB_WARNING,'GEN','MPPDB_CHECK3D_REAL_MG','NPAS_ll reduced')
+    END IF
+    !
+    MAX_DIFF(:) = 0.0
+    !
+    DO IPAS=1,NPAS_ll
+      IF ((IPAS.EQ.2) .AND. G_PTAB_ON_DEVICE ) ZTAB = PTAB ! the 2 time test the value on host
+      !
+      IF(MPPDB_FATHER_WORLD) THEN
+        IF (MPPDB_IRANK_WORLD.EQ.0) THEN
+          I_FIRST_SON = MPPDB_NBPROC_WORLD
+          CALL MPI_SENDRECV(SIZE(ZTAB),1,MNHINT_MPI,I_FIRST_SON,NTAG, &
+                            ISIZEOTHER,1,MNHINT_MPI,I_FIRST_SON,NTAG, &
+                            MPPDB_INTRA_COMM,MPI_STATUS_IGNORE,IINFO_ll)
+          IF (SIZE(ZTAB)==ISIZEOTHER) THEN
+            CALL MPI_RECV(ZTAB_SON,SIZE(ZTAB_SON),MNHREAL_MPI,I_FIRST_SON, &
+                    NTAG,MPPDB_INTRA_COMM,MPI_STATUS_IGNORE,IINFO_ll)
+            ZTAB_DIFF(:,:,:,IPAS) = ABS ( ZTAB(:,:,:) - ZTAB_SON(:,:,:) )
+            MAX_VAL(IPAS)  = MAXVAL( ABS (ZTAB_SON) )
+            MAX_DIFF(IPAS) = MAXVAL( ZTAB_DIFF (:,:,:,IPAS) )
+            !
+            IF ( MAX_VAL(IPAS) .EQ. 0.0 ) THEN
+              ZDIV=1.0
+            ELSE
+              ZDIV=MAX_VAL(IPAS)
+            END IF
+            IF ( MAX_DIFF(IPAS)/ZDIV > ZPRECISION ) THEN
+              OK(IPAS) = .FALSE.
+            ELSE
+              OK(IPAS) = .TRUE.
+            END IF
+          END IF
+        END IF
+      ELSE
+        I_FIRST_FATHER = 0
+        CALL MPI_SENDRECV(SIZE(ZTAB),1,MNHINT_MPI,I_FIRST_FATHER,NTAG, &
+                          ISIZEOTHER,1,MNHINT_MPI,I_FIRST_FATHER,NTAG, &
+                          MPPDB_INTRA_COMM,MPI_STATUS_IGNORE,IINFO_ll)
+        IF (SIZE(ZTAB)==ISIZEOTHER) THEN
+          CALL MPI_SEND(ZTAB,SIZE(ZTAB),MNHREAL_MPI,I_FIRST_FATHER, &
+                        NTAG, MPPDB_INTRA_COMM, IINFO_ll)
+        END IF
+      END IF
+      !
+      CALL MPPDB_BARRIER()
+      !
+    END DO
+    !
+    IF (MPPDB_FATHER_WORLD .AND. MPPDB_IRANK_WORLD.EQ.0) THEN
+      YMSG=ADJUSTL(MESSAGE)
+      IF (SIZE(ZTAB)==ISIZEOTHER) THEN
+        IF (NPAS_ll == 1) THEN
+#ifdef _COLOR_OUTPUT
+          IF ( OK(1) ) THEN
+            write(*, '( A29,A22,A40," Error:       ",e15.8,"                        MAXVAL= ",e15.8 )' ) &
+                  achar(27)//'[32mMPPDB_CHECKMG :: OK'//achar(27)//'[0m ','',YMSG, MAX_DIFF(1),MAX_VAL(1)
+          ELSE
+            write(*, '( A29,A22,A40," Error:       ",e15.8,"                        MAXVAL= ",e15.8 )' ) &
+                achar(27)//'[31mMPPDB_CHECKMG :: KO'//achar(27)//'[0m ','',YMSG, MAX_DIFF(1),MAX_VAL(1)
+          END IF
+#else
+          IF ( OK(1) ) THEN
+            write(*, '(" MPPDB_CHECKMG :: OK MPPDB_CHECKMG =",A40," Error=",e15.8," MAXVAL=",e15.8)' ) &
+                  MESSAGE,MAX_DIFF(1),MAX_VAL(1)
+          ELSE
+            write(*, '(" MPPDB_CHECKMG :: KO MPPDB_CHECKMG =",A40," Error=",e15.8," MAXVAL=",e15.8)' ) &
+                  MESSAGE,MAX_DIFF(1),MAX_VAL(1)
+          END IF
+#endif
+          flush(unit=OUTPUT_UNIT)
+        ELSE IF (NPAS_ll == 2) THEN
+#ifdef _COLOR_OUTPUT
+          IF ( OK(1) .AND. OK(2) ) THEN
+            write(*, '( A51,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  achar(27)//'[32mMPPDB_CHECKMG :: OK on host, OK on device'//achar(27)//'[0m ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          ELSE IF ( .NOT.OK(1) .AND. .NOT.OK(2) ) THEN
+            write(*, '( A519,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8,"LOC=",3I4.3," ",3I4.3 )' ) &
+                  achar(27)//'[31mMPPDB_CHECKMG :: KO on host, KO on device'//achar(27)//'[0m ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1),&
+                  MAXLOC(ZTAB_DIFF(:,:,:,2)),MAXLOC(ZTAB_DIFF(:,:,:,1))
+          ELSE IF ( .NOT.OK(1) ) THEN
+            write(*, '( A51,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  achar(27)//'[33mMPPDB_CHECKMG :: OK on host, KO on device'//achar(27)//'[0m ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          ELSE IF ( .NOT.OK(2) ) THEN
+            write(*, '( A51,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  achar(27)//'[33mMPPDB_CHECKMG :: KO on host, OK on device'//achar(27)//'[0m ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          END IF
+#else
+          IF ( OK(1) .AND. OK(2) ) THEN
+            write(*, '( A42,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  'MPPDB_CHECKMG :: OK on host, OK on device ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          ELSE IF ( .NOT.OK(1) .AND. .NOT.OK(2) ) THEN
+            write(*, '( A42,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  'MPPDB_CHECKMG :: KO on host, KO on device ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          ELSE IF ( .NOT.OK(1) ) THEN
+            write(*, '( A42,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  'MPPDB_CHECKMG :: OK on host, KO on device ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          ELSE IF ( .NOT.OK(2) ) THEN
+            write(*, '( A42,A40," Errors: host=",e15.8," device=",e15.8," MAXVALS=",e15.8,e15.8 )' ) &
+                  'MPPDB_CHECKMG :: KO on host, OK on device ',YMSG, &
+                  MAX_DIFF(2),MAX_DIFF(1),MAX_VAL(2),MAX_VAL(1)
+          END IF
+#endif
+          flush(unit=OUTPUT_UNIT)
+        ELSE
+          CALL PRINT_MSG(NVERB_WARNING,'GEN','MPPDB_CHECKMG','NPAS_ll>2 not (yet) implemented')
+        END IF
+      ELSE
+#ifdef _COLOR_OUTPUT
+        WRITE (*,'( A,I10,I10,A40 )') achar(27)//'[31mMPPDB_CHECKMG :: KO: array sizes different on 2 sides'//achar(27)//'[0m ',&
+                                  SIZE(ZTAB),ISIZEOTHER,YMSG
+#else
+        WRITE (*,'( A,I10,I10,A40 )') 'MPPDB_CHECKMG :: KO: array sizes different on 2 sides',SIZE(ZTAB),ISIZEOTHER,YMSG
+#endif
+      END IF
+    END IF
+#endif
+  END SUBROUTINE MPPDB_CHECK3D_REAL_MG
-- 
GitLab