40 use,
intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_loc, c_f_pointer
47 character(len=:),
allocatable :: name
50 real(kind=
rp),
pointer :: x(:) => null()
54 real(kind=
dp),
pointer :: x_dp(:) => null()
56 type(c_ptr) :: x_d = c_null_ptr
58 integer(kind=i8) :: global_count = 0_i8
60 integer(kind=i8) :: offset = 0_i8
62 logical :: replicated = .false.
74 character(len=:),
allocatable :: name
76 real(kind=
rp),
pointer :: x(:) => null()
78 type(c_ptr) :: x_d = c_null_ptr
80 type(
mesh_t),
pointer :: msh => null()
94 character(len=:),
allocatable :: name
136 procedure, pass(this) :: mesh_array_count => &
145 procedure, pass(this) :: find_mesh_array => &
161 character(len=*),
intent(in) :: name
165 if (len_trim(name) .eq. 0)
then
166 call neko_error(
"Checkpoint payload name cannot be empty")
168 if (name(1:1) .eq.
"/" .or. &
169 name(len_trim(name):len_trim(name)) .eq.
"/")
then
170 call neko_error(
"Checkpoint payload names cannot start or end with '/'")
172 if (index(trim(name),
"//") .gt. 0)
then
173 call neko_error(
"Checkpoint payload names cannot contain empty groups")
176 this%name = trim(name)
185 if (
allocated(this%fields))
then
186 do i = 1,
size(this%fields)
187 if (
associated(this%fields(i)%ptr))
nullify(this%fields(i)%ptr)
189 deallocate(this%fields)
192 if (
allocated(this%series))
then
193 do i = 1,
size(this%series)
194 if (
associated(this%series(i)%ptr))
nullify(this%series(i)%ptr)
196 deallocate(this%series)
199 if (
allocated(this%arrays))
then
200 do i = 1,
size(this%arrays)
201 if (
associated(this%arrays(i)%ptr))
then
202 if (
associated(this%arrays(i)%ptr%x))
then
203 nullify(this%arrays(i)%ptr%x)
205 if (
associated(this%arrays(i)%ptr%x_dp))
then
206 nullify(this%arrays(i)%ptr%x_dp)
208 this%arrays(i)%ptr%x_d = c_null_ptr
209 deallocate(this%arrays(i)%ptr)
212 deallocate(this%arrays)
215 if (
allocated(this%mesh_arrays))
then
216 do i = 1,
size(this%mesh_arrays)
217 if (
associated(this%mesh_arrays(i)%ptr))
then
218 if (
associated(this%mesh_arrays(i)%ptr%x))
then
219 nullify(this%mesh_arrays(i)%ptr%x)
221 this%mesh_arrays(i)%ptr%x_d = c_null_ptr
222 nullify(this%mesh_arrays(i)%ptr%msh)
223 nullify(this%mesh_arrays(i)%ptr%Xh)
224 deallocate(this%mesh_arrays(i)%ptr)
227 deallocate(this%mesh_arrays)
230 if (
allocated(this%name))
deallocate(this%name)
238 type(
field_t),
target,
intent(in) :: fld
244 n = this%field_count()
246 if (
associated(this%fields(i)%ptr, fld))
then
248 "Field already registered in checkpoint payload '" // &
249 trim(this%name) //
"'")
254 if (n .gt. 0) tmp(1:n) = this%fields
255 tmp(n + 1)%ptr => fld
256 call move_alloc(tmp, this%fields)
268 do j = 1, fld_series%size()
271 if (trim(fld_series%lf(i)%name) .eq. &
272 trim(fld_series%lf(j)%name))
then
273 call neko_error(
"Duplicate field name in checkpoint series")
278 n = this%series_count()
280 if (
associated(this%series(i)%ptr, fld_series))
then
281 call neko_error(
"Field series already registered in checkpoint " // &
282 "payload '" // trim(this%name) //
"'")
287 if (n .gt. 0) tmp(1:n) = this%series
288 tmp(n + 1)%ptr => fld_series
289 call move_alloc(tmp, this%series)
311 device_ptr, replicated)
313 character(len=*),
intent(in) :: name
314 real(kind=
rp),
target,
intent(inout) :: x(:)
315 integer(kind=i8),
intent(in),
optional :: global_count, offset
316 type(c_ptr),
intent(in),
optional :: device_ptr
317 logical,
intent(in),
optional :: replicated
318 real(kind=
rp),
pointer :: flat(:)
320 if (.not. is_contiguous(x))
then
321 call neko_error(
"Checkpoint array '" // trim(name) //
"' must be " // &
324 call c_f_pointer(c_loc(x(1)), flat, [
size(x)])
326 offset, device_ptr, replicated)
338 device_ptr, replicated)
340 character(len=*),
intent(in) :: name
341 real(kind=
rp),
target,
intent(inout) :: x(:,:)
342 integer(kind=i8),
intent(in),
optional :: global_count, offset
343 type(c_ptr),
intent(in),
optional :: device_ptr
344 logical,
intent(in),
optional :: replicated
345 real(kind=
rp),
pointer :: flat(:)
347 if (.not. is_contiguous(x))
then
348 call neko_error(
"Checkpoint array '" // trim(name) //
"' must be " // &
351 call c_f_pointer(c_loc(x(1,1)), flat, [
size(x)])
353 offset, device_ptr, replicated)
365 device_ptr, replicated)
367 character(len=*),
intent(in) :: name
368 real(kind=
rp),
target,
intent(inout) :: x(:,:,:)
369 integer(kind=i8),
intent(in),
optional :: global_count, offset
370 type(c_ptr),
intent(in),
optional :: device_ptr
371 logical,
intent(in),
optional :: replicated
372 real(kind=
rp),
pointer :: flat(:)
374 if (.not. is_contiguous(x))
then
375 call neko_error(
"Checkpoint array '" // trim(name) //
"' must be " // &
378 call c_f_pointer(c_loc(x(1,1,1)), flat, [
size(x)])
380 offset, device_ptr, replicated)
392 device_ptr, replicated)
394 character(len=*),
intent(in) :: name
395 real(kind=
rp),
target,
intent(inout) :: x(:,:,:,:)
396 integer(kind=i8),
intent(in),
optional :: global_count, offset
397 type(c_ptr),
intent(in),
optional :: device_ptr
398 logical,
intent(in),
optional :: replicated
399 real(kind=
rp),
pointer :: flat(:)
401 if (.not. is_contiguous(x))
then
402 call neko_error(
"Checkpoint array '" // trim(name) //
"' must be " // &
405 call c_f_pointer(c_loc(x(1,1,1,1)), flat, [
size(x)])
407 offset, device_ptr, replicated)
419 character(len=*),
intent(in) :: name
420 real(kind=
rp),
target,
intent(inout) :: x(:,:,:,:)
421 type(
mesh_t),
target,
intent(in) :: msh
422 type(
space_t),
target,
intent(in) :: Xh
423 type(c_ptr),
intent(in),
optional :: device_ptr
424 real(kind=
rp),
pointer :: flat(:)
426 if (any(shape(x) .ne. [xh%lx, xh%ly, xh%lz, msh%nelv]))
then
427 call neko_error(
"Checkpoint mesh array must have shape " // &
428 "(lx, ly, lz, nelv)")
430 if (.not. is_contiguous(x))
then
431 call neko_error(
"Checkpoint array '" // trim(name) //
"' must be " // &
434 call c_f_pointer(c_loc(x(1,1,1,1)), flat, [
size(x)])
448 offset, device_ptr, replicated)
450 character(len=*),
intent(in) :: name
451 real(kind=
rp),
pointer,
intent(inout) :: x(:)
452 integer(kind=i8),
intent(in),
optional :: global_count, offset
453 type(c_ptr),
intent(in),
optional :: device_ptr
454 logical,
intent(in),
optional :: replicated
456 logical :: is_replicated
461 is_replicated = .false.
462 if (
present(replicated)) is_replicated = replicated
464 if (is_replicated)
then
465 if (
present(global_count) .or.
present(offset))
then
466 call neko_error(
"Replicated checkpoint arrays do not take a " // &
467 "global count or offset")
469 else if (.not.
present(global_count) .or. .not.
present(offset))
then
470 call neko_error(
"Distributed checkpoint arrays require a global " // &
474 n = this%array_count()
476 if (n .gt. 0) tmp(1:n) = this%arrays
477 allocate(tmp(n + 1)%ptr)
478 tmp(n + 1)%ptr%name = trim(name)
479 tmp(n + 1)%ptr%x => x
480 tmp(n + 1)%ptr%replicated = is_replicated
481 if (is_replicated)
then
482 tmp(n + 1)%ptr%global_count = int(
size(x),
i8)
483 tmp(n + 1)%ptr%offset = 0_i8
485 tmp(n + 1)%ptr%global_count = global_count
486 tmp(n + 1)%ptr%offset = offset
487 if (tmp(n + 1)%ptr%offset .lt. 0_i8 .or. &
488 tmp(n + 1)%ptr%global_count .lt. int(
size(x),
i8) .or. &
489 tmp(n + 1)%ptr%offset + int(
size(x),
i8) .gt. &
490 tmp(n + 1)%ptr%global_count)
then
491 call neko_error(
"Invalid checkpoint array selection")
494 if (
present(device_ptr)) tmp(n + 1)%ptr%x_d = device_ptr
495 call move_alloc(tmp, this%arrays)
508 character(len=*),
intent(in) :: name
509 real(kind=
dp),
contiguous,
target,
intent(inout) :: x(:)
510 integer(kind=i8),
intent(in),
optional :: global_count, offset
511 logical,
intent(in),
optional :: replicated
513 logical :: is_replicated
518 is_replicated = .false.
519 if (
present(replicated)) is_replicated = replicated
521 if (is_replicated)
then
522 if (
present(global_count) .or.
present(offset))
then
523 call neko_error(
"Replicated checkpoint arrays do not take a " // &
524 "global count or offset")
526 else if (.not.
present(global_count) .or. .not.
present(offset))
then
527 call neko_error(
"Distributed checkpoint arrays require a global " // &
531 n = this%array_count()
533 if (n .gt. 0) tmp(1:n) = this%arrays
534 allocate(tmp(n + 1)%ptr)
535 tmp(n + 1)%ptr%name = trim(name)
536 tmp(n + 1)%ptr%x_dp => x
537 tmp(n + 1)%ptr%replicated = is_replicated
538 if (is_replicated)
then
539 tmp(n + 1)%ptr%global_count = int(
size(x),
i8)
540 tmp(n + 1)%ptr%offset = 0_i8
542 tmp(n + 1)%ptr%global_count = global_count
543 tmp(n + 1)%ptr%offset = offset
544 if (tmp(n + 1)%ptr%offset .lt. 0_i8 .or. &
545 tmp(n + 1)%ptr%global_count .lt. int(
size(x),
i8) .or. &
546 tmp(n + 1)%ptr%offset + int(
size(x),
i8) .gt. &
547 tmp(n + 1)%ptr%global_count)
then
548 call neko_error(
"Invalid checkpoint array selection")
551 call move_alloc(tmp, this%arrays)
564 character(len=*),
intent(in) :: name
565 real(kind=
rp),
pointer,
intent(inout) :: x(:)
566 type(
mesh_t),
target,
intent(in) :: msh
567 type(
space_t),
target,
intent(in) :: Xh
568 type(c_ptr),
intent(in),
optional :: device_ptr
574 if (
size(x) .ne. msh%nelv * xh%lxyz)
then
576 "Checkpoint mesh array size does not match its mesh " // &
577 "and function space")
580 n = this%mesh_array_count()
582 if (n .gt. 0) tmp(1:n) = this%mesh_arrays
583 allocate(tmp(n + 1)%ptr)
584 tmp(n + 1)%ptr%name = trim(name)
585 tmp(n + 1)%ptr%x => x
586 tmp(n + 1)%ptr%msh => msh
587 tmp(n + 1)%ptr%Xh => xh
588 if (
present(device_ptr)) tmp(n + 1)%ptr%x_d = device_ptr
589 call move_alloc(tmp, this%mesh_arrays)
597 character(len=*),
intent(in) :: name
600 if (len_trim(name) .eq. 0)
then
601 call neko_error(
"Checkpoint field name cannot be empty")
603 if (index(trim(name),
"/") .gt. 0)
then
604 call neko_error(
"Checkpoint field names cannot contain '/'")
607 do i = 1, this%field_count()
608 if (trim(this%fields(i)%ptr%name) .eq. trim(name))
then
609 call neko_error(
"Duplicate field name '" // trim(name) // &
610 "' in checkpoint payload '" // trim(this%name) //
"'")
614 do i = 1, this%series_count()
615 do j = 1, this%series(i)%ptr%size()
616 if (trim(this%series(i)%ptr%lf(j)%name) .eq. trim(name))
then
617 call neko_error(
"Duplicate field name '" // trim(name) // &
618 "' in checkpoint payload '" // trim(this%name) //
"'")
623 do i = 1, this%array_count()
624 if (trim(this%arrays(i)%ptr%name) .eq. trim(name))
then
625 call neko_error(
"Duplicate field or array name '" // trim(name) // &
626 "' in checkpoint payload '" // trim(this%name) //
"'")
630 do i = 1, this%mesh_array_count()
631 if (trim(this%mesh_arrays(i)%ptr%name) .eq. trim(name))
then
632 call neko_error(
"Duplicate field or array name '" // trim(name) // &
633 "' in checkpoint payload '" // trim(this%name) //
"'")
645 if (
allocated(this%fields))
then
646 n =
size(this%fields)
659 if (
allocated(this%series))
then
660 n =
size(this%series)
673 if (
allocated(this%arrays))
then
674 n =
size(this%arrays)
687 if (
allocated(this%mesh_arrays))
then
688 n =
size(this%mesh_arrays)
700 character(len=*),
intent(in) :: name
705 do i = 1, this%field_count()
706 if (trim(this%fields(i)%ptr%name) .eq. trim(name))
then
707 fld => this%fields(i)%ptr
719 character(len=*),
intent(in) :: name
724 do i = 1, this%series_count()
725 if (trim(this%series(i)%ptr%f%name) .eq. trim(name))
then
726 series => this%series(i)%ptr
738 character(len=*),
intent(in) :: name
743 do i = 1, this%array_count()
744 if (trim(this%arrays(i)%ptr%name) .eq. trim(name))
then
745 array => this%arrays(i)%ptr
757 character(len=*),
intent(in) :: name
762 do i = 1, this%mesh_array_count()
763 if (trim(this%mesh_arrays(i)%ptr%name) .eq. trim(name))
then
764 array => this%mesh_arrays(i)%ptr
Format-independent checkpoint payloads.
subroutine checkpoint_payload_validate_name(this, name)
Validate that a dataset name is non-empty and unique in a payload.
subroutine checkpoint_payload_add_series(this, fld_series)
Add a field series using the native names of its lag fields.
subroutine checkpoint_payload_add_field(this, fld)
Add a field using its native name as the dataset name.
pure integer function checkpoint_payload_series_count(this)
Return the number of field series in a payload.
subroutine add_array_4d(this, name, x, global_count, offset, device_ptr, replicated)
Add a rank-four contiguous real array.
subroutine checkpoint_payload_init(this, name)
Initialize a payload.
type(field_series_t) function, pointer checkpoint_payload_find_series(this, name)
Find a field series by the native name of its base field.
subroutine checkpoint_payload_add_array(this, name, x, global_count, offset, device_ptr, replicated)
Store a flattened real array in a payload.
pure integer function checkpoint_payload_field_count(this)
Return the number of fields in a payload.
subroutine checkpoint_payload_free(this)
Release all pointers held by a payload.
type(field_t) function, pointer checkpoint_payload_find_field(this, name)
Find a field by its native name.
subroutine add_array_1d(this, name, x, global_count, offset, device_ptr, replicated)
Add a rank-one real array.
subroutine add_mesh_array_4d(this, name, x, msh, xh, device_ptr)
Add a four-dimensional nodal mesh array.
type(checkpoint_array_t) function, pointer checkpoint_payload_find_array(this, name)
Find an array descriptor by dataset name.
subroutine add_array_2d(this, name, x, global_count, offset, device_ptr, replicated)
Add a rank-two contiguous real array.
subroutine checkpoint_payload_add_array_dp(this, name, x, global_count, offset, replicated)
Store a rank-one double-precision array in a payload.
subroutine checkpoint_payload_add_mesh_array(this, name, x, msh, xh, device_ptr)
Store a flattened nodal mesh array in a payload.
pure integer function checkpoint_payload_array_count(this)
Return the number of arrays in a payload.
type(checkpoint_mesh_array_t) function, pointer checkpoint_payload_find_mesh_array(this, name)
Find a mesh-array descriptor by dataset name.
pure integer function checkpoint_payload_mesh_array_count(this)
Return the number of mesh arrays in a payload.
subroutine add_array_3d(this, name, x, global_count, offset, device_ptr, replicated)
Add a rank-three contiguous real array.
Contains the field_serties_t type.
integer, parameter, public i8
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
Defines a function space.
Pointer wrapper around checkpoint_array_t.
A named real array and its selection in a global checkpoint dataset.
Pointer wrapper around checkpoint_mesh_array_t.
A named nodal real array distributed over mesh elements.
Pointer wrapper used to keep payload addresses stable as the list grows.
A named collection of live fields to checkpoint together.
field_ptr_t, To easily obtain a pointer to a field
A wrapper for a pointer to a field_series_t.
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
The function space for the SEM solution fields.