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