Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fld_file.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2023, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
36 use num_types, only : rp, dp, sp, i8
38 use field, only : field_t
39 use field_list, only : field_list_t
40 use dofmap, only : dofmap_t
41 use space, only : space_t
42 use structs, only : array_ptr_t
43 use vector, only : vector_t
45 use vector, only : vector_t
46 use space, only : space_t
47 use logger, only : neko_log, log_size
48 use mesh, only : mesh_t
49 use mask, only : mask_t
52 use comm
53 use datadist, only : linear_dist_t
54 use math, only : vlmin, vlmax, sabscmp
58 use mpi_f08
59 implicit none
60 private
61
62 real(kind=dp), private, allocatable :: tmp_dp(:)
63 real(kind=sp), private, allocatable :: tmp_sp(:)
64
66 type, public, extends(generic_file_t) :: fld_file_t
67 logical :: dp_precision = .false.
68 ! These flags can be manipulated to skip writing certain fields
69 ! that will then be put into scalars.
70 logical :: skip_pressure = .true.
71 logical :: skip_velocity = .true.
72 logical :: skip_temperature = .true.
73 logical :: write_mesh = .false.
74 type(mask_t) :: mask
75 contains
76 procedure :: read => fld_file_read
77 procedure :: write => fld_file_write_manager
78 procedure, private :: write_all => fld_file_write
79 procedure, private :: write_masked => fld_file_write_masked
80 procedure :: set_precision => fld_file_set_precision
81 procedure :: set_mask => fld_file_set_mask
82 procedure :: get_fld_fname => fld_file_get_fld_fname
83 procedure :: get_next_output_fname => fld_file_get_next_output_fname
84 procedure :: get_meta_fname => fld_file_get_meta_fname
85 end type fld_file_t
86
87
88contains
89
104 subroutine fld_file_select_from_field_list(this, data, p, u, v, w, tem, &
105 scalar_fields, n_scalar_fields, write_pressure, write_velocity, &
106 write_temperature, dof)
107 class(fld_file_t), intent(in) :: this
108 type(field_list_t), intent(in) :: data
109 type(array_ptr_t), intent(inout) :: p, u, v, w, tem
110 type(array_ptr_t), allocatable, intent(inout) :: scalar_fields(:)
111 integer, intent(out) :: n_scalar_fields
112 logical, intent(out) :: write_pressure, write_velocity, write_temperature
113 type(dofmap_t), pointer, intent(out) :: dof
114 integer :: i, idx, n_fields
115
116 n_scalar_fields = 0
117 write_pressure = .false.
118 write_velocity = .false.
119 write_temperature = .false.
120 n_fields = data%size()
121 idx = 1
122
123 if (n_fields .eq. 0) then
124 call neko_error('Empty field_list_t cannot be written to an fld file')
125 end if
126
127 if (.not. this%skip_pressure) then
128 if (idx .le. n_fields) then
129 p%ptr => data%items(idx)%ptr%x(:,1,1,1)
130 write_pressure = .true.
131 idx = idx + 1
132 end if
133 end if
134
135 if (.not. this%skip_velocity) then
136 if (idx + 2 .le. n_fields) then
137 u%ptr => data%items(idx+0)%ptr%x(:,1,1,1)
138 v%ptr => data%items(idx+1)%ptr%x(:,1,1,1)
139 w%ptr => data%items(idx+2)%ptr%x(:,1,1,1)
140 write_velocity = .true.
141 idx = idx + 3
142 end if
143 end if
144
145 if (.not. this%skip_temperature) then
146 if (idx .le. n_fields) then
147 tem%ptr => data%items(idx)%ptr%x(:,1,1,1)
148 write_temperature = .true.
149 idx = idx + 1
150 end if
151 end if
152
153 if (idx .le. n_fields) then
154 n_scalar_fields = n_fields - idx + 1
155 allocate(scalar_fields(n_scalar_fields))
156 do i = 1, n_scalar_fields
157 scalar_fields(i)%ptr => data%items(idx + i - 1)%ptr%x(:,1,1,1)
158 end do
159 end if
160
161 dof => data%dof(1)
163
165 subroutine fld_file_write_manager(this, data, t)
166 class(fld_file_t), intent(inout) :: this
167 class(*), target, intent(in) :: data
168 real(kind=rp), intent(in), optional :: t
169
170 if (this%mask%is_set()) then
171 call this%write_masked(data, this%mask, t)
172 else
173 call this%write_all(data, t)
174 end if
175
176 end subroutine fld_file_write_manager
177
180 subroutine fld_file_write(this, data, t)
181 class(fld_file_t), intent(inout) :: this
182 class(*), target, intent(in) :: data
183 real(kind=rp), intent(in), optional :: t
184 type(array_ptr_t) :: x, y, z, u, v, w, p, tem
185 real(kind=rp), allocatable, target :: tempo(:)
186 type(mesh_t), pointer :: msh
187 type(dofmap_t), pointer :: dof
188 type(space_t), pointer :: Xh
189 real(kind=dp) :: time
190 character(len= 132) :: hdr
191 character :: rdcode(10)
192 character(len=6) :: id_str
193 character(len= 1024) :: fname
194 character(len= 1024) :: name
195 integer :: file_unit
196 integer :: i, ierr, n, suffix_pos, tslash_pos
197 integer :: lx, ly, lz, lxyz, gdim, glb_nelv, nelv, offset_el
198 integer, allocatable :: idx(:)
199 type(mpi_status) :: status
200 type(mpi_file) :: fh
201 integer (kind=MPI_OFFSET_KIND) :: mpi_offset, byte_offset, temp_offset
202 real(kind=sp), parameter :: test_pattern = 6.54321
203 type(array_ptr_t), allocatable :: scalar_fields(:)
204 logical :: write_mesh, write_velocity, write_pressure, write_temperature
205 integer :: fld_data_size, n_scalar_fields
206 type(field_list_t) :: dummy_list
207 type(field_t), pointer :: ptr
208
209 if (present(t)) then
210 time = real(t, dp)
211 else
212 time = 0d0
213 end if
214
215 nullify(msh)
216 nullify(dof)
217 nullify(xh)
218 n_scalar_fields = 0
219 write_pressure = .false.
220 write_velocity = .false.
221 write_temperature = .false.
222
223 select type (data)
224 type is (fld_file_data_t)
225 nelv = data%nelv
226 lx = data%lx
227 ly = data%ly
228 lz = data%lz
229 gdim = data%gdim
230 glb_nelv = data%glb_nelv
231 offset_el = data%offset_el
232
233 if (data%x%size() .gt. 0) x%ptr => data%x%x
234 if (data%y%size() .gt. 0) y%ptr => data%y%x
235 if (data%z%size() .gt. 0) z%ptr => data%z%x
236 if (gdim .eq. 2) z%ptr => data%y%x
237 if (data%u%size() .gt. 0) then
238 u%ptr => data%u%x
239 ! In case only u is actually allocated, point the other comps to u
240 ! so that we don't die on trying to write them
241 if (data%v%size() .le. 0) v%ptr => data%u%x
242 if (data%w%size() .le. 0) w%ptr => data%u%x
243 write_velocity = .true.
244 end if
245 if (data%v%size() .gt. 0) v%ptr => data%v%x
246 if (data%w%size() .gt. 0) w%ptr => data%w%x
247 if (data%p%size() .gt. 0) then
248 p%ptr => data%p%x
249 write_pressure = .true.
250 end if
251 if (data%t%size() .gt. 0) then
252 write_temperature = .true.
253 tem%ptr => data%t%x
254 end if
255 ! If gdim = 2 and Z-velocity component exists,
256 ! it is stored in last scalar field
257 if (gdim .eq. 2 .and. data%w%size() .gt. 0) then
258 n_scalar_fields = data%n_scalars + 1
259 allocate(scalar_fields(n_scalar_fields))
260 do i = 1, n_scalar_fields -1
261 scalar_fields(i)%ptr => data%s(i)%x
262 end do
263 scalar_fields(n_scalar_fields)%ptr => data%w%x
264 else
265 n_scalar_fields = data%n_scalars
266 allocate(scalar_fields(n_scalar_fields+1))
267 do i = 1, n_scalar_fields
268 scalar_fields(i)%ptr => data%s(i)%x
269 end do
270 scalar_fields(n_scalar_fields+1)%ptr => data%w%x
271 end if
272 ! This is very stupid...
273 ! Some compilers cannot handle that these pointers dont point to anything
274 ! (although they are not used) this fixes a segfault due to this.
275 if (nelv .eq. 0) then
276 allocate(tempo(1))
277 x%ptr => tempo
278 y%ptr => tempo
279 z%ptr => tempo
280 u%ptr => tempo
281 v%ptr => tempo
282 w%ptr => tempo
283 p%ptr => tempo
284 tem%ptr => tempo
285 end if
286
287 allocate(idx(nelv))
288 do i = 1, nelv
289 idx(i) = data%idx(i)
290 end do
291 type is (field_t)
292 call dummy_list%init(1)
293 ptr => data ! For the sake of intel
294 call dummy_list%assign(1, ptr)
295 call fld_file_select_from_field_list(this, dummy_list, p, u, v, w, tem, &
296 scalar_fields, n_scalar_fields, write_pressure, write_velocity, &
297 write_temperature, dof)
298 nullify(dummy_list%items(1)%ptr)
299 nullify(ptr)
300 deallocate(dummy_list%items)
301 type is (field_list_t)
302 call fld_file_select_from_field_list(this, data, p, u, v, w, tem, &
303 scalar_fields, n_scalar_fields, write_pressure, write_velocity, &
304 write_temperature, dof)
305 class default
306 call neko_error('Invalid data')
307 end select
308 ! Fix things for pointers that do not exist in all data types...
309 if (associated(dof)) then
310 x%ptr => dof%x(:,1,1,1)
311 y%ptr => dof%y(:,1,1,1)
312 z%ptr => dof%z(:,1,1,1)
313 msh => dof%msh
314 xh => dof%Xh
315 end if
316
317 if (associated(msh)) then
318 nelv = msh%nelv
319 glb_nelv = msh%glb_nelv
320 offset_el = msh%offset_el
321 gdim = msh%gdim
322 ! Store global idx of each element
323 allocate(idx(msh%nelv))
324 do i = 1, msh%nelv
325 idx(i) = msh%elements(i)%e%id()
326 end do
327 end if
328
329 if (associated(xh)) then
330 lx = xh%lx
331 ly = xh%ly
332 lz = xh%lz
333 end if
334
335 lxyz = lx*ly*lz
336 n = nelv*lxyz
337
338 if (this%dp_precision) then
339 fld_data_size = mpi_double_precision_size
340 else
341 fld_data_size = mpi_real_size
342 end if
343 if (this%dp_precision) then
344 allocate(tmp_dp(gdim*n))
345 else
346 allocate(tmp_sp(gdim*n))
347 end if
348
349
350 !
351 ! Create fld header for NEKTON's multifile output
352 !
353
354 call this%increment_counter()
355 ! Check if I should write the mesh. Always override at the start counters
356 if (.not. this%write_mesh) then
357 write_mesh = (this%get_counter() .eq. this%get_start_counter())
358 else
359 write_mesh = this%write_mesh
360 end if
361 call mpi_allreduce(mpi_in_place, write_mesh, 1, &
362 mpi_logical, mpi_lor, neko_comm)
363 call mpi_allreduce(mpi_in_place, write_velocity, 1, &
364 mpi_logical, mpi_lor, neko_comm)
365 call mpi_allreduce(mpi_in_place, write_pressure, 1, &
366 mpi_logical, mpi_lor, neko_comm)
367 call mpi_allreduce(mpi_in_place, write_temperature, 1, &
368 mpi_logical, mpi_lor, neko_comm)
369 call mpi_allreduce(mpi_in_place, n_scalar_fields, 1, &
370 mpi_integer, mpi_max, neko_comm)
371
372 ! Build rdcode note that for field_t, we only support scalar
373 ! fields at the moment
374 rdcode = ' '
375 i = 1
376 if (write_mesh) then
377 rdcode(i) = 'X'
378 i = i + 1
379 end if
380 if (write_velocity) then
381 rdcode(i) = 'U'
382 i = i + 1
383 end if
384 if (write_pressure) then
385 rdcode(i) = 'P'
386 i = i + 1
387 end if
388 if (write_temperature) then
389 rdcode(i) = 'T'
390 i = i + 1
391 end if
392 if (n_scalar_fields .gt. 0 ) then
393 rdcode(i) = 'S'
394 i = i + 1
395 write(rdcode(i), '(i1)') (n_scalar_fields)/10
396 i = i + 1
397 write(rdcode(i), '(i1)') (n_scalar_fields) - 10*((n_scalar_fields)/10)
398 i = i + 1
399 end if
400
402 write(hdr, 1) fld_data_size, lx, ly, lz, glb_nelv, glb_nelv,&
403 time, this%get_counter(), 1, 1, (rdcode(i), i = 1, 10)
4041 format('#std', 1x, i1, 1x, i2, 1x, i2, 1x, i2, 1x, i10, 1x, i10, &
405 1x, e20.13, 1x, i9, 1x, i6, 1x, i6, 1x, 10a)
406
407 ! Change to NEKTON's fld file format
408 fname = this%get_fld_fname()
409
410 call mpi_file_open(neko_comm, trim(fname), &
411 mpi_mode_wronly + mpi_mode_create, mpi_info_null, fh, &
412 ierr)
413
414 call mpi_file_write_all(fh, hdr, 132, mpi_character, status, ierr)
415 mpi_offset = 132 * mpi_character_size
416
417 call mpi_file_write_all(fh, test_pattern, 1, mpi_real, status, ierr)
418 mpi_offset = mpi_offset + mpi_real_size
419
420 byte_offset = mpi_offset + &
421 int(offset_el, i8) * int(mpi_integer_size, i8)
422 call mpi_file_write_at_all(fh, byte_offset, idx, nelv, &
423 mpi_integer, status, ierr)
424 mpi_offset = mpi_offset + int(glb_nelv, i8) * int(mpi_integer_size, i8)
425 deallocate(idx)
426 if (write_mesh) then
427
428 byte_offset = mpi_offset + int(offset_el, i8) * &
429 (int(gdim*lxyz, i8) * &
430 int(fld_data_size, i8))
431 call fld_file_write_vector_field(this, fh, byte_offset, &
432 x%ptr, y%ptr, z%ptr, &
433 n, gdim, lxyz, nelv)
434 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
435 (int(gdim *lxyz, i8) * &
436 int(fld_data_size, i8))
437 end if
438 if (write_velocity) then
439 byte_offset = mpi_offset + int(offset_el, i8) * &
440 (int(gdim * (lxyz), i8) * int(fld_data_size, i8))
441 call fld_file_write_vector_field(this, fh, byte_offset, &
442 u%ptr, v%ptr, w%ptr, n, gdim, lxyz, nelv)
443
444 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
445 (int(gdim * (lxyz), i8) * &
446 int(fld_data_size, i8))
447
448 end if
449
450 if (write_pressure) then
451 byte_offset = mpi_offset + int(offset_el, i8) * &
452 (int((lxyz), i8) * int(fld_data_size, i8))
453 call fld_file_write_field(this, fh, byte_offset, p%ptr, n)
454 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
455 (int((lxyz), i8) * int(fld_data_size, i8))
456 end if
457
458 if (write_temperature) then
459 byte_offset = mpi_offset + int(offset_el, i8) * &
460 (int((lxyz), i8) * &
461 int(fld_data_size, i8))
462 call fld_file_write_field(this, fh, byte_offset, tem%ptr, n)
463 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
464 (int((lxyz), i8) * &
465 int(fld_data_size, i8))
466 end if
467
468 temp_offset = mpi_offset
469
470 do i = 1, n_scalar_fields
471 ! Without this redundant if statement Cray optimizes this loop to
472 ! Oblivion
473 if (i .eq. 2) then
474 mpi_offset = int(temp_offset, i8) + int(1_i8*glb_nelv, i8) * &
475 (int(lxyz, i8) * int(fld_data_size, i8))
476 end if
477 byte_offset = int(mpi_offset, i8) + int(offset_el, i8) * &
478 (int((lxyz), i8) * &
479 int(fld_data_size, i8))
480 call fld_file_write_field(this, fh, byte_offset, scalar_fields(i)%ptr, n)
481 mpi_offset = int(mpi_offset, i8) + int(glb_nelv, i8) * &
482 (int(lxyz, i8) * &
483 int(fld_data_size, i8))
484 end do
485
486 if (gdim .eq. 3) then
487
489 if (write_mesh) then
490 !The offset is:
491 ! mpioff + element_off * 2(min max value)
492 ! * 4(single precision) * gdim(dimensions)
493 byte_offset = int(mpi_offset, i8) + &
494 int(offset_el, i8) * &
495 int(2, i8) * &
496 int(mpi_real_size, i8) * &
497 int(gdim, i8)
498 call fld_file_write_metadata_vector(this, fh, byte_offset, &
499 x%ptr, y%ptr, z%ptr, gdim, lxyz, nelv)
500 mpi_offset = int(mpi_offset, i8) + &
501 int(glb_nelv, i8) * &
502 int(2, i8) * &
503 int(mpi_real_size, i8) * &
504 int(gdim, i8)
505 end if
506
507 if (write_velocity) then
508 byte_offset = int(mpi_offset, i8) + &
509 int(offset_el, i8) * &
510 int(2, i8) * &
511 int(mpi_real_size, i8) * &
512 int(gdim, i8)
513 call fld_file_write_metadata_vector(this, fh, byte_offset, &
514 u%ptr, v%ptr, w%ptr, gdim, lxyz, nelv)
515 mpi_offset = int(mpi_offset, i8) + &
516 int(glb_nelv, i8) * &
517 int(2, i8) * &
518 int(mpi_real_size, i8) * &
519 int(gdim, i8)
520
521 end if
522
523 if (write_pressure) then
524 byte_offset = int(mpi_offset, i8) + &
525 int(offset_el, i8) * &
526 int(2, i8) * &
527 int(mpi_real_size, i8)
528 call fld_file_write_metadata_scalar(this, fh, byte_offset, &
529 p%ptr, lxyz, nelv)
530 mpi_offset = int(mpi_offset, i8) + &
531 int(glb_nelv, i8) * &
532 int(2, i8) * &
533 int(mpi_real_size, i8)
534
535 end if
536
537 if (write_temperature) then
538 byte_offset = int(mpi_offset, i8) + &
539 int(offset_el, i8) * &
540 int(2, i8) * &
541 int(mpi_real_size, i8)
542 call fld_file_write_metadata_scalar(this, fh, byte_offset, &
543 tem%ptr, lxyz, nelv)
544 mpi_offset = int(mpi_offset, i8) + &
545 int(glb_nelv, i8) * &
546 int(2, i8) * &
547 int(mpi_real_size, i8)
548
549 end if
550
551
552
553 temp_offset = mpi_offset
554
555 do i = 1, n_scalar_fields
556 ! Without this redundant if statement, Cray optimizes this loop to
557 ! Oblivion
558 if (i .eq. 2) then
559 mpi_offset = int(temp_offset, i8) + &
560 int(1_i8*glb_nelv, i8) * &
561 int(2, i8) * &
562 int(mpi_real_size, i8)
563 end if
564
565 byte_offset = int(mpi_offset, i8) + &
566 int(offset_el, i8) * &
567 int(2, i8) * &
568 int(mpi_real_size, i8)
569 call fld_file_write_metadata_scalar(this, fh, byte_offset, &
570 scalar_fields(i)%ptr, lxyz, nelv)
571 mpi_offset = int(mpi_offset, i8) + &
572 int(glb_nelv, i8) * &
573 int(2, i8) * &
574 int(mpi_real_size, i8)
575 end do
576 end if
577
578
579 call mpi_file_sync(fh, ierr)
580 call mpi_file_close(fh, ierr)
581 ! Write metadata file
582 if (pe_rank .eq. 0) then
583 call filename_name(this%get_base_fname(), name)
584
585 open(newunit = file_unit, &
586 file = this%get_meta_fname(), status = 'replace')
587 ! The following string will specify that the files in the file series
588 ! are defined by the filename followed by a 0.
589 ! This 0 is necessary as it specifies the index of number of files
590 ! the output file is split across.
591 ! In the past, many .f files were generated for each write.
592 ! To be consistent with this the trailing 0 is still necessary today.
593 write(file_unit, fmt = '(A,A,A)') 'filetemplate: ', &
594 trim(name), '%01d.f%05d'
595 write(file_unit, fmt = '(A,i5)') 'firsttimestep: ', &
596 this%get_start_counter()
597 write(file_unit, fmt = '(A,i5)') 'numtimesteps: ', &
598 (this%get_counter() + 1) - this%get_start_counter()
599 close(file_unit)
600 end if
601
602 if (allocated(tmp_dp)) deallocate(tmp_dp)
603 if (allocated(tmp_sp)) deallocate(tmp_sp)
604 if (allocated(tempo)) deallocate(tempo)
605 if (allocated(scalar_fields)) deallocate(scalar_fields)
606
607 end subroutine fld_file_write
608
611 subroutine fld_file_write_masked(this, data, mask, t)
612 class(fld_file_t), intent(inout) :: this
613 class(*), target, intent(in) :: data
614 type(mask_t), intent(in) :: mask
615 real(kind=rp), intent(in), optional :: t
616 type(array_ptr_t) :: x, y, z, u, v, w, p, tem
617 real(kind=rp), allocatable, target :: tempo(:)
618 type(mesh_t), pointer :: msh
619 type(dofmap_t), pointer :: dof
620 type(space_t), pointer :: Xh
621 real(kind=dp) :: time
622 character(len= 132) :: hdr
623 character :: rdcode(10)
624 character(len=6) :: id_str
625 character(len= 1024) :: fname
626 character(len= 1024) :: name
627 integer :: file_unit
628 integer :: i, ierr, n, suffix_pos, tslash_pos
629 integer :: lx, ly, lz, lxyz, gdim, glb_nelv, nelv, offset_el
630 integer, allocatable :: idx(:)
631 type(mpi_status) :: status
632 type(mpi_file) :: fh
633 integer (kind=MPI_OFFSET_KIND) :: mpi_offset, byte_offset, temp_offset
634 real(kind=sp), parameter :: test_pattern = 6.54321
635 type(array_ptr_t), allocatable :: scalar_fields(:)
636 logical :: write_mesh, write_velocity, write_pressure, write_temperature
637 integer :: fld_data_size, n_scalar_fields
638 type(field_list_t) :: dummy_list
639 type(field_t), pointer :: ptr
640
641 if (present(t)) then
642 time = real(t, dp)
643 else
644 time = 0d0
645 end if
646
647 nullify(msh)
648 nullify(dof)
649 nullify(xh)
650 n_scalar_fields = 0
651 write_pressure = .false.
652 write_velocity = .false.
653 write_temperature = .false.
654
655 select type (data)
656 type is (fld_file_data_t)
657 nelv = data%nelv
658 lx = data%lx
659 ly = data%ly
660 lz = data%lz
661 gdim = data%gdim
662 glb_nelv = data%glb_nelv
663 offset_el = data%offset_el
664
665 if (data%x%size() .gt. 0) x%ptr => data%x%x
666 if (data%y%size() .gt. 0) y%ptr => data%y%x
667 if (data%z%size() .gt. 0) z%ptr => data%z%x
668 if (gdim .eq. 2) z%ptr => data%y%x
669 if (data%u%size() .gt. 0) then
670 u%ptr => data%u%x
671 ! In case only u is actually allocated, point the other comps to u
672 ! so that we don't die on trying to write them
673 if (data%v%size() .le. 0) v%ptr => data%u%x
674 if (data%w%size() .le. 0) w%ptr => data%u%x
675 write_velocity = .true.
676 end if
677 if (data%v%size() .gt. 0) v%ptr => data%v%x
678 if (data%w%size() .gt. 0) w%ptr => data%w%x
679 if (data%p%size() .gt. 0) then
680 p%ptr => data%p%x
681 write_pressure = .true.
682 end if
683 if (data%t%size() .gt. 0) then
684 write_temperature = .true.
685 tem%ptr => data%t%x
686 end if
687 ! If gdim = 2 and Z-velocity component exists,
688 ! it is stored in last scalar field
689 if (gdim .eq. 2 .and. data%w%size() .gt. 0) then
690 n_scalar_fields = data%n_scalars + 1
691 allocate(scalar_fields(n_scalar_fields))
692 do i = 1, n_scalar_fields -1
693 scalar_fields(i)%ptr => data%s(i)%x
694 end do
695 scalar_fields(n_scalar_fields)%ptr => data%w%x
696 else
697 n_scalar_fields = data%n_scalars
698 allocate(scalar_fields(n_scalar_fields+1))
699 do i = 1, n_scalar_fields
700 scalar_fields(i)%ptr => data%s(i)%x
701 end do
702 scalar_fields(n_scalar_fields+1)%ptr => data%w%x
703 end if
704 ! This is very stupid...
705 ! Some compilers cannot handle that these pointers dont point to anything
706 ! (although they are not used) this fixes a segfault due to this.
707 if (nelv .eq. 0) then
708 allocate(tempo(1))
709 x%ptr => tempo
710 y%ptr => tempo
711 z%ptr => tempo
712 u%ptr => tempo
713 v%ptr => tempo
714 w%ptr => tempo
715 p%ptr => tempo
716 tem%ptr => tempo
717 end if
718
719 allocate(idx(nelv))
720 do i = 1, nelv
721 idx(i) = data%idx(i)
722 end do
723 type is (field_t)
724 call dummy_list%init(1)
725 ptr => data ! For the sake of intel
726 call dummy_list%assign(1, ptr)
727 call fld_file_select_from_field_list(this, dummy_list, p, u, v, w, tem, &
728 scalar_fields, n_scalar_fields, write_pressure, write_velocity, &
729 write_temperature, dof)
730 nullify(dummy_list%items(1)%ptr)
731 nullify(ptr)
732 deallocate(dummy_list%items)
733 type is (field_list_t)
734 call fld_file_select_from_field_list(this, data, p, u, v, w, tem, &
735 scalar_fields, n_scalar_fields, write_pressure, write_velocity, &
736 write_temperature, dof)
737 class default
738 call neko_error('Invalid data')
739 end select
740 ! Fix things for pointers that do not exist in all data types...
741 if (associated(dof)) then
742 x%ptr => dof%x(:,1,1,1)
743 y%ptr => dof%y(:,1,1,1)
744 z%ptr => dof%z(:,1,1,1)
745 msh => dof%msh
746 xh => dof%Xh
747 end if
748
749 if (associated(msh)) then
750 nelv = msh%nelv
751 glb_nelv = msh%glb_nelv
752 offset_el = msh%offset_el
753 gdim = msh%gdim
754 ! Store global idx of each element
755 allocate(idx(msh%nelv))
756 do i = 1, msh%nelv
757 idx(i) = msh%elements(i)%e%id()
758 end do
759 end if
760
761 if (associated(xh)) then
762 lx = xh%lx
763 ly = xh%ly
764 lz = xh%lz
765 end if
766
767 ! Up to now, all data types have dealt with their stuff.
768 ! Now overwrite with the masked info
769 lxyz = lx*ly*lz
770 nelv = mask%size() / lxyz
771 if (mod(mask%size(), lxyz) /= 0) then
772 call neko_error("Mask size must be a multiple of the number of elements in the mesh.")
773 end if
774 call mpi_allreduce(nelv, glb_nelv, 1, &
775 mpi_integer, mpi_sum, neko_comm)
776 call mpi_scan(nelv, offset_el, 1, &
777 mpi_integer, mpi_sum, neko_comm, ierr)
778 offset_el = offset_el - nelv
779
780 if (allocated(idx)) then
781 deallocate(idx)
782 end if
783
784 allocate(idx(nelv))
785 do i = 1, nelv
786 idx(i) = offset_el + i
787 end do
788 n = nelv*lxyz
789
790 if (this%dp_precision) then
791 fld_data_size = mpi_double_precision_size
792 else
793 fld_data_size = mpi_real_size
794 end if
795 if (this%dp_precision) then
796 allocate(tmp_dp(gdim*n))
797 else
798 allocate(tmp_sp(gdim*n))
799 end if
800
801
802 !
803 ! Create fld header for NEKTON's multifile output
804 !
805
806 call this%increment_counter()
807 ! Check if I should write the mesh. Always override at the start counters
808 if (.not. this%write_mesh) then
809 write_mesh = (this%get_counter() .eq. this%get_start_counter())
810 else
811 write_mesh = this%write_mesh
812 end if
813 call mpi_allreduce(mpi_in_place, write_mesh, 1, &
814 mpi_logical, mpi_lor, neko_comm)
815 call mpi_allreduce(mpi_in_place, write_velocity, 1, &
816 mpi_logical, mpi_lor, neko_comm)
817 call mpi_allreduce(mpi_in_place, write_pressure, 1, &
818 mpi_logical, mpi_lor, neko_comm)
819 call mpi_allreduce(mpi_in_place, write_temperature, 1, &
820 mpi_logical, mpi_lor, neko_comm)
821 call mpi_allreduce(mpi_in_place, n_scalar_fields, 1, &
822 mpi_integer, mpi_max, neko_comm)
823
824 ! Build rdcode note that for field_t, we only support scalar
825 ! fields at the moment
826 rdcode = ' '
827 i = 1
828 if (write_mesh) then
829 rdcode(i) = 'X'
830 i = i + 1
831 end if
832 if (write_velocity) then
833 rdcode(i) = 'U'
834 i = i + 1
835 end if
836 if (write_pressure) then
837 rdcode(i) = 'P'
838 i = i + 1
839 end if
840 if (write_temperature) then
841 rdcode(i) = 'T'
842 i = i + 1
843 end if
844 if (n_scalar_fields .gt. 0 ) then
845 rdcode(i) = 'S'
846 i = i + 1
847 write(rdcode(i), '(i1)') (n_scalar_fields)/10
848 i = i + 1
849 write(rdcode(i), '(i1)') (n_scalar_fields) - 10*((n_scalar_fields)/10)
850 i = i + 1
851 end if
852
854 write(hdr, 1) fld_data_size, lx, ly, lz, glb_nelv, glb_nelv,&
855 time, this%get_counter(), 1, 1, (rdcode(i), i = 1, 10)
8561 format('#std', 1x, i1, 1x, i2, 1x, i2, 1x, i2, 1x, i10, 1x, i10, &
857 1x, e20.13, 1x, i9, 1x, i6, 1x, i6, 1x, 10a)
858
859 ! Change to NEKTON's fld file format
860 fname = this%get_fld_fname()
861
862 call mpi_file_open(neko_comm, trim(fname), &
863 mpi_mode_wronly + mpi_mode_create, mpi_info_null, fh, &
864 ierr)
865
866 call mpi_file_write_all(fh, hdr, 132, mpi_character, status, ierr)
867 mpi_offset = 132 * mpi_character_size
868
869 call mpi_file_write_all(fh, test_pattern, 1, mpi_real, status, ierr)
870 mpi_offset = mpi_offset + mpi_real_size
871
872 byte_offset = mpi_offset + &
873 int(offset_el, i8) * int(mpi_integer_size, i8)
874 call mpi_file_write_at_all(fh, byte_offset, idx, nelv, &
875 mpi_integer, status, ierr)
876 mpi_offset = mpi_offset + int(glb_nelv, i8) * int(mpi_integer_size, i8)
877 deallocate(idx)
878 if (write_mesh) then
879
880 byte_offset = mpi_offset + int(offset_el, i8) * &
881 (int(gdim*lxyz, i8) * &
882 int(fld_data_size, i8))
883 call fld_file_write_vector_field_masked(this, fh, byte_offset, &
884 x%ptr, y%ptr, z%ptr, &
885 n, gdim, lxyz, nelv, lx, ly, lz, mask%get())
886 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
887 (int(gdim *lxyz, i8) * &
888 int(fld_data_size, i8))
889 end if
890 if (write_velocity) then
891 byte_offset = mpi_offset + int(offset_el, i8) * &
892 (int(gdim * (lxyz), i8) * int(fld_data_size, i8))
893 call fld_file_write_vector_field_masked(this, fh, byte_offset, &
894 u%ptr, v%ptr, w%ptr, n, gdim, lxyz, nelv, lx, ly, lz, mask%get())
895
896 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
897 (int(gdim * (lxyz), i8) * &
898 int(fld_data_size, i8))
899
900 end if
901
902 if (write_pressure) then
903 byte_offset = mpi_offset + int(offset_el, i8) * &
904 (int((lxyz), i8) * int(fld_data_size, i8))
905 call fld_file_write_field_masked(this, fh, byte_offset, p%ptr, n, mask%get())
906 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
907 (int((lxyz), i8) * int(fld_data_size, i8))
908 end if
909
910 if (write_temperature) then
911 byte_offset = mpi_offset + int(offset_el, i8) * &
912 (int((lxyz), i8) * &
913 int(fld_data_size, i8))
914 call fld_file_write_field_masked(this, fh, byte_offset, tem%ptr, n, mask%get())
915 mpi_offset = mpi_offset + int(glb_nelv, i8) * &
916 (int((lxyz), i8) * &
917 int(fld_data_size, i8))
918 end if
919
920 temp_offset = mpi_offset
921
922 do i = 1, n_scalar_fields
923 ! Without this redundant if statement Cray optimizes this loop to
924 ! Oblivion
925 if (i .eq. 2) then
926 mpi_offset = int(temp_offset, i8) + int(1_i8*glb_nelv, i8) * &
927 (int(lxyz, i8) * int(fld_data_size, i8))
928 end if
929 byte_offset = int(mpi_offset, i8) + int(offset_el, i8) * &
930 (int((lxyz), i8) * &
931 int(fld_data_size, i8))
932 call fld_file_write_field_masked(this, fh, byte_offset, scalar_fields(i)%ptr, n, mask%get())
933 mpi_offset = int(mpi_offset, i8) + int(glb_nelv, i8) * &
934 (int(lxyz, i8) * &
935 int(fld_data_size, i8))
936 end do
937
938 if (gdim .eq. 3) then
939
941 if (write_mesh) then
942 !The offset is:
943 ! mpioff + element_off * 2(min max value)
944 ! * 4(single precision) * gdim(dimensions)
945 byte_offset = int(mpi_offset, i8) + &
946 int(offset_el, i8) * &
947 int(2, i8) * &
948 int(mpi_real_size, i8) * &
949 int(gdim, i8)
950 call fld_file_write_metadata_vector_masked(this, fh, byte_offset, &
951 x%ptr, y%ptr, z%ptr, gdim, lxyz, nelv, lx, ly, lz, n, mask%get())
952 mpi_offset = int(mpi_offset, i8) + &
953 int(glb_nelv, i8) * &
954 int(2, i8) * &
955 int(mpi_real_size, i8) * &
956 int(gdim, i8)
957 end if
958
959 if (write_velocity) then
960 byte_offset = int(mpi_offset, i8) + &
961 int(offset_el, i8) * &
962 int(2, i8) * &
963 int(mpi_real_size, i8) * &
964 int(gdim, i8)
965 call fld_file_write_metadata_vector_masked(this, fh, byte_offset, &
966 u%ptr, v%ptr, w%ptr, gdim, lxyz, nelv, lx, ly, lz, n, mask%get())
967 mpi_offset = int(mpi_offset, i8) + &
968 int(glb_nelv, i8) * &
969 int(2, i8) * &
970 int(mpi_real_size, i8) * &
971 int(gdim, i8)
972
973 end if
974
975 if (write_pressure) then
976 byte_offset = int(mpi_offset, i8) + &
977 int(offset_el, i8) * &
978 int(2, i8) * &
979 int(mpi_real_size, i8)
980 call fld_file_write_metadata_scalar_masked(this, fh, byte_offset, &
981 p%ptr, lxyz, nelv, lx, ly, lz, n, mask%get())
982 mpi_offset = int(mpi_offset, i8) + &
983 int(glb_nelv, i8) * &
984 int(2, i8) * &
985 int(mpi_real_size, i8)
986
987 end if
988
989 if (write_temperature) then
990 byte_offset = int(mpi_offset, i8) + &
991 int(offset_el, i8) * &
992 int(2, i8) * &
993 int(mpi_real_size, i8)
994 call fld_file_write_metadata_scalar_masked(this, fh, byte_offset, &
995 tem%ptr, lxyz, nelv, lx, ly, lz, n, mask%get())
996 mpi_offset = int(mpi_offset, i8) + &
997 int(glb_nelv, i8) * &
998 int(2, i8) * &
999 int(mpi_real_size, i8)
1000
1001 end if
1002
1003
1004
1005 temp_offset = mpi_offset
1006
1007 do i = 1, n_scalar_fields
1008 ! Without this redundant if statement, Cray optimizes this loop to
1009 ! Oblivion
1010 if (i .eq. 2) then
1011 mpi_offset = int(temp_offset, i8) + &
1012 int(1_i8*glb_nelv, i8) * &
1013 int(2, i8) * &
1014 int(mpi_real_size, i8)
1015 end if
1016
1017 byte_offset = int(mpi_offset, i8) + &
1018 int(offset_el, i8) * &
1019 int(2, i8) * &
1020 int(mpi_real_size, i8)
1021 call fld_file_write_metadata_scalar_masked(this, fh, byte_offset, &
1022 scalar_fields(i)%ptr, lxyz, nelv, lx, ly, lz, n, mask%get())
1023 mpi_offset = int(mpi_offset, i8) + &
1024 int(glb_nelv, i8) * &
1025 int(2, i8) * &
1026 int(mpi_real_size, i8)
1027 end do
1028 end if
1029
1030
1031 call mpi_file_sync(fh, ierr)
1032 call mpi_file_close(fh, ierr)
1033 ! Write metadata file
1034 if (pe_rank .eq. 0) then
1035 call filename_name(this%get_base_fname(), name)
1036
1037 open(newunit = file_unit, &
1038 file = this%get_meta_fname(), status = 'replace')
1039 ! The following string will specify that the files in the file series
1040 ! are defined by the filename followed by a 0.
1041 ! This 0 is necessary as it specifies the index of number of files
1042 ! the output file is split across.
1043 ! In the past, many .f files were generated for each write.
1044 ! To be consistent with this the trailing 0 is still necessary today.
1045 write(file_unit, fmt = '(A,A,A)') 'filetemplate: ', &
1046 trim(name), '%01d.f%05d'
1047 write(file_unit, fmt = '(A,i5)') 'firsttimestep: ', &
1048 this%get_start_counter()
1049 write(file_unit, fmt = '(A,i5)') 'numtimesteps: ', &
1050 (this%get_counter() + 1) - this%get_start_counter()
1051 close(file_unit)
1052 end if
1053
1054 if (allocated(tmp_dp)) deallocate(tmp_dp)
1055 if (allocated(tmp_sp)) deallocate(tmp_sp)
1056 if (allocated(tempo)) deallocate(tempo)
1057 if (allocated(scalar_fields)) deallocate(scalar_fields)
1058
1059 end subroutine fld_file_write_masked
1060
1061 subroutine fld_file_write_metadata_vector(this, fh, byte_offset, x, y, z, &
1062 gdim, lxyz, nelv)
1063 class(fld_file_t), intent(inout) :: this
1064 type(mpi_file), intent(inout) :: fh
1065 integer, intent(in) :: gdim, lxyz, nelv
1066 real(kind=rp), intent(in) :: x(lxyz, nelv), y(lxyz, nelv), z(lxyz, nelv)
1067 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1068 integer :: el, j, ierr, nout
1069 type(mpi_status) :: status
1070 real(kind=sp) :: buffer(2*gdim*nelv)
1071
1072 j = 1
1073 do el = 1, nelv
1074 buffer(j+0) = real(vlmin(x(1, el), lxyz), sp)
1075 buffer(j+1) = real(vlmax(x(1, el), lxyz), sp)
1076 buffer(j+2) = real(vlmin(y(1, el), lxyz), sp)
1077 buffer(j+3) = real(vlmax(y(1, el), lxyz), sp)
1078 j = j + 4
1079 if (gdim .eq. 3) then
1080 buffer(j+0) = real(vlmin(z(1, el), lxyz), sp)
1081 buffer(j+1) = real(vlmax(z(1, el), lxyz), sp)
1082 j = j + 2
1083 end if
1084 end do
1085
1086 ! write out data
1087 nout = 2*gdim*nelv
1088
1089 call mpi_file_write_at_all(fh, byte_offset, buffer, nout, &
1090 mpi_real, status, ierr)
1091
1092 end subroutine fld_file_write_metadata_vector
1093
1094 subroutine fld_file_write_metadata_vector_masked(this, fh, byte_offset, x, y, z, &
1095 gdim, lxyz, nelv, lx, ly, lz, n, mask)
1096 class(fld_file_t), intent(inout) :: this
1097 type(mpi_file), intent(inout) :: fh
1098 integer, intent(in) :: gdim, lxyz, nelv, lx, ly, lz, n
1099 real(kind=rp), intent(in) :: x(lxyz, *), y(lxyz, *), z(lxyz, *)
1100 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1101 integer, intent(in) :: mask(n)
1102 integer :: el, j, ierr, nout, i_m, nidx(4), e_m
1103 type(mpi_status) :: status
1104 real(kind=sp) :: buffer(2*gdim*nelv)
1105
1106 j = 1
1107 do el = 1, nelv
1108 i_m = 1 + lxyz * (el - 1) ! Offset in the mask array
1109 nidx = nonlinear_index(mask(i_m), lx, ly, lz)
1110 e_m = nidx(4) ! Actual element in the field array
1111 buffer(j+0) = real(vlmin(x(1, e_m), lxyz), sp)
1112 buffer(j+1) = real(vlmax(x(1, e_m), lxyz), sp)
1113 buffer(j+2) = real(vlmin(y(1, e_m), lxyz), sp)
1114 buffer(j+3) = real(vlmax(y(1, e_m), lxyz), sp)
1115 j = j + 4
1116 if (gdim .eq. 3) then
1117 buffer(j+0) = real(vlmin(z(1, e_m), lxyz), sp)
1118 buffer(j+1) = real(vlmax(z(1, e_m), lxyz), sp)
1119 j = j + 2
1120 end if
1121 end do
1122
1123 ! write out data
1124 nout = 2*gdim*nelv
1125
1126 call mpi_file_write_at_all(fh, byte_offset, buffer, nout, &
1127 mpi_real, status, ierr)
1128
1130
1131 subroutine fld_file_write_metadata_scalar(this, fh, byte_offset, x, lxyz, &
1132 nelv)
1133 class(fld_file_t), intent(inout) :: this
1134 type(mpi_file), intent(inout) :: fh
1135 integer, intent(in) :: lxyz, nelv
1136 real(kind=rp), intent(in) :: x(lxyz, nelv)
1137 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1138 integer :: el, j, ierr, nout
1139 type(mpi_status) :: status
1140 real(kind=sp) :: buffer(2*nelv)
1141
1142 j = 1
1143 do el = 1, nelv
1144 buffer(j+0) = real(vlmin(x(1, el), lxyz), sp)
1145 buffer(j+1) = real(vlmax(x(1, el), lxyz), sp)
1146 j = j + 2
1147 end do
1148
1149 ! write out data
1150 nout = 2*nelv
1151
1152 call mpi_file_write_at_all(fh, byte_offset, buffer, nout, &
1153 mpi_real, status, ierr)
1154
1155 end subroutine fld_file_write_metadata_scalar
1156
1157 subroutine fld_file_write_metadata_scalar_masked(this, fh, byte_offset, x, lxyz, &
1158 nelv, lx, ly, lz, n, mask)
1159 class(fld_file_t), intent(inout) :: this
1160 type(mpi_file), intent(inout) :: fh
1161 integer, intent(in) :: lxyz, nelv, lx, ly, lz, n
1162 real(kind=rp), intent(in) :: x(lxyz, *)
1163 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1164 integer, intent(in) :: mask(n)
1165 integer :: el, j, ierr, nout, i_m, nidx(4), e_m
1166 type(mpi_status) :: status
1167 real(kind=sp) :: buffer(2*nelv)
1168
1169 j = 1
1170 do el = 1, nelv
1171 i_m = 1 + lxyz * (el - 1) ! Offset in the mask array
1172 nidx = nonlinear_index(mask(i_m), lx, ly, lz)
1173 e_m = nidx(4) ! Actual element in the field array
1174 buffer(j+0) = real(vlmin(x(1, e_m), lxyz), sp)
1175 buffer(j+1) = real(vlmax(x(1, e_m), lxyz), sp)
1176 j = j + 2
1177 end do
1178
1179 ! write out data
1180 nout = 2*nelv
1181
1182 call mpi_file_write_at_all(fh, byte_offset, buffer, nout, &
1183 mpi_real, status, ierr)
1184
1186
1187 subroutine fld_file_write_field(this, fh, byte_offset, p, n)
1188 class(fld_file_t), intent(inout) :: this
1189 type(mpi_file), intent(inout) :: fh
1190 integer, intent(inout) :: n
1191 real(kind=rp), intent(inout) :: p(n)
1192 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1193 integer :: i, ierr
1194 type(mpi_status) :: status
1195
1196 if ( this%dp_precision) then
1197 do i = 1, n
1198 tmp_dp(i) = real(p(i), dp)
1199 end do
1200
1201 call mpi_file_write_at_all(fh, byte_offset, tmp_dp, n, &
1202 mpi_double_precision, status, ierr)
1203 else
1204 do i = 1, n
1205 tmp_sp(i) = real(p(i), sp)
1206 end do
1207 call mpi_file_write_at_all(fh, byte_offset, tmp_sp, n, &
1208 mpi_real, status, ierr)
1209 end if
1210
1211 end subroutine fld_file_write_field
1212
1213 subroutine fld_file_write_field_masked(this, fh, byte_offset, p, n, mask)
1214 class(fld_file_t), intent(inout) :: this
1215 type(mpi_file), intent(inout) :: fh
1216 integer, intent(inout) :: n
1217 real(kind=rp), intent(inout) :: p(:)
1218 integer, intent(in) :: mask(n)
1219 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1220 integer :: i, ierr
1221 type(mpi_status) :: status
1222
1223 if ( this%dp_precision) then
1224 do i = 1, n
1225 tmp_dp(i) = real(p(mask(i)), dp)
1226 end do
1227
1228 call mpi_file_write_at_all(fh, byte_offset, tmp_dp, n, &
1229 mpi_double_precision, status, ierr)
1230 else
1231 do i = 1, n
1232 tmp_sp(i) = real(p(mask(i)), sp)
1233 end do
1234 call mpi_file_write_at_all(fh, byte_offset, tmp_sp, n, &
1235 mpi_real, status, ierr)
1236 end if
1237
1238 end subroutine fld_file_write_field_masked
1239
1240 subroutine fld_file_write_vector_field(this, fh, byte_offset, x, y, z, n, &
1241 gdim, lxyz, nelv)
1242 class(fld_file_t), intent(inout) :: this
1243 type(mpi_file), intent(inout) :: fh
1244 integer, intent(in) :: n, gdim, lxyz, nelv
1245 real(kind=rp), intent(in) :: x(lxyz, nelv), y(lxyz, nelv), z(lxyz, nelv)
1246 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1247 integer :: i, el, j, ierr
1248 type(mpi_status) :: status
1249
1250 if (this%dp_precision) then
1251 i = 1
1252 do el = 1, nelv
1253 do j = 1, lxyz
1254 tmp_dp(i) = real(x(j, el), dp)
1255 i = i +1
1256 end do
1257 do j = 1, lxyz
1258 tmp_dp(i) = real(y(j, el), dp)
1259 i = i +1
1260 end do
1261 if (gdim .eq. 3) then
1262 do j = 1, lxyz
1263 tmp_dp(i) = real(z(j, el), dp)
1264 i = i +1
1265 end do
1266 end if
1267 end do
1268 call mpi_file_write_at_all(fh, byte_offset, tmp_dp, gdim*n, &
1269 mpi_double_precision, status, ierr)
1270 else
1271 i = 1
1272 do el = 1, nelv
1273 do j = 1, lxyz
1274 tmp_sp(i) = real(x(j, el), sp)
1275 i = i +1
1276 end do
1277 do j = 1, lxyz
1278 tmp_sp(i) = real(y(j, el), sp)
1279 i = i +1
1280 end do
1281 if (gdim .eq. 3) then
1282 do j = 1, lxyz
1283 tmp_sp(i) = real(z(j, el), sp)
1284 i = i +1
1285 end do
1286 end if
1287 end do
1288 call mpi_file_write_at_all(fh, byte_offset, tmp_sp, gdim*n, &
1289 mpi_real, status, ierr)
1290 end if
1291
1292
1293 end subroutine fld_file_write_vector_field
1294
1295 subroutine fld_file_write_vector_field_masked(this, fh, byte_offset, x, y, z, n, &
1296 gdim, lxyz, nelv, lx, ly, lz, mask)
1297 class(fld_file_t), intent(inout) :: this
1298 type(mpi_file), intent(inout) :: fh
1299 integer, intent(in) :: n, gdim, lxyz, lx, ly, lz, nelv
1300 real(kind=rp), intent(in) :: x(lxyz, *), y(lxyz, *), z(lxyz, *)
1301 integer (kind=MPI_OFFSET_KIND), intent(in) :: byte_offset
1302 integer, intent(in) :: mask(n)
1303 integer :: i, el, j, ierr, i_m, e_m, nidx(4)
1304 type(mpi_status) :: status
1305
1306 if (this%dp_precision) then
1307 i = 1
1308 do el = 1, nelv
1309 i_m = 1 + lxyz * (el - 1) ! Offset in the mask array
1310 nidx = nonlinear_index(mask(i_m), lx, ly, lz)
1311 e_m = nidx(4) ! Actual element in the field array
1312 do j = 1, lxyz
1313 tmp_dp(i) = real(x(j, e_m), dp)
1314 i = i +1
1315 end do
1316 do j = 1, lxyz
1317 tmp_dp(i) = real(y(j, e_m), dp)
1318 i = i +1
1319 end do
1320 if (gdim .eq. 3) then
1321 do j = 1, lxyz
1322 tmp_dp(i) = real(z(j, e_m), dp)
1323 i = i +1
1324 end do
1325 end if
1326 end do
1327 call mpi_file_write_at_all(fh, byte_offset, tmp_dp, gdim*n, &
1328 mpi_double_precision, status, ierr)
1329 else
1330 i = 1
1331 do el = 1, nelv
1332 i_m = 1 + lxyz * (el - 1) ! Offset in the mask array
1333 nidx = nonlinear_index(mask(i_m), lx, ly, lz)
1334 e_m = nidx(4) ! Actual element in the field array
1335 do j = 1, lxyz
1336 tmp_sp(i) = real(x(j, e_m), sp)
1337 i = i +1
1338 end do
1339 do j = 1, lxyz
1340 tmp_sp(i) = real(y(j, e_m), sp)
1341 i = i +1
1342 end do
1343 if (gdim .eq. 3) then
1344 do j = 1, lxyz
1345 tmp_sp(i) = real(z(j, e_m), sp)
1346 i = i +1
1347 end do
1348 end if
1349 end do
1350 call mpi_file_write_at_all(fh, byte_offset, tmp_sp, gdim*n, &
1351 mpi_real, status, ierr)
1352 end if
1353
1354
1356
1358 subroutine fld_file_read(this, data)
1359 class(fld_file_t) :: this
1360 class(*), target, intent(inout) :: data
1361 character(len= 132) :: hdr
1362 integer :: ierr, suffix_pos, i, j
1363 type(mpi_file) :: fh
1364 type(mpi_status) :: status
1365 character(len= 1024) :: fname, base_fname, meta_fname, string, path
1366 logical :: meta_file, read_mesh, read_velocity, read_pressure
1367 logical :: read_temp
1368 character(len=6) :: suffix
1369 integer (kind=MPI_OFFSET_KIND) :: mpi_offset, byte_offset
1370 integer :: lx, ly, lz, glb_nelv, counter, lxyz
1371 integer :: FLD_DATA_SIZE, n_scalars, n
1372 integer :: file_unit
1373 real(kind=rp) :: time
1374 real(kind=sp) :: temp
1375 type(linear_dist_t) :: dist
1376 real(kind=sp), parameter :: test_pattern = 6.54321
1377 character :: rdcode(10), temp_str(4)
1378 character(len=LOG_SIZE) :: log_buf
1379
1380 select type (data)
1381 type is (fld_file_data_t)
1382 call filename_chsuffix(this%get_base_fname(), meta_fname, 'nek5000')
1383
1384 inquire(file = trim(meta_fname), exist = meta_file)
1385 if (meta_file .and. data%meta_nsamples .eq. 0) then
1386 if (pe_rank .eq. 0) then
1387 open(newunit = file_unit, file = trim(meta_fname))
1388 read(file_unit, fmt = '(A)') string
1389 read(string(14:), fmt = '(A)') string
1390 string = trim(string)
1391
1392 data%fld_series_fname = string(:scan(trim(string), '%')-1)
1393 data%fld_series_fname = adjustl(data%fld_series_fname)
1394 data%fld_series_fname = trim(data%fld_series_fname)//'0'
1395
1396 read(file_unit, fmt = '(A)') string
1397 read(string(scan(string, ':')+1:), *) data%meta_start_counter
1398 read(file_unit, fmt = '(A)') string
1399 read(string(scan(string, ':')+1:), *) data%meta_nsamples
1400 close(file_unit)
1401
1402 write(log_buf,*) 'Reading meta file for fld series'
1403 call neko_log%message(log_buf)
1404 write(log_buf,*) 'Name: ', trim(data%fld_series_fname)
1405 call neko_log%message(log_buf)
1406 write(log_buf,*) 'Start counter: ', data%meta_start_counter
1407 call neko_log%message(log_buf)
1408 write(log_buf,*) 'Nsamples: ', data%meta_nsamples
1409 call neko_log%message(log_buf)
1410
1411 end if
1412 call mpi_bcast(data%fld_series_fname, 1024, mpi_character, 0, &
1413 neko_comm, ierr)
1414 call mpi_bcast(data%meta_start_counter, 1, mpi_integer, 0, &
1415 neko_comm, ierr)
1416 call mpi_bcast(data%meta_nsamples, 1, mpi_integer, 0, &
1417 neko_comm, ierr)
1418
1419 if (this%get_counter() .eq. -1) then
1420 call this%set_start_counter(data%meta_start_counter)
1421 call this%set_counter(data%meta_start_counter)
1422 end if
1423 end if
1424
1425 if (meta_file) then
1426 call filename_path(this%get_base_fname(), path)
1427 write(suffix, '(a,i5.5)') 'f', this%get_counter()
1428 fname = trim(path) // trim(data%fld_series_fname) // '.' // suffix
1429 if (this%get_counter() .ge. &
1430 data%meta_nsamples+data%meta_start_counter) then
1431 call neko_error('Trying to read more fld files than exist')
1432 end if
1433 else
1434 write(suffix, '(a,i5.5)') 'f', this%get_counter()
1435 call filename_chsuffix(trim(this%get_base_fname()), fname, suffix)
1436 end if
1437 call mpi_file_open(neko_comm, trim(fname), &
1438 mpi_mode_rdonly, mpi_info_null, fh, ierr)
1439
1440 if (ierr .ne. 0) call neko_error("Could not read "//trim(fname))
1441
1442 call neko_log%message('Reading fld file ' // trim(fname))
1443
1444 call mpi_file_read_all(fh, hdr, 132, mpi_character, status, ierr)
1445 ! This read can prorbably be done wihtout the temp variables,
1446 ! temp_str, i, j
1447
1448 read(hdr, 1) temp_str, fld_data_size, lx, ly, lz, glb_nelv, glb_nelv, &
1449 time, counter, i, j, (rdcode(i), i = 1, 10)
14501 format(4a, 1x, i1, 1x, i2, 1x, i2, 1x, i2, 1x, i10, 1x, i10, &
1451 1x, e20.13, 1x, i9, 1x, i6, 1x, i6, 1x, 10a)
1452 if (data%nelv .eq. 0) then
1453 dist = linear_dist_t(glb_nelv, pe_rank, pe_size, neko_comm)
1454 data%nelv = dist%num_local()
1455 data%offset_el = dist%start_idx()
1456 end if
1457 data%lx = lx
1458 data%ly = ly
1459 data%lz = lz
1460 data%glb_nelv = glb_nelv
1461 data%t_counter = counter
1462 data%time = time
1463 lxyz = lx * ly * lz
1464 n = lxyz * data%nelv
1465
1466 if (lz .eq. 1) then
1467 data%gdim = 2
1468 else
1469 data%gdim = 3
1470 end if
1471
1472
1473 if (fld_data_size .eq. mpi_double_precision_size) then
1474 this%dp_precision = .true.
1475 else
1476 this%dp_precision = .false.
1477 end if
1478 if (this%dp_precision) then
1479 allocate(tmp_dp(data%gdim*n))
1480 else
1481 allocate(tmp_sp(data%gdim*n))
1482 end if
1483
1484
1485 i = 1
1486 read_mesh = .false.
1487 read_velocity = .false.
1488 read_pressure = .false.
1489 read_temp = .false.
1490 if (rdcode(i) .eq. 'X') then
1491 read_mesh = .true.
1492 call data%x%init(n)
1493 call data%y%init(n)
1494 call data%z%init(n)
1495 i = i + 1
1496 end if
1497 if (rdcode(i) .eq. 'U') then
1498 read_velocity = .true.
1499 call data%u%init(n)
1500 call data%v%init(n)
1501 call data%w%init(n)
1502 i = i + 1
1503 end if
1504 if (rdcode(i) .eq. 'P') then
1505 read_pressure = .true.
1506 call data%p%init(n)
1507 i = i + 1
1508 end if
1509 if (rdcode(i) .eq. 'T') then
1510 read_temp = .true.
1511 call data%t%init(n)
1512 i = i + 1
1513 end if
1514 n_scalars = 0
1515 if (rdcode(i) .eq. 'S') then
1516 i = i + 1
1517 read(rdcode(i),*) n_scalars
1518 n_scalars = n_scalars*10
1519 i = i + 1
1520 read(rdcode(i),*) j
1521 n_scalars = n_scalars+j
1522 i = i + 1
1523 if (allocated(data%s)) then
1524 if (data%n_scalars .ne. n_scalars) then
1525 do j = 1, data%n_scalars
1526 call data%s(j)%free()
1527 end do
1528 deallocate(data%s)
1529 data%n_scalars = n_scalars
1530 allocate(data%s(n_scalars))
1531 do j = 1, data%n_scalars
1532 call data%s(j)%init(n)
1533 end do
1534 end if
1535 else
1536 data%n_scalars = n_scalars
1537 allocate(data%s(data%n_scalars))
1538 do j = 1, data%n_scalars
1539 call data%s(j)%init(n)
1540 end do
1541 end if
1542 i = i + 1
1543 end if
1544
1545 mpi_offset = 132 * mpi_character_size
1546 call mpi_file_read_at_all(fh, mpi_offset, temp, 1, &
1547 mpi_real, status, ierr)
1548 if (.not. sabscmp(temp, test_pattern, epsilon(1.0_sp))) then
1549 call neko_error('Incorrect format for fld file, &
1550 &test pattern does not match.')
1551 end if
1552 mpi_offset = mpi_offset + mpi_real_size
1553
1554
1555 if (allocated(data%idx)) then
1556 if (size(data%idx) .ne. data%nelv) then
1557 deallocate(data%idx)
1558 allocate(data%idx(data%nelv))
1559 end if
1560 else
1561 allocate(data%idx(data%nelv))
1562 end if
1563
1564 byte_offset = mpi_offset + &
1565 int(data%offset_el, i8) * int(mpi_integer_size, i8)
1566
1567 call mpi_file_read_at_all(fh, byte_offset, data%idx, data%nelv, &
1568 mpi_integer, status, ierr)
1569
1570 mpi_offset = mpi_offset + &
1571 int(data%glb_nelv, i8) * int(mpi_integer_size, i8)
1572
1573 if (read_mesh) then
1574 byte_offset = mpi_offset + int(data%offset_el, i8) * &
1575 (int(data%gdim*lxyz, i8) * &
1576 int(fld_data_size, i8))
1577 call fld_file_read_vector_field(this, fh, byte_offset, &
1578 data%x, data%y, data%z, data)
1579 mpi_offset = mpi_offset + int(data%glb_nelv, i8) * &
1580 (int(data%gdim *lxyz, i8) * &
1581 int(fld_data_size, i8))
1582 end if
1583
1584 if (read_velocity) then
1585 byte_offset = mpi_offset + int(data%offset_el, i8) * &
1586 (int(data%gdim*lxyz, i8) * &
1587 int(fld_data_size, i8))
1588 call fld_file_read_vector_field(this, fh, byte_offset, &
1589 data%u, data%v, data%w, data)
1590 mpi_offset = mpi_offset + int(data%glb_nelv, i8) * &
1591 (int(data%gdim *lxyz, i8) * &
1592 int(fld_data_size, i8))
1593 end if
1594
1595 if (read_pressure) then
1596 byte_offset = mpi_offset + int(data%offset_el, i8) * &
1597 (int(lxyz, i8) * &
1598 int(fld_data_size, i8))
1599 call fld_file_read_field(this, fh, byte_offset, data%p, data)
1600 mpi_offset = mpi_offset + int(data%glb_nelv, i8) * &
1601 (int(lxyz, i8) * &
1602 int(fld_data_size, i8))
1603 end if
1604
1605 if (read_temp) then
1606 byte_offset = mpi_offset + int(data%offset_el, i8) * &
1607 (int(lxyz, i8) * &
1608 int(fld_data_size, i8))
1609 call fld_file_read_field(this, fh, byte_offset, data%t, data)
1610 mpi_offset = mpi_offset + int(data%glb_nelv, i8) * &
1611 (int(lxyz, i8) * &
1612 int(fld_data_size, i8))
1613 end if
1614
1615 do i = 1, n_scalars
1616 byte_offset = mpi_offset + int(data%offset_el, i8) * &
1617 (int(lxyz, i8) * &
1618 int(fld_data_size, i8))
1619 call fld_file_read_field(this, fh, byte_offset, data%s(i), data)
1620 mpi_offset = mpi_offset + int(data%glb_nelv, i8) * &
1621 (int(lxyz, i8) * &
1622 int(fld_data_size, i8))
1623 end do
1624
1625 call device_sync()
1626 call this%increment_counter()
1627
1628 if (allocated(tmp_dp)) deallocate(tmp_dp)
1629 if (allocated(tmp_sp)) deallocate(tmp_sp)
1630 class default
1631 call neko_error('Currently we only read into fld_file_data_t, &
1632 &please use that data structure instead.')
1633 end select
1634
1635 end subroutine fld_file_read
1636
1637 subroutine fld_file_read_field(this, fh, byte_offset, x, fld_data)
1638 class(fld_file_t), intent(inout) :: this
1639 type(vector_t), intent(inout) :: x
1640 type(fld_file_data_t) :: fld_data
1641 integer(kind=MPI_OFFSET_KIND) :: byte_offset
1642 type(mpi_file) :: fh
1643 type(mpi_status) :: status
1644 integer :: n, ierr, lxyz, i
1645
1646 n = x%size()
1647 lxyz = fld_data%lx * fld_data%ly * fld_data%lz
1648
1649 if (this%dp_precision) then
1650 call mpi_file_read_at_all(fh, byte_offset, tmp_dp, n, &
1651 mpi_double_precision, status, ierr)
1652 else
1653 call mpi_file_read_at_all(fh, byte_offset, tmp_sp, n, &
1654 mpi_real, status, ierr)
1655 end if
1656
1657 if (this%dp_precision) then
1658 do i = 1, n
1659 x%x(i) = tmp_dp(i)
1660 end do
1661 else
1662 do i = 1, n
1663 x%x(i) = tmp_sp(i)
1664 end do
1665 end if
1666
1667 call x%copy_from(host_to_device, sync = .false.)
1668
1669 end subroutine fld_file_read_field
1670
1671
1672 subroutine fld_file_read_vector_field(this, fh, byte_offset, &
1673 x, y, z, fld_data)
1674 class(fld_file_t), intent(inout) :: this
1675 type(vector_t), intent(inout) :: x, y, z
1676 type(fld_file_data_t) :: fld_data
1677 integer(kind=MPI_OFFSET_KIND) :: byte_offset
1678 type(mpi_file) :: fh
1679 type(mpi_status) :: status
1680 integer :: n, ierr, lxyz, i, j, e, nd
1681
1682 n = x%size()
1683 nd = n*fld_data%gdim
1684 lxyz = fld_data%lx*fld_data%ly*fld_data%lz
1685
1686 if (this%dp_precision) then
1687 call mpi_file_read_at_all(fh, byte_offset, tmp_dp, nd, &
1688 mpi_double_precision, status, ierr)
1689 else
1690 call mpi_file_read_at_all(fh, byte_offset, tmp_sp, nd, &
1691 mpi_real, status, ierr)
1692 end if
1693
1694
1695 if (this%dp_precision) then
1696 i = 1
1697 do e = 1, fld_data%nelv
1698 do j = 1, lxyz
1699 x%x((e-1)*lxyz+j) = tmp_dp(i)
1700 i = i + 1
1701 end do
1702 do j = 1, lxyz
1703 y%x((e-1)*lxyz+j) = tmp_dp(i)
1704 i = i + 1
1705 end do
1706 if (fld_data%gdim .eq. 3) then
1707 do j = 1, lxyz
1708 z%x((e-1)*lxyz+j) = tmp_dp(i)
1709 i = i + 1
1710 end do
1711 end if
1712 end do
1713 else
1714 i = 1
1715 do e = 1, fld_data%nelv
1716 do j = 1, lxyz
1717 x%x((e-1)*lxyz+j) = tmp_sp(i)
1718 i = i +1
1719 end do
1720 do j = 1, lxyz
1721 y%x((e-1)*lxyz+j) = tmp_sp(i)
1722 i = i +1
1723 end do
1724 if (fld_data%gdim .eq. 3) then
1725 do j = 1, lxyz
1726 z%x((e-1)*lxyz+j) = tmp_sp(i)
1727 i = i +1
1728 end do
1729 end if
1730 end do
1731 end if
1732
1733 call x%copy_from(host_to_device, sync = .false.)
1734 call y%copy_from(host_to_device, sync = .false.)
1735 if (fld_data%gdim .eq. 3) then
1736 call z%copy_from(host_to_device, sync = .false.)
1737 end if
1738
1739 end subroutine fld_file_read_vector_field
1740
1741 subroutine fld_file_set_precision(this, precision)
1742 class(fld_file_t) :: this
1743 integer, intent(in) :: precision
1744
1745 if (precision .eq. dp) then
1746 this%dp_precision = .true.
1747 else if (precision .eq. sp) then
1748 this%dp_precision = .false.
1749 else
1750 call neko_error('Invalid precision')
1751 end if
1752
1753 end subroutine fld_file_set_precision
1754
1755 subroutine fld_file_set_mask(this, mask)
1756 class(fld_file_t) :: this
1757 type(mask_t), intent(inout), optional :: mask
1758
1759 if (present(mask)) then
1760 call this%mask%init_from_mask(mask)
1761 else
1762 call this%mask%free()
1763 end if
1764
1765 end subroutine fld_file_set_mask
1766
1767 function fld_file_get_fld_fname(this) result(fname)
1768 class(fld_file_t), intent(in) :: this
1769 character(len=1024) :: fname
1770 integer :: counter
1771
1772 counter = this%get_counter()
1773 fname = fld_file_format_fname(this, counter)
1774
1775 end function fld_file_get_fld_fname
1776
1780 function fld_file_get_next_output_fname(this) result(fname)
1781 class(fld_file_t), intent(in) :: this
1782 character(len=1024) :: fname
1783 integer :: counter
1784
1785 counter = this%get_counter()
1786 if (counter .eq. -1) then
1787 counter = this%get_start_counter()
1788 else
1789 counter = counter + 1
1790 end if
1791
1792 fname = fld_file_format_fname(this, counter)
1793
1795
1797 function fld_file_format_fname(this, counter) result(fname)
1798 class(fld_file_t), intent(in) :: this
1799 integer, intent(in) :: counter
1800 character(len=1024) :: fname
1801 character(len=1024) :: path, name
1802
1803 call filename_path(this%get_base_fname(), path)
1804 call filename_name(this%get_base_fname(), name)
1805
1806 write(fname, '(a,a,a,i5.5)') trim(path), trim(name), '0.f', counter
1807
1808 end function fld_file_format_fname
1809
1810 function fld_file_get_meta_fname(this) result(fname)
1811 class(fld_file_t), intent(in) :: this
1812 character(len=1024) :: fname
1813 character(len=1024) :: path, name, id_str
1814
1815 call filename_path(this%get_base_fname(), path)
1816 call filename_name(this%get_base_fname(), name)
1817
1818 write(id_str, '(i5,a)') this%get_start_counter(), '.nek5000'
1819 write(fname, '(a,a,a)') trim(path), trim(name), trim(adjustl(id_str))
1820
1821 end function fld_file_get_meta_fname
1822
1823end module fld_file
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
double real
Synchronize a device or stream.
Definition device.F90:119
Generic buffer that is extended with buffers of varying rank.
Definition buffer.F90:34
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
integer, public pe_rank
MPI rank.
Definition comm.F90:59
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
Defines practical data distributions.
Definition datadist.f90:34
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
Module for file I/O operations.
Definition file.f90:34
Simple module to handle fld file series. Provides an interface to the different fields sotred in a fl...
NEKTON fld file format.
Definition fld_file.f90:35
character(len=1024) function fld_file_get_next_output_fname(this)
Get the physical file name generated by the next write. The fld writer increments its counter during ...
subroutine fld_file_write_metadata_vector_masked(this, fh, byte_offset, x, y, z, gdim, lxyz, nelv, lx, ly, lz, n, mask)
subroutine fld_file_write_field_masked(this, fh, byte_offset, p, n, mask)
character(len=1024) function fld_file_get_fld_fname(this)
real(kind=dp), dimension(:), allocatable, private tmp_dp
Definition fld_file.f90:62
subroutine fld_file_select_from_field_list(this, data, p, u, v, w, tem, scalar_fields, n_scalar_fields, write_pressure, write_velocity, write_temperature, dof)
Map a field_list_t to fld file output slots.
Definition fld_file.f90:107
subroutine fld_file_write_vector_field_masked(this, fh, byte_offset, x, y, z, n, gdim, lxyz, nelv, lx, ly, lz, mask)
subroutine fld_file_set_precision(this, precision)
subroutine fld_file_read_vector_field(this, fh, byte_offset, x, y, z, fld_data)
subroutine fld_file_write_metadata_scalar_masked(this, fh, byte_offset, x, lxyz, nelv, lx, ly, lz, n, mask)
subroutine fld_file_write_manager(this, data, t)
Manage writer to use.
Definition fld_file.f90:166
subroutine fld_file_read(this, data)
Load a field from a NEKTON fld file.
subroutine fld_file_write_vector_field(this, fh, byte_offset, x, y, z, n, gdim, lxyz, nelv)
subroutine fld_file_set_mask(this, mask)
character(len=1024) function fld_file_get_meta_fname(this)
subroutine fld_file_write_masked(this, data, mask, t)
Write fields to a NEKTON fld file from a masked array.
Definition fld_file.f90:612
subroutine fld_file_write_metadata_vector(this, fh, byte_offset, x, y, z, gdim, lxyz, nelv)
real(kind=sp), dimension(:), allocatable, private tmp_sp
Definition fld_file.f90:63
subroutine fld_file_read_field(this, fh, byte_offset, x, fld_data)
subroutine fld_file_write_field(this, fh, byte_offset, p, n)
character(len=1024) function fld_file_format_fname(this, counter)
Format the physical file name for a counter value.
subroutine fld_file_write_metadata_scalar(this, fh, byte_offset, x, lxyz, nelv)
subroutine fld_file_write(this, data, t)
Write fields to a NEKTON fld file.
Definition fld_file.f90:181
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.f90:60
pure logical function, public sabscmp(x, y, tol)
Return single precision absolute comparison .
Definition math.f90:120
real(kind=rp) function, public vlmin(vec, n)
minimun value of a vector of length n
Definition math.f90:755
real(kind=rp) function, public vlmax(vec, n)
maximum value of a vector of length n
Definition math.f90:740
Defines a mesh.
Definition mesh.f90:34
MPI derived types.
Definition mpi_types.f90:34
integer, public mpi_double_precision_size
Size of MPI type double precision.
Definition mpi_types.f90:66
integer, public mpi_character_size
Size of MPI type character.
Definition mpi_types.f90:67
integer, public mpi_real_size
Size of MPI type real.
Definition mpi_types.f90:65
integer, public mpi_integer_size
Size of MPI type integer.
Definition mpi_types.f90:68
integer, parameter, public i2
Definition num_types.f90:5
integer, parameter, public i8
Definition num_types.f90:7
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a function space.
Definition space.f90:34
Defines structs that are used... Dont know if we should keep it though.
Definition structs.f90:2
Utilities.
Definition utils.f90:35
subroutine, public filename_name(fname, name)
Extract the base name of a file (without path and suffix)
Definition utils.f90:103
subroutine, public filename_chsuffix(fname, new_fname, new_suffix)
Change a filename's suffix.
Definition utils.f90:156
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition utils.f90:74
subroutine, public filename_path(fname, path)
Extract the path to a file.
Definition utils.f90:88
Defines a vector.
Definition vector.f90:34
Load-balanced linear distribution .
Definition datadist.f90:50
field_list_t, To be able to group fields together
Interface for NEKTON fld files.
Definition fld_file.f90:66
A generic file handler.
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51
The function space for the SEM solution fields.
Definition space.f90:64
Pointer to array.
Definition structs.f90:14