!! Copyright (C) Stichting Deltares, 2005-2014. !! !! This file is part of iMOD. !! !! This program is free software: you can redistribute it and/or modify !! it under the terms of the GNU General Public License as published by !! the Free Software Foundation, either version 3 of the License, or !! (at your option) any later version. !! !! This program is distributed in the hope that it will be useful, !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! GNU General Public License for more details. !! !! You should have received a copy of the GNU General Public License !! along with this program. If not, see . !! !! Contact: imod.support@deltares.nl !! Stichting Deltares !! P.O. Box 177 !! 2600 MH Delft, The Netherlands. MODULE MOD_CORRKD USE MOD_IDF_PAR, ONLY : IDFOBJ USE MOD_UTL, ONLY : UTL_CREATEDIR USE MOD_IDF, ONLY : IDFREAD,IDFGETVAL,IDFOPEN,IDFWRITEDIM,IDFPUTVAL,ITOS,IDFGETLOC,IDFIROWICOL,IDFDEALLOCATE USE MOD_CORRKD_PAR REAL,PARAMETER,PRIVATE :: MINIMALKD=0.0 REAL,PARAMETER,PRIVATE :: MINIMALC=10.0 REAL,ALLOCATABLE,DIMENSION(:),PRIVATE :: KDNEW,KD,C,DIKTE,TOP,BOT,IBND,KH,KV,ANIF CONTAINS !###====================================================================== SUBROUTINE CORRKD_MAIN() !###====================================================================== IMPLICIT NONE REAL :: SUMKD,TD,X,Y,C1,C2,C3,DZ,D INTEGER :: IR,IC,IL1,IROW,ICOL,IL2,ILAY,I LOGICAL :: LEX REAL,PARAMETER :: MINCC=5.0 !WAS 25.0 DO ILAY=1,NLAY IF(ILAY.LT.NLAY)THEN IF(.NOT.IDFREAD(C_IDF(ILAY),C_IDF(ILAY)%FNAME,0))RETURN ENDIF IF(.NOT.IDFREAD(KD_IDF(ILAY),KD_IDF(ILAY)%FNAME,0)) RETURN IF(.NOT.IDFREAD(TOP_IDF(ILAY),TOP_IDF(ILAY)%FNAME,0)) RETURN IF(.NOT.IDFREAD(BOT_IDF(ILAY),BOT_IDF(ILAY)%FNAME,0)) RETURN IF(.NOT.IDFREAD(IBND_IDF(ILAY),IBND_IDF(ILAY)%FNAME,0))RETURN IF(TRIM(ANIF_IDF(ILAY)%FNAME).NE.'')THEN IF(.NOT.IDFREAD(ANIF_IDF(ILAY),ANIF_IDF(ILAY)%FNAME,0))RETURN ENDIF END DO !## copy settings idf kd and kd_new KDNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) KDNEW_IDF(NLAY+1) =KD_IDF(NLAY) KDNEW_IDF(NLAY+2) =KD_IDF(NLAY) TOPNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) BOTNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) KHNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) KVNEW_IDF(1:NLAY-1) =KD_IDF(1:NLAY-1) AQFNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) AQTNEW_IDF(1:NLAY-1)=KD_IDF(1:NLAY-1) IBNDNEW_IDF(1:NLAY) =KD_IDF(1:NLAY) CNEW_IDF(1:NLAY-1) =KD_IDF(1:NLAY-1) DO ILAY=1,NLAY TOPNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\TOP_L'// TRIM(ITOS(ILAY))//'.IDF' BOTNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\BOT_L'// TRIM(ITOS(ILAY))//'.IDF' KHNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\KH_L'// TRIM(ITOS(ILAY))//'.IDF' IF(ILAY.NE.NLAY)KVNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\KV_L'// TRIM(ITOS(ILAY))//'.IDF' KDNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\KDW_L'// TRIM(ITOS(ILAY))//'.IDF' IF(ILAY.NE.NLAY)CNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\C_L'// TRIM(ITOS(ILAY))//'.IDF' IBNDNEW_IDF(ILAY)%FNAME=TRIM(OUTPUTMAP)//'\IBND_L'//TRIM(ITOS(ILAY))//'.IDF' AQFNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\AQF_L'// TRIM(ITOS(ILAY))//'.IDF' IF(ILAY.NE.NLAY)AQTNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\AQT_L'// TRIM(ITOS(ILAY))//'.IDF' IF(ILAY.NE.NLAY)CNEW_IDF(ILAY)%FNAME =TRIM(OUTPUTMAP)//'\C_L'// TRIM(ITOS(ILAY))//'.IDF' I=INDEX(KDNEW_IDF(ILAY)%FNAME,'\',.TRUE.)-1 CALL UTL_CREATEDIR(KDNEW_IDF(ILAY)%FNAME(:I)) IF(.NOT.IDFOPEN(KDNEW_IDF(ILAY)%IU ,KDNEW_IDF(ILAY)%FNAME ,'WO',0,1)) RETURN IF(.NOT.IDFOPEN(TOPNEW_IDF(ILAY)%IU,TOPNEW_IDF(ILAY)%FNAME,'WO',0,1)) RETURN IF(.NOT.IDFOPEN(BOTNEW_IDF(ILAY)%IU,BOTNEW_IDF(ILAY)%FNAME,'WO',0,1)) RETURN IF(.NOT.IDFOPEN(KHNEW_IDF(ILAY)%IU ,KHNEW_IDF(ILAY)%FNAME ,'WO',0,1)) RETURN IF(ILAY.NE.NLAY)THEN IF(.NOT.IDFOPEN(KVNEW_IDF(ILAY)%IU ,KVNEW_IDF(ILAY)%FNAME ,'WO',0,1)) RETURN IF(.NOT.IDFOPEN(AQTNEW_IDF(ILAY)%IU,AQTNEW_IDF(ILAY)%FNAME,'WO',0,1)) RETURN IF(.NOT.IDFOPEN(CNEW_IDF(ILAY)%IU,CNEW_IDF(ILAY)%FNAME,'WO',0,1)) RETURN ENDIF IF(.NOT.IDFOPEN(IBNDNEW_IDF(ILAY)%IU,IBNDNEW_IDF(ILAY)%FNAME,'WO',0,1))RETURN IF(.NOT.IDFOPEN(AQFNEW_IDF(ILAY)%IU,AQFNEW_IDF(ILAY)%FNAME,'WO',0,1)) RETURN END DO KDNEW_IDF(NLAY+1)%FNAME=TRIM(OUTPUTMAP)//'\SUMKD_OLD.IDF' KDNEW_IDF(NLAY+2)%FNAME=TRIM(OUTPUTMAP)//'\SUMKD_NEW.IDF' IF(.NOT.IDFOPEN(KDNEW_IDF(NLAY+1)%IU,KDNEW_IDF(NLAY+1)%FNAME,'WO',0,1))RETURN IF(.NOT.IDFOPEN(KDNEW_IDF(NLAY+2)%IU,KDNEW_IDF(NLAY+2)%FNAME,'WO',0,1))RETURN !## reshuffle kd according to thickness layers without resistance in between them KDNEW_IDF%DMIN= 10.0E10; KDNEW_IDF%DMAX=-10.0E10 DO IROW=1,KD_IDF(1)%NROW DO ICOL=1,KD_IDF(1)%NCOL CALL IDFGETLOC(KD_IDF(1),IROW,ICOL,X,Y) ANIF=1.0 DO ILAY=1,NLAY CALL IDFIROWICOL(KD_IDF(ILAY),IR,IC,X,Y) KD(ILAY)=IDFGETVAL(KD_IDF(ILAY),IR,IC) IF(ILAY.LT.NLAY)THEN CALL IDFIROWICOL(C_IDF(ILAY),IR,IC,X,Y) C(ILAY)=IDFGETVAL(C_IDF(ILAY),IR,IC) ENDIF IF(ANIF_IDF(ILAY)%IU.GT.0)THEN CALL IDFIROWICOL(ANIF_IDF(ILAY),IR,IC,X,Y) ANIF(ILAY)=IDFGETVAL(ANIF_IDF(ILAY),IR,IC) ENDIF END DO KDNEW=KD TOP=TOP_IDF%NODATA; BOT=BOT_IDF%NODATA DO ILAY=1,NLAY CALL IDFIROWICOL(TOP_IDF(ILAY),IR,IC,X,Y) TOP(ILAY)=IDFGETVAL(TOP_IDF(ILAY),IR,IC) CALL IDFIROWICOL(BOT_IDF(ILAY),IR,IC,X,Y) BOT(ILAY)=IDFGETVAL(BOT_IDF(ILAY),IR,IC) CALL IDFIROWICOL(IBND_IDF(ILAY),IR,IC,X,Y) IBND(ILAY)=IDFGETVAL(IBND_IDF(ILAY),IR,IC) ENDDO !## correct thicknesses aquifers from TOP TO BOTTOM (1E IS 0.5 METER DIK) ! ILAY=1 ! DZ=TOP(ILAY)-BOT(ILAY) ! !## shift first aquitard down ! IF(DZ.LT.MAXZ(ILAY))THEN ! DZ=MAXZ(ILAY)-DZ ! BOT(ILAY) =BOT(ILAY) -DZ ! TOP(ILAY+1)=TOP(ILAY+1)-DZ ! ENDIF !## correct thicknesses DO ILAY=1,NLAY IF(BOT(ILAY).GT.TOP(ILAY))BOT(ILAY)=TOP(ILAY) IF(ILAY.LT.NLAY)THEN IF(TOP(ILAY+1).GT.BOT(ILAY))TOP(ILAY+1)=BOT(ILAY) ENDIF ENDDO DIKTE=0.0 DO ILAY=1,NLAY IF(TOP(ILAY).NE.TOP_IDF(ILAY)%NODATA.AND.BOT(ILAY).NE.BOT_IDF(ILAY)%NODATA)THEN DIKTE(ILAY)=TOP(ILAY)-BOT(ILAY) IF(DIKTE(ILAY).LE.0.001)DIKTE(ILAY)=0.0 ENDIF ENDDO IL1 =1 SUMKD=0.0 KDNEW(NLAY+1)=0.0 KDNEW(NLAY+2)=0.0 DO ILAY=1,NLAY IF(TOP(ILAY).EQ.TOP_IDF(ILAY)%NODATA.OR.BOT(ILAY).EQ.BOT_IDF(ILAY)%NODATA)THEN TD=SUM(DIKTE(IL1:ILAY)) DO IL2=IL1,ILAY IF(TD.NE.0.0)THEN KDNEW(IL2)=SUMKD*(DIKTE(IL2)/TD) !## total kd * fraction ELSE KDNEW(IL2)=0.0 ENDIF ENDDO EXIT ENDIF SUMKD=SUMKD+KD(ILAY) KDNEW(NLAY+1)=KDNEW(NLAY+1)+KD(ILAY) LEX=.FALSE. IF(ILAY.LT.NLAY)THEN !## resistance too big IF(C(ILAY).GT.MINVC)LEX=.TRUE. !## anisotropy stops IF(ANIF(ILAY).LT.1.0.AND.ANIF(ILAY+1).GE.1.0)LEX=.TRUE. ENDIF IF(ILAY.EQ.NLAY)LEX=.TRUE. !## moria IF(ILAY.EQ.1)LEX=.TRUE. IF(LEX)THEN TD=SUM(DIKTE(IL1:ILAY)) DO IL2=IL1,ILAY IF(TD.NE.0.0)THEN KDNEW(IL2)=SUMKD*(DIKTE(IL2)/TD) ELSE KDNEW(IL2)=0.0 ENDIF ENDDO SUMKD=0.0 IL1=ILAY+1 ENDIF END DO !## (moria) reset in anisotropy area kd DO ILAY=1,NLAY IF(ANIF(ILAY).LT.1.0)KDNEW(ILAY)=KD(ILAY) ! IF(ANIF(ILAY).LT.1.0.AND.KDNEW(ILAY).EQ.0.0)KDNEW(ILAY)=KD(ILAY) ENDDO !## sum sum kd eq 0 ibnd=0 IF(KDNEW(NLAY+1).LE.0.0)THEN; DO ILAY=1,NLAY; IBND(ILAY)=0; ENDDO; ENDIF !## compute k and correct if > maxk DO ILAY=1,NLAY KH(ILAY)=0.0 !; IF(TOP(ILAY)-BOT(ILAY).GT.0.001) D=MAX(0.1,(TOP(ILAY)-BOT(ILAY))) KH(ILAY)=KDNEW(ILAY)/D !(TOP(ILAY)-BOT(ILAY)) ! moria ! IF(KH(ILAY).GT.MAXK)THEN ! KH(ILAY)=MAXK ! KDNEW(ILAY)=KH(ILAY)*(TOP(ILAY)-BOT(ILAY)) ! ENDIF ENDDO KDNEW(NLAY+2)=0.0 DO ILAY=1,NLAY IF(KDNEW(ILAY).NE.KDNEW_IDF(ILAY)%NODATA)KDNEW(NLAY+2)=KDNEW(NLAY+2)+KDNEW(ILAY) END DO DO ILAY=1,NLAY+2 IF(KDNEW(ILAY).LT.0.001)KDNEW(ILAY)=0.0 KDNEW(ILAY)=MAX(MINIMALKD,KDNEW(ILAY)) CALL IDFIROWICOL(KDNEW_IDF(ILAY),IR,IC,X,Y) CALL IDFPUTVAL(KDNEW_IDF(ILAY),IR,IC,KDNEW(ILAY)) KDNEW_IDF(ILAY)%DMIN=MIN(KDNEW_IDF(ILAY)%DMIN,KDNEW(ILAY)) KDNEW_IDF(ILAY)%DMAX=MAX(KDNEW_IDF(ILAY)%DMAX,KDNEW(ILAY)) ENDDO DO ILAY=NLAY,1,-1 IF(KDNEW(ILAY).GT.0.0)EXIT IBND(ILAY)=0 ENDDO DO ILAY=1,NLAY ! CALL IDFIROWICOL(TOPNEW_IDF(ILAY),IR,IC,X,Y) ! CALL IDFPUTVAL(TOPNEW_IDF(ILAY),IR,IC,TOP(ILAY)) ! CALL IDFIROWICOL(BOTNEW_IDF(ILAY),IR,IC,X,Y) ! CALL IDFPUTVAL(BOTNEW_IDF(ILAY),IR,IC,BOT(ILAY)) CALL IDFIROWICOL(IBNDNEW_IDF(ILAY),IR,IC,X,Y) CALL IDFPUTVAL(IBNDNEW_IDF(ILAY),IR,IC,IBND(ILAY)) ! CALL IDFIROWICOL(KHNEW_IDF(ILAY),IR,IC,X,Y) ! CALL IDFPUTVAL(KHNEW_IDF(ILAY),IR,IC,KH(ILAY)) ! IF(ILAY.NE.NLAY)THEN ! CALL IDFIROWICOL(KVNEW_IDF(ILAY),IR,IC,X,Y) ! KV(ILAY)=0.0; IF(BOT(ILAY)-TOP(ILAY+1).GT.0.001)KV(ILAY)=(BOT(ILAY)-TOP(ILAY+1))/C(ILAY) ! CALL IDFPUTVAL(KVNEW_IDF(ILAY),IR,IC,KV(ILAY)) ! CALL IDFIROWICOL(AQTNEW_IDF(ILAY),IR,IC,X,Y) ! CALL IDFPUTVAL(AQTNEW_IDF(ILAY),IR,IC,BOT(ILAY)-TOP(ILAY+1)) ! ENDIF ! CALL IDFIROWICOL(AQFNEW_IDF(ILAY),IR,IC,X,Y) ! CALL IDFPUTVAL(AQFNEW_IDF(ILAY),IR,IC,TOP(ILAY)-BOT(ILAY)) ENDDO ! DO ILAY=1,NLAY-1 ! CALL IDFIROWICOL(CNEW_IDF(ILAY),IR,IC,X,Y) ! C1=0.0; C2=0.0; C3=0.0 ! IF(IBND(ILAY).NE.0)THEN !.AND.IBND(ILAY+1).NE.0)THEN ! IF(KH(ILAY).GT.0.0)C1=(TOP(ILAY)-BOT(ILAY))/(KH(ILAY)/3.0) ! IF(KV(ILAY).GT.0.0)THEN ! IF(ILAY.EQ.1)THEN ! C2=(BOT(ILAY)-TOP(ILAY+1))/KV(ILAY) ! ELSE ! IF(C(ILAY).GT.MINCC)C2=(BOT(ILAY)-TOP(ILAY+1))/KV(ILAY) ! ENDIF ! ENDIF ! IF(KH(ILAY+1).GT.0.0)THEN ! C3=(TOP(ILAY+1)-BOT(ILAY+1))/(KH(ILAY+1)/3.0) ! ENDIF ! ENDIF ! CALL IDFPUTVAL(CNEW_IDF(ILAY),IR,IC,MAX(MINCC,0.5*C1+C2+0.5*C3)) ! ENDDO END DO WRITE(6,'(A,F10.2)') '+progress ',REAL(IROW)*100.0/REAL(KD_IDF(1)%NROW) END DO DO ILAY=1,NLAY+2 IF(.NOT.IDFWRITEDIM(0,KDNEW_IDF(ILAY)))THEN ENDIF END DO DO ILAY=1,NLAY IF(.NOT.IDFWRITEDIM(0,TOPNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,BOTNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,IBNDNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,KHNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,AQFNEW_IDF(ILAY)))RETURN IF(ILAY.NE.NLAY)THEN IF(.NOT.IDFWRITEDIM(0,AQTNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,KVNEW_IDF(ILAY)))RETURN IF(.NOT.IDFWRITEDIM(0,CNEW_IDF(ILAY)))RETURN ENDIF END DO END SUBROUTINE CORRKD_MAIN !###====================================================================== SUBROUTINE CORRKD_ALLOCATE() !###====================================================================== IMPLICIT NONE ALLOCATE(KD_IDF(NLAY),C_IDF(NLAY-1),TOP_IDF(NLAY),BOT_IDF(NLAY),KDNEW_IDF(NLAY+2),ANIF(NLAY)) ALLOCATE(AQFNEW_IDF(NLAY),AQTNEW_IDF(NLAY-1),CNEW_IDF(NLAY-1)) ALLOCATE(TOPNEW_IDF(NLAY),BOTNEW_IDF(NLAY),KHNEW_IDF(NLAY),KVNEW_IDF(NLAY-1),IBND_IDF(NLAY),IBNDNEW_IDF(NLAY),ANIF_IDF(NLAY)) ALLOCATE(DIKTE(NLAY),C(NLAY-1),KD(NLAY),KDNEW(NLAY+2),TOP(NLAY),BOT(NLAY),IBND(NLAY),KH(NLAY),KV(NLAY-1)) !ALLOCATE(MAXZ(NLAY)) END SUBROUTINE CORRKD_ALLOCATE !###====================================================================== SUBROUTINE CORRKD_DEALLOCATE() !###====================================================================== IMPLICIT NONE IF(ALLOCATED(KD_IDF))THEN; CALL IDFDEALLOCATE(KD_IDF,SIZE(KD_IDF)); DEALLOCATE(KD_IDF); ENDIF IF(ALLOCATED(C_IDF))THEN; CALL IDFDEALLOCATE(C_IDF,SIZE(C_IDF)); DEALLOCATE(C_IDF); ENDIF IF(ALLOCATED(TOP_IDF))THEN; CALL IDFDEALLOCATE(TOP_IDF,SIZE(TOP_IDF)); DEALLOCATE(TOP_IDF); ENDIF IF(ALLOCATED(BOT_IDF))THEN; CALL IDFDEALLOCATE(BOT_IDF,SIZE(BOT_IDF)); DEALLOCATE(BOT_IDF); ENDIF IF(ALLOCATED(KDNEW_IDF))THEN; CALL IDFDEALLOCATE(KDNEW_IDF,SIZE(KDNEW_IDF)); DEALLOCATE(KDNEW_IDF); ENDIF IF(ALLOCATED(TOPNEW_IDF))THEN; CALL IDFDEALLOCATE(TOPNEW_IDF,SIZE(TOPNEW_IDF)); DEALLOCATE(TOPNEW_IDF); ENDIF IF(ALLOCATED(BOTNEW_IDF))THEN; CALL IDFDEALLOCATE(BOTNEW_IDF,SIZE(BOTNEW_IDF)); DEALLOCATE(BOTNEW_IDF); ENDIF IF(ALLOCATED(KHNEW_IDF))THEN; CALL IDFDEALLOCATE(KHNEW_IDF,SIZE(KHNEW_IDF)); DEALLOCATE(KHNEW_IDF); ENDIF IF(ALLOCATED(KVNEW_IDF))THEN; CALL IDFDEALLOCATE(KVNEW_IDF,SIZE(KVNEW_IDF)); DEALLOCATE(KVNEW_IDF); ENDIF IF(ALLOCATED(IBND_IDF))THEN; CALL IDFDEALLOCATE(IBND_IDF,SIZE(IBND_IDF)); DEALLOCATE(IBND_IDF); ENDIF IF(ALLOCATED(IBNDNEW_IDF))THEN; CALL IDFDEALLOCATE(IBNDNEW_IDF,SIZE(IBNDNEW_IDF)); DEALLOCATE(IBNDNEW_IDF); ENDIF IF(ALLOCATED(ANIF_IDF))THEN; CALL IDFDEALLOCATE(ANIF_IDF,SIZE(ANIF_IDF)); DEALLOCATE(ANIF_IDF); ENDIF IF(ALLOCATED(CNEW_IDF))THEN; CALL IDFDEALLOCATE(CNEW_IDF,SIZE(CNEW_IDF)); DEALLOCATE(CNEW_IDF); ENDIF IF(ALLOCATED(AQFNEW_IDF))THEN; CALL IDFDEALLOCATE(AQFNEW_IDF,SIZE(AQFNEW_IDF)); DEALLOCATE(AQFNEW_IDF); ENDIF IF(ALLOCATED(AQTNEW_IDF))THEN; CALL IDFDEALLOCATE(AQTNEW_IDF,SIZE(AQTNEW_IDF)); DEALLOCATE(AQTNEW_IDF); ENDIF IF(ALLOCATED(DIKTE))DEALLOCATE(DIKTE) IF(ALLOCATED(C)) DEALLOCATE(C) IF(ALLOCATED(ANIF)) DEALLOCATE(ANIF) IF(ALLOCATED(KD)) DEALLOCATE(KD) IF(ALLOCATED(KDNEW))DEALLOCATE(KDNEW) IF(ALLOCATED(TOP)) DEALLOCATE(TOP) IF(ALLOCATED(BOT)) DEALLOCATE(BOT) IF(ALLOCATED(IBND)) DEALLOCATE(IBND) IF(ALLOCATED(KH)) DEALLOCATE(KH) IF(ALLOCATED(KV)) DEALLOCATE(KV) !IF(ALLOCATED(MAXZ)) DEALLOCATE(MAXZ) END SUBROUTINE CORRKD_DEALLOCATE END MODULE MOD_CORRKD