MPI-AMRVAC 3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_convert.t
Go to the documentation of this file.
2
3 use mpi
4 use mod_variables, only: max_nw
5
6 implicit none
7 public
8
9 abstract interface
10
11 function sub_convert_vars(ixI^L, ixO^L, w, x, nwc) result(wnew)
13 integer, intent(in) :: ixi^l,ixo^l, nwc
14 double precision, intent(in) :: w(ixi^s, 1:nw)
15 double precision, intent(in) :: x(ixi^s,1:ndim)
16 double precision :: wnew(ixo^s, 1:nwc)
17 end function sub_convert_vars
18
19
20 end interface
22 procedure(sub_convert_vars), pointer, nopass :: phys_convert_vars
23 integer :: nwc
24 character(len=40) :: file_suffix
25 character(len=40) :: dataset_names(max_nw)
26 type(convert_vars_method), pointer :: next
27 end type convert_vars_method
29contains
30
31 subroutine init_convert()
32 !initialize the head of the linked list of convert methods
34 end subroutine init_convert
35
36 ! shortcut
37 subroutine add_convert_method2(phys_convert_vars, nwc, aux_variable_names, file_suffix)
40 integer, intent(in) :: nwc
41 character(len=*),intent(in):: aux_variable_names
42 character(len=*), intent(in) :: file_suffix
43
44 interface
45 function phys_convert_vars(ixI^L, ixO^L, w, x, nwc) result(wnew)
47 integer, intent(in) :: ixI^L, ixO^L, nwc
48 double precision, intent(in) :: w(ixI^S, 1:nw)
49 double precision, intent(in) :: x(ixI^S,1:ndim)
50 double precision :: wnew(ixO^S, 1:nwc)
51 end function phys_convert_vars
52 end interface
53
54 call add_convert_method(phys_convert_vars, nwc, get_names_from_string(aux_variable_names,nwc), file_suffix)
55
56 end subroutine add_convert_method2
57
58 subroutine add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
59 use mod_comm_lib, only: mpistop
60 integer, intent(in) :: nwc
61 character(len=*), intent(in) :: dataset_names(:)
62 character(len=*), intent(in) :: file_suffix
63
64 interface
65 function phys_convert_vars(ixI^L, ixO^L, w, x, nwc) result(wnew)
67 integer, intent(in) :: ixI^L, ixO^L, nwc
68 double precision, intent(in) :: w(ixI^S, 1:nw)
69 double precision, intent(in) :: x(ixI^S,1:ndim)
70 double precision :: wnew(ixO^S, 1:nwc)
71 end function phys_convert_vars
72 end interface
73
74 type(convert_vars_method), pointer :: temp
75
76 if(nwc .gt. max_nw) then
77 call mpistop("INCREASE max_nw ")
78 endif
79
80 allocate(temp)
81 temp%phys_convert_vars => phys_convert_vars
82 temp%nwc = nwc
83 temp%file_suffix = file_suffix
84 temp%dataset_names(1:nwc) = dataset_names(1:nwc)
85 temp%next => head_convert_vars_methods
87 end subroutine add_convert_method
88
89
90 subroutine convert_all()
91 type(convert_vars_method), pointer :: temp
93 do while(associated(temp))
94 call convert_dat_generic(temp%nwc, temp%dataset_names, temp%file_suffix, temp%phys_convert_vars)
95 temp=>temp%next
96 end do
97 end subroutine convert_all
98
99 ! Copied from subroutine write_snapshot in amrvacio/mod_input_output
100 ! the staggered values are not saved in this subroutine!
101 subroutine convert_dat_generic(nwc, dataset_names, file_suffix, convert_vars)
102
103 use mod_forest
107
108 integer :: file_handle, igrid, Morton_no, iwrite
109 integer :: ipe, ix_buffer(2*ndim+1), n_values
110 integer :: ixI^L, ixO^L, n_ghost(2*ndim)
111 integer :: ixOs^L,n_values_stagger
112 integer :: iorecvstatus(MPI_STATUS_SIZE)
113 integer :: ioastatus(MPI_STATUS_SIZE)
114 integer :: igrecvstatus(MPI_STATUS_SIZE)
115 integer :: istatus(MPI_STATUS_SIZE)
116 type(tree_node), pointer :: pnode
117 integer(kind=MPI_OFFSET_KIND) :: offset_tree_info
118 integer(kind=MPI_OFFSET_KIND) :: offset_block_data
119 integer(kind=MPI_OFFSET_KIND) :: offset_offsets
120 double precision, allocatable :: w_buffer(:)
121 double precision, allocatable:: converted_vars(:^D&,:)
122
123 integer :: idim, itag
124 integer, allocatable :: block_ig(:, :)
125 integer, allocatable :: block_lvl(:)
126 integer(kind=MPI_OFFSET_KIND), allocatable :: block_offset(:)
127
128 integer, intent(in) :: nwc
129 character(len=*), intent(in) :: dataset_names(:)
130 character(len=*), intent(in) :: file_suffix
131 interface
132
133 function convert_vars(ixI^L, ixO^L,w,x,nwc) result(wres)
135 integer, intent(in) :: ixI^L, ixO^L, nwc
136 double precision, intent(in) :: x(ixI^S,1:ndim)
137 double precision, intent(in) :: w(ixI^S,1:nw)
138 double precision :: wres(ixO^S,1:nwc)
139 end function convert_vars
140
141 end interface
142
143
144 call mpi_barrier(icomm, ierrmpi)
145
146 ! Allocate send/receive buffer
147 n_values = count_ix(ixg^ll) * nw
148 allocate(w_buffer(n_values))
149
150 ! Allocate arrays with information about grid blocks
151 allocate(block_ig(ndim, nleafs))
152 allocate(block_lvl(nleafs))
153 allocate(block_offset(nleafs+1))
154
155 ! master processor
156 if (mype==0) then
157 call create_output_file(file_handle, snapshotnext, ".dat", file_suffix)
158
159 ! Don't know offsets yet, we will write header again later
160 offset_tree_info = -1
161 offset_block_data = -1
162 call snapshot_write_header1(file_handle, offset_tree_info, &
163 offset_block_data, dataset_names, nwc)
164
165 call mpi_file_get_position(file_handle, offset_tree_info, ierrmpi)
166
167 call write_forest(file_handle)
168
169 ! Collect information about the spatial index (ig^D) and refinement level
170 ! of leaves
171 do morton_no = morton_start(0), morton_stop(npe-1)
172 igrid = sfc(1, morton_no)
173 ipe = sfc(2, morton_no)
174 pnode => igrid_to_node(igrid, ipe)%node
175
176 block_ig(:, morton_no) = [ pnode%ig^d ]
177 block_lvl(morton_no) = pnode%level
178 block_offset(morton_no) = 0 ! Will be determined later
179 end do
180
181 call mpi_file_write(file_handle, block_lvl, size(block_lvl), &
182 mpi_integer, istatus, ierrmpi)
183
184 call mpi_file_write(file_handle, block_ig, size(block_ig), &
185 mpi_integer, istatus, ierrmpi)
186
187 ! Block offsets are currently unknown, but will be overwritten later
188 call mpi_file_get_position(file_handle, offset_offsets, ierrmpi)
189 call mpi_file_write(file_handle, block_offset(1:nleafs), nleafs, &
190 mpi_offset, istatus, ierrmpi)
191
192 call mpi_file_get_position(file_handle, offset_block_data, ierrmpi)
193
194 ! Check whether data was written as expected
195 if (offset_block_data - offset_tree_info /= &
196 (nleafs + nparents) * size_logical + &
197 nleafs * ((1+ndim) * size_int + 2 * size_int)) then
198 if (mype == 0) then
199 print *, "Warning: MPI_OFFSET type /= 8 bytes"
200 print *, "This *could* cause problems when reading .dat files"
201 end if
202 end if
203
204 block_offset(1) = offset_block_data
205 iwrite = 0
206 end if
207
208 do morton_no=morton_start(mype), morton_stop(mype)
209 igrid = sfc_to_igrid(morton_no)
210 itag = morton_no
211 block=>ps(igrid)
212 ! this might be used in convert function,
213 ! it was not used when the output is already computed vars (write_snapshot)
214 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
215
216 ! start copied from block_shape_io,
217 ! because nwc is needed as parameter
218 ! TODO check if this will be used elsewehere and put it in separate subroutine
219 n_ghost(:) = 0
220
221 if(save_physical_boundary) then
222 do idim=1,ndim
223 ! Include ghost cells on lower boundary
224 if(ps(igrid)%is_physical_boundary(2*idim-1)) n_ghost(idim)=nghostcells
225 ! Include ghost cells on upper boundary
226 if(ps(igrid)%is_physical_boundary(2*idim)) n_ghost(ndim+idim)=nghostcells
227 end do
228 end if
229
230 {ixomin^d = ixmlo^d - n_ghost(^d)\}
231 {ixomax^d = ixmhi^d + n_ghost(ndim+^d)\}
232
233 n_values = count_ix(ixo^l) * nwc
234 ! end copied from block_shape_io
235
236 {iximin^d = ixglo^d\}
237 {iximax^d = ixghi^d\}
238
239 w_buffer(1:n_values) = pack(convert_vars(ixi^l, ixo^l,ps(igrid)%w(ixi^s, 1:nw), ps(igrid)%x(ixi^s, 1:ndim),nwc), .true.)
240
241 ix_buffer(1) = n_values
242 ix_buffer(2:) = n_ghost
243
244 if (mype /= 0) then
245 call mpi_send(ix_buffer, 2*ndim+1, &
246 mpi_integer, 0, itag, icomm, ierrmpi)
247 call mpi_send(w_buffer, n_values, &
248 mpi_double_precision, 0, itag, icomm, ierrmpi)
249 else
250 iwrite = iwrite+1
251 call mpi_file_write(file_handle, ix_buffer(2:), &
252 2*ndim, mpi_integer, istatus, ierrmpi)
253 call mpi_file_write(file_handle, w_buffer, &
254 n_values, mpi_double_precision, istatus, ierrmpi)
255
256 ! Set offset of next block
257 block_offset(iwrite+1) = block_offset(iwrite) + &
258 int(n_values, mpi_offset_kind) * size_double + &
259 2 * ndim * size_int
260 end if
261 end do
262
263 ! Write data communicated from other processors
264 if (mype == 0) then
265 do ipe = 1, npe-1
266 do morton_no=morton_start(ipe), morton_stop(ipe)
267 iwrite=iwrite+1
268 itag=morton_no
269
270 call mpi_recv(ix_buffer, 2*ndim+1, mpi_integer, ipe, itag, icomm,&
271 igrecvstatus, ierrmpi)
272 n_values = ix_buffer(1)
273
274 call mpi_recv(w_buffer, n_values, mpi_double_precision,&
275 ipe, itag, icomm, iorecvstatus, ierrmpi)
276
277 call mpi_file_write(file_handle, ix_buffer(2:), &
278 2*ndim, mpi_integer, istatus, ierrmpi)
279 call mpi_file_write(file_handle, w_buffer, &
280 n_values, mpi_double_precision, istatus, ierrmpi)
281
282 ! Set offset of next block
283 block_offset(iwrite+1) = block_offset(iwrite) + &
284 int(n_values, mpi_offset_kind) * size_double + &
285 2 * ndim * size_int
286 end do
287 end do
288
289 ! Write block offsets (now we know them)
290 call mpi_file_seek(file_handle, offset_offsets, mpi_seek_set, ierrmpi)
291 call mpi_file_write(file_handle, block_offset(1:nleafs), nleafs, &
292 mpi_offset, istatus, ierrmpi)
293
294 ! Write header again, now with correct offsets
295 call mpi_file_seek(file_handle, 0_mpi_offset_kind, mpi_seek_set, ierrmpi)
296 call snapshot_write_header1(file_handle, offset_tree_info, &
297 offset_block_data, dataset_names, nwc)
298
299 call mpi_file_close(file_handle, ierrmpi)
300 end if
301
302 call mpi_barrier(icomm, ierrmpi)
303
304 end subroutine convert_dat_generic
305
306end module mod_convert
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
subroutine convert_dat_generic(nwc, dataset_names, file_suffix, convert_vars)
subroutine add_convert_method2(phys_convert_vars, nwc, aux_variable_names, file_suffix)
Definition mod_convert.t:38
type(convert_vars_method), pointer head_convert_vars_methods
Definition mod_convert.t:28
subroutine init_convert()
Definition mod_convert.t:32
subroutine add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
Definition mod_convert.t:59
subroutine convert_all()
Definition mod_convert.t:91
Module with basic grid data structures.
Definition mod_forest.t:2
integer, dimension(:), allocatable, save sfc_to_igrid
Go from a Morton number to an igrid index (for a single processor)
Definition mod_forest.t:53
integer, dimension(:), allocatable, save morton_start
First Morton number per processor.
Definition mod_forest.t:62
integer, save nleafs
Number of leaf block.
Definition mod_forest.t:76
integer, dimension(:), allocatable, save morton_stop
Last Morton number per processor.
Definition mod_forest.t:65
integer, dimension(:,:), allocatable, save sfc
Array to go from a Morton number to an igrid and processor index. Sfc(1:3, MN) contains [igrid,...
Definition mod_forest.t:43
integer, save nparents
Number of parent blocks.
Definition mod_forest.t:73
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
Definition mod_forest.t:32
subroutine, public write_forest(file_handle)
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer, parameter ndim
Number of spatial dimensions for grid variables.
subroutine, public create_output_file(fh, ix, extension, suffix)
Standard method for creating a new output file.
subroutine, public block_shape_io(igrid, n_ghost, ixol, n_values)
Determine the shape of a block for output (whether to include ghost cells, and on which sides)
subroutine, public snapshot_write_header1(fh, offset_tree, offset_block, dataset_names, nw_vars)
Write header for a snapshot, generalize cons_wnames and nw.
character(len=name_len) function, dimension(1:nwc), public get_names_from_string(aux_variable_names, nwc)
pure integer function, public count_ix(ixol)
Compute number of elements in index range.
integer nw
Total number of variables.
integer, parameter max_nw
Maximum number of variables.
The data structure that contains information about a tree node/grid block.
Definition mod_forest.t:11