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 might &
184 &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
226 ! For scalar fields, require indices in 1:this%n_scalars
227 if (s_index_list(i) < 1 .or. &
228 s_index_list(i) > this%n_scalars) then
229 call neko_error("s_index_list entry out of bounds")
230 end if
231 call global_interp%evaluate(s_target_list%x(i), &
232 this%s(s_index_list(i))%x, on_host = .false.)
233 end if
234 end do
235
236 ! otherwise, just copy element-to-element
237 else
238 do i = 1, s_target_list%size()
239 call global_interp%evaluate(s_target_list%x(i), this%s(i)%x, &
240 on_host = .false.)
241 end do
242 end if ! present s_index_list
243 end if ! present s_tgt
244
245 call global_interp%free()
246
247 else ! No interpolation, but potentially just from different spaces
248
249 ! throw an error is the space is not passed
250 if (.not. associated(xh)) call neko_error("Xh is not associated")
251
252 ! Build a space_t object from the data in the fld file
253 call prev_xh%init(gll, this%lx, this%ly, this%lz)
254 call space_interp%init(xh, prev_xh)
255
256 ! Do the space-to-space interpolation
257 if (present(u)) call space_interp%map(u%x, this%u%x, this%nelv, xh)
258 if (present(v)) call space_interp%map(v%x, this%v%x, this%nelv, xh)
259 if (present(w)) call space_interp%map(w%x, this%w%x, this%nelv, xh)
260 if (present(p)) call space_interp%map(p%x, this%p%x, this%nelv, xh)
261 if (present(t)) call space_interp%map(t%x, this%t%x, this%nelv, xh)
262 if (present(s_target_list)) then
263
264 ! If the index list exists, use it as a "mask"
265 if (present(s_index_list)) then
266 do i = 1, size(s_index_list)
267
268 ! 0 means we want temperature
269 if (s_index_list(i) .eq. 0) then
270 call space_interp%map(s_target_list%x(i), &
271 this%t%x, this%nelv, xh)
272 else
273 call space_interp%map(s_target_list%x(i), &
274 this%s(s_index_list(i))%x, this%nelv, xh)
275 end if
276 end do
277
278 ! otherwise, just copy element-to-element
279 else
280 do i = 1, s_target_list%size()
281 call space_interp%map(s_target_list%x(i), this%s(i)%x, &
282 this%nelv, xh)
283 end do
284 end if ! present s_index_list
285 end if ! present s_tgt
286
287 call space_interp%free
288 call prev_xh%free
289
290 end if ! if interpolate
291
292 nullify(dof)
293 nullify(xh)
294 nullify(msh)
295
296 end subroutine fld_file_data_import_fields
297
301 subroutine fld_file_data_init(this, nelv, offset_el)
302 class(fld_file_data_t), intent(inout) :: this
303 integer, intent(in), optional :: nelv, offset_el
304
305 call this%free()
306 if (present(nelv)) this%nelv = nelv
307 if (present(offset_el)) this%offset_el = offset_el
308
309 end subroutine fld_file_data_init
310
312 function fld_file_data_size(this) result(i)
313 class(fld_file_data_t) :: this
314 integer :: i
315 i = 0
316 if (this%u%size() .gt. 0) i = i + 1
317 if (this%v%size() .gt. 0) i = i + 1
318 if (this%w%size() .gt. 0) i = i + 1
319 if (this%p%size() .gt. 0) i = i + 1
320 if (this%t%size() .gt. 0) i = i + 1
321 i = i + this%n_scalars
322
323 end function fld_file_data_size
324
326 subroutine fld_file_data_init_same(this, fld_file, n)
327 class(fld_file_data_t), target, intent(inout) :: this
328 class(fld_file_data_t), target, intent(in) :: fld_file
329 integer, intent(in) :: n
330 integer :: i, j
331
332 if (fld_file%u%size() .gt. 0) then
333 call this%u%init(n)
334 end if
335 if (fld_file%v%size() .gt. 0) then
336 call this%v%init(n)
337 end if
338 if (fld_file%w%size() .gt. 0) then
339 call this%w%init(n)
340 end if
341 if (fld_file%p%size() .gt. 0) then
342 call this%p%init(n)
343 end if
344 if (fld_file%t%size() .gt. 0) then
345 call this%t%init(n)
346 end if
347 this%n_scalars = fld_file%n_scalars
348 allocate(this%s(fld_file%n_scalars))
349 do j = 1, fld_file%n_scalars
350 call this%s(j)%init(n)
351 end do
352
353 end subroutine fld_file_data_init_same
354
356 subroutine fld_file_data_init_n_fields(this, n_fields, n)
357 class(fld_file_data_t), target, intent(inout) :: this
358 integer, intent(in) :: n, n_fields
359 integer :: i, j
360
361
362 if (n_fields .gt. 0) then
363 call this%u%init(n)
364 end if
365 if (n_fields .gt. 1) then
366 call this%v%init(n)
367 end if
368 if (n_fields .gt. 2) then
369 call this%w%init(n)
370 end if
371 if (n_fields .gt. 3) then
372 call this%p%init(n)
373 end if
374 if (n_fields .gt. 4) then
375 call this%t%init(n)
376 end if
377 if (n_fields .gt. 5) then
378 this%n_scalars = n_fields-5
379 allocate(this%s(this%n_scalars))
380 do j = 1, this%n_scalars
381 call this%s(j)%init(n)
382 end do
383 end if
384
385 end subroutine fld_file_data_init_n_fields
386
388 subroutine fld_file_data_get_list(this, ptr_list, n)
389 class(fld_file_data_t), target, intent(in) :: this
390 integer, intent(in) :: n
391 integer :: i, j
392 type(vector_ptr_t), intent(inout) :: ptr_list(n)
393 i = 1
394 if (this%u%size() .gt. 0) then
395 ptr_list(i)%ptr => this%u
396 i = i + 1
397 end if
398 if (this%v%size() .gt. 0) then
399 ptr_list(i)%ptr => this%v
400 i = i + 1
401 end if
402 if (this%w%size() .gt. 0) then
403 ptr_list(i)%ptr => this%w
404 i = i + 1
405 end if
406 if (this%p%size() .gt. 0) then
407 ptr_list(i)%ptr => this%p
408 i = i + 1
409 end if
410 if (this%t%size() .gt. 0) then
411 ptr_list(i)%ptr => this%t
412 i = i + 1
413 end if
414 do j = 1, this%n_scalars
415 ptr_list(i)%ptr => this%s(j)
416 i = i +1
417 end do
418
419 end subroutine fld_file_data_get_list
420
421
422
424 subroutine fld_file_data_scale(this, c)
425 class(fld_file_data_t), intent(inout) :: this
426 real(kind=rp), intent(in) :: c
427 integer :: i
428
429 if (this%u%size() .gt. 0) call cmult(this%u%x, c, this%u%size())
430 if (this%v%size() .gt. 0) call cmult(this%v%x, c, this%v%size())
431 if (this%w%size() .gt. 0) call cmult(this%w%x, c, this%w%size())
432 if (this%p%size() .gt. 0) call cmult(this%p%x, c, this%p%size())
433 if (this%t%size() .gt. 0) call cmult(this%t%x, c, this%t%size())
434
435 do i = 1, this%n_scalars
436 if (this%s(i)%size() .gt. 0) call cmult(this%s(i)%x, c, this%s(i)%size())
437 end do
438
439 end subroutine fld_file_data_scale
440
442 subroutine fld_file_data_add(this, other)
443 class(fld_file_data_t), intent(inout) :: this
444 class(fld_file_data_t), intent(in) :: other
445 integer :: i, n
446
447 if (this%u%size() .gt. 0) call add2(this%u%x, other%u%x, this%u%size())
448 if (this%v%size() .gt. 0) call add2(this%v%x, other%v%x, this%v%size())
449 if (this%w%size() .gt. 0) call add2(this%w%x, other%w%x, this%w%size())
450 if (this%p%size() .gt. 0) call add2(this%p%x, other%p%x, this%p%size())
451 if (this%t%size() .gt. 0) call add2(this%t%x, other%t%x, this%t%size())
452
453 do i = 1, this%n_scalars
454 if (this%s(i)%size() .gt. 0) call add2(this%s(i)%x, other%s(i)%x, &
455 this%s(i)%size())
456 end do
457 end subroutine fld_file_data_add
458
460 subroutine fld_file_data_free(this)
461 class(fld_file_data_t), intent(inout) :: this
462 integer :: i
463 call this%x%free()
464 call this%y%free()
465 call this%z%free()
466 call this%u%free()
467 call this%v%free()
468 call this%w%free()
469 call this%p%free()
470 call this%t%free()
471 if (allocated(this%s)) then
472 do i = 1, this%n_scalars
473 call this%s(i)%free()
474 end do
475 deallocate(this%s)
476 end if
477 this%n_scalars = 0
478 this%time = 0.0
479 this%glb_nelv = 0
480 this%nelv = 0
481 this%offset_el = 0
482 this%lx = 0
483 this%ly = 0
484 this%lz = 0
485 this%t_counter = 0
486 this%meta_nsamples = 0
487 this%meta_start_counter = 0
488 if (allocated(this%idx)) deallocate(this%idx)
489 end subroutine fld_file_data_free
490
501 subroutine fld_file_data_generate_interpolator(this, global_interp, to_dof, &
502 to_msh, tolerance, padding, global_interp_subdict)
503 class(fld_file_data_t), intent(in) :: this
504 type(global_interpolation_t), intent(inout) :: global_interp
505 type(dofmap_t), intent(in), target :: to_dof
506 type(mesh_t), intent(in), target :: to_msh
507 real(kind=dp), intent(in), optional :: tolerance
508 real(kind=dp), intent(in), optional :: padding
509 type(json_file), intent(inout), optional :: global_interp_subdict
510
511 ! --- variables for interpolation
512 type(space_t) :: fld_Xh
513 real(kind=rp), allocatable :: x_coords(:,:,:,:), y_coords(:,:,:,:), &
514 z_coords(:,:,:,:)
515 real(kind=rp) :: center_x, center_y, center_z
516 integer :: e, i
517 real(kind=rp) :: tol_ = glob_interp_tol
518 ! ---
519
520 type(space_t), pointer :: to_xh
521 to_xh => to_dof%Xh
522
523 ! Safeguard in case we didn't read mesh information
524 if (.not. allocated(this%x%x) .or. &
525 .not. allocated(this%y%x) .or. &
526 .not. allocated(this%z%x)) call neko_error("Unable to retrieve &
527 &mesh information from fld data.")
528
529 ! Create a space based on the fld data
530 call fld_xh%init(gll, this%lx, this%ly, this%lz)
531
532 ! These are the coordinates of our current dofmap
533 ! that we use for the interpolation
534 allocate(x_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
535 allocate(y_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
536 allocate(z_coords(to_xh%lx, to_xh%ly, to_xh%lz, to_msh%nelv))
537
538 ! JSON subdict takes precedence over dummy argument, but if neither is
539 ! provided throw an error
540 if (present(global_interp_subdict)) then
541 call json_get_or_default(global_interp_subdict, "tolerance", tol_, &
542 tol_)
543 else if (present(tolerance)) then
544 tol_ = tolerance
545 else
546 call neko_error("No tolerance provided for interpolation! " // &
547 "Please provide a tolerance or a subdict with a tolerance entry.")
548 end if
549
554 do e = 1, to_msh%nelv
555 center_x = 0d0
556 center_y = 0d0
557 center_z = 0d0
558 do i = 1, to_xh%lxyz
559 center_x = center_x + to_dof%x(i, 1, 1, e)
560 center_y = center_y + to_dof%y(i, 1, 1, e)
561 center_z = center_z + to_dof%z(i, 1, 1, e)
562 end do
563 center_x = center_x / to_xh%lxyz
564 center_y = center_y / to_xh%lxyz
565 center_z = center_z / to_xh%lxyz
566 do i = 1, to_xh%lxyz
567 x_coords(i, 1, 1, e) = to_dof%x(i, 1, 1, e) - &
568 tol_ * (to_dof%x(i, 1, 1, e) - center_x)
569 y_coords(i, 1, 1, e) = to_dof%y(i, 1, 1, e) - &
570 tol_ * (to_dof%y(i, 1, 1, e) - center_y)
571 z_coords(i, 1, 1, e) = to_dof%z(i, 1, 1, e) - &
572 tol_ * (to_dof%z(i, 1, 1, e) - center_z)
573 end do
574 end do
575
576 ! The initialization is done based on the variables created from
577 ! fld data.
578 if (present(global_interp_subdict)) then
579 call global_interp%init(this%x%x, this%y%x, this%z%x, &
580 this%gdim, this%nelv, fld_xh, &
581 global_interp_subdict)
582 else
583 call global_interp%init(this%x%x, this%y%x, this%z%x, &
584 this%gdim, this%nelv, fld_xh, &
585 tol = tolerance, pad = padding)
586 end if
587
588 call global_interp%find_points(x_coords, y_coords, z_coords, &
589 to_dof%size())
590
591 deallocate(x_coords)
592 deallocate(y_coords)
593 deallocate(z_coords)
594 call fld_xh%free()
595
597
598end 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:412
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:727
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:157
integer, parameter, public neko_fname_len
Definition utils.f90:40
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