! Part of Dflow3d a 3D Navier Stokes solver with variable density for
! simulations of near field dredge plume mixing
! Copyright (C) 2012 Lynyrd de Wit
! 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 .
subroutine chkdt
USE nlist
implicit none
! include 'param.txt'
! include 'common.txt'
include 'mpif.h'
integer ierr
real dr2,dz2,df,df2,kcoeff,tmp1,tmp2,tmp3,Courant,dtmp
! IF (nobst>0.and.bp(1)%forever.eq.0.and.time_np+dt.gt.bp(1)%t0.and.counter<10) THEN
! counter=counter+1
! Courant=0.1
! IF (rank.eq.0) THEN
! write(*,*),'Placement bedplume, CFL=0.1 for 10 time steps ',counter,dt
! ENDIF
! ELSE
Courant = CFL
! ENDIF
IF (istep.le.10) THEN
dt = dt_ini
ELSE
dt = dt_max
ENDIF
IF (CNdiffz.eq.1) THEN
dz2 = 1.e9*dz*dz ! no dt restriction for vertical diff with CN implicit scheme
ELSE
dz2 = dz * dz
ENDIF
do k=1,kmax
do j=1,jmax
do i=1,imax
df = Rp(i)*dphi
df2 = df * df
dr2 = dr(i) * dr(i)
kcoeff = ekm(i,j,k) /rnew(i,j,k)
tmp1 = ( abs(Unew(i,j,k)) / ( Rp(i+1)-Rp(i) ) ) +
& ( abs(Vnew(i,j,k)) / df ) +
& ( abs(Wnew(i,j,k)) / dz )
tmp2 = ( 1.0/dr2 + 1.0/df2 + 1.0/dz2 )
tmp3 = 1.0 / ( 1.0 * tmp2 * kcoeff + tmp1 + 1.e-12 )
tmp3 =Courant *tmp3
dt = min( dt , tmp3 )
dtmp = dt
! if (abs(dt)/abs(dt_max).le.0.7) then
! write(*,*)'rank,i,j,k,dt=',rank,i,j,k,dt
! write(*,*)'U,V,W:',Unew(i,j,k),Vnew(i,j,k),Wnew(i,j,k)
! write(*,*)'*i-1: U,V,W:',Unew(i-1,j,k),Vnew(i-1,j,k),Wnew(i-1,j,k)
! write(*,*)'*j-1:U,V,W:',Unew(i,j-1,k),Vnew(i,j-1,k),Wnew(i,j-1,k)
! write(*,*)'*k-1:U,V,W:',Unew(i,j,k-1),Vnew(i,j,k-1),Wnew(i,j,k-1)
! write(*,*)'*i+1: U,V,W:',Unew(i+1,j,k),Vnew(i+1,j,k),Wnew(i+1,j,k)
! write(*,*)'*j+1:U,V,W:',Unew(i,j+1,k),Vnew(i,j+1,k),Wnew(i,j+1,k)
! write(*,*)'*k+1:U,V,W:',Unew(i,j,k+1),Vnew(i,j,k+1),Wnew(i,j,k+1)
! write(*,*)'Rp*dphi,Rp(i+1)-Rp(i),dz',df,Rp(i+1)-Rp(i),dz
! write(*,*)'dyn viscosity nu,ekm,rho:',kcoeff,ekm(i,j,k),rnew(i,j,k)
! write(*,*)'dt CFL,dt visc:',1./tmp1,1./(tmp2*kcoeff)
! call output(99999,time_np)
! CALL writeerror(10000)
! endif
enddo
enddo
enddo
if (dt<1.e-12) then
write(*,*),'rank,dt',rank,dt
endif
call mpi_allreduce(dtmp,dt,1,mpi_real8,mpi_min,mpi_comm_world,ierr)
! call mpi_allreduce(dtmp,dt,1,mpi_real,mpi_min,mpi_comm_world,ierr)
if (isnan(dt)) stop 'ERROR, QUITING DFLOW3D: "dt" is a NaN'
if (dt<1.e-12) stop 'ERROR, QUITING DFLOW3D: "dt" is smaller than 1e-12'
if (time_int.eq.'AB2'.or.time_int.eq.'AB3') then
if (dtimax) CALL writeerror(110)
IF (his(n)%i<0) CALL writeerror(111)
IF (his(n)%j>jmax*px) CALL writeerror(120)
IF (his(n)%j<0) CALL writeerror(121)
IF (his(n)%k>kmax) CALL writeerror(130)
IF (his(n)%k<0) CALL writeerror(131)
his(n)%x=Rp(his(n)%i)*cos_u(his(n)%j-rank*jmax)-schuif_x
his(n)%y=Rp(his(n)%i)*sin_u(his(n)%j-rank*jmax)
his(n)%z=his(n)%k*dz-0.5*dz
ENDDO
END SUBROUTINE init_his
! subroutine appendhis(rank,istep,time,Unew,Vnew,Wnew,P,Cnew,Rnew)
subroutine appendhis
USE history_array
USE nlist
implicit none
! include 'param.txt'
!include 'common.txt'
! REAL Unew(0:i1,0:j1,0:k1),Vnew(0:i1,0:j1,0:k1),Wnew(0:i1,0:j1,0:k1)
! REAL Rnew(0:i1,0:j1,0:k1),Cnew(0:i1,0:j1,0:k1),P(0:i1,0:j1,0:k1)
! REAL time
integer n,r,nf
his(1)%t(istep)=time_np !Unew is already updated, therefore it is output at time_np
DO n=1,nhispoint
r=INT((his(n)%j-1)/jmax)
IF (rank.eq.r) THEN
i=his(n)%i
j=his(n)%j-rank*jmax
k=his(n)%k
his(n)%U(istep)=Unew(i,j,k)*cos_u(j)-Vnew(i,j,k)*sin_v(j)
his(n)%V(istep)=Vnew(i,j,k)*cos_v(j)+Unew(i,j,k)*sin_u(j)
his(n)%W(istep)=Wnew(i,j,k)
his(n)%P(istep)=Pold(i,j,k)+P(i,j,k)
his(n)%RHO(istep)=Rnew(i,j,k)
DO nf=1,nfrac
his(n)%C(nf,istep)=Cnew(nf,i,j,k)
ENDDO
ENDIF
ENDDO
end SUBROUTINE
! subroutine finalize_his(rank,istep)
subroutine finalize_his
USE history_array
USE nlist
USE netcdf
implicit none
! include 'param.txt'
include 'mpif.h'
! real UU(1:200000)
integer ierr,n,r,tag,status(MPI_STATUS_SIZE),nf
INTEGER (8) :: ps
REAL :: Uhis(1:nhispoint,1:istep),Vhis(1:nhispoint,1:istep),Whis(1:nhispoint,1:istep)
REAL :: Phis(1:nhispoint,1:istep),Chis(1:nfrac,1:nhispoint,1:istep),RHOhis(1:nhispoint,1:istep)
REAL :: xhis(1:nhispoint),yhis(1:nhispoint),zhis(1:nhispoint)
INTEGER :: ihis(1:nhispoint),jhis(1:nhispoint),khis(1:nhispoint)
REAL :: this(1:istep)
! We are writing 3D, 2D and 1D data, a nhispoint x istep grid.
integer, parameter :: NDIMS1 = 2
integer, parameter :: NDIMS2 = 1
integer, parameter :: NDIMS3 = 3
integer, parameter :: NDIMS4 = 1
! integer, parameter :: NX = imax, NY = jmax, NZ = kmax
! When we create netCDF files, variables and dimensions, we get back
! an ID for each one.
integer :: ncid, varid1,varid2,varid3, varid4, varid5, varid6, varid7, varid8
integer :: varid9,varid10,varid11,varid12,varid13
integer :: dimids1(NDIMS1), dimids2(NDIMS2),dimids3(NDIMS3),dimids4(NDIMS4)
integer :: nhis_dimid,time_dimid,nfrac_dimid
character(1024) :: svnversion
character(1024) :: svnurl
include 'version.inc'
IF (rank>0) THEN
DO n=1,nhispoint
r=INT((his(n)%j-1)/jmax)
IF (rank.eq.r) THEN
tag=INT(r*n)
call mpi_sendrecv_replace(his(n)%U ,200000,MPI_REAL8,0,10,0,10, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%V ,200000,MPI_REAL8,0,11,0,11, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%W ,200000,MPI_REAL8,0,12,0,12, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%P ,200000,MPI_REAL8,0,13,0,13, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%C,20*200000,MPI_REAL8,0,14,0,14, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%RHO ,200000,MPI_REAL8,0,15,0,15, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%x ,1,MPI_REAL8,0,16,0,16, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%y ,1,MPI_REAL8,0,17,0,17, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%z ,1,MPI_REAL8,0,18,0,18, MPI_COMM_WORLD,status,ierr)
ENDIF
ENDDO
ELSE
DO n=1,nhispoint
r=INT((his(n)%j-1)/jmax)
IF (rank.ne.r) THEN
call mpi_sendrecv_replace(his(n)%U ,200000,MPI_REAL8,r,10,r,10, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%V ,200000,MPI_REAL8,r,11,r,11, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%W ,200000,MPI_REAL8,r,12,r,12, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%P ,200000,MPI_REAL8,r,13,r,13, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%C ,20*200000,MPI_REAL8,r,14,r,14, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%RHO ,200000,MPI_REAL8,r,15,r,15, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%x ,1,MPI_REAL8,r,16,r,16, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%y ,1,MPI_REAL8,r,17,r,17, MPI_COMM_WORLD,status,ierr)
call mpi_sendrecv_replace(his(n)%z ,1,MPI_REAL8,r,18,r,18, MPI_COMM_WORLD,status,ierr)
ENDIF
ENDDO
ENDIF
IF (rank.eq.0) THEN
DO n=1,nhispoint
Uhis(n,1:istep)=his(n)%U(1:istep)
Vhis(n,1:istep)=his(n)%V(1:istep)
Whis(n,1:istep)=his(n)%W(1:istep)
DO k=1,nfrac
Chis(k,n,1:istep)=his(n)%C(k,1:istep)
ENDDO
Phis(n,1:istep)=his(n)%P(1:istep)
RHOhis(n,1:istep)=his(n)%RHO(1:istep)
xhis(n)=his(n)%x
yhis(n)=his(n)%y
zhis(n)=his(n)%z
ihis(n)=his(n)%i
jhis(n)=his(n)%j
khis(n)=his(n)%k
ENDDO
this(1:istep)=his(1)%t(1:istep)
! Create the netCDF file. The nf90_clobber parameter tells netCDF to
! overwrite this file, if it already exists.
call check( nf90_create('history.nc', NF90_CLOBBER, ncid) )
! Define the dimensions. NetCDF will hand back an ID for each.
call check( nf90_def_dim(ncid, "nhis_dim", nhispoint, nhis_dimid) )
call check( nf90_def_dim(ncid, "time_dim", istep, time_dimid) )
if (nfrac>0) then
call check( nf90_def_dim(ncid, "nfrac_dim", nfrac, nfrac_dimid) )
endif
! The dimids array is used to pass the IDs of the dimensions of
! the variables. Note that in fortran arrays are stored in
! column-major format.
dimids1 = (/ nhis_dimid, time_dimid/)
dimids2 = (/ nhis_dimid /)
if (nfrac>0) then
dimids3 = (/ nfrac_dimid, nhis_dimid, time_dimid/)
endif
dimids4 = (/ time_dimid/)
! Define the variable. The type of the variable in this case is
! NF90_DOUBLE (4-byte double).
call check( nf90_def_var(ncid, "Uhis", NF90_DOUBLE, dimids1, varid1) )
call check( nf90_put_att(ncid, varid1, 'units', 'm/s') )
call check( nf90_put_att(ncid, varid1, 'long_name', 'Time history of U velocity at specific history location') )
call check( nf90_def_var(ncid, "Vhis", NF90_DOUBLE, dimids1, varid2) )
call check( nf90_put_att(ncid, varid2, 'units', 'm/s') )
call check( nf90_put_att(ncid, varid2, 'long_name', 'Time history of V velocity at specific history location') )
call check( nf90_def_var(ncid, "Whis", NF90_DOUBLE, dimids1, varid3) )
call check( nf90_put_att(ncid, varid3, 'units', 'm/s') )
call check( nf90_put_att(ncid, varid3, 'long_name', 'Time history of W velocity at specific history location') )
call check( nf90_def_var(ncid, "RHOhis", NF90_DOUBLE, dimids1, varid4) )
call check( nf90_put_att(ncid, varid4, 'units', 'kg/m3') )
call check( nf90_put_att(ncid, varid4, 'long_name', 'Time history of density at specific history location') )
call check( nf90_def_var(ncid, "Phis", NF90_DOUBLE, dimids1, varid5) )
call check( nf90_put_att(ncid, varid5, 'units', 'Pa') )
call check( nf90_put_att(ncid, varid5, 'long_name', 'Time history of pressure at specific history location') )
if (nfrac>0) then
call check( nf90_def_var(ncid, "Chis", NF90_DOUBLE, dimids3, varid6) )
call check( nf90_put_att(ncid, varid6, 'units', '-') )
call check( nf90_put_att(ncid, varid6, 'long_name', 'Time history of volume concentration
& of each fraction at specific history location') )
endif
call check( nf90_def_var(ncid, "xhis", NF90_DOUBLE, dimids2, varid7) )
call check( nf90_put_att(ncid, varid7, 'units', 'm') )
call check( nf90_put_att(ncid, varid7, 'long_name', 'X coordinate of specific history location') )
call check( nf90_def_var(ncid, "yhis", NF90_DOUBLE, dimids2, varid8) )
call check( nf90_put_att(ncid, varid8, 'units', 'm') )
call check( nf90_put_att(ncid, varid8, 'long_name', 'Y coordinate of specific history location') )
call check( nf90_def_var(ncid, "zhis", NF90_DOUBLE, dimids2, varid9) )
call check( nf90_put_att(ncid, varid9, 'units', 'm') )
call check( nf90_put_att(ncid, varid9, 'long_name', 'Z coordinate of specific history location') )
call check( nf90_def_var(ncid, "ihis", NF90_INT, dimids2, varid10) )
call check( nf90_put_att(ncid, varid10, 'units', '-') )
call check( nf90_put_att(ncid, varid10, 'long_name', 'i coordinate of specific history location') )
call check( nf90_def_var(ncid, "jhis", NF90_INT, dimids2, varid11) )
call check( nf90_put_att(ncid, varid11, 'units', '-') )
call check( nf90_put_att(ncid, varid11, 'long_name', 'j coordinate of specific history location') )
call check( nf90_def_var(ncid, "khis", NF90_INT, dimids2, varid12) )
call check( nf90_put_att(ncid, varid12, 'units', '-') )
call check( nf90_put_att(ncid, varid12, 'long_name', 'k coordinate of specific history location') )
call check( nf90_def_var(ncid, "time_his", NF90_DOUBLE, dimids4, varid13) )
call check( nf90_put_att(ncid, varid13, 'units', 's') )
call check( nf90_put_att(ncid, varid13, 'long_name', 'Time series of history') )
! also add svn info in output files:
CALL check( nf90_put_att(ncid,nf90_global, "svnversion", trim(svnversion)))
CALL check( nf90_put_att(ncid,nf90_global, "svnurl", trim(svnurl)))
! End define mode. This tells netCDF we are done defining metadata.
call check( nf90_enddef(ncid) )
! Write the pretend data to the file. Although netCDF supports
! reading and writing subsets of data, in this case we write all the
! data in one operation.
call check( nf90_put_var(ncid, varid1, Uhis) )
call check( nf90_put_var(ncid, varid2, Vhis) )
call check( nf90_put_var(ncid, varid3, Whis) )
call check( nf90_put_var(ncid, varid4, RHOhis) )
call check( nf90_put_var(ncid, varid5, Phis) )
if (nfrac>0) then
call check( nf90_put_var(ncid, varid6, Chis) )
endif
call check( nf90_put_var(ncid, varid7, xhis) )
call check( nf90_put_var(ncid, varid8, yhis) )
call check( nf90_put_var(ncid, varid9, zhis) )
call check( nf90_put_var(ncid, varid10, ihis) )
call check( nf90_put_var(ncid, varid11, jhis) )
call check( nf90_put_var(ncid, varid12, khis) )
call check( nf90_put_var(ncid, varid13, this) )
call check( nf90_close(ncid) )
ENDIF
END SUBROUTINE