fluxes_base.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: fluxes_base.f90 #
5 !# #
6 !# Copyright (C) 2007-2017 #
7 !# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8 !# Manuel Jung <mjung@astrophysik.uni-kiel.de> #
9 !# Jannes Klee <jklee@astrophysik.uni-kiel.de> #
10 !# #
11 !# This program is free software; you can redistribute it and/or modify #
12 !# it under the terms of the GNU General Public License as published by #
13 !# the Free Software Foundation; either version 2 of the License, or (at #
14 !# your option) any later version. #
15 !# #
16 !# This program is distributed in the hope that it will be useful, but #
17 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
18 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
19 !# NON INFRINGEMENT. See the GNU General Public License for more #
20 !# details. #
21 !# #
22 !# You should have received a copy of the GNU General Public License #
23 !# along with this program; if not, write to the Free Software #
24 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
25 !# #
26 !#############################################################################
27 
28 !----------------------------------------------------------------------------!
38 !----------------------------------------------------------------------------!
41  USE mesh_base_mod
42  USE marray_base_mod
47  USE common_dict
48 #ifdef PARALLEL
49 #ifdef HAVE_MPI_MOD
50  USE mpi
51 #endif
52 #endif
53  IMPLICIT NONE
54 #ifdef PARALLEL
55 #ifdef HAVE_MPIF_H
56  include 'mpif.h'
57 #endif
58 #endif
59  !--------------------------------------------------------------------------!
60  PRIVATE
61  TYPE, ABSTRACT, EXTENDS (logging_base) :: fluxes_base
63  CLASS(reconstruction_base), ALLOCATABLE &
64  :: reconstruction
65  CLASS(marray_base), ALLOCATABLE &
66  :: minwav,maxwav
67  CLASS(marray_compound), POINTER :: prim, & !< primitive/conservative
68  cons, & !< state vectors on cell faces
69  pfluxes
72  REAL, DIMENSION(:,:,:,:), POINTER, CONTIGUOUS &
73  :: bxflux,byflux, &
74  bzflux,bxfold, &
75  byfold,bzfold
76  CONTAINS
77  PROCEDURE :: initfluxes
78  procedure(calculatefluxes), DEFERRED :: calculatefluxes
79  PROCEDURE :: calculatefacedata
80  PROCEDURE :: getboundaryflux
81  procedure(finalize), DEFERRED :: finalize
82  PROCEDURE :: finalize_base
83  END TYPE fluxes_base
84 
85  abstract INTERFACE
86  SUBROUTINE calculatefluxes(this,Mesh,Physics,pvar,cvar, &
87  xfluxdydz,yfluxdzdx,zfluxdxdy)
89  IMPLICIT NONE
90  CLASS(fluxes_base), INTENT(INOUT) :: this
91  CLASS(mesh_base), INTENT(IN) :: Mesh
92  CLASS(physics_base), INTENT(INOUT) :: Physics
93  CLASS(marray_compound),INTENT(INOUT):: pvar,cvar
94  REAL, DIMENSION(Mesh%IGMIN:Mesh%IGMAX,Mesh%JGMIN:Mesh%JGMAX,Mesh%KGMIN:Mesh%KGMAX,Physics%VNUM), &
95  INTENT(OUT) :: xfluxdydz,yfluxdzdx,zfluxdxdy
96  END SUBROUTINE
97  SUBROUTINE finalize(this)
98  IMPORT fluxes_base
99  IMPLICIT NONE
100  CLASS(fluxes_base), INTENT(INOUT) :: this
101  END SUBROUTINE
102  END INTERFACE
103  INTEGER, PARAMETER :: kt = 1
104 ! INTEGER, PARAMETER :: HLL = 2
105 ! INTEGER, PARAMETER :: HLLC = 3
106 ! INTEGER, PARAMETER :: EXACT = 4
107  !--------------------------------------------------------------------------!
108  PUBLIC :: &
109  ! types
110  fluxes_base, &
111  ! constants
112  kt!, HLL, HLLC, EXACT
113  !--------------------------------------------------------------------------!
114 
115 CONTAINS
116 
118  SUBROUTINE initfluxes(this,Mesh,Physics,config,IO,ftype,fname)
119  IMPLICIT NONE
120  !------------------------------------------------------------------------!
121  CLASS(fluxes_base), INTENT(INOUT) :: this
122  CLASS(mesh_base), INTENT(IN) :: Mesh
123  CLASS(physics_base), INTENT(IN) :: Physics
124  TYPE(Dict_TYP),POINTER :: config,IO
125  INTEGER :: err
126  INTEGER :: ftype
127  CHARACTER(LEN=*) :: fname
128  !------------------------------------------------------------------------!
129  TYPE(Dict_TYP),POINTER :: IOrec => null()
130  INTEGER :: valwrite,i
131  CHARACTER(LEN=60) :: key
132  !------------------------------------------------------------------------!
133  CALL this%InitLogging(ftype,fname)
134 
135  ! check initialization of Mesh and Physics
136  IF (.NOT.mesh%Initialized().OR..NOT.physics%Initialized()) &
137  CALL this%Error("InitFluxes","mesh and/or physics module uninitialized")
138 
139  ! allocate memory for all arrays used in fluxes
140  ALLOCATE(this%minwav,this%maxwav, &
141  this%bxflux(mesh%JGMIN:mesh%JGMAX,mesh%KGMIN:mesh%KGMAX,2,physics%VNUM), &
142  this%byflux(mesh%KGMIN:mesh%KGMAX,mesh%IGMIN:mesh%IGMAX,2,physics%VNUM), &
143  this%bzflux(mesh%IGMIN:mesh%IGMAX,mesh%JGMIN:mesh%JGMAX,2,physics%VNUM), &
144  this%bxfold(mesh%JGMIN:mesh%JGMAX,mesh%KGMIN:mesh%KGMAX,2,physics%VNUM), &
145  this%byfold(mesh%KGMIN:mesh%KGMAX,mesh%IGMIN:mesh%IGMAX,2,physics%VNUM), &
146  this%bzfold(mesh%IGMIN:mesh%IGMAX,mesh%JGMIN:mesh%JGMAX,2,physics%VNUM), &
147  stat = err)
148  IF (err.NE.0) THEN
149  CALL this%Error("InitFluxes", "Unable to allocate memory.")
150  END IF
151 
152  ! create RANK 1 mesh arrays
153  this%minwav = marray_base(mesh%NDIMS)
154  this%maxwav = marray_base(mesh%NDIMS)
155 
156  ! initialize state vectors on cell interfaces
157  CALL physics%new_statevector(this%prim,primitive,mesh%NFACES)
158  CALL physics%new_statevector(this%cons,conservative,mesh%NFACES)
159 
160  ! initialize state vector for physical fluxes
161  CALL physics%new_statevector(this%pfluxes,conservative,mesh%NFACES)
162 
163  ! print some information
164  CALL this%Info(" FLUXES---> fluxes type " // trim(this%GetName()))
165 
166  ! enable output of reconstructed cell face data if requested
167  CALL getattr(config, "output/pstates", valwrite,0)
168  IF(valwrite.EQ.1) THEN
169  DO i=1, physics%VNUM
170  key = trim(physics%pvarname(i)) // "_pstates"
171  CALL setattr(io, trim(key), &
172  this%prim%data5d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,:,i))
173  END DO
174  END IF
175  CALL getattr(config, "output/cstates", valwrite, 0)
176  IF(valwrite.EQ.1) THEN
177  DO i=1, physics%VNUM
178  key = trim(physics%cvarname(i)) // "_cstates"
179  CALL setattr(io, trim(key), &
180  this%cons%data5d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,:,i))
181  END DO
182  END IF
183  CALL getattr(config, "output/pfluxes", valwrite, 0)
184  IF(valwrite.EQ.1) THEN
185  DO i=1, physics%VNUM
186  key = trim(physics%pvarname(i)) // "_pfluxes"
187  CALL setattr(io, trim(key), &
188  this%pfluxes%data5d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,:,i))
189  END DO
190  END IF
191 
192  CALL getattr(config, "output/wave_speeds", valwrite, 0)
193  IF(valwrite.EQ.1) THEN
194  CALL setattr(io, "minwav", &
195  this%minwav%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,1:mesh%NDIMS))
196  CALL setattr(io, "maxwav", &
197  this%maxwav%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,1:mesh%NDIMS))
198  END IF
199 
200  ! initialize reconstruction modules
201  CALL new_reconstruction(this%Reconstruction,mesh,physics,config,iorec)
202 
203  ! add output data of reconstruction modules to IO dictionary
204  IF(ASSOCIATED(iorec)) CALL setattr(io,"reconstruction",iorec)
205 
206 
207  ! initialize boundary fluxes
208  this%bxflux(:,:,:,:) = 0.
209  this%byflux(:,:,:,:) = 0.
210  this%bzflux(:,:,:,:) = 0.
211  this%bxfold(:,:,:,:) = 0.
212  this%byfold(:,:,:,:) = 0.
213  this%bzfold(:,:,:,:) = 0.
214  END SUBROUTINE initfluxes
215 
219  FUNCTION getboundaryflux(this,Mesh,Physics,direction,comm) RESULT(bflux)
220  IMPLICIT NONE
221  !------------------------------------------------------------------------!
222  CLASS(fluxes_base), INTENT(IN) :: this
223  CLASS(mesh_base), INTENT(IN) :: mesh
224  CLASS(physics_base), INTENT(IN) :: physics
225  INTEGER :: direction
226  REAL, DIMENSION(Physics%VNUM) :: bflux
227  INTEGER, OPTIONAL :: comm ! communicator for MPI
228  !------------------------------------------------------------------------!
229 #ifdef PARALLEL
230  REAL, DIMENSION(Physics%VNUM) :: bflux_local
231  INTEGER :: sender_rank(1),dest_ranks(1),rank0(1)
232  INTEGER :: dest_comm,union_comm
233  INTEGER :: world_group,dest_group,union_group,sender_group
234  INTEGER :: ierror
235 #endif
236  !------------------------------------------------------------------------!
237  INTENT(IN) :: direction
238  !------------------------------------------------------------------------!
239 #ifdef PARALLEL
240  IF (PRESENT(comm)) THEN
241  dest_comm = comm
242  ELSE
243  dest_comm = mpi_comm_null
244  END IF
245 #endif
246  SELECT CASE(direction)
247  CASE(west) ! western boundary flux
248 #ifdef PARALLEL
249  IF (mesh%mycoords(1).EQ.0) THEN
250  bflux_local(:) = sum(sum(this%bxflux(mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,1,:),1),1)
251  ELSE
252  bflux_local(:) = 0.0
253  END IF
254 #else
255  bflux = sum(sum(this%bxflux(mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,1,:),1),1)
256 #endif
257  CASE(east) ! eastern boundary flux
258 #ifdef PARALLEL
259  IF (mesh%mycoords(1).EQ.mesh%dims(1)-1) THEN
260  bflux_local(:) = sum(sum(this%bxflux(mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,2,:),1),1)
261  ELSE
262  bflux_local(:) = 0.0
263  END IF
264 #else
265  bflux = sum(sum(this%bxflux(mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,2,:),1),1)
266 #endif
267  CASE(south) ! southern boundary flux
268 #ifdef PARALLEL
269  IF (mesh%mycoords(2).EQ.0) THEN
270  bflux_local(:) = sum(sum(this%byflux(mesh%KMIN:mesh%KMAX,mesh%IMIN:mesh%IMAX,1,:),1),1)
271  ELSE
272  bflux_local(:) = 0.0
273  END IF
274 #else
275  bflux = sum(sum(this%byflux(mesh%KMIN:mesh%KMAX,mesh%IMIN:mesh%IMAX,1,:),1),1)
276 #endif
277  CASE (north) ! northern boundary flux
278 #ifdef PARALLEL
279  IF (mesh%mycoords(2).EQ.mesh%dims(2)-1) THEN
280  bflux_local(:) = sum(sum(this%byflux(mesh%KMIN:mesh%KMAX,mesh%IMIN:mesh%IMAX,2,:),1),1)
281  ELSE
282  bflux_local(:) = 0.0
283  END IF
284 #else
285  bflux = sum(sum(this%byflux(mesh%KMIN:mesh%KMAX,mesh%IMIN:mesh%IMAX,2,:),1),1)
286 #endif
287  CASE (bottom) ! bottom boundary flux
288 #ifdef PARALLEL
289  IF (mesh%mycoords(3).EQ.0) THEN
290  bflux_local(:) = sum(sum(this%bzflux(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,1,:),1),1)
291  ELSE
292  bflux_local(:) = 0.0
293  END IF
294 #else
295  bflux = sum(sum(this%bzflux(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,1,:),1),1)
296 #endif
297  CASE (top) ! topper boundary flux
298 #ifdef PARALLEL
299  IF (mesh%mycoords(3).EQ.mesh%dims(3)-1) THEN
300  bflux_local(:) = sum(sum(this%bzflux(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,2,:),1),1)
301  ELSE
302  bflux_local(:) = 0.0
303  END IF
304 #else
305  bflux = sum(sum(this%bzflux(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,2,:),1),1)
306 #endif
307  CASE DEFAULT
308  CALL this%Error("GetBoundaryFlux","wrong direction")
309  END SELECT
310 
311 #ifdef PARALLEL
312  ! if dest_comm is the world comm, use simpler and faster AllReduce
313  IF(dest_comm.EQ.mpi_comm_world) THEN
314  CALL mpi_allreduce(bflux_local,bflux,physics%VNUM,default_mpi_real, &
315  mpi_sum,mpi_comm_world,ierror)
316  ELSE
317  ! create world group
318  CALL mpi_comm_group(mpi_comm_world,world_group,ierror)
319  ! determine the destination for the result
320  IF(dest_comm.NE.mpi_comm_null) THEN
321  dest_comm = comm
322  ! set destination group
323  CALL mpi_comm_group(dest_comm,dest_group,ierror)
324  ELSE
325  ! if no communicator is given, send the result
326  ! to the rank0 process
327  dest_ranks(1) = 0
328  CALL mpi_group_incl(world_group,1,dest_ranks,dest_group,ierror)
329  END IF
330  ! collect and sum up the result in process with rank 0 with respect to the
331  ! subset of MPI processes at the boundary under consideration
332  IF (mesh%comm_boundaries(direction).NE.mpi_comm_null) THEN
333  CALL mpi_reduce(bflux_local,bflux,physics%VNUM,default_mpi_real, &
334  mpi_sum,0,mesh%comm_boundaries(direction),ierror)
335  ELSE
336  bflux(:) = 0.0
337  END IF
338  ! get sender group
339  rank0(1) = mesh%rank0_boundaries(direction)
340  CALL mpi_group_incl(world_group,1,rank0,sender_group,ierror)
341  ! merge sender with destination
342  CALL mpi_group_union(sender_group,dest_group,union_group,ierror)
343  ! create a communicator for the union group
344  CALL mpi_comm_create(mpi_comm_world,union_group,union_comm,ierror)
345  IF (union_comm.NE.mpi_comm_null) THEN
346  ! get rank of sender in union group
347  rank0(1) = 0
348  CALL mpi_group_translate_ranks(sender_group,1,rank0,union_group,sender_rank,ierror)
349  IF (sender_rank(1).EQ.mpi_undefined) &
350  CALL this%Error("GetBoundaryFlux","sender rank undefined")
351  ! send result to all processes in communicator 'union_comm'
352  CALL mpi_bcast(bflux,physics%VNUM,default_mpi_real,sender_rank(1),union_comm,ierror)
353  ! free union communicator
354  CALL mpi_comm_free(union_comm,ierror)
355  END IF
356  ! free all groups
357  CALL mpi_group_free(union_group,ierror)
358  CALL mpi_group_free(sender_group,ierror)
359  CALL mpi_group_free(world_group,ierror)
360  CALL mpi_group_free(dest_group,ierror)
361  END IF
362 
363 #endif
364  END FUNCTION getboundaryflux
365 
367  PURE SUBROUTINE calculatefacedata(this,Mesh,Physics,pvar,cvar)
369  IMPLICIT NONE
370  !------------------------------------------------------------------------!
371  CLASS(fluxes_base), INTENT(INOUT) :: this
372  CLASS(mesh_base), INTENT(IN) :: mesh
373  CLASS(physics_base), INTENT(INOUT) :: physics
374  CLASS(marray_compound),INTENT(INOUT):: pvar,cvar
375  !------------------------------------------------------------------------!
376  ! reconstruct data on cell faces
377  IF (this%Reconstruction%PrimRecon()) THEN
378  CALL this%Reconstruction%CalculateStates(mesh,physics,pvar,this%prim)
379  CALL physics%Convert2Conservative(this%prim,this%cons)
380  ELSE
381  CALL this%Reconstruction%CalculateStates(mesh,physics,cvar,this%cons)
382  CALL physics%Convert2Primitive(this%cons,this%prim)
383  END IF
384 
385  ! update the speed of sound on cell faces (non-isotherml physics only)
386  SELECT TYPE(phys => physics)
387  CLASS IS(physics_euler)
388  SELECT TYPE(prim => this%prim)
389  CLASS IS(statevector_euler)
390  CALL phys%UpdateSoundSpeed(prim)
391  END SELECT
392  END SELECT
393 
394  ! get minimal & maximal wave speeds on cell interfaces
395  CALL physics%CalculateWaveSpeeds(mesh,this%prim%data5d,this%cons%data5d,this%minwav,this%maxwav)
396  END SUBROUTINE calculatefacedata
397 
399  SUBROUTINE finalize_base(this)
400  IMPLICIT NONE
401  !------------------------------------------------------------------------!
402  CLASS(fluxes_base), INTENT(INOUT) :: this
403  !------------------------------------------------------------------------!
404  IF (.NOT.this%Initialized()) &
405  CALL this%Error("CloseFluxes","not initialized")
406  CALL this%minwav%Destroy()
407  CALL this%maxwav%Destroy()
408  CALL this%prim%Destroy()
409  CALL this%cons%Destroy()
410  CALL this%pfluxes%Destroy()
411  DEALLOCATE(this%cons,this%prim,this%pfluxes,this%minwav,this%maxwav, &
412  this%bxflux,this%byflux,this%bzflux,this%bxfold,this%byfold,this%bzfold)
413  CALL this%Reconstruction%Finalize()
414  DEALLOCATE(this%Reconstruction)
415  END SUBROUTINE finalize_base
416 
417 END MODULE fluxes_base_mod
subroutine finalize(this)
Destructor of common class.
real function, dimension(physics%vnum) getboundaryflux(this, Mesh, Physics, direction, comm)
Get fluxes at boundaries.
integer, save default_mpi_real
default real type for MPI
type(logging_base), save this
derived class for compound of mesh arrays
base class for mesh arrays
Definition: marray_base.f90:36
Basic fosite module.
common data structure
subroutine new_reconstruction(Reconstruction, Mesh, Physics, config, IO)
pure subroutine calculatefacedata(this, Mesh, Physics, pvar, cvar)
Calcualtes face data with reconstruction methods (e. g. limiters)
subroutine initfluxes(this, Mesh, Physics, config, IO, ftype, fname)
Initialize Fluxes.
constructor for physics class
subroutine finalize_base(this)
Destructor.
basic mesh array class
Definition: marray_base.f90:64
integer, parameter, public kt
named integer constants for flavour of state vectors
Basic physics module.
Dictionary for generic data types.
Definition: common_dict.f90:61
physics module for 1D,2D and 3D non-isothermal Euler equations
base module for numerical flux functions
Definition: fluxes_base.f90:39
constructor for reconstruction class