63 = 2.50662827463100050241576528481104525300698674
69 TYPE(c_ptr) :: pfdensity, pfphi
70 TYPE(c_ptr) :: plan_r2c
71 TYPE(c_ptr) :: plan_c2r
72 REAL(c_double),
DIMENSION(:,:),
POINTER &
73 :: fdensity,fphi,block
74 COMPLEX(C_DOUBLE_COMPLEX),
DIMENSION(:,:),
POINTER &
75 :: cfdensity, cfphi, cblock
77 REAL(c_double),
DIMENSION(:,:,:),
POINTER &
79 COMPLEX(C_DOUBLE_COMPLEX),
DIMENSION(:,:,:),
POINTER &
82 REAL,
DIMENSION(:,:,:),
POINTER :: phi
83 REAL,
DIMENSION(:,:),
POINTER :: tmp2d
84 REAL,
DIMENSION(:,:),
POINTER :: phi2d
85 REAL,
DIMENSION(:),
POINTER :: height1d
88 INTEGER,
DIMENSION(:),
POINTER :: sizes
89 INTEGER,
POINTER :: mcut
96 INTEGER,
DIMENSION(:),
POINTER :: displ, num
98 REAL,
DIMENSION(:,:),
POINTER :: sbuf1,sbuf2,& !< send buffers
127 TYPE(
dict_typ),
POINTER :: config,IO
129 INTEGER :: err, valwrite
130 CHARACTER(LEN=32) :: info_str
132 CALL this%InitGravity(mesh,physics,
"spectral",config,io)
134#if !defined(HAVE_FFTW)
135 CALL this%Error(
"InitGravity_spectral", &
136 "Mandatory requirement fft has not been enabled. "//&
137 "Please add --with-fftw=$FFTWDIR or similar to configure call.")
139#if defined(HAVE_FFTW)
142 IF(.NOT.(mesh%dims(2).EQ.1)) &
143 CALL this%Error(
"InitGravity_spectral", &
144 "Only domains shaped as annular rings are allowed (N x 1 decompositions).")
157 IF(.NOT.(mod(mesh%JNUM,2)==0))
THEN
158 CALL this%Error(
"InitGravity_spectral", &
159 "The spectral poisson solver needs an even number of cells " // &
160 "in the phi direction due to the discrete cosinus transform.")
167 IF(mesh%IMAX.EQ.mesh%INUM)
THEN
168 this%IMAX = mesh%IMAX+1
170 this%IMAX = mesh%IMAX
174 this%IMAX = mesh%IMAX+1
177 this%INUM = this%IMAX - mesh%IMIN + 1
180 this%MNUM = mesh%JNUM/2+1
182 ALLOCATE(this%phi2D(mesh%IGMIN:mesh%IGMAX,mesh%JGMIN:mesh%JGMAX), &
183 this%tmp2D(mesh%IGMIN:mesh%IGMAX,mesh%JGMIN:mesh%JGMAX), &
185 this%height1D(1:mesh%INUM), &
189 this%sbuf1(mesh%GNUM,mesh%JNUM), &
190 this%rbuf1(mesh%GNUM,mesh%JNUM), &
191 this%sbuf2(mesh%GNUM,mesh%JNUM), &
192 this%rbuf2(mesh%GNUM,mesh%JNUM), &
193 this%displ(0:this%GetNumProcs()-1),&
194 this%num(0:this%GetNumProcs()-1),&
199 CALL this%Error(
"gravity_spectral::InitGravity_spectral",
"memory allocation failed")
203 this%pot%data1d(:) = 0.0
205 CALL getattr(config,
"green", this%green, 1)
206 SELECT CASE(this%green)
210 CALL this%Error(
"gravity_spectral::InitGravity_spectral",
"type of Green's function should be one of 1,2,3")
213 CALL getattr(config,
"sigma", this%sigma, 0.05)
214 this%height1D(:) = this%sigma
220 CALL getattr(config,
"mcut", this%mcut, this%MNUM)
221 this%mcut = min(this%mcut,this%MNUM)
226 CALL getattr(config,
"ecut", this%ecut, 0.)
228 CALL this%Info(
" Initializing")
230 WRITE (info_str,
'(I8)') this%green
231 CALL this%Info(
" green-fn type: " // trim(info_str))
232 WRITE (info_str,
'(ES8.2)') this%sigma
233 CALL this%Info(
" sigma: " // trim(info_str))
237 this%p_FI = fftw_alloc_real(int(2*this%MNUM * (this%INUM)*(mesh%INUM), c_size_t))
238 CALL c_f_pointer(this%p_FI, this%FI, &
239 [2*this%MNUM,this%INUM,mesh%INUM])
240 CALL c_f_pointer(this%p_FI, this%cFI, &
241 [this%MNUM,this%INUM,mesh%INUM])
244 this%pFdensity = fftw_alloc_real(int(2*this%MNUM*mesh%INUM, c_size_t))
245 CALL c_f_pointer(this%pFdensity, this%Fdensity, &
246 [2*this%MNUM,mesh%INUM])
247 CALL c_f_pointer(this%pFdensity, this%cFdensity, &
248 [mesh%JNUM/2+1,mesh%INUM])
250 this%pFphi = fftw_alloc_real(int(2*this%MNUM*this%INUM,c_size_t))
251 CALL c_f_pointer(this%pFphi, this%Fphi, &
252 [2*this%MNUM, this%INUM])
253 CALL c_f_pointer(this%pFphi, this%cFphi, &
254 [mesh%JNUM/2+1, this%INUM])
257 CALL this%Error(
"InitGravity_spectral",
"Memory allocation failed.")
259 this%block => this%Fdensity(:,mesh%IMIN:mesh%IMAX)
260 this%cblock => this%cFdensity(:,mesh%IMIN:mesh%IMAX)
269 this%sizes(1) = mesh%JNUM
270 this%plan_r2c = fftw_plan_many_dft_r2c(1, this%sizes, (mesh%IMAX-mesh%IMIN+1),&
271 this%block, this%sizes, &
273 this%cblock, this%sizes, &
277 this%sizes(1) = mesh%JNUM
278 this%plan_c2r = fftw_plan_many_dft_c2r(1, this%sizes, this%INUM, &
279 this%cFphi, this%sizes, &
281 this%Fphi, this%sizes, &
285 IF(this%ecut.GT.0.) &
286 CALL setattr(io,
"mcut",ref(this%mcut))
289 this%displ((this%GetRank())) = (mesh%IMIN-1)*2*this%mcut
290 this%num((this%GetRank())) = (mesh%IMAX-mesh%IMIN+1)*2*this%mcut
291 CALL mpi_allgather(mpi_in_place, 0, mpi_datatype_null, &
292 this%displ, 1, mpi_integer, mpi_comm_world, this%mpi_error)
293 CALL mpi_allgather(mpi_in_place, 0, mpi_datatype_null, &
294 this%num, 1, mpi_integer, mpi_comm_world, this%mpi_error)
298 CALL this%PrecomputeI(mesh, physics)
300 CALL this%Info(
" .. done initializing")
311 TYPE(
dict_typ),
POINTER :: config,IO
316 CALL getattr(config,
"output/potential", valwrite, 0)
317 IF (valwrite .EQ. 1.AND.
ALLOCATED(this%pot))
THEN
318 IF (
ASSOCIATED(this%pot%data4d)) &
319 CALL setattr(io,
"potential", &
320 this%pot%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,4))
337 REAL :: cumsum(
this%mnum)
338 INTEGER :: mcut(mesh%imin:mesh%imax)
340 DO i=mesh%IMIN,mesh%IMAX
341 cumsum(1) =
this%Fdensity(2*1-1,i)**2 +
this%Fdensity(2*1,i)**2
343 cumsum(m) = cumsum(m-1) +
this%Fdensity(2*m-1,i)**2 +
this%Fdensity(2*m,i)**2
346 IF(abs(cumsum(m)/cumsum(
this%MNUM)-1.).LT.
this%ecut)
THEN
355 CALL mpi_allreduce(mpi_in_place,res,1,mpi_integer,mpi_max,mpi_comm_world,ier)
360#if defined(HAVE_FFTW)
369 REAL,
INTENT(IN) :: time
371 INTEGER :: i,k,m,i0,oldmcut
373 INTEGER :: status(MPI_STATUS_SIZE)
377 SELECT TYPE(p => pvar)
379 DO k=mesh%KMIN, mesh%KMAX
380 DO i=mesh%IMIN, mesh%IMAX
381 this%Fdensity(1:mesh%JNUM,i) = p%density%data3d(i,mesh%JMIN:mesh%JMAX,k)
385 CALL this%Error(
"gravity_spectral::CalcPotential",
"unsupported state vector")
388 CALL fftw_execute_dft_r2c(this%plan_r2c, this%block, this%cblock)
390 IF(this%ecut.GT.0.)
THEN
393 this%mcut = this%CalcMcut(mesh)
396 this%displ = this%displ / oldmcut * this%mcut
397 this%num = this%num / oldmcut * this%mcut
403 CALL mpi_allgatherv(mpi_in_place, 0, mpi_datatype_null,&
404 this%Fdensity(1:2*this%mcut,1:mesh%INUM), &
406 mpi_comm_world, this%mpi_error)
430 this%FPhi(2*m-1,i) = this%FPhi(2*m-1,i) &
431 + this%Fdensity(2*m-1,i0) * this%FI(2*m-1,i,i0)
433 this%FPhi(2*m,i) = this%FPhi(2*m,i) &
434 + this%Fdensity(2*m,i0) * this%FI(2*m-1,i,i0)
440 CALL fftw_execute_dft_c2r(this%plan_c2r, this%cFphi, this%Fphi)
443 this%phi2D(i+mesh%IMIN-1,mesh%JMIN:mesh%JMAX) = this%FPhi(1:mesh%JNUM,i)
449 IF (mesh%neighbor(
west).NE.mpi_proc_null) &
450 this%sbuf1 = this%phi2D(mesh%IMIN:mesh%IMIN+mesh%GNUM-1,mesh%JMIN:mesh%JMAX)
451 CALL mpi_sendrecv(this%sbuf1,mesh%GNUM*mesh%JNUM, &
454 mpi_any_tag,mesh%comm_cart,status,this%mpi_error)
455 IF (mesh%neighbor(
east).NE.mpi_proc_null) &
456 this%phi2D(mesh%IMAX+1:mesh%IGMAX,mesh%JMIN:mesh%JMAX) = this%rbuf1
458 IF (mesh%neighbor(
east).NE.mpi_proc_null) &
459 this%sbuf2 = this%phi2D(mesh%IMAX-mesh%GNUM+1:mesh%IMAX,mesh%JMIN:mesh%JMAX)
460 CALL mpi_sendrecv(this%sbuf2,mesh%GNUM*mesh%JNUM, &
463 mpi_any_tag,mesh%comm_cart,status,this%mpi_error)
464 IF (mesh%neighbor(
west).NE.mpi_proc_null) &
465 this%phi2D(mesh%IGMIN:mesh%IMIN-1,mesh%JMIN:mesh%JMAX) = this%rbuf2
467 this%phi2D(mesh%IGMIN:mesh%IGMAX,mesh%JGMIN:mesh%JMIN-1) &
468 = this%phi2D(mesh%IGMIN:mesh%IGMAX,mesh%JMAX-mesh%GNUM+1:mesh%JMAX)
469 this%phi2D(mesh%IGMIN:mesh%IGMAX,mesh%JMAX+1:mesh%JGMAX) &
470 = this%phi2D(mesh%IGMIN:mesh%IGMAX,mesh%JMIN:mesh%JMIN+mesh%GNUM-1)
500 REAL,
INTENT(IN) :: dr2
501 INTEGER,
INTENT(IN) :: green
502 REAL,
INTENT(IN) :: sigma
509 g = -1.0 *
bessel_k0e(dr2/(4.0*sigma*sigma)) &
535 TYPE(c_ptr) :: plan_r2c
536 INTEGER :: i1, i, j, k
538 CHARACTER(LEN=128) :: str
539 REAL,
DIMENSION(Mesh%JMIN:Mesh%JMAX) &
541 REAL,
DIMENSION(1:Mesh%INUM+1) :: r,hx,hy
542 REAL,
DIMENSION(Mesh%JMIN:Mesh%JMAX,Mesh%IMIN:this%IMAX) :: dr2
543 INTEGER :: rank, howmany, istride, idist, ostride, odist
544 INTEGER,
DIMENSION(1) &
547 INTEGER,
DIMENSION(0:(this%GetNumProcs())-1) :: num,displ
552 howmany = this%INUM * mesh%INUM
557 plan_r2c = fftw_plan_many_dft_r2c(rank, n, howmany, &
565 phi = mesh%curv%center(mesh%IMIN,mesh%JMIN:mesh%JMAX,mesh%KMIN,2)&
566 - mesh%curv%center(mesh%IMIN,mesh%JMIN,mesh%KMIN,2)
568 r(mesh%IMIN:this%IMAX) = mesh%radius%bcenter(mesh%IMIN:this%IMAX,mesh%JMIN,mesh%KMIN)
569 hx(mesh%IMIN:this%IMAX) = mesh%hx%bcenter(mesh%IMIN:this%IMAX,mesh%JMIN,mesh%KMIN)
570 hy(mesh%IMIN:this%IMAX) = mesh%hy%bcenter(mesh%IMIN:this%IMAX,mesh%JMIN,mesh%KMIN)
572 displ(this%GetRank()) = (mesh%IMIN-1)
573 num(this%GetRank()) = this%INUM
574 CALL mpi_allgather(mpi_in_place, 0, mpi_datatype_null, &
575 displ, 1, mpi_integer, mpi_comm_world, this%mpi_error)
576 CALL mpi_allgather(mpi_in_place, 0, mpi_datatype_null, &
577 num, 1, mpi_integer, mpi_comm_world, this%mpi_error)
578 CALL mpi_allgatherv(mpi_in_place, 0, mpi_datatype_null, &
581 CALL mpi_allgatherv(mpi_in_place, 0, mpi_datatype_null, &
584 CALL mpi_allgatherv(mpi_in_place, 0, mpi_datatype_null, &
589 DO k=mesh%KMIN,mesh%KMAX
592 DO i=mesh%IMIN,this%IMAX
593 DO j=mesh%JMIN,mesh%JMAX
594 r0 = mesh%radius%faces(i,j,k,1)
595 dr2(j,i) = r(i1)**2 + r0**2 - 2.*r(i1)*r0*cos(phi(j))
599 this%FI(1:mesh%JNUM,1:this%INUM,i1) &
600 = 2.0 *
pi * hx(i1) * hy(i1) * mesh%dx &
601 * physics%Constants%GN &
607 CALL fftw_execute_dft_r2c(plan_r2c, this%FI, this%cFI)
610 CALL fftw_destroy_plan(plan_r2c)
617 notzero = sum(abs(this%FI(2:2*this%MNUM:2,:,:)))/(this%MNUM*mesh%JNUM*this%INUM)
621 mpi_comm_world, this%mpi_error)
623 IF(notzero.GT.1.)
THEN
624 WRITE(str,
'(A,ES12.4,A)')
"Imag(FI) should be zero, but ",notzero,&
626 CALL this%Warning(
"ProcomputeI_spectral",trim(str))
629 this%FI(2:2*this%MNUM:2,:,:) = 0.
642 REAL,
INTENT(IN) :: time,dt
648 CALL this%CalcPotential(mesh,physics,time,pvar)
656 DO k = mesh%KMIN,mesh%KMAX
658 DO j = mesh%JMIN-mesh%JP1,mesh%JMAX+mesh%JP1
660 DO i = mesh%IMIN-mesh%IP1,mesh%IMAX
661 this%accel%data4d(i,j,k,1) = -1.0*(this%phi2D(i+1,j)-this%phi2D(i,j))/mesh%dlx%data3d(i,j,k)
662 this%accel%data4d(i,j,k,2) = -1.0*(this%phi2D(i+1,j+1)+this%phi2D(i,j+1) &
663 -this%phi2D(i+1,j-1)-this%phi2D(i,j-1))&
664 /(4.0*mesh%dly%data3d(i,j,k))
665 this%pot%data4d(i,j,k,1) = 0.5*(this%phi2D(i,j)+this%phi2D(i+1,j))
666 this%pot%data4d(i,j,k,2) = this%phi2D(i+1,j)
667 this%pot%data4d(i,j,k,3) = 0.25*(this%phi2D(i,j)+this%phi2D(i+1,j)+this%phi2D(i,j+1)+this%phi2D(i+1,j+1))
721 TYPE(
marray_base),
INTENT(INOUT) :: bccsound,h_ext,height
723 REAL,
DIMENSION(Mesh%IGMIN:Mesh%IGMAX,Mesh%JGMIN:Mesh%JGMAX,2) &
731 DO k=mesh%KMIN-mesh%KP1,mesh%KMAX
732 DO j=mesh%JMIN-mesh%JP1,mesh%JMAX
733 DO i=mesh%IMIN-mesh%IP1,mesh%IMAX
734 phi(i,j,1) = mesh%hy%faces(i,j,k,2)*mesh%hz%faces(i,j,k,2)/mesh%hx%faces(i,j,k,2)&
735 * this%pot%data4d(i,j,k,2)
736 phi(i,j,2) = mesh%hx%faces(i,j,k,4)*mesh%hz%faces(i,j,k,4)/mesh%hy%faces(i,j,k,4)&
737 * this%pot%data4d(i,j,k,3)
742 DO k=mesh%KMIN,mesh%KMAX
743 DO j=mesh%JMIN,mesh%JMAX
744 DO i=mesh%IMIN,mesh%IMAX
745 this%tmp2D(i,j) = - 1./mesh%sqrtg%bcenter(i,j,k) &
746 * ( (phi(i,j,1) - phi(i-1,j,1)) / mesh%dlx%data3d(i,j,k) &
747 + (phi(i,j,2) - phi(i,j-1,2)) / mesh%dly%data3d(i,j,k))
752 IF (
ASSOCIATED(h_ext%data1d).AND.(h_ext.match.height).AND. &
753 (minval(h_ext%data1d,mask=mesh%without_ghost_zones%mask1d(:)).GT.0.0))
THEN
755 DO k=mesh%KGMIN,mesh%KGMAX
756 DO j=mesh%JGMIN,mesh%JGMAX
757 DO i=mesh%IGMIN,mesh%IGMAX
758 cs2 = bccsound%data3d(i,j,k)**2
759 p =
sqrttwopi*physics%Constants%GN*pvar%data4d(i,j,k,physics%DENSITY)*h_ext%data3d(i,j,k)/cs2
760 q = 1. + this%tmp2D(i,j)*h_ext%data3d(i,j,k)**2/cs2
762 height%data3d(i,j,k) = h_ext%data3d(i,j,k) / (p+sqrt(q+p*p))
768 DO k=mesh%KGMIN,mesh%KGMAX
769 DO j=mesh%JGMIN,mesh%JGMAX
770 DO i=mesh%IGMIN,mesh%IGMAX
771 cs2 = bccsound%data3d(i,j,k)**2
772 p =
sqrttwopi*physics%Constants%GN*pvar%data4d(i,j,k,physics%DENSITY)*mesh%radius%bcenter(i,j,k)/cs2
773 q = this%tmp2D(i,j)*h_ext%data3d(i,j,k)**2/cs2
775 height%data3d(i,j,k) = mesh%radius%bcenter(i,j,k) / (p+sqrt(q+p*p))
789#if defined(HAVE_FFTW)
791 CALL fftw_destroy_plan(this%plan_r2c)
792 CALL fftw_destroy_plan(this%plan_c2r)
801 this%displ,this%num,&
810 CALL fftw_free(this%p_FI)
811 CALL fftw_free(this%pFdensity)
812 CALL fftw_free(this%pFphi)
817 IF (
ALLOCATED(this%pot))
DEALLOCATE(this%pot)
818 CALL this%Finalize_base()
Dictionary for generic data types.
type(logging_base), save this
base module for numerical flux functions
elemental real function, public bessel_k0e(x)
Compute the exponential scaled modified Bessel function of the second kind e.g. K0e = EXP(x) * K0(x) ...
generic gravity terms module providing functionaly common to all gravity terms
2D poisson solver using spectral methods for direct integration
subroutine updategravity_single(this, Mesh, Physics, Fluxes, pvar, time, dt)
elemental real function greenfunction(dr2, green, sigma)
Green's function.
subroutine calcpotential(this, Mesh, Physics, time, pvar)
subroutine initgravity_spectral(this, Mesh, Physics, config, IO)
real, parameter sqrttwopi
integer function calcmcut(this, Mesh)
subroutine precomputei(this, Mesh, Physics)
Precomputes the fourier transform.
subroutine calcdiskheight_single(this, Mesh, Physics, pvar, bccsound, h_ext, height)
compute disk pressure scale height for geometrically thin self-gravitating disks
subroutine finalize(this)
Destructor of logging_base class.
integer, save default_mpi_real
default real type for MPI
base class for mesh arrays
integer, save knum
array sizes
derived class for compound of mesh arrays
integer, parameter east
named constant for eastern boundary
subroutine setoutput(this, config, IO)
Setup mesh fields for i/o.
integer, parameter west
named constant for western boundary
physics module for 1D,2D and 3D isothermal Euler equations