MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_slice.t
Go to the documentation of this file.
1!> Writes D-1 slice, can do so in various formats, depending on slice_type
4 use mod_comm_lib, only: mpistop
5 implicit none
6
7 !> Slice coordinates, see @ref slices.md
8 double precision :: slicecoord(1000)
9
10 !> Maximum number of slices
11 integer, parameter :: nslicemax=1000
12
13 !> Number of slices to output
14 integer :: nslices
15
16 !> The slice direction for each slice
17 integer :: slicedir(nslicemax)
18
19 !> tag for MPI message
20 integer, private :: itag
21
22 !> choose data type of slice: vtu, vtuCC, dat, or csv
23 character(len=std_len) :: slice_type
24
25 !> igrid and ipe of the leaf blocks on the slice, with the first (1,1:2) stores the nleafs and nparents
26 integer, allocatable :: sfc_sub(:,:)
27
28contains
29
30 subroutine write_slice
32 ! Writes a D-1 slice
33 ! by Oliver Porth
34 ! 22.Nov 2011
35 integer :: islice
36
37 do islice=1,nslices
38 call put_slice(slicedir(islice),slicecoord(islice))
39 end do
40
42 end subroutine write_slice
43
44 subroutine put_slice(dir,xslice)
47 ! Writes a D-1 slice
48 ! For ONED simulations, output will be appended to one csv-file per slice
49 ! slices are sensitive to the saveprim switch and
50 ! can contain auxiliary io variables (nwauxio)
51 ! Thus csv or vtu(CC)-files with primitive variables are obtained.
52 ! when slice_type='dat', we save a D-1 dat file for potential restarts
53 ! by Oliver Porth
54 ! 22.Nov 2011
55 integer, intent(in) :: dir
56 double precision, intent(in) :: xslice
57 ! .. local ..
58 double precision,dimension(0:nw+nwauxio) :: normconv
59 integer :: Njgrid, jgrid
60 integer, dimension(ndim-1) :: ixsubGlo, ixsubGhi
61 integer, dimension(ndim-1) :: ixsubMlo, ixsubMhi
62 integer :: size_subblock_io, nx^D, slice_fh, nwexpand
63 integer :: type_subblock_io, type_subblockC_io, type_subblock_x_io, type_subblockC_x_io
64 integer, dimension(ndim) :: sizes, subsizes, start
65
66 double precision, dimension(ndim-1) :: xprobminsub, xprobmaxsub
67 integer, dimension(ndim-1) :: block_nx_sub, domain_nx_sub
68 logical, dimension(ndim-1) :: periodBsub
69
70 ! Preamble:
71 nx^d=ixmhi^d-ixmlo^d+1;
72 slice_fh=unitslice
73
74 if (ndim==1) then
75 nwexpand = nwauxio
76 else
77 if(slice_type/='dat')then
78 nwexpand = nwauxio
79 else
80 nwexpand = 0
81 endif
82 end if
83
84 ! Do a last consistency check:
85 select case(dir)
86 {case(^d)
87 if(xslice<xprobmin^d.or.xslice>xprobmax^d) &
88 call mpistop("slice out of bounds")
89 \}
90 end select
91
92 ! Traverse the forest and fill nodes:
93 call select_slice(dir,xslice,.false.,slice_fh,normconv)
94
95 ! Create the MPI-datatype and select indices:
96 {^ifthreed
97 select case(dir)
98 case (1)
99 sizes(1) = ixghi2; sizes(2) = ixghi3;
100 ixsubglo(1) = ixglo2; ixsubglo(2) = ixglo3;
101 ixsubghi(1) = ixghi2; ixsubghi(2) = ixghi3;
102 subsizes(1)=nx2;subsizes(2)=nx3;
103 start(1)=ixmlo2-1;start(2)=ixmlo3-1;
104 size_subblock_io=nx2*nx3*(nw+nwexpand)*size_double
105 xprobminsub(1)=xprobmin2; xprobmaxsub(1)=xprobmax2;
106 xprobminsub(2)=xprobmin3; xprobmaxsub(2)=xprobmax3;
107 domain_nx_sub(1)=domain_nx2; domain_nx_sub(2)=domain_nx3;
108 block_nx_sub(1)=block_nx2; block_nx_sub(2)=block_nx3;
109 periodbsub(1)=periodb(2); periodbsub(2)=periodb(3);
110 case (2)
111 sizes(1) = ixghi1; sizes(2) = ixghi3;
112 ixsubglo(1) = ixglo1; ixsubglo(2) = ixglo3;
113 ixsubghi(1) = ixghi1; ixsubghi(2) = ixghi3;
114 subsizes(1)=nx1;subsizes(2)=nx3;
115 start(1)=ixmlo1-1;start(2)=ixmlo3-1;
116 size_subblock_io=nx1*nx3*(nw+nwexpand)*size_double
117 xprobminsub(1)=xprobmin1; xprobmaxsub(1)=xprobmax1;
118 xprobminsub(2)=xprobmin3; xprobmaxsub(2)=xprobmax3;
119 domain_nx_sub(1)=domain_nx1; domain_nx_sub(2)=domain_nx3;
120 block_nx_sub(1)=block_nx1; block_nx_sub(2)=block_nx3;
121 periodbsub(1)=periodb(1); periodbsub(2)=periodb(3);
122 case (3)
123 ixsubglo(1) = ixglo1; ixsubglo(2) = ixglo2;
124 ixsubghi(1) = ixghi1; ixsubghi(2) = ixghi2;
125 sizes(1) = ixghi1; sizes(2) = ixghi2;
126 subsizes(1)=nx1;subsizes(2)=nx2;
127 start(1)=ixmlo1-1;start(2)=ixmlo2-1;
128 size_subblock_io=nx1*nx2*(nw+nwexpand)*size_double
129 xprobminsub(1)=xprobmin1; xprobmaxsub(1)=xprobmax1;
130 xprobminsub(2)=xprobmin2; xprobmaxsub(2)=xprobmax2;
131 domain_nx_sub(1)=domain_nx1; domain_nx_sub(2)=domain_nx2;
132 block_nx_sub(1)=block_nx1; block_nx_sub(2)=block_nx2;
133 periodbsub(1)=periodb(1); periodbsub(2)=periodb(2);
134 case default
135 call mpistop("slice direction not clear in put_slice")
136 end select
137 }
138 {^iftwod
139 select case(dir)
140 case (1)
141 ixsubglo(1) = ixglo2; ixsubghi(1) = ixghi2;
142 sizes(1) = ixghi2
143 subsizes(1)=nx2
144 start(1)=ixmlo2-1
145 size_subblock_io=nx2*(nw+nwexpand)*size_double
146 xprobminsub(1)=xprobmin2; xprobmaxsub(1)=xprobmax2;
147 domain_nx_sub(1)=domain_nx2;
148 block_nx_sub(1)=block_nx2;
149 periodbsub(1)=periodb(2);
150 case (2)
151 ixsubglo(1) = ixglo1; ixsubghi(1) = ixghi1;
152 sizes(1) = ixghi1
153 subsizes(1)=nx1
154 start(1)=ixmlo1-1
155 size_subblock_io=nx1*(nw+nwexpand)*size_double
156 xprobminsub(1)=xprobmin1; xprobmaxsub(1)=xprobmax1;
157 domain_nx_sub(1)=domain_nx1;
158 block_nx_sub(1)=block_nx1;
159 periodbsub(1)=periodb(1);
160 case default
161 call mpistop("slice direction not clear in put_slice")
162 end select
163 }
164 {^ifoned
165 size_subblock_io=(nw+nwexpand)*size_double
166 }
167
168 {^nooned
169 {^de&ixsubmlo(^de-1) = ixsubglo(^de-1)+nghostcells;}
170 {^de&ixsubmhi(^de-1) = ixsubghi(^de-1)-nghostcells;}
171 }
172
173 sizes(ndim)=nw+nwexpand
174 subsizes(ndim)=nw+nwexpand
175 start(ndim)=0
176
177 ! Types for center variables:
178 call mpi_type_create_subarray(ndim,sizes,subsizes,start, &
179 mpi_order_fortran,mpi_double_precision, &
180 type_subblock_io,ierrmpi)
181 call mpi_type_commit(type_subblock_io,ierrmpi)
182
183 sizes(ndim)=^nd
184 subsizes(ndim)=^nd
185 start(ndim)=0
186 call mpi_type_create_subarray(ndim,sizes,subsizes,start, &
187 mpi_order_fortran,mpi_double_precision, &
188 type_subblock_x_io,ierrmpi)
189 call mpi_type_commit(type_subblock_x_io,ierrmpi)
190
191
192 ! Types for corner variables:
193 subsizes(1:ndim-1) = subsizes(1:ndim-1) + 1
194 start(1:ndim-1) = start(1:ndim-1) - 1
195 sizes(ndim)=nw+nwexpand
196 subsizes(ndim)=nw+nwexpand
197 start(ndim)=0
198
199 call mpi_type_create_subarray(ndim,sizes,subsizes,start, &
200 mpi_order_fortran,mpi_double_precision, &
201 type_subblockc_io,ierrmpi)
202 call mpi_type_commit(type_subblockc_io,ierrmpi)
203
204 sizes(ndim)=^nd
205 subsizes(ndim)=^nd
206 start(ndim)=0
207 call mpi_type_create_subarray(ndim,sizes,subsizes,start, &
208 mpi_order_fortran,mpi_double_precision, &
209 type_subblockc_x_io,ierrmpi)
210 call mpi_type_commit(type_subblockc_x_io,ierrmpi)
211
212
213 ! local number of sub-grids:
215
216 ! Now output using various schemes:
217 if (ndim==1) then
218 call put_slice_zerod
219 else
220 select case(slice_type)
221 case ('csv')
222 call put_slice_csv
223 case ('dat')
224 call put_slice_dat
225 case ('vtu', 'vtuCC')
226 call put_slice_vtu
227 end select
228 end if
229
230 do jgrid=1,njgrid
231 call dealloc_subnode(jgrid)
232 end do
233
234 call mpi_type_free(type_subblock_io,ierrmpi)
235 call mpi_type_free(type_subblock_x_io,ierrmpi)
236 call mpi_type_free(type_subblockc_io,ierrmpi)
237 call mpi_type_free(type_subblockc_x_io,ierrmpi)
238
239 if (allocated(sfc_sub)) deallocate(sfc_sub)
240
241 contains
242
243 subroutine put_slice_vtu
244
246 integer :: status(MPI_STATUS_SIZE), ipe
247 logical :: fileopen
248 character(len=1024) :: filename
249 character(len=name_len) :: wnamei(1:nw+nwauxio),xandwnamei(1:ndim+nw+nwauxio)
250 character(len=1024) :: outfilehead
251
252 if (mype==0) then
253
254 inquire(slice_fh,opened=fileopen)
255 if(.not.fileopen)then
256 ! generate filename:
257 write(filename,"(a,i1.1,a,i4.4,a)") trim(base_filename)//'_d',dir,'_x'//slice_label(xslice)//'_n',slicenext,'.vtu'
258 open(slice_fh,file=filename,status='unknown',form='formatted')
259 end if
260 ! get and write the header:
261 call getheadernames(wnamei,xandwnamei,outfilehead)
262 ! generate xml header
263 write(slice_fh,'(a)')'<?xml version="1.0"?>'
264 write(slice_fh,'(a)',advance='no') '<VTKFile type="UnstructuredGrid"'
265 if(type_endian==1)then
266 write(slice_fh,'(a)')' version="0.1" byte_order="LittleEndian">'
267 else
268 write(slice_fh,'(a)')' version="0.1" byte_order="BigEndian">'
269 endif
270 write(slice_fh,'(a)')' <UnstructuredGrid>'
271 write(slice_fh,'(a)')'<FieldData>'
272 write(slice_fh,'(2a)')'<DataArray type="Float32" Name="TIME" ',&
273 'NumberOfTuples="1" format="ascii">'
274 write(slice_fh,*) real(global_time*time_convert_factor)
275 write(slice_fh,'(a)')'</DataArray>'
276 write(slice_fh,'(a)')'</FieldData>'
277
278 ! write to file:
279 do jgrid=1, njgrid
280 call write_slice_vtk(jgrid,slice_fh,wnamei)
281 end do
282
283 ! create a recv buffer using allocate, will be deallocated at the end of the routine:
284 call alloc_subnode(njgrid+1,dir,nwauxio)
285
286 end if
287
288 ! Also communicate the normconv array since processor zero might not have it yet:
289 if (npe>1) then
290 do ipe=1,npe-1
291 do jgrid=1,morton_sub_stop(ipe)-morton_sub_start(ipe)+1
292 itag=morton_sub_start(ipe)+jgrid-1
293 itag=itag*5
294 if (ipe == mype ) then
295 call mpi_send(ps_sub(jgrid)%x,1,type_subblock_x_io,0,itag,icomm,ierrmpi)
296 call mpi_send(ps_sub(jgrid)%w,1,type_subblock_io,0,itag+1,icomm,ierrmpi)
297 call mpi_send(ps_sub(jgrid)%xC,1,type_subblockc_x_io,0,itag+2,icomm,ierrmpi)
298 call mpi_send(ps_sub(jgrid)%wC,1,type_subblockc_io,0,itag+3,icomm,ierrmpi)
299 call mpi_send(normconv,nw+nwauxio+1,mpi_double_precision,0,itag+4,icomm,ierrmpi)
300 end if
301 if (mype == 0) then
302 call mpi_recv(ps_sub(njgrid+1)%x,1,type_subblock_x_io,ipe,itag,icomm,status,ierrmpi)
303 call mpi_recv(ps_sub(njgrid+1)%w,1,type_subblock_io,ipe,itag+1,icomm,status,ierrmpi)
304 call mpi_recv(ps_sub(njgrid+1)%xC,1,type_subblockc_x_io,ipe,itag+2,icomm,status,ierrmpi)
305 call mpi_recv(ps_sub(njgrid+1)%wC,1,type_subblockc_io,ipe,itag+3,icomm,status,ierrmpi)
306 call mpi_recv(normconv,nw+nwauxio+1,mpi_double_precision,ipe,&
307 itag+4,icomm,status,ierrmpi)
308 call write_slice_vtk(njgrid+1,slice_fh,wnamei)
309 end if
310 end do
311 end do
312 endif
313
314 if (mype==0) then
315
316 write(slice_fh,'(a)')'</UnstructuredGrid>'
317 write(slice_fh,'(a)')'</VTKFile>'
318 close(slice_fh)
319 call dealloc_subnode(njgrid+1)
320
321 end if
322
323 end subroutine put_slice_vtu
324
325 subroutine write_slice_vtk(jgrid,slice_fh,wnamei)
326
327 ! this only works for 2D and 3D, 1D reduction (line to point) not allowed
328 integer, intent(in) :: jgrid, slice_fh
329 character(len=name_len), intent(in) :: wnamei(1:nw+nwauxio)
330 ! This remainder part only for more than 1D, but nesting with NOONED gives problems
331 {#IFNDEF D1
332 ! .. local ..
333 double precision :: x_VTK(1:3)
334 double precision, parameter :: minvalue = 1.0d-99, maxvalue = 1.0d+99
335 integer :: ixC^L, ixCC^L, nc, np, iw
336 integer :: nx^DM, nxC^DM, icell, ix^DM
337 integer :: VTK_type
338
339 {^dm&ixccmin^dm = ixsubmlo(^dm);}
340 {^dm&ixccmax^dm = ixsubmhi(^dm);}
341 {^dm&ixcmin^dm = ixsubmlo(^dm)-1;}
342 {^dm&ixcmax^dm = ixsubmhi(^dm);}
343
344 nx^dm=ixccmax^dm-ixccmin^dm+1;
345 nxc^dm=nx^dm+1;
346 nc={nx^dm*} ! Number of cells per subgrid
347 np={nxc^dm*} ! Number of corner points per subgrid
348
349 ! we write out every grid as one VTK PIECE
350 write(slice_fh,'(a,i7,a,i7,a)') &
351 '<Piece NumberOfPoints="',np,'" NumberOfCells="',nc,'">'
352
353 !==============================
354 ! celldata or pointdata?
355 !==============================
356 select case(slice_type)
357
358 case('vtuCC') ! celldata
359 write(slice_fh,'(a)')'<CellData>'
360 do iw=1,nw+nwauxio
361 if(iw<=nw) then
362 if(.not.w_write(iw)) cycle
363 endif
364 write(slice_fh,'(a,a,a)')&
365 '<DataArray type="Float64" Name="',trim(wnamei(iw)),'" format="ascii">'
366 write(slice_fh,'(200(1pe14.6))') {^dm&(|}roundoff_minmax(ps_sub(jgrid)%w(ix^dm,iw)*normconv(iw),minvalue,maxvalue),{ix^dm=ixccmin^dm,ixccmax^dm)}
367 write(slice_fh,'(a)')'</DataArray>'
368 enddo
369 write(slice_fh,'(a)')'</CellData>'
370
371
372 case('vtu') ! pointdata
373 write(slice_fh,'(a)')'<PointData>'
374 do iw=1,nw+nwauxio
375 if(iw<=nw) then
376 if(.not.w_write(iw)) cycle
377 endif
378 write(slice_fh,'(a,a,a)')&
379 '<DataArray type="Float64" Name="',trim(wnamei(iw)),'" format="ascii">'
380 write(slice_fh,'(200(1pe14.6))') {^dm&(|}roundoff_minmax(ps_sub(jgrid)%wC(ix^dm,iw)*normconv(iw),minvalue,maxvalue),{ix^dm=ixcmin^dm,ixcmax^dm)}
381 write(slice_fh,'(a)')'</DataArray>'
382 enddo
383 write(slice_fh,'(a)')'</PointData>'
384
385
386 end select
387 !==============================
388 ! Done: celldata or pointdata?
389 !==============================
390
391 !==============================
392 ! output Cornerpoints
393 !==============================
394 write(slice_fh,'(a)')'<Points>'
395 write(slice_fh,'(a)')'<DataArray type="Float32" NumberOfComponents="3" format="ascii">'
396 ! write cell corner coordinates in a backward dimensional loop, always 3D output
397 {do ix^dmb=ixcmin^dmb,ixcmax^dmb \}
398 x_vtk(1:3)=zero;
399 x_vtk(1:ndim)=ps_sub(jgrid)%xC(ix^dm,1:ndim)*normconv(0);
400 write(slice_fh,'(3(1pe14.6))') x_vtk
401 {^dm&end do \}
402 write(slice_fh,'(a)')'</DataArray>'
403 write(slice_fh,'(a)')'</Points>'
404 !==============================
405 ! Done: output Cornerpoints
406 !==============================
407
408 !==============================
409 ! cell Metainformation
410 !==============================
411 write(slice_fh,'(a)')'<Cells>'
412
413 ! connectivity part
414 write(slice_fh,'(a)')'<DataArray type="Int32" Name="connectivity" format="ascii">'
415
416 {^dm& do ix^dmb=1,nx^dmb\}
417 {^iftwod
418 write(slice_fh,'(2(i7,1x))')ix1-1,ix1
419 }{^ifthreed
420 write(slice_fh,'(4(i7,1x))')(ix2-1)*nxc1+ix1-1, &
421 (ix2-1)*nxc1+ix1,ix2*nxc1+ix1-1,ix2*nxc1+ix1
422 }{^dm& end do\}
423
424 write(slice_fh,'(a)')'</DataArray>'
425
426 ! offsets data array
427 write(slice_fh,'(a)')'<DataArray type="Int32" Name="offsets" format="ascii">'
428 do icell=1,nc
429 write(slice_fh,'(i7)') icell*(2**(^nd-1))
430 end do
431 write(slice_fh,'(a)')'</DataArray>'
432
433 ! VTK cell type data array
434 write(slice_fh,'(a)')'<DataArray type="Int32" Name="types" format="ascii">'
435 ! VTK_LINE=3; VTK_PIXEL=8; VTK_VOXEL=11 -> vtk-syntax
436 {^iftwod vtk_type=3 \}
437 {^ifthreed vtk_type=8 \}
438 do icell=1,nc
439 write(slice_fh,'(i2)') vtk_type
440 enddo
441 write(slice_fh,'(a)')'</DataArray>'
442
443 write(slice_fh,'(a)')'</Cells>'
444 !==============================
445 ! Done: cell Metainformation
446 !==============================
447 write(slice_fh,'(a)')'</Piece>'
448
449 }
450 end subroutine write_slice_vtk
451
452 subroutine put_slice_csv
453
455 integer :: iw, ipe, itag
456 integer :: status(MPI_STATUS_SIZE)
457 logical :: fileopen
458 character(len=1024) :: filename
459 character(len=name_len) :: wnamei(1:nw+nwauxio),xandwnamei(1:ndim+nw+nwauxio)
460 character(len=1024) :: outfilehead
461 character(len=1024) :: line
462
463 if (mype==0) then
464 inquire(slice_fh,opened=fileopen)
465 if(.not.fileopen)then
466 ! generate filename:
467 write(filename,"(a,i1.1,a,i4.4,a)") trim(base_filename)//'_d',dir,'_x'//slice_label(xslice)//'_n',slicenext,'.csv'
468 open(slice_fh,file=filename,status='unknown',form='formatted')
469 end if
470 ! get and write the header:
471 call getheadernames(wnamei,xandwnamei,outfilehead)
472 line=''
473 do iw=1,ndim+nw+nwauxio-1
474 line = trim(line)//trim(xandwnamei(iw))//', '
475 end do
476 line = trim(line)//trim(xandwnamei(ndim+nw+nwauxio))
477 write(slice_fh,'(a)')trim(line)
478 ! create a recv buffer using allocate, will be deallocated at the end of the routine:
479 call alloc_subnode(njgrid+1,dir,nwauxio)
480
481 ! write to file:
482 do jgrid=1, njgrid
483 call put_slice_line(jgrid,slice_fh)
484 end do
485 end if
486
487 ! Also communicate the normconv array since processor zero might not have it yet:
488 if (npe>1) then
489 do ipe=1,npe-1
490 do jgrid=1,morton_sub_stop(ipe)-morton_sub_start(ipe)+1
491 itag=morton_sub_start(ipe)+jgrid-1
492 if (ipe == mype ) then
493 call mpi_send(ps_sub(jgrid)%x,1,type_subblock_x_io,0,itag,icomm,ierrmpi)
494 call mpi_send(ps_sub(jgrid)%w,1,type_subblock_io,0,itag,icomm,ierrmpi)
495 call mpi_send(normconv,nw+nwauxio+1,mpi_double_precision,0,itag,icomm,ierrmpi)
496 end if
497 if (mype == 0) then
498 call mpi_recv(ps_sub(njgrid+1)%x,1,type_subblock_x_io,ipe,itag,icomm,status,ierrmpi)
499 call mpi_recv(ps_sub(njgrid+1)%w,1,type_subblock_io,ipe,itag,icomm,status,ierrmpi)
500 call mpi_recv(normconv,nw+nwauxio+1,mpi_double_precision,ipe,&
501 itag,icomm,status,ierrmpi)
502 call put_slice_line(njgrid+1,slice_fh)
503 end if
504 end do
505 end do
506 endif
507
508 if (mype==0) then
509 close(slice_fh)
510 call dealloc_subnode(njgrid+1)
511 end if
512
513 end subroutine put_slice_csv
514
515 subroutine put_slice_line(jout,file_handle)
516 integer, intent(in) :: jout, file_handle
517 ! .. local ..
518 double precision, parameter :: minvalue = 1.0d-99, maxvalue = 1.0d+99
519 integer :: ix^D,idir,iw
520 character(len=1024) ::line, data
521
522 {^ifthreed
523 do ix2=ixsubmlo(2),ixsubmhi(2)
524 do ix1=ixsubmlo(1),ixsubmhi(1)
525 \}
526 {^iftwod
527 do ix1=ixsubmlo(1),ixsubmhi(1)
528 }
529 ! Format the line:
530 line = ''
531 do idir=1,ndim
532 {^ifthreed
533 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%x(ix1,ix2,idir),minvalue,maxvalue)
534 }
535 {^iftwod
536 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%x(ix1,idir),minvalue,maxvalue)
537 }
538 {^ifoned
539 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%x(idir),minvalue,maxvalue)
540 }
541
542 line = trim(line)//trim(data)//', '
543 end do
544 do iw = 1,nw+nwauxio-1
545 {^ifthreed
546 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,ix2,iw)*normconv(iw),minvalue,maxvalue)
547 }
548 {^iftwod
549 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,iw)*normconv(iw),minvalue,maxvalue)
550 }
551 {^ifoned
552 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(iw)*normconv(iw),minvalue,maxvalue)
553 }
554 line = trim(line)//trim(data)//', '
555 end do
556 {^ifthreed
557 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,ix2,nw+nwauxio)*normconv(nw+nwauxio),minvalue,maxvalue)
558 }
559 {^iftwod
560 write(data,"(es14.6)")roundoff_minmax(ps_sub(jout)%w(ix1,nw+nwauxio)*normconv(nw+nwauxio),minvalue,maxvalue)
561 }
562 line = trim(line)//trim(data)
563 write(file_handle,'(a)')trim(line)
564 {^iftwod
565 end do
566 }
567 {^ifthreed
568 end do
569 end do
570 \}
571
572 end subroutine put_slice_line
573
574 subroutine put_slice_dat
575
579
580 integer, dimension(max_blocks*2) :: iorequest
581 integer, dimension(MPI_STATUS_SIZE,max_blocks) :: iostatus
582 integer(kind=MPI_OFFSET_KIND) :: offset, offset1
583 integer :: nsubleafs
584 integer :: amode, status(MPI_STATUS_SIZE), iwrite
585 character(len=1024) :: filename
586 character(len=name_len) :: dname
587
588 integer :: nsubparents, iw, ileaf, inode
589 integer(kind=MPI_OFFSET_KIND) :: block_offset, tree_offset
590 integer, allocatable :: block_ig_sub(:,:)
591 integer, allocatable :: block_lvl_sub(:)
592 integer(kind=MPI_OFFSET_KIND), allocatable :: block_offset_sub(:)
593 logical, allocatable :: isleaf_sub(:)
594 type(tree_node), pointer :: pnode
595
596 nsubleafs=morton_sub_stop(npe-1)
597
598 ! only on processor 0, prepare all the data for writing header
599 if (mype==0) then
600
601 if (nsubleafs /= sfc_sub(0,1)) error stop "nsubleafs /= sfc_sub(0,1)"
602 nsubparents = sfc_sub(0,2)
603 allocate(block_ig_sub(ndim-1,nsubleafs))
604 allocate(block_lvl_sub(nsubleafs))
605 allocate(block_offset_sub(nsubleafs))
606 allocate(isleaf_sub(nsubleafs+nsubparents))
607
608 block_offset = int(0,kind=mpi_offset_kind)
609 ileaf = 0
610 ! get block_ig_sub, block_lvl_sub, block_offset_sub
611 do inode=1,nsubleafs+nsubparents
612 if (sfc_sub(inode,1) == 0) then
613 isleaf_sub(inode) = .false.
614 else
615 isleaf_sub(inode) = .true.
616 pnode => igrid_to_node(sfc_sub(inode,1),sfc_sub(inode,2))%node
617 ileaf = ileaf + 1
618 {^ifthreed
619 select case (dir)
620 case (1)
621 block_ig_sub(:,ileaf) = [ pnode%ig2, pnode%ig3 ]
622 case (2)
623 block_ig_sub(:,ileaf) = [ pnode%ig1, pnode%ig3 ]
624 case (3)
625 block_ig_sub(:,ileaf) = [ pnode%ig1, pnode%ig2 ]
626 end select
627 }
628 {^iftwod
629 select case (dir)
630 case (1)
631 block_ig_sub(:,ileaf) = [ pnode%ig2 ]
632 case (2)
633 block_ig_sub(:,ileaf) = [ pnode%ig1 ]
634 end select
635 }
636 block_lvl_sub(ileaf) = pnode%level
637 ! will not save ghost cells, start from offset_block_data
638 block_offset_sub(ileaf) = block_offset
639 block_offset = block_offset + int(2*(ndim-1)*size_int,kind=mpi_offset_kind)
640 block_offset = block_offset + int(product(block_nx_sub)*nw*size_double,kind=mpi_offset_kind)
641 end if
642 end do
643 end if
644
645 ! generate filename
646 write(filename,"(a,i1.1,a,i4.4,a)") trim(base_filename)//'_d',dir,'_x'//slice_label(xslice)//'_n',slicenext,'.dat'
647
648 if(mype==0) then
649 open(unit=slice_fh,file=filename,status='replace')
650 close(unit=slice_fh)
651 end if
652
653 ! header writing
654 if (mype==0) then
655 ! call select_slice(dir,xslice,.true.,slice_fh,normconv)
656 amode=ior(mpi_mode_append,mpi_mode_wronly)
657 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null, &
658 slice_fh,ierrmpi)
659
660 call mpi_file_write(slice_fh, version_number, 1, mpi_integer, status, ierrmpi)
661 ! two offsets for tree and block data
662 call mpi_file_write(slice_fh, 0, 1, mpi_integer, status, ierrmpi)
663 call mpi_file_write(slice_fh, 0, 1, mpi_integer, status, ierrmpi)
664 call mpi_file_write(slice_fh, nw, 1, mpi_integer, status, ierrmpi)
665 call mpi_file_write(slice_fh, ndir, 1, mpi_integer, status, ierrmpi)
666 call mpi_file_write(slice_fh, ndim-1, 1, mpi_integer, status, ierrmpi)
667 call mpi_file_write(slice_fh, levmax_sub, 1, mpi_integer, status, ierrmpi)
668 call mpi_file_write(slice_fh, nsubleafs, 1, mpi_integer, status, ierrmpi)
669 call mpi_file_write(slice_fh, nsubparents, 1, mpi_integer, status, ierrmpi)
670 call mpi_file_write(slice_fh, it, 1, mpi_integer, status, ierrmpi)
671 ! Note: It is nice when this double has an even number of 4 byte
672 ! integers before it (for alignment)
673 call mpi_file_write(slice_fh, global_time, 1, mpi_double_precision, status, ierrmpi)
674
675 call mpi_file_write(slice_fh, xprobminsub, ndim-1, &
676 mpi_double_precision, status, ierrmpi)
677 call mpi_file_write(slice_fh, xprobmaxsub, ndim-1, &
678 mpi_double_precision, status, ierrmpi)
679 call mpi_file_write(slice_fh, domain_nx_sub, ndim-1, &
680 mpi_integer, status, ierrmpi)
681 call mpi_file_write(slice_fh, block_nx_sub, ndim-1, &
682 mpi_integer, status, ierrmpi)
683
684 ! Periodicity (assume all variables are periodic if one is)
685 call mpi_file_write(slice_fh, periodbsub, ndim-1, mpi_logical, status, ierrmpi)
686
687 ! Geometry
688 call mpi_file_write(slice_fh, geometry_name(1:name_len), &
689 name_len, mpi_character, status, ierrmpi)
690
691 ! Write stagger grid mark
692 call mpi_file_write(slice_fh, stagger_grid, 1, mpi_logical, status, ierrmpi)
693
694 do iw = 1, nw
695 ! using directly trim(adjustl((cons_wnames(iw)))) in MPI_FILE_WRITE call
696 ! does not work, there will be trailing characters
697 dname = trim(adjustl((cons_wnames(iw))))
698 call mpi_file_write(slice_fh, dname, name_len, mpi_character, status, ierrmpi)
699 end do
700
701 ! Physics related information
702 call mpi_file_write(slice_fh, physics_type, name_len, mpi_character, status, ierrmpi)
703
704 ! Format:
705 ! integer :: n_par
706 ! double precision :: values(n_par)
707 ! character(n_par * name_len) :: names
708 call phys_write_info(slice_fh)
709
710 ! Write snapshotnext etc., which is useful for restarting.
711 ! Note we add one, since snapshotnext is updated *after* this procedure
712 if(pass_wall_time.or.save_now) then
713 call mpi_file_write(slice_fh, snapshotnext, 1, mpi_integer, status, ierrmpi)
714 else
715 call mpi_file_write(slice_fh, snapshotnext+1, 1, mpi_integer, status, ierrmpi)
716 end if
717 call mpi_file_write(slice_fh, slicenext, 1, mpi_integer, status, ierrmpi)
718 call mpi_file_write(slice_fh, collapsenext, 1, mpi_integer, status, ierrmpi)
719
720 call mpi_file_get_position(slice_fh, tree_offset, ierrmpi)
721 call mpi_file_write(slice_fh, isleaf_sub, nsubleafs+nsubparents, mpi_logical, status, ierrmpi)
722 call mpi_file_write(slice_fh, block_lvl_sub, nsubleafs, mpi_integer, status, ierrmpi)
723 call mpi_file_write(slice_fh, block_ig_sub, size(block_ig_sub), mpi_integer, status, ierrmpi)
724
725 ! add the block_offset(above) to block_offset_sub
726 call mpi_file_get_position(slice_fh, block_offset, ierrmpi)
727 block_offset_sub(:) = block_offset_sub(:) + block_offset + &
728 int(nsubleafs*2*size_int, kind=mpi_offset_kind)
729
730 call mpi_file_write(slice_fh, block_offset_sub, nsubleafs, mpi_offset, status, ierrmpi)
731
732 ! get the right block_offset
733 call mpi_file_get_position(slice_fh, block_offset, ierrmpi)
734 if (block_offset - tree_offset /= &
735 (nsubleafs + nsubparents) * size_logical + &
736 nsubleafs * ((ndim-1+1) * size_int + 2 * size_int)) then
737 print *, "Warning: MPI_OFFSET type /= 8 bytes"
738 print *, "This *could* cause problems when reading .dat files"
739 end if
740
741 ! come back to write offsets
742 call mpi_file_seek(slice_fh, int(size_int,kind=mpi_offset_kind), mpi_seek_set, ierrmpi)
743 call mpi_file_write(slice_fh, int(tree_offset), 1, mpi_integer, status, ierrmpi)
744 call mpi_file_write(slice_fh, int(block_offset), 1, mpi_integer, status, ierrmpi)
745
746 call mpi_file_close(slice_fh,ierrmpi)
747 end if
748
749 ! Broadcast nsubleafs and nsubparents to all processors
750 call mpi_bcast(nsubleafs, 1, mpi_integer, 0, icomm, ierrmpi)
751 call mpi_bcast(nsubparents, 1, mpi_integer, 0, icomm, ierrmpi)
752
753 ! Allocate block_offset_sub on all processors (if not already allocated on processor 0)
754 if (mype /= 0) then
755 allocate(block_offset_sub(nsubleafs))
756 end if
757
758 ! Broadcast block_offset_sub from processor 0 to all processors
759 call mpi_bcast(block_offset_sub, nsubleafs, mpi_offset, 0, icomm, ierrmpi)
760
761 amode=ior(mpi_mode_create,mpi_mode_wronly)
762 call mpi_file_open(icomm,filename,amode,mpi_info_null,slice_fh,ierrmpi)
763 iorequest=mpi_request_null
764 iwrite=0
765
766 do jgrid=1,njgrid
767 iwrite=iwrite+1
768 offset=block_offset_sub(int(morton_sub_start(mype)+jgrid-1))
769 call mpi_file_iwrite_at(slice_fh,offset,0,2*(ndim-1),mpi_integer,iorequest(iwrite),ierrmpi)
770 iwrite=iwrite+1
771 offset1=offset+int(2*(ndim-1)*size_int,kind=mpi_offset_kind)
772 call mpi_file_iwrite_at(slice_fh,offset1,ps_sub(jgrid)%w,1,type_subblock_io, &
773 iorequest(iwrite),ierrmpi)
774 end do
775
776 if (iwrite>0) call mpi_waitall(iwrite,iorequest,iostatus,ierrmpi)
777 call mpi_barrier(icomm, ierrmpi)
778 call mpi_file_close(slice_fh,ierrmpi)
779
780 deallocate(block_offset_sub)
781 if (mype == 0) then
782 deallocate(block_ig_sub)
783 deallocate(block_lvl_sub)
784 deallocate(isleaf_sub)
785 end if
786
787 end subroutine put_slice_dat
788
789 subroutine put_slice_zerod
790
792 integer:: iw
793 integer :: amode, iwrite, status(MPI_STATUS_SIZE)
794 logical, save :: opened=.false.
795 character(len=name_len) :: wnamei(1:nw+nwauxio),xandwnamei(1:ndim+nw+nwauxio)
796 character(len=1024) :: outfilehead
797 character(len=1024) ::line, data
798 character(len=1024) :: filename
799
800 {^ifoned
801 ! generate filename:
802 write(filename,"(a,i1.1,a,i4.4,a)") trim(base_filename)//'_d',dir,'_x'//slice_label(xslice)//'.csv'
803
804 ! Open for header:
805 if (.not. opened .and. mype==0) then
806 amode=ior(mpi_mode_create,mpi_mode_wronly)
807 amode=ior(amode,mpi_mode_append)
808 call mpi_file_open(mpi_comm_self,filename,amode, &
809 mpi_info_null,slice_fh,ierrmpi)
810 ! Create the header:
811 call getheadernames(wnamei,xandwnamei,outfilehead)
812 line = 'time'
813 do iw=1,nw+nwauxio+ndim
814 line = trim(line)//', '//trim(xandwnamei(iw))
815 enddo
816 ! Write header:
817 call mpi_file_write(slice_fh,line,len_trim(line), &
818 mpi_character,status,ierrmpi)
819 call mpi_file_write(slice_fh,achar(10),1,mpi_character,status,ierrmpi)
820 call mpi_file_close(slice_fh, ierrmpi)
821 opened=.true.
822 endif ! opened
823 ! Now we let the processor, which holds the data, write - therefore barrier.
824 call mpi_barrier(icomm,ierrmpi)
825
826 ! There should be only one processor holding the point:
827 if (njgrid > 0) then
828 amode=ior(mpi_mode_create,mpi_mode_wronly)
829 amode=ior(amode,mpi_mode_append)
830 call mpi_file_open(mpi_comm_self,filename,amode, &
831 mpi_info_null,slice_fh,ierrmpi)
832
833 ! Format the line:
834 write(data,"(es14.6)")global_time
835 line = trim(data)
836 write(data,"(es14.6)")ps_sub(1)%x
837 line = trim(line)//', '//trim(data)
838 do iw = 1,nw+nwauxio
839 write(data,"(es14.6)")ps_sub(1)%w(iw)*normconv(iw)
840 line = trim(line)//', '//trim(data)
841 end do
842 !
843 call mpi_file_write(slice_fh,trim(line),len_trim(line), &
844 mpi_character,status,ierrmpi)
845 call mpi_file_write(slice_fh,achar(10),1,mpi_character,status,ierrmpi)
846 call mpi_file_close(slice_fh, ierrmpi)
847 end if ! Njgrid > 0
848 }
849 end subroutine put_slice_zerod
850
851 end subroutine put_slice
852
853 subroutine select_slice(dir,xslice,writeonly,file_handle,normconv)
856 integer, intent(in) :: dir
857 double precision, intent(in) :: xslice
858 integer, intent(in) :: file_handle
859 logical, intent(in) :: writeonly
860 double precision,dimension(0:nw+nwauxio),intent(out) :: normconv
861 ! .. local ..
862 integer :: ig^D, jgrid, slice_fh, ipe, mylevmax
863 integer, dimension(nlevelshi) :: igslice
864 integer, allocatable :: iglevel1_sub_sfc(:)
865 integer :: ig^L, ngsub1, jglevel1, igsorted, kgrid, ngmax
866
867 kgrid = 0
868 jgrid = 0
869 mylevmax = 0
870 jglevel1 = 0
871
872 ! Find the global slice index for every level:
873 call get_igslice(dir,xslice,igslice)
874 igmin^d=1;igmax^d=ng^d(1);
875
876 ! Traverse forest to find grids indicating slice:
877 select case(dir)
878 {case(^d)
879 igmin^d=igslice(1);
880 igmax^d=igslice(1);
881 \}
882 case default
883 call mpistop("slice direction not clear in select_slice")
884 end select
885
886 ! total number of level 1 blocks in the slice
887 ngsub1={(igmax^d-igmin^d+1)|*}
888 allocate(iglevel1_sub_sfc(ngsub1))
889 if (.not. allocated(sfc_sub)) then
890 {^ifthreed
891 ngmax = ngsub1*(4**refine_max_level-1)
892 \}
893 {^iftwod
894 ngmax = ngsub1*(2**refine_max_level-1)
895 \}
896 {^ifoned
897 ngmax = ngsub1
898 \}
899 allocate(sfc_sub(0:ngmax,1:3)) ! the first three are nleafs, nparents and isleaf (0 or 1)
900 sfc_sub = 0
901 end if
902
903 ! get the sfc index of the level 1 blocks in the slice
904 {do ig^db=igmin^db,igmax^db\}
905 jglevel1=jglevel1+1
906 iglevel1_sub_sfc(jglevel1)=iglevel1_sfc(ig^d)
907 {end do \}
908
909 ! Sort the array from small to big using quicksort
910 call quicksort_integer(iglevel1_sub_sfc, 1, ngsub1)
911
912 ! traverse level 1 blocks depending on the sub morton order
913 do igsorted=1,ngsub1
914 {ig^d=sfc_iglevel1(^d,iglevel1_sub_sfc(igsorted))\}
915 call traverse_slice(tree_root(ig^d))
916 end do
917 deallocate(iglevel1_sub_sfc)
918
919 if (.not.writeonly) then
920 ! Synchronize the levmax_sub for output (only rank 0 needs it):
921 levmax_sub = mylevmax
922 call mpi_allreduce(mpi_in_place,levmax_sub,1,mpi_integer,mpi_max,icomm,ierrmpi)
923
924 ! Communicate the subgrid indices according to new Morton sub-sfc:
925 morton_sub_start(:) = 1
926 do ipe=0,npe-1
927 call mpi_gather(jgrid,1,mpi_integer,morton_sub_stop,1,mpi_integer,ipe,icomm,ierrmpi)
928 end do
929
930 do ipe = 0, npe-2
933 end do
934 end if
935
936 contains
937
938 recursive subroutine traverse_slice(tree)
939 implicit none
940 type(tree_node_ptr) :: tree
941 integer :: ic^d
942 integer, dimension(MPI_STATUS_SIZE) :: status
943
944 ! if (writeonly) then
945 ! call MPI_FILE_WRITE(file_handle,tree%node%leaf,1,MPI_LOGICAL, &
946 ! status,ierrmpi)
947 ! end if
948 if (mype==0) then
949 kgrid = kgrid + 1
950 sfc_sub(kgrid,1) = tree%node%igrid
951 sfc_sub(kgrid,2) = tree%node%ipe
952 if (tree%node%leaf) then
953 sfc_sub(0,1) = sfc_sub(0,1) + 1
954 sfc_sub(kgrid,3) = 1
955 else
956 sfc_sub(0,2) = sfc_sub(0,2) + 1
957 sfc_sub(kgrid,3) = 0
958 end if
959 end if
960
961 if (tree%node%leaf) then
962 if (tree%node%ipe == mype.and..not.writeonly) then
963 mylevmax = max(mylevmax,tree%node%level)
964 call fill_subnode(tree%node%igrid,tree%node%active,jgrid,dir,xslice,normconv)
965 end if
966 return
967 end if
968 ! We are out for leaves now, continue for branches
969
970 ! Get the correct child:
971 select case (dir)
972 {case (^d)
973 ic^d = igslice(tree%node%level+1) - 2 * tree%node%ig^d + 2
974 \}
975 case default
976 call mpistop("slice direction not clear in traverse_slice")
977 end select
978
979 ! Recursively descend into the correct child branch:
980 {^ifthreed
981 select case(dir)
982 case (1)
983 do ic3=1,2
984 do ic2=1,2
985 call traverse_slice(tree%node%child(ic^d))
986 end do
987 end do
988 case (2)
989 do ic3=1,2
990 do ic1=1,2
991 call traverse_slice(tree%node%child(ic^d))
992 end do
993 end do
994 case (3)
995 do ic2=1,2
996 do ic1=1,2
997 call traverse_slice(tree%node%child(ic^d))
998 end do
999 end do
1000 case default
1001 call mpistop("slice direction not clear in traverse_slice")
1002 end select
1003 }
1004 {^iftwod
1005 select case(dir)
1006 case (1)
1007 do ic2=1,2
1008 call traverse_slice(tree%node%child(ic^d))
1009 end do
1010 case (2)
1011 do ic1=1,2
1012 call traverse_slice(tree%node%child(ic^d))
1013 end do
1014 case default
1015 call mpistop("slice direction not clear in traverse_slice")
1016 end select
1017 }
1018 {^ifoned
1019 call traverse_slice(tree%node%child(ic^d))
1020 }
1021
1022 end subroutine traverse_slice
1023
1024 end subroutine select_slice
1025
1026 subroutine fill_subnode(igrid,active,jgrid,dir,xslice,normconv)
1029 integer, intent(in) :: igrid, dir
1030 integer, intent(inout) :: jgrid
1031 logical, intent(in) :: active
1032 double precision, intent(in) :: xslice
1033 double precision,dimension(0:nw+nwauxio),intent(out) :: normconv
1034 ! .. local ..
1035 double precision, dimension(ixMlo^D-1:ixMhi^D,ndim) :: xC_TMP, xC
1036 double precision, dimension(ixMlo^D:ixMhi^D,ndim) :: xCC_TMP, xCC
1037 double precision, dimension(ixMlo^D-1:ixMhi^D,nw+nwauxio) :: wC_TMP
1038 double precision, dimension(ixMlo^D:ixMhi^D,nw+nwauxio) :: wCC_TMP
1039 double precision, dimension(ixG^T) :: x_save
1040 integer :: ixslice, nwexpand, ixC^L, ixCC^L
1041 logical :: mask(ixG^T)
1042
1043 mask=.false.
1044 ! increase grid-count:
1045 jgrid=jgrid+1
1046 ! Allocate subdim solution array:
1047 if (ndim==1) then
1048 nwexpand = nwauxio
1049 else
1050 if(slice_type/='dat')then
1051 nwexpand = nwauxio
1052 else
1053 nwexpand = 0
1054 endif
1055 end if
1056 call alloc_subnode(jgrid,dir,nwexpand)
1057 call fill_subnode_info(igrid,jgrid,dir)
1058
1059 mask(ixm^t)=.true.
1060
1061 ! Now hunt for the index closest to the slice:
1062 {^ifoned
1063 ixslice = minloc(dabs(xslice-ps(igrid)%x(:,dir)),1,mask(:))
1064 }
1065 {^iftwod
1066 select case (dir)
1067 case (1)
1068 ixslice = minloc(dabs(xslice-ps(igrid)%x(:,ixmlo2,dir)),1,mask(:,ixmlo2))
1069 case (2)
1070 ixslice = minloc(dabs(xslice-ps(igrid)%x(ixmlo1,:,dir)),1,mask(ixmlo1,:))
1071 case default
1072 call mpistop("slice direction not clear in fill_subnode")
1073 end select
1074 }
1075 {^ifthreed
1076 select case (dir)
1077 case (1)
1078 ixslice = minloc(dabs(xslice-ps(igrid)%x(:,ixmlo2,ixmlo3,dir)),1,mask(:,ixmlo2,ixmlo3))
1079 case (2)
1080 ixslice = minloc(dabs(xslice-ps(igrid)%x(ixmlo1,:,ixmlo3,dir)),1,mask(ixmlo1,:,ixmlo3))
1081 case (3)
1082 ixslice = minloc(dabs(xslice-ps(igrid)%x(ixmlo1,ixmlo2,:,dir)),1,mask(ixmlo1,ixmlo2,:))
1083 case default
1084 call mpistop("slice direction not clear in fill_subnode")
1085 end select
1086 }
1087
1088 call calc_x(igrid,xc,xcc)
1089 ! Set the coordinate to be exactly on the slice:
1090 xc(:^d&,dir) = xslice
1091 xcc(:^d&,dir) = xslice
1092 call calc_grid(unitslice,igrid,xc,xcc,xc_tmp,xcc_tmp,wc_tmp,wcc_tmp,normconv,&
1093 ixc^l,ixcc^l,.true.)
1094 ! CC stands for CellCenter
1095 ! C stands for Corner
1096
1097 ! Fill the subdimensional solution and position array:
1098 {^ifoned
1099 ps_sub(jgrid)%w(1:nw+nwexpand) = wcc_tmp(ixslice,1:nw+nwexpand)
1100 ps_sub(jgrid)%x(1:ndim) = xcc_tmp(ixslice,1:ndim)
1101 ps_sub(jgrid)%wC(1:nw+nwexpand) = wc_tmp(ixslice,1:nw+nwexpand)
1102 ps_sub(jgrid)%xC(1:ndim) = xc_tmp(ixslice,1:ndim)
1103 }
1104 {^iftwod
1105 select case (dir)
1106 case (1)
1107 ps_sub(jgrid)%w(ixccmin2:ixccmax2,1:nw+nwexpand) &
1108 = wcc_tmp(ixslice,ixccmin2:ixccmax2,1:nw+nwexpand)
1109 ps_sub(jgrid)%x(ixccmin2:ixccmax2,1:ndim) &
1110 = xcc_tmp(ixslice,ixccmin2:ixccmax2,1:ndim)
1111 ps_sub(jgrid)%wC(ixcmin2:ixcmax2,1:nw+nwexpand) &
1112 = wc_tmp(ixslice,ixcmin2:ixcmax2,1:nw+nwexpand)
1113 ps_sub(jgrid)%xC(ixcmin2:ixcmax2,1:ndim) &
1114 = xc_tmp(ixslice,ixcmin2:ixcmax2,1:ndim)
1115 case (2)
1116 ps_sub(jgrid)%w(ixccmin1:ixccmax1,1:nw+nwexpand) &
1117 = wcc_tmp(ixccmin1:ixccmax1,ixslice,1:nw+nwexpand)
1118 ps_sub(jgrid)%x(ixccmin1:ixccmax1,1:ndim) &
1119 = xcc_tmp(ixccmin1:ixccmax1,ixslice,1:ndim)
1120 ps_sub(jgrid)%wC(ixcmin1:ixcmax1,1:nw+nwexpand) &
1121 = wc_tmp(ixcmin1:ixcmax1,ixslice,1:nw+nwexpand)
1122 ps_sub(jgrid)%xC(ixcmin1:ixcmax1,1:ndim) &
1123 = xc_tmp(ixcmin1:ixcmax1,ixslice,1:ndim)
1124 case default
1125 call mpistop("slice direction not clear in fill_subnode")
1126 end select
1127 }
1128 {^ifthreed
1129 select case (dir)
1130 case (1)
1131 ps_sub(jgrid)%w(ixccmin2:ixccmax2,ixccmin3:ixccmax3,1:nw+nwexpand) = &
1132 wcc_tmp(ixslice,ixccmin2:ixccmax2,ixccmin3:ixccmax3,1:nw+nwexpand)
1133 ps_sub(jgrid)%x(ixccmin2:ixccmax2,ixccmin3:ixccmax3,1:ndim) = &
1134 xcc_tmp(ixslice,ixccmin2:ixccmax2,ixccmin3:ixccmax3,1:ndim)
1135 ps_sub(jgrid)%wC(ixcmin2:ixcmax2,ixcmin3:ixcmax3,1:nw+nwexpand) = &
1136 wc_tmp(ixslice,ixcmin2:ixcmax2,ixcmin3:ixcmax3,1:nw+nwexpand)
1137 ps_sub(jgrid)%xC(ixcmin2:ixcmax2,ixcmin3:ixcmax3,1:ndim) = &
1138 xc_tmp(ixslice,ixcmin2:ixcmax2,ixcmin3:ixcmax3,1:ndim)
1139 case (2)
1140 ps_sub(jgrid)%w(ixccmin1:ixccmax1,ixccmin3:ixccmax3,1:nw+nwexpand) = &
1141 wcc_tmp(ixccmin1:ixccmax1,ixslice,ixccmin3:ixccmax3,1:nw+nwexpand)
1142 ps_sub(jgrid)%x(ixccmin1:ixccmax1,ixccmin3:ixccmax3,1:ndim) = &
1143 xcc_tmp(ixccmin1:ixccmax1,ixslice,ixccmin3:ixccmax3,1:ndim)
1144 ps_sub(jgrid)%wC(ixcmin1:ixcmax1,ixcmin3:ixcmax3,1:nw+nwexpand) = &
1145 wc_tmp(ixcmin1:ixcmax1,ixslice,ixcmin3:ixcmax3,1:nw+nwexpand)
1146 ps_sub(jgrid)%xC(ixcmin1:ixcmax1,ixcmin3:ixcmax3,1:ndim) = &
1147 xc_tmp(ixcmin1:ixcmax1,ixslice,ixcmin3:ixcmax3,1:ndim)
1148 case (3)
1149 ps_sub(jgrid)%w(ixccmin1:ixccmax1,ixccmin2:ixccmax2,1:nw+nwexpand) = &
1150 wcc_tmp(ixccmin1:ixccmax1,ixccmin2:ixccmax2,ixslice,1:nw+nwexpand)
1151 ps_sub(jgrid)%x(ixccmin1:ixccmax1,ixccmin2:ixccmax2,1:ndim) = &
1152 xcc_tmp(ixccmin1:ixccmax1,ixccmin2:ixccmax2,ixslice,1:ndim)
1153 ps_sub(jgrid)%wC(ixcmin1:ixcmax1,ixcmin2:ixcmax2,1:nw+nwexpand) = &
1154 wc_tmp(ixcmin1:ixcmax1,ixcmin2:ixcmax2,ixslice,1:nw+nwexpand)
1155 ps_sub(jgrid)%xC(ixcmin1:ixcmax1,ixcmin2:ixcmax2,1:ndim) = &
1156 xc_tmp(ixcmin1:ixcmax1,ixcmin2:ixcmax2,ixslice,1:ndim)
1157 case default
1158 call mpistop("slice direction not clear in fill_subnode")
1159 end select
1160 }
1161
1162 end subroutine fill_subnode
1163
1164 subroutine alloc_subnode(jgrid,dir,nwexpand)
1166 integer, intent(in) :: jgrid, dir, nwexpand
1167
1168 ! take care, what comes out is not necessarily a right handed system!
1169 {^ifoned
1170 allocate(ps_sub(jgrid)%w(1:nw+nwexpand),ps_sub(jgrid)%x(1:ndim))
1171 allocate(ps_sub(jgrid)%wC(1:nw+nwexpand),ps_sub(jgrid)%xC(1:ndim))
1172 }
1173 {^iftwod
1174 select case (dir)
1175 case (1)
1176 allocate(ps_sub(jgrid)%w(ixglo2:ixghi2,1:nw+nwexpand),&
1177 ps_sub(jgrid)%x(ixglo2:ixghi2,1:ndim), &
1178 ps_sub(jgrid)%wC(ixglo2:ixghi2,1:nw+nwexpand),&
1179 ps_sub(jgrid)%xC(ixglo2:ixghi2,1:ndim))
1180 case (2)
1181 allocate(ps_sub(jgrid)%w(ixglo1:ixghi1,1:nw+nwexpand),&
1182 ps_sub(jgrid)%x(ixglo1:ixghi1,1:ndim), &
1183 ps_sub(jgrid)%wC(ixglo1:ixghi1,1:nw+nwexpand),&
1184 ps_sub(jgrid)%xC(ixglo1:ixghi1,1:ndim))
1185 case default
1186 call mpistop("slice direction not clear in alloc_subnode")
1187 end select
1188 }
1189 {^ifthreed
1190 select case (dir)
1191 case (1)
1192 allocate(ps_sub(jgrid)%w(ixglo2:ixghi2,ixglo3:ixghi3,1:nw+nwexpand),&
1193 ps_sub(jgrid)%x(ixglo2:ixghi2,ixglo3:ixghi3,1:ndim), &
1194 ps_sub(jgrid)%wC(ixglo2:ixghi2,ixglo3:ixghi3,1:nw+nwexpand),&
1195 ps_sub(jgrid)%xC(ixglo2:ixghi2,ixglo3:ixghi3,1:ndim))
1196 case (2)
1197 allocate(ps_sub(jgrid)%w(ixglo1:ixghi1,ixglo3:ixghi3,1:nw+nwexpand),&
1198 ps_sub(jgrid)%x(ixglo1:ixghi1,ixglo3:ixghi3,1:ndim), &
1199 ps_sub(jgrid)%wC(ixglo1:ixghi1,ixglo3:ixghi3,1:nw+nwexpand),&
1200 ps_sub(jgrid)%xC(ixglo1:ixghi1,ixglo3:ixghi3,1:ndim))
1201 case (3)
1202 allocate(ps_sub(jgrid)%w(ixglo1:ixghi1,ixglo2:ixghi2,1:nw+nwexpand),&
1203 ps_sub(jgrid)%x(ixglo1:ixghi1,ixglo2:ixghi2,1:ndim), &
1204 ps_sub(jgrid)%wC(ixglo1:ixghi1,ixglo2:ixghi2,1:nw+nwexpand),&
1205 ps_sub(jgrid)%xC(ixglo1:ixghi1,ixglo2:ixghi2,1:ndim))
1206 case default
1207 call mpistop("slice direction not clear in alloc_subnode")
1208 end select
1209 }
1210 end subroutine alloc_subnode
1211
1212 subroutine dealloc_subnode(jgrid)
1214 integer, intent(in) :: jgrid
1215
1216 if (jgrid==0) then
1217 call mpistop("trying to delete a non-existing grid in dealloc_subnode")
1218 end if
1219
1220 deallocate(ps_sub(jgrid)%w,ps_sub(jgrid)%x,ps_sub(jgrid)%wC,ps_sub(jgrid)%xC)
1221
1222 ! reset the global node info:
1223 node_sub(:,jgrid)=0
1224 rnode_sub(:,jgrid)=zero
1225
1226 end subroutine dealloc_subnode
1227
1228 subroutine fill_subnode_info(igrid,jgrid,dir)
1230 integer, intent(in) :: igrid,jgrid,dir
1231
1232 node_sub(plevel_,jgrid)=node(plevel_,igrid)
1233 {^ifthreed
1234 select case(dir)
1235 case (1)
1236 node_sub(pig1_,jgrid)=node(pig2_,igrid)
1237 node_sub(pig2_,jgrid)=node(pig3_,igrid)
1238 rnode_sub(rpdx1_,jgrid)=rnode(rpdx2_,igrid)
1239 rnode_sub(rpdx2_,jgrid)=rnode(rpdx3_,igrid)
1240 rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin2_,igrid)
1241 rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin3_,igrid)
1242 case (2)
1243 node_sub(pig1_,jgrid)=node(pig1_,igrid)
1244 node_sub(pig2_,jgrid)=node(pig3_,igrid)
1245 rnode_sub(rpdx1_,jgrid)=rnode(rpdx1_,igrid)
1246 rnode_sub(rpdx2_,jgrid)=rnode(rpdx3_,igrid)
1247 rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin1_,igrid)
1248 rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin3_,igrid)
1249 case (3)
1250 node_sub(pig1_,jgrid)=node(pig1_,igrid)
1251 node_sub(pig2_,jgrid)=node(pig2_,igrid)
1252 rnode_sub(rpdx1_,jgrid)=rnode(rpdx1_,igrid)
1253 rnode_sub(rpdx2_,jgrid)=rnode(rpdx2_,igrid)
1254 rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin1_,igrid)
1255 rnode_sub(rpxmin2_,jgrid)=rnode(rpxmin2_,igrid)
1256 case default
1257 call mpistop("slice direction not clear in fill_subnode_info")
1258 end select
1259 }
1260 {^iftwod
1261 select case(dir)
1262 case (1)
1263 node_sub(pig1_,jgrid)=node(pig2_,igrid)
1264 rnode_sub(rpdx1_,jgrid)=rnode(rpdx2_,igrid)
1265 rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin2_,igrid)
1266 case (2)
1267 node_sub(pig1_,jgrid)=node(pig1_,igrid)
1268 rnode_sub(rpdx1_,jgrid)=rnode(rpdx1_,igrid)
1269 rnode_sub(rpxmin1_,jgrid)=rnode(rpxmin1_,igrid)
1270 case default
1271 call mpistop("slice direction not clear in fill_subnode_info")
1272 end select
1273 }
1274 {^ifoned
1275 }
1276
1277 end subroutine fill_subnode_info
1278
1279 subroutine get_igslice(dir,x,igslice)
1281 integer, intent(in) :: dir
1282 double precision, intent(in) :: x
1283 integer, dimension(nlevelshi), intent(out) :: igslice
1284 ! .. local ..
1285 double precision :: distance
1286 integer :: level
1287 !double precision :: xsgrid(ndim,nlevelshi),qs(ndim),xmgrid(ndim,3),xnew,xlgrid(ndim,3)
1288 !integer :: nbefore
1289
1290 if (x.ne.x) &
1291 call mpistop("get_igslice: your slice position is NaN!")
1292
1293 select case (dir)
1294 {case (^d)
1295 select case (stretch_type(^d))
1296 case (stretch_none) ! This dimension is unstretched
1297 if (x<=xprobmin^d) then
1298 igslice=1
1299 else if (x>=xprobmax^d) then
1300 do level=1,refine_max_level
1301 igslice(level)=ng^d(level)
1302 end do
1303 else
1304 distance=x-xprobmin^d
1305 do level = 1, refine_max_level
1306 igslice(level) = ceiling(distance/dg^d(level))
1307 end do
1308 end if
1309
1310 case (stretch_uni) ! Uniform stretching
1311
1312 if (x<=xprobmin^d) then
1313 igslice=1
1314 else if (x>=xprobmax^d) then
1315 do level=1,refine_max_level
1316 igslice(level)=ng^d(level)
1317 end do
1318 else
1319 distance=x-xprobmin^d
1320 do level=1,refine_max_level
1321 igslice(level)= ceiling(dlog(distance/dxfirst(level,^d)*(qstretch(level,^d)-1.d0)+1.d0)&
1322 /dlog(qstretch(level,^d))/dble(block_nx^d))
1323 end do
1324 end if
1325
1326 case (stretch_symm) ! Symmetric stretching
1327 ! symmetric stretch about 0.5*(xprobmin+xprobmax)
1328 if (x<=xprobmin^d) then
1329 igslice=1
1330 else if (x>=xprobmax^d) then
1331 do level=1,refine_max_level
1332 igslice(level)=ng^d(level)
1333 end do
1334 else if(x<xprobmin^d+xstretch^d) then
1335 distance=xprobmin^d+xstretch^d-x
1336 ! stretch to left from xprobmin+xstretch
1337 do level=1,refine_max_level
1338 igslice(level) = nstretchedblocks(level,^d)/2-int(dlog(distance*(qstretch(level,^d)-one)/&
1339 dxfirst(level,^d)+one)/dlog(qstretch(level,^d))/dble(block_nx^d))
1340 end do
1341 else if(x>xprobmax^d-xstretch^d) then
1342 distance=x-xprobmax^d+xstretch^d
1343 ! stretch to right from xprobmax-xstretch
1344 do level=1,refine_max_level
1345 igslice(level) = ceiling(dlog(distance*(qstretch(level,^d)-one)/&
1346 dxfirst(level,^d)+one)/dlog(qstretch(level,^d))/dble(block_nx^d))+ng^d(level)-nstretchedblocks(level,^d)/2
1347 end do
1348 else
1349 ! possible non-stretched central part
1350 distance=x-xprobmin^d-xstretch^d
1351 do level=1,refine_max_level
1352 igslice(level)=nstretchedblocks(level,^d)/2+ceiling(distance/dg^d(level))
1353 end do
1354 end if
1355 !xsgrid(^D,1)=half*(xprobmax^D-xprobmin^D)&
1356 ! /(half*domain_nx^D-half*nstretchedblocks_baselevel(^D)*block_nx^D &
1357 ! +(one-qstretch_baselevel(^D)**(half*nstretchedblocks_baselevel(^D)*block_nx^D)) &
1358 ! /(one-qstretch_baselevel(^D)))
1359 !xmgrid(^D,1)=xsgrid(^D,1)*(domain_nx^D-nstretchedblocks_baselevel(^D)*block_nx^D)
1360 !xlgrid(^D,1)=xsgrid(^D,1)
1361
1362 !if (x .ge. xmgrid(^D,1)*half) then
1363 ! xnew=x-xmgrid(^D,1)*half
1364 ! do level=1,refine_max_level
1365 ! qs(^D)=qstretch_baselevel(^D)**(one/2.d0**(level-1))
1366 ! if (level .gt. 1) xsgrid(^D,level)=xsgrid(^D,level-1)/(one+qs(^D))
1367 ! nbefore=(domain_nx^D/block_nx^D-nstretchedblocks_baselevel(^D)/2)*2**(level-1)
1368 ! igslice(level)=floor((dlog(one-xnew/xsgrid(^D,level)*(one-qs(^D)))/dlog(qs(^D))-1.e-16)/block_nx^D)+1+nbefore
1369 ! if (x>=xprobmax^D) igslice(level)=domain_nx^D*2**(level-1)
1370 ! end do
1371 !else if(x .ge. -xmgrid(^D,1)*half) then
1372 ! xnew=x+xmgrid(^D,1)*half
1373 ! do level=1,refine_max_level
1374 ! nbefore=nstretchedblocks_baselevel(^D)/2*2**(level-1)
1375 ! if (level .gt. 1) xlgrid(^D,level)=xlgrid(^D,level-1)/2.d0
1376 ! igslice(level)=floor(((xnew-1.e-16)/xlgrid(^D,level))/block_nx^D)+1+nbefore
1377 ! end do
1378 !else
1379 ! xnew=xmgrid(^D,1)*half-x
1380 ! do level=1,refine_max_level
1381 ! qs(^D)=qstretch_baselevel(^D)**(one/2.d0**(level-1))
1382 ! if (level .gt. 1) xsgrid(^D,level)=xsgrid(^D,level-1)/(one+qs(^D))
1383 ! igslice(level)=nstretchedblocks_baselevel(^D)/2*2**(level-1) &
1384 ! -floor((dlog(one-xnew/xsgrid(^D,level)*(one-qs(^D)))/dlog(qs(^D)))/block_nx^D)
1385 ! if (x<=xprobmin^D) igslice(level)=1
1386 ! end do
1387 !end if
1388
1389 case default
1390 call mpistop("stretch type not supported by get_igslice")
1391 end select
1392 \}
1393 case default
1394 call mpistop("slice direction not clear in get_igslice")
1395 end select
1396
1397 end subroutine get_igslice
1398
1399 double precision function roundoff_minmax(val,minval,maxval)
1400 implicit none
1401 double precision,intent(in) :: val, minval, maxval
1402
1403 roundoff_minmax = val
1404
1405 if (abs(roundoff_minmax) .le. minval) then
1406 roundoff_minmax = 0.0d0
1407 end if
1408
1409 if (roundoff_minmax .gt. maxval) then
1410 roundoff_minmax = maxval
1411 else if (roundoff_minmax .lt. -maxval) then
1412 roundoff_minmax = -maxval
1413 end if
1414
1415 ! Replace NaN with maxval (e.g. Paraview chokes on ASCII NaN):
1417
1418 end function roundoff_minmax
1419
1420 recursive subroutine quicksort_integer(arr, left, right)
1421 implicit none
1422 integer, intent(inout) :: arr(:)
1423 integer, intent(in) :: left, right
1424 ! .. local ..
1425 integer :: pivot, i, j, temp
1426
1427 if (left < right) then
1428 ! Choose pivot (using middle element)
1429 pivot = arr((left + right) / 2)
1430 i = left - 1
1431 j = right + 1
1432
1433 do
1434 ! Find elements to swap
1435 do
1436 i = i + 1
1437 if (arr(i) >= pivot) exit
1438 end do
1439
1440 do
1441 j = j - 1
1442 if (arr(j) <= pivot) exit
1443 end do
1444
1445 if (i >= j) exit
1446
1447 ! Swap elements
1448 temp = arr(i)
1449 arr(i) = arr(j)
1450 arr(j) = temp
1451 end do
1452
1453 ! Recursively sort subarrays
1454 call quicksort_integer(arr, left, j)
1455 call quicksort_integer(arr, j + 1, right)
1456 end if
1457
1458 end subroutine quicksort_integer
1459
1460
1461 !> Signed slice coordinate for the file names, such as +0.500000D+00
1462 character(len=13) function slice_label(xslice)
1463 double precision, intent(in) :: xslice
1464 write(slice_label,"(D13.6)") xslice
1465 if(xslice >= 0.0d0) slice_label(1:1) = "+"
1466 end function slice_label
1467
1468end module mod_slice
1469
recursive subroutine traverse_slice(tree)
Definition mod_slice.t:939
subroutine put_slice_vtu
Definition mod_slice.t:244
Module with basic data types used in amrvac.
integer, parameter size_double
Size (in bytes) of double precision real.
integer, parameter name_len
Default length for names (of e.g. variables).
integer, parameter size_logical
Size (in bytes) of default logical.
integer, parameter size_int
Size (in bytes) of default integer.
Handles computations for coordinates and variables in output.
subroutine getheadernames(wnamei, xandwnamei, outfilehead)
get all variables names
subroutine calc_grid(qunit, igrid, xc, xcc, xc_tmp, xcc_tmp, wc_tmp, wcc_tmp, normconv, ixcl, ixccl, first)
Compute both corner as well as cell-centered values for output.
subroutine calc_x(igrid, xc, xcc)
computes cell corner (xC) and cell center (xCC) coordinates
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module with basic grid data structures.
Definition mod_forest.t:2
integer, dimension(:), allocatable, save morton_sub_start
Definition mod_forest.t:70
integer, dimension(:), allocatable, save morton_sub_stop
Definition mod_forest.t:70
integer, dimension(:^d &), allocatable, save iglevel1_sfc
iglevel1_sfc(ig^D) gives the Morton number for grid ig^D
Definition mod_forest.t:53
integer, dimension(:,:), allocatable, save sfc_iglevel1
Space filling curve for level 1 grid. sfc_iglevel1(^D, MN) gives ig^D (the spatial index of the grid)...
Definition mod_forest.t:50
type(tree_node_ptr), dimension(:^d &), allocatable, save tree_root
Pointers to the coarse grid.
Definition mod_forest.t:32
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:35
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer, parameter stretch_uni
Unidirectional stretching from a side.
double precision global_time
The global simulation time.
double precision xstretch
physical extent of stretched border in symmetric stretching
double precision, dimension(:), allocatable dg
extent of grid blocks in domain per dimension, in array over levels
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision time_convert_factor
Conversion factor for time unit.
integer, dimension(:,:), allocatable nstretchedblocks
(even) number of (symmetrically) stretched blocks per level and dimension
integer icomm
The MPI communicator.
integer, dimension(:), allocatable ng
number of grid blocks in domain per dimension, in array over levels
integer mype
The rank of the current MPI task.
integer block_nx
number of cells for each dimension in grid block excluding ghostcells
integer slicenext
IO: slice output number/label.
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
double precision, dimension(:), allocatable, parameter d
double precision, dimension(:,:), allocatable qstretch
Stretching factors and first cell size for each AMR level and dimension.
integer npe
The number of MPI tasks.
integer nwauxio
Number of auxiliary variables that are only included in output.
integer, parameter stretch_none
No stretching.
logical, dimension(:), allocatable w_write
if true write the w variable in output
logical, dimension(ndim) periodb
True for dimensions with periodic boundaries.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
integer nghostcells
Number of ghost cells surrounding a grid.
integer, dimension(ndim) stretch_type
What kind of stretching is used per dimension.
double precision, dimension(:,:), allocatable rnode_sub
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
integer refine_max_level
Maximal number of AMR levels.
integer, parameter stretch_symm
Symmetric stretching around the center.
double precision, dimension(:,:), allocatable dxfirst
integer, dimension(:,:), allocatable node
integer, dimension(:,:), allocatable node_sub
logical save_now
whether a manually inserted snapshot is saved
integer, parameter version_number
Version number of the .dat file output.
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_write_info), pointer phys_write_info
Definition mod_physics.t:85
character(len=name_len) physics_type
String describing the physics type of the simulation.
Definition mod_physics.t:49
Writes D-1 slice, can do so in various formats, depending on slice_type.
Definition mod_slice.t:2
subroutine fill_subnode_info(igrid, jgrid, dir)
Definition mod_slice.t:1229
subroutine get_igslice(dir, x, igslice)
Definition mod_slice.t:1280
subroutine fill_subnode(igrid, active, jgrid, dir, xslice, normconv)
Definition mod_slice.t:1027
integer, parameter nslicemax
Maximum number of slices.
Definition mod_slice.t:11
subroutine alloc_subnode(jgrid, dir, nwexpand)
Definition mod_slice.t:1165
subroutine put_slice(dir, xslice)
Definition mod_slice.t:45
character(len=13) function slice_label(xslice)
Signed slice coordinate for the file names, such as +0.500000D+00.
Definition mod_slice.t:1463
subroutine write_slice
Definition mod_slice.t:31
integer, dimension(:,:), allocatable sfc_sub
igrid and ipe of the leaf blocks on the slice, with the first (1,1:2) stores the nleafs and nparents
Definition mod_slice.t:26
double precision, dimension(1000) slicecoord
Slice coordinates, see Slice output.
Definition mod_slice.t:8
character(len=std_len) slice_type
choose data type of slice: vtu, vtuCC, dat, or csv
Definition mod_slice.t:23
integer, dimension(nslicemax) slicedir
The slice direction for each slice.
Definition mod_slice.t:17
double precision function roundoff_minmax(val, minval, maxval)
Definition mod_slice.t:1400
integer nslices
Number of slices to output.
Definition mod_slice.t:14
subroutine select_slice(dir, xslice, writeonly, file_handle, normconv)
Definition mod_slice.t:854
subroutine dealloc_subnode(jgrid)
Definition mod_slice.t:1213
recursive subroutine quicksort_integer(arr, left, right)
Definition mod_slice.t:1421
Pointer to a tree_node.
Definition mod_forest.t:9
The data structure that contains information about a tree node/grid block.
Definition mod_forest.t:14