Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fld_file_data.f90
Go to the documentation of this file.
1
9 use num_types, only : rp, dp
10 use math, only : cmult, add2
11 use vector, only : vector_t, vector_ptr_t
13 use field, only : field_t
14 use field_list, only : field_list_t
15 use logger, only : neko_log, log_size
16 use device, only : host_to_device
17 use dofmap, only : dofmap_t
19 use json_module, only : json_file
20 use space, only : space_t, gll
24 use mesh, only : mesh_t
25 implicit none
26 private
27
28 type, public :: fld_file_data_t
29 type(vector_t) :: x
30 type(vector_t) :: y
31 type(vector_t) :: z
32 type(vector_t) :: u
33 type(vector_t) :: v
34 type(vector_t) :: w
35 type(vector_t) :: p
36 type(vector_t) :: t
37 integer, allocatable :: idx(:)
38 type(vector_t), allocatable :: s(:)
39 integer :: gdim
40 integer :: n_scalars = 0
41 real(kind=rp) :: time = 0.0
42 integer :: glb_nelv = 0
43 integer :: nelv = 0
44 integer :: offset_el = 0
45 integer :: lx = 0
46 integer :: ly = 0
47 integer :: lz = 0
48 integer :: t_counter = 0
49 ! meta file information (if any)
51 integer :: meta_nsamples = 0
52 integer :: meta_start_counter = 0
54 character(len=1024) :: fld_series_fname
55 contains
56 procedure, pass(this) :: init => fld_file_data_init
57 procedure, pass(this) :: free => fld_file_data_free
58 procedure, pass(this) :: scale => fld_file_data_scale
59 procedure, pass(this) :: add => fld_file_data_add
60 procedure, pass(this) :: size => fld_file_data_size
61 procedure, pass(this) :: get_list => fld_file_data_get_list
62 procedure, pass(this) :: init_same => fld_file_data_init_same
63 procedure, pass(this) :: init_n_fields => fld_file_data_init_n_fields
65 procedure, pass(this) :: generate_interpolator => &
68 procedure, pass(this) :: import_fields => fld_file_data_import_fields
69 end type fld_file_data_t
70
71contains
72
106 subroutine fld_file_data_import_fields(this, u, v, w, p, t, &
107 s_target_list, s_index_list, interpolate, tolerance, padding, &
108 global_interp_subdict)
109 class(fld_file_data_t), intent(inout) :: this
110 type(field_t), pointer, intent(inout), optional :: u,v,w,p,t
111 type(field_list_t), intent(inout), optional :: s_target_list
112 integer, intent(in), optional :: s_index_list(:)
113 logical, intent(in), optional :: interpolate
114 real(kind=dp), intent(in), optional :: tolerance
115 real(kind=dp), intent(in), optional :: padding
116 type(json_file), intent(inout), optional :: global_interp_subdict
117
118 integer :: i
119
120 ! ---- For the mesh to mesh interpolation
121 logical :: mesh_mismatch
122 logical :: interpolate_
123 type(global_interpolation_t) :: global_interp
124 type(dofmap_t), pointer :: dof
125 type(mesh_t) , pointer :: msh
126 ! -----
127
128 ! ---- For space to space interpolation
129 type(space_t) :: prev_Xh
130 type(space_t) , pointer :: Xh
131 type(interpolator_t) :: space_interp
132 ! ----
133
134 character(len=LOG_SIZE) :: log_buf
135
136 ! ---- Default values
137 interpolate_ = .false.
138 if (present(interpolate)) interpolate_ = interpolate
139 ! ----
140
141 !
142 ! Handle the passing of arguments and pointers
143 !
144 dof => null()
145 msh => null()
146 xh => null()
147
148 if (present(u)) then
149 dof => u%dof; msh => u%msh; xh => u%Xh
150 else if (present(v)) then
151 dof => v%dof; msh => v%msh; xh => v%Xh
152 else if (present(w)) then
153 dof => w%dof; msh => w%msh; xh => w%Xh
154 else if (present(p)) then
155 dof => p%dof; msh => p%msh; xh => p%Xh
156 else if (present(t)) then
157 dof => t%dof; msh => t%msh; xh => t%Xh
158 else if (present(s_target_list)) then
159 if (s_target_list%size() .eq. 0) then
160 call neko_error("Scalar target list is empty")
161 else
162 dof => s_target_list%items(1)%ptr%dof
163 msh => s_target_list%items(1)%ptr%msh
164 xh => s_target_list%items(1)%ptr%Xh
165 end if
166 else
167 call neko_error("At least one field must be passed")
168 end if
169
170 !
171 ! Check that the data in the fld file matches the current case.
172 ! Note that this is a safeguard and there are corner cases where
173 ! two different meshes have the same dimension and same # of elements
174 ! but this should be enough to cover obvious cases.
175 !
176 mesh_mismatch = (this%glb_nelv .ne. msh%glb_nelv .or. &
177 this%gdim .ne. msh%gdim)
178
179 if (mesh_mismatch .and. .not. interpolate_) then
180 call neko_error("The fld file must match the current mesh! " // &
181 "Use 'interpolate': 'true' to enable interpolation.")
182 else if (.not. mesh_mismatch .and. interpolate_) then
183 call neko_log%warning("You have activated interpolation but you " // &
184 "might still be using the same mesh.")
185 end if
186
187 !
188 ! Handling of interpolation and I/O
189 !
190 if (interpolate_) then
191
192 ! Throw error if dof or msh are not specified
193 ! This should never be thrown, but just in case.
194 if (.not. associated(dof) .or. .not. associated(msh)) then
195 call neko_error("both dof and msh must be associated")
196 end if
197
198 ! Generates an interpolator object and performs the point search
199 ! NOTE: optional arguments are managed in the subroutine, but if both
200 ! are provided the JSON subdict takes precedence
201 call this%generate_interpolator(global_interp, dof, msh, &
202 tolerance = tolerance, padding = padding, &
203 global_interp_subdict = global_interp_subdict)
204
205 ! Evaluate all the fields
206 if (present(u)) call global_interp%evaluate(u%x(:,1,1,1), this%u%x, &
207 on_host = .false.)
208 if (present(v)) call global_interp%evaluate(v%x(:,1,1,1), this%v%x, &
209 on_host = .false.)
210 if (present(w)) call global_interp%evaluate(w%x(:,1,1,1), this%w%x, &
211 on_host = .false.)
212 if (present(p)) call global_interp%evaluate(p%x(:,1,1,1), this%p%x, &
213 on_host = .false.)
214 if (present(t)) call global_interp%evaluate(t%x(:,1,1,1), this%t%x, &
215 on_host = .false.)
216 if (present(s_target_list)) then
217
218 ! If the index list exists, use it as a "mask"
219 if (present(s_index_list)) then
220 do i = 1, size(s_index_list)
221 ! Take care that if we set i=0 we want temperature
222 if (s_index_list(i) .eq. 0) then
223 call global_interp%evaluate(s_target_list%x(i), &
224 this%t%x, on_host = .false.)
225 else if (s_index_list(i) .ge. 1 .and. &
226 s_index_list(i) .le. this%n_scalars) then
227 call global_interp%evaluate(s_target_list%x(i), &
228 this%s(s_index_list(i))%x, on_host = .false.)
229 else
230 call neko_error("s_index_list entry out of bounds")
231 end if
232 end do
233
234 ! otherwise, just copy element-to-element
235 else
236 do i = 1, s_target_list%size()
237 call global_interp%evaluate(s_target_list%x(i), this%s(i)%x, &
238 on_host = .false.)
239 end do
240 end if ! present s_index_list
241 end if ! present s_tgt
242
243 call global_interp%free()
244
245 else ! No interpolation, but potentially just from different spaces
246
247 ! throw an error is the space is not passed
248 if (.not. associated(xh)) call neko_error("Xh is not associated")
249
250 ! Build a space_t object from the data in the fld file
251 call prev_xh%init(gll, this%lx, this%ly, this%lz)
252 call space_interp%init(xh, prev_xh)
253
254 ! Do the space-to-space interpolation
255 if (present(u)) call space_interp%map(u%x, this%u%x, this%nelv, xh)
256 if (present(v)) call space_interp%map(v%x, this%v%x, this%nelv, xh)
257 if (present(w)) call space_interp%map(w%x, this%w%x, this%nelv, xh)
258 if (present(p)) call space_interp%map(p%x, this%p%x, this%nelv, xh)
259 if (present(t)) call space_interp%map(t%x, this%t%x, this%nelv, xh)
260 if (present(s_target_list)) then
261
262 ! If the index list exists, use it as a "mask"
263 if (present(s_index_list)) then
264 do i = 1, size(s_index_list)
265
266 ! 0 means we want temperature
267 if (s_index_list(i) .eq. 0) then
268 call space_interp%map(s_target_list%x(i), &
269 this%t%x, this%nelv, xh)
270 else if (s_index_list(i) .ge. 1 .and. &
271 s_index_list(i) .le. this%n_scalars) then
272 call space_interp%map(s_target_list%x(i), &
273 this%s(s_index_list(i))%x, this%nelv, xh)
274 else
275 call neko_error("s_index_list entry out of bounds")
276 end if
277 end do
278
279 ! otherwise, just copy element-to-element
280 else
281 do i = 1, s_target_list%size()
282 call space_interp%map(s_target_list%x(i), this%s(i)%x, &
283 this%nelv, xh)
284 end do
285 end if ! present s_index_list
286 end if ! present s_tgt
287
288 call space_interp%free
289 call prev_xh%free
290
291 end if ! if interpolate
292
293 nullify(dof)
294 nullify(xh)
295 nullify(msh)
296
297 end subroutine fld_file_data_import_fields
298
302 subroutine fld_file_data_init(this, nelv, offset_el)
303 class(fld_file_data_t), intent(inout) :: this
304 integer, intent(in), optional :: nelv, offset_el
305
306 call this%free()
307 if (present(nelv)) this%nelv = nelv
308 if (present(offset_el)) this%offset_el = offset_el
309
310 end subroutine fld_file_data_init
311
313 function fld_file_data_size(this) result(i)
314 class(fld_file_data_t) :: this
315 integer :: i
316 i = 0
317 if (this%u%size() .gt. 0) i = i + 1
318 if (this%v%size() .gt. 0) i = i + 1
319 if (this%w%size() .gt. 0) i = i + 1
320 if (this%p%size() .gt. 0) i = i + 1
321 if (this%t%size() .gt. 0) i = i + 1
322 i = i + this%n_scalars
323
324 end function fld_file_data_size
325
327 subroutine fld_file_data_init_same(this, fld_file, n)
328 class(fld_file_data_t), target, intent(inout) :: this
329 class(fld_file_data_t), target, intent(in) :: fld_file
330 integer, intent(in) :: n
331 integer :: i, j
332
333 if (fld_file%u%size() .gt. 0) then
334 call this%u%init(n)
335 end if
336 if (fld_file%v%size() .gt. 0) then
337 call this%v%init(n)
338 end if
339 if (fld_file%w%size() .gt. 0) then
340 call this%w%init(n)
341 end if
342 if (fld_file%p%size() .gt. 0) then
343 call this%p%init(n)
344 end if
345 if (fld_file%t%size() .gt. 0) then
346 call this%t%init(n)
347 end if
348 this%n_scalars = fld_file%n_scalars
349 allocate(this%s(fld_file%n_scalars))
350 do j = 1, fld_file%n_scalars
351 call this%s(j)%init(n)
352 end do
353
354 end subroutine fld_file_data_init_same
355
357 subroutine fld_file_data_init_n_fields(this, n_fields, n)
358 class(fld_file_data_t), target, intent(inout) :: this
359 integer, intent(in) :: n, n_fields
360 integer :: i, j
361
362
363 if (n_fields .gt. 0) then
364 call this%u%init(n)
365 end if
366 if (n_fields .gt. 1) then
367 call this%v%init(n)
368 end if
369 if (n_fields .gt. 2) then
370 call this%w%init(n)
371 end if
372 if (n_fields .gt. 3) then
373 call this%p%init(n)
374 end if
375 if (n_fields .gt. 4) then
376 call this%t%init(n)
377 end if
378 if (n_fields .gt. 5) then
379 this%n_scalars = n_fields-5
380 allocate(this%s(this%n_scalars))
381 do j = 1, this%n_scalars
382 call this%s(j)%init(n)
383 end do
384 end if
385
386 end subroutine fld_file_data_init_n_fields
387
389 subroutine fld_file_data_get_list(this, ptr_list, n)
390 class(fld_file_data_t), target, intent(in) :: this
391 integer, intent(in) :: n
392 integer :: i, j
393 type(vector_ptr_t), intent(inout) :: ptr_list(n)
394 i = 1
395 if (this%u%size() .gt. 0) then
396 ptr_list(i)%ptr => this%u
397 i = i + 1
398 end if
399 if (this%v%size() .gt. 0) then
400 ptr_list(i)%ptr => this%v
401 i = i + 1
402 end if
403 if (this%w%size() .gt. 0) then
404 ptr_list(i)%ptr => this%w
405 i = i + 1
406 end if
407 if (this%p%size() .gt. 0) then
408 ptr_list(i)%ptr => this%p
409 i = i + 1
410 end if
411 if (this%t%size() .gt. 0) then
412 ptr_list(i)%ptr => this%t
413 i = i + 1
414 end if
415 do j = 1, this%n_scalars
416 ptr_list(i)%ptr => this%s(j)
417 i = i +1
418 end do
419
420 end subroutine fld_file_data_get_list
421
422
423
425 subroutine fld_file_data_scale(this, c)
426 class(fld_file_data_t), intent(inout) :: this
427 real(kind=rp), intent(in) :: c
428 integer :: i
429
430 if (this%u%size() .gt. 0) call cmult(this%u%x, c, this%u%size())
431 if (this%v%size() .gt. 0) call cmult(this%v%x, c, this%v%size())
432 if (this%w%size() .gt. 0) call cmult(this%w%x, c, this%w%size())
433 if (this%p%size() .gt. 0) call cmult(this%p%x, c, this%p%size())
434 if (this%t%size() .gt. 0) call cmult(this%t%x, c, this%t%size())
435
436 do i = 1, this%n_scalars
437 if (this%s(i)%size() .gt. 0) call cmult(this%s(i)%x, c, this%s(i)%size())
438 end do
439
440 end subroutine fld_file_data_scale
441
443 subroutine fld_file_data_add(this, other)
444 class(fld_file_data_t), intent(inout) :: this
445 class(fld_file_data_t), intent(in) :: other
446 integer :: i, n
447
448 if (this%u%size() .gt. 0) call add2(this%u%x, other%u%x, this%u%size())
449 if (this%v%size() .gt. 0) call add2(this%v%x, other%v%x, this%v%size())
450 if (this%w%size() .gt. 0) call add2(this%w%x, other%w%x, this%w%size())
451 if (this%p%size() .gt. 0) call add2(this%p%x, other%p%x, this%p%size())
452 if (this%t%size() .gt. 0) call add2(this%t%x, other%t%x, this%t%size())
453
454 do i = 1, this%n_scalars
455 if (this%s(i)%size() .gt. 0) call add2(this%s(i)%x, other%s(i)%x, &
456 this%s(i)%size())
457 end do
458 end subroutine fld_file_data_add
459
461 subroutine fld_file_data_free(this)
462 class(fld_file_data_t), intent(inout) :: this
463 integer :: i
464 call this%x%free()
465 call this%y%free()
466 call this%z%free()
467 call this%u%free()
468 call this%v%free()
469 call this%w%free()
470 call this%p%free()
471 call this%t%free()
472 if (allocated(this%s)) then
473 do i = 1, this%n_scalars
474 call this%s(i)%free()
475 end do
476 deallocate(this%s)
477 end if
478 this%n_scalars = 0
479 this%time = 0.0
480 this%glb_nelv = 0
481 this%nelv = 0
482 this%offset_el = 0
483 this%lx = 0
484 this%ly = 0
485 this%lz = 0
486 this%t_counter = 0
487 this%meta_nsamples = 0
488 this%meta_start_counter = 0
489 if (allocated(this%idx)) deallocate(this%idx)
490 end subroutine fld_file_data_free
491
502 subroutine fld_file_data_generate_interpolator(this, global_interp, to_dof, &
503 to_msh, tolerance, padding, global_interp_subdict)
504 class(fld_file_data_t), intent(in) :: this
505 type(global_interpolation_t), intent(inout) :: global_interp
506 type(dofmap_t), intent(in), target :: to_dof
507 type(mesh_t), intent(in), target :: to_msh
508 real(kind=dp), intent(in), optional :: tolerance
509 real(kind=dp), intent(in), optional :: padding
510 type(json_file), intent(inout), optional :: global_interp_subdict
511
512 ! --- variables for interpolation
513 type(space_t) :: fld_Xh
514 real(kind=rp), allocatable :: x_coords(:,:,:,:), y_coords(:,:,:,:), &
515 z_coords(:,:,:,:)
516 real(kind=rp) :: center_x, center_y, center_z
517 integer :: e, i
518 real(kind=rp) :: tol_ = glob_interp_tol
519 ! ---
520
521 type(space_t), pointer :: to_xh
522 to_xh => to_dof%Xh
523
524 ! Safeguard in case we didn't read mesh information
525 if (.not. allocated(this%x%x) .or. &
526 .not. allocated(this%y%x) .or. &
527 .not. allocated(this%z%x)) call neko_error("Unable to retrieve &
528 &mesh information from fld data.")
529
530 ! Create a space based on the fld data
531 call fld_xh%init(gll, this%lx, this%ly, this%lz)
532
533 ! These are the coordinates of our current dofmap
534 ! that we use for the interpolation
535 allocate(x_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
536 allocate(y_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
537 allocate(z_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
538
539 ! JSON subdict takes precedence over dummy argument, but if neither is
540 ! provided throw an error
541 if (present(global_interp_subdict)) then
542 call json_get_or_default(global_interp_subdict, "tolerance", tol_, &
543 tol_)
544 else if (present(tolerance)) then
545 tol_ = tolerance
546 else
547 call neko_error("No tolerance provided for interpolation! " // &
548 "Please provide a tolerance or a subdict with a tolerance entry.")
549 end if
550
555 do e = 1, to_msh%nelv
556 center_x = 0d0
557 center_y = 0d0
558 center_z = 0d0
559 do i = 1, to_xh%lxyz
560 center_x = center_x + to_dof%x(i, 1, 1, e)
561 center_y = center_y + to_dof%y(i, 1, 1, e)
562 center_z = center_z + to_dof%z(i, 1, 1, e)
563 end do
564 center_x = center_x / to_xh%lxyz
565 center_y = center_y / to_xh%lxyz
566 center_z = center_z / to_xh%lxyz
567 do i = 1, to_xh%lxyz
568 x_coords(i, 1, 1, e) = to_dof%x(i, 1, 1, e) - &
569 tol_ * (to_dof%x(i, 1, 1, e) - center_x)
570 y_coords(i, 1, 1, e) = to_dof%y(i, 1, 1, e) - &
571 tol_ * (to_dof%y(i, 1, 1, e) - center_y)
572 z_coords(i, 1, 1, e) = to_dof%z(i, 1, 1, e) - &
573 tol_ * (to_dof%z(i, 1, 1, e) - center_z)
574 end do
575 end do
576
577 ! The initialization is done based on the variables created from
578 ! fld data.
579 if (present(global_interp_subdict)) then
580 call global_interp%init(this%x%x, this%y%x, this%z%x, &
581 this%gdim, this%nelv, fld_xh, &
582 global_interp_subdict)
583 else
584 call global_interp%init(this%x%x, this%y%x, this%z%x, &
585 this%gdim, this%nelv, fld_xh, &
586 tol = tolerance, pad = padding)
587 end if
588
589 call global_interp%find_points(x_coords, y_coords, z_coords, &
590 to_dof%size())
591
592 deallocate(x_coords)
593 deallocate(y_coords)
594 deallocate(z_coords)
595 call fld_xh%free()
596
598
599end module fld_file_data
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
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
Simple module to handle fld file series. Provides an interface to the different fields sotred in a fl...
integer function fld_file_data_size(this)
Get the number of initialized fields in this fld file.
subroutine fld_file_data_init_same(this, fld_file, n)
Genereate same fields as in another fld_file.
subroutine fld_file_data_get_list(this, ptr_list, n)
Get a list with pointers to the fields in the fld file.
subroutine fld_file_data_import_fields(this, u, v, w, p, t, s_target_list, s_index_list, interpolate, tolerance, padding, global_interp_subdict)
Imports fields from an fld_file_data object, potentially with interpolation.
subroutine fld_file_data_free(this)
Deallocate fld file data type.
subroutine fld_file_data_init(this, nelv, offset_el)
Initializes a fld_file_data object.
subroutine fld_file_data_init_n_fields(this, n_fields, n)
Generate same fields as in another fld_file.
subroutine fld_file_data_scale(this, c)
Scale the values stored in this fld_file_data.
subroutine fld_file_data_add(this, other)
Add the values in another fld file to this.
subroutine fld_file_data_generate_interpolator(this, global_interp, to_dof, to_msh, tolerance, padding, global_interp_subdict)
Generates a global_interpolation object to interpolate the fld data.
NEKTON fld file format.
Definition fld_file.f90:35
Implements global_interpolation given a dofmap.
real(kind=dp), parameter, public glob_interp_tol
real(kind=dp), parameter, public glob_interp_pad
Routines to interpolate between different spaces.
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:79
integer, parameter, public log_size
Definition log.f90:45
Definition math.f90:60
subroutine, public cmult(a, c, n)
Multiplication by constant c .
Definition math.f90:447
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:776
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:49
Utilities.
Definition utils.f90:35
integer function, public extract_fld_file_index(fld_filename, default_index)
Extracts the index of a field file. For example, "myfield.f00045" will return 45. If the suffix of th...
Definition utils.f90:203
integer, parameter, public neko_fname_len
Definition utils.f90:41
Defines a vector.
Definition vector.f90:34
field_list_t, To be able to group fields together
Implements global interpolation for arbitrary points in the domain.
Interpolation between two space::space_t.
The function space for the SEM solution fields.
Definition space.f90:63