Neko  0.8.99
A portable framework for high-order spectral element flow simulations
chkp_file.f90
Go to the documentation of this file.
1 ! Copyright (c) 2021-2022, 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 !
35 module chkp_file
36  use generic_file
37  use field_series
38  use checkpoint
39  use num_types
40  use field
41  use dofmap, only: dofmap_t
42  use device_math
43  use utils
44  use space
45  use mesh
46  use math
47  use interpolation
48  use neko_mpi_types
49  use comm
51  implicit none
52  private
53 
55  type, public, extends(generic_file_t) :: chkp_file_t
56  type(space_t) :: chkp_xh
57  type(space_t), pointer :: sim_xh
58  type(interpolator_t) :: space_interp
59  type(global_interpolation_t) :: global_interp
60  logical :: mesh2mesh
61  contains
62  procedure :: read => chkp_file_read
63  procedure :: read_field => chkp_read_field
64  procedure :: write => chkp_file_write
65  end type chkp_file_t
66 
67 contains
68 
70  subroutine chkp_file_write(this, data, t)
71  class(chkp_file_t), intent(inout) :: this
72  class(*), target, intent(in) :: data
73  real(kind=rp), intent(in), optional :: t
74  real(kind=dp) :: time
75  character(len=5) :: id_str
76  character(len=1024) :: fname
77  integer :: ierr, suffix_pos, optional_fields
78  type(field_t), pointer :: u, v, w, p, s
79  type(field_t), pointer :: abx1,abx2
80  type(field_t), pointer :: aby1,aby2
81  type(field_t), pointer :: abz1,abz2
82  type(field_t), pointer :: abs1,abs2
83  type(field_series_t), pointer :: ulag => null()
84  type(field_series_t), pointer :: vlag => null()
85  type(field_series_t), pointer :: wlag => null()
86  type(field_series_t), pointer :: slag => null()
87  real(kind=rp), pointer :: dtlag(:), tlag(:)
88  type(mesh_t), pointer :: msh
89  type(mpi_status) :: status
90  type(mpi_file) :: fh
91  integer (kind=MPI_OFFSET_KIND) :: mpi_offset, byte_offset
92  integer(kind=i8) :: n_glb_dofs, dof_offset
93  logical :: write_lag, write_scalar, write_dtlag, write_scalarlag, write_abvel
94  integer :: i
95 
96  if (present(t)) then
97  time = real(t,dp)
98  else
99  time = 0d0
100  end if
101 
102  select type(data)
103  type is (chkp_t)
104 
105  if ( .not. associated(data%u) .or. &
106  .not. associated(data%v) .or. &
107  .not. associated(data%w) .or. &
108  .not. associated(data%p) ) then
109  call neko_error('Checkpoint not initialized')
110  end if
111 
112  u => data%u
113  v => data%v
114  w => data%w
115  p => data%p
116  msh => u%msh
117 
118  optional_fields = 0
119 
120  if (associated(data%ulag)) then
121  ulag => data%ulag
122  vlag => data%vlag
123  wlag => data%wlag
124  write_lag = .true.
125  optional_fields = optional_fields + 1
126  else
127  write_lag = .false.
128  end if
129 
130  if (associated(data%s)) then
131  s => data%s
132  write_scalar = .true.
133  optional_fields = optional_fields + 2
134  else
135  write_scalar = .false.
136  end if
137 
138  if (associated(data%tlag)) then
139  tlag => data%tlag
140  dtlag => data%dtlag
141  write_dtlag = .true.
142  optional_fields = optional_fields + 4
143  else
144  write_dtlag = .false.
145  end if
146  write_abvel = .false.
147  if (associated(data%abx1)) then
148  abx1 => data%abx1
149  abx2 => data%abx2
150  aby1 => data%aby1
151  aby2 => data%aby2
152  abz1 => data%abz1
153  abz2 => data%abz2
154  optional_fields = optional_fields + 8
155  write_abvel = .true.
156  end if
157  write_scalarlag = .false.
158  if (associated(data%abs1)) then
159  slag => data%slag
160  abs1 => data%abs1
161  abs2 => data%abs2
162  optional_fields = optional_fields + 16
163  write_scalarlag = .true.
164  end if
165  class default
166  call neko_error('Invalid data')
167  end select
168 
169 
170  suffix_pos = filename_suffix_pos(this%fname)
171  write(id_str, '(i5.5)') this%counter
172  fname = trim(this%fname(1:suffix_pos-1))//id_str//'.chkp'
173 
174 
175  dof_offset = int(msh%offset_el, i8) * int(u%Xh%lx * u%Xh%ly * u%Xh%lz, i8)
176  n_glb_dofs = int(u%Xh%lx * u%Xh%ly * u%Xh%lz, i8) * int(msh%glb_nelv, i8)
177 
178  call mpi_file_open(neko_comm, trim(fname), &
179  mpi_mode_wronly + mpi_mode_create, mpi_info_null, fh, ierr)
180  call mpi_file_write_all(fh, msh%glb_nelv, 1, mpi_integer, status, ierr)
181  call mpi_file_write_all(fh, msh%gdim, 1, mpi_integer, status, ierr)
182  call mpi_file_write_all(fh, u%Xh%lx, 1, mpi_integer, status, ierr)
183  call mpi_file_write_all(fh, optional_fields, 1, mpi_integer, status, ierr)
184  call mpi_file_write_all(fh, time, 1, mpi_double_precision, status, ierr)
185 
186 
187  !
188  ! Dump mandatory checkpoint data
189  !
190 
191  byte_offset = 4_i8 * int(mpi_integer_size,i8) + int(mpi_double_precision_size,i8)
192  byte_offset = byte_offset + &
193  dof_offset * int(mpi_real_prec_size, i8)
194  call mpi_file_write_at_all(fh, byte_offset,u%x, u%dof%size(), &
195  mpi_real_precision, status, ierr)
196  mpi_offset = 4_i8 * int(mpi_integer_size,i8) + int(mpi_double_precision_size,i8)
197  mpi_offset = mpi_offset +&
198  n_glb_dofs * int(mpi_real_prec_size, i8)
199 
200  byte_offset = mpi_offset + &
201  dof_offset * int(mpi_real_prec_size, i8)
202  call mpi_file_write_at_all(fh, byte_offset, v%x, v%dof%size(), &
203  mpi_real_precision, status, ierr)
204  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
205 
206  byte_offset = mpi_offset + &
207  dof_offset * int(mpi_real_prec_size, i8)
208  call mpi_file_write_at_all(fh, byte_offset, w%x, w%dof%size(), &
209  mpi_real_precision, status, ierr)
210  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
211 
212  byte_offset = mpi_offset + &
213  dof_offset * int(mpi_real_prec_size, i8)
214  call mpi_file_write_at_all(fh, byte_offset, p%x, p%dof%size(), &
215  mpi_real_precision, status, ierr)
216  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
217 
218  !
219  ! Dump optional payload
220  !
221 
222  if (write_lag) then
223 
224  do i = 1, ulag%size()
225  byte_offset = mpi_offset + &
226  dof_offset * int(mpi_real_prec_size, i8)
227  ! We should not need this extra associate block, ant it works
228  ! great without it for GNU, Intel, NEC and Cray, but throws an
229  ! ICE with NAG.
230  associate(x => ulag%lf(i)%x)
231  call mpi_file_write_at_all(fh, byte_offset, x, &
232  ulag%lf(i)%dof%size(), mpi_real_precision, status, ierr)
233  end associate
234  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
235  end do
236 
237  do i = 1, vlag%size()
238  byte_offset = mpi_offset + &
239  dof_offset * int(mpi_real_prec_size, i8)
240  ! We should not need this extra associate block, ant it works
241  ! great without it for GNU, Intel, NEC and Cray, but throws an
242  ! ICE with NAG.
243  associate(x => vlag%lf(i)%x)
244  call mpi_file_write_at_all(fh, byte_offset, x, &
245  vlag%lf(i)%dof%size(), mpi_real_precision, status, ierr)
246  end associate
247  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
248  end do
249 
250  do i = 1, wlag%size()
251  byte_offset = mpi_offset + &
252  dof_offset * int(mpi_real_prec_size, i8)
253  ! We should not need this extra associate block, ant it works
254  ! great without it for GNU, Intel, NEC and Cray, but throws an
255  ! ICE with NAG.
256  associate(x => wlag%lf(i)%x)
257  call mpi_file_write_at_all(fh, byte_offset, x, &
258  wlag%lf(i)%dof%size(), mpi_real_precision, status, ierr)
259  end associate
260  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
261  end do
262 
263  end if
264 
265  if (write_scalar) then
266  byte_offset = mpi_offset + &
267  dof_offset * int(mpi_real_prec_size, i8)
268  call mpi_file_write_at_all(fh, byte_offset, s%x, p%dof%size(), &
269  mpi_real_precision, status, ierr)
270  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
271  end if
272 
273  if (write_dtlag) then
274  call mpi_file_write_at_all(fh, mpi_offset, tlag, 10, mpi_real_precision, status, ierr)
275  mpi_offset = mpi_offset + 10_i8 * int(mpi_real_prec_size, i8)
276  call mpi_file_write_at_all(fh, mpi_offset, dtlag, 10, mpi_real_precision, status, ierr)
277  mpi_offset = mpi_offset + 10_i8 * int(mpi_real_prec_size, i8)
278  end if
279 
280  if (write_abvel) then
281  byte_offset = mpi_offset + &
282  dof_offset * int(mpi_real_prec_size, i8)
283  call mpi_file_write_at_all(fh, byte_offset, abx1%x, abx1%dof%size(), &
284  mpi_real_precision, status, ierr)
285  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
286  byte_offset = mpi_offset + &
287  dof_offset * int(mpi_real_prec_size, i8)
288  call mpi_file_write_at_all(fh, byte_offset, abx2%x, abx1%dof%size(), &
289  mpi_real_precision, status, ierr)
290  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
291  byte_offset = mpi_offset + &
292  dof_offset * int(mpi_real_prec_size, i8)
293  call mpi_file_write_at_all(fh, byte_offset, aby1%x, abx1%dof%size(), &
294  mpi_real_precision, status, ierr)
295  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
296  byte_offset = mpi_offset + &
297  dof_offset * int(mpi_real_prec_size, i8)
298  call mpi_file_write_at_all(fh, byte_offset, aby2%x, abx1%dof%size(), &
299  mpi_real_precision, status, ierr)
300  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
301  byte_offset = mpi_offset + &
302  dof_offset * int(mpi_real_prec_size, i8)
303  call mpi_file_write_at_all(fh, byte_offset, abz1%x, abx1%dof%size(), &
304  mpi_real_precision, status, ierr)
305  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
306  byte_offset = mpi_offset + &
307  dof_offset * int(mpi_real_prec_size, i8)
308  call mpi_file_write_at_all(fh, byte_offset, abz2%x, abx1%dof%size(), &
309  mpi_real_precision, status, ierr)
310  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
311  end if
312 
313  if (write_scalarlag) then
314  do i = 1, slag%size()
315  byte_offset = mpi_offset + &
316  dof_offset * int(mpi_real_prec_size, i8)
317  ! We should not need this extra associate block, ant it works
318  ! great without it for GNU, Intel, NEC and Cray, but throws an
319  ! ICE with NAG.
320  associate(x => slag%lf(i)%x)
321  call mpi_file_write_at_all(fh, byte_offset, x, &
322  slag%lf(i)%dof%size(), mpi_real_precision, status, ierr)
323  end associate
324  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
325  end do
326 
327  byte_offset = mpi_offset + &
328  dof_offset * int(mpi_real_prec_size, i8)
329  call mpi_file_write_at_all(fh, byte_offset, abs1%x, abx1%dof%size(), &
330  mpi_real_precision, status, ierr)
331  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
332  byte_offset = mpi_offset + &
333  dof_offset * int(mpi_real_prec_size, i8)
334  call mpi_file_write_at_all(fh, byte_offset, abs2%x, abx1%dof%size(), &
335  mpi_real_precision, status, ierr)
336  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
337  end if
338 
339  call mpi_file_close(fh, ierr)
340 
341  this%counter = this%counter + 1
342 
343  end subroutine chkp_file_write
344 
346  subroutine chkp_file_read(this, data)
347  class(chkp_file_t) :: this
348  class(*), target, intent(inout) :: data
349  type(chkp_t), pointer :: chkp
350  character(len=5) :: id_str
351  character(len=1024) :: fname
352  integer :: ierr, suffix_pos
353  type(field_t), pointer :: u, v, w, p, s
354  type(field_series_t), pointer :: ulag => null()
355  type(field_series_t), pointer :: vlag => null()
356  type(field_series_t), pointer :: wlag => null()
357  type(field_series_t), pointer :: slag => null()
358  type(mesh_t), pointer :: msh
359  type(mpi_status) :: status
360  type(mpi_file) :: fh
361  type(field_t), pointer :: abx1,abx2
362  type(field_t), pointer :: aby1,aby2
363  type(field_t), pointer :: abz1,abz2
364  type(field_t), pointer :: abs1,abs2
365  real(kind=rp), allocatable :: x_coord(:,:,:,:)
366  real(kind=rp), allocatable :: y_coord(:,:,:,:)
367  real(kind=rp), allocatable :: z_coord(:,:,:,:)
368  real(kind=rp), pointer :: dtlag(:), tlag(:)
369  integer (kind=MPI_OFFSET_KIND) :: mpi_offset, byte_offset
370  integer(kind=i8) :: n_glb_dofs, dof_offset
371  integer :: glb_nelv, gdim, lx, have_lag, have_scalar, nel, optional_fields, have_dtlag
372  integer :: have_abvel, have_scalarlag
373  logical :: read_lag, read_scalar, read_dtlag, read_abvel, read_scalarlag
374  real(kind=rp) :: tol
375  real(kind=rp) :: center_x, center_y, center_z
376  integer :: i, e
377  type(dofmap_t) :: dof
378 
379  call this%check_exists()
380 
381  select type(data)
382  type is (chkp_t)
383 
384  if ( .not. associated(data%u) .or. &
385  .not. associated(data%v) .or. &
386  .not. associated(data%w) .or. &
387  .not. associated(data%p) ) then
388  call neko_error('Checkpoint not initialized')
389  end if
390 
391  u => data%u
392  v => data%v
393  w => data%w
394  p => data%p
396  if (allocated(data%previous_mesh%elements)) then
397  msh => data%previous_mesh
398  this%mesh2mesh = .true.
399  tol = data%mesh2mesh_tol
400  else
401  msh => u%msh
402  this%mesh2mesh = .false.
403  end if
404 
405  if (associated(data%ulag)) then
406  ulag => data%ulag
407  vlag => data%vlag
408  wlag => data%wlag
409  read_lag = .true.
410  else
411  read_lag = .false.
412  end if
413 
414  if (associated(data%s)) then
415  s => data%s
416  read_scalar = .true.
417  else
418  read_scalar = .false.
419  end if
420  if (associated(data%dtlag)) then
421  dtlag => data%dtlag
422  tlag => data%tlag
423  read_dtlag = .true.
424  else
425  read_dtlag = .false.
426  end if
427  read_abvel = .false.
428  if (associated(data%abx1)) then
429  abx1 => data%abx1
430  abx2 => data%abx2
431  aby1 => data%aby1
432  aby2 => data%aby2
433  abz1 => data%abz1
434  abz2 => data%abz2
435  read_abvel = .true.
436  end if
437  read_scalarlag = .false.
438  if (associated(data%abs1)) then
439  slag => data%slag
440  abs1 => data%abs1
441  abs2 => data%abs2
442  read_scalarlag = .true.
443  end if
444 
445  chkp => data
446 
447  class default
448  call neko_error('Invalid data')
449  end select
450 
451 
452 
453  call mpi_file_open(neko_comm, trim(this%fname), &
454  mpi_mode_rdonly, mpi_info_null, fh, ierr)
455  call mpi_file_read_all(fh, glb_nelv, 1, mpi_integer, status, ierr)
456  call mpi_file_read_all(fh, gdim, 1, mpi_integer, status, ierr)
457  call mpi_file_read_all(fh, lx, 1, mpi_integer, status, ierr)
458  call mpi_file_read_all(fh, optional_fields, 1, mpi_integer, status, ierr)
459  call mpi_file_read_all(fh, chkp%t, 1, mpi_double_precision, status, ierr)
460 
461  have_lag = mod(optional_fields,2)/1
462  have_scalar = mod(optional_fields,4)/2
463  have_dtlag = mod(optional_fields,8)/4
464  have_abvel = mod(optional_fields,16)/8
465  have_scalarlag = mod(optional_fields,32)/16
466 
467  if ( ( glb_nelv .ne. msh%glb_nelv ) .or. &
468  ( gdim .ne. msh%gdim) .or. &
469  ( (have_lag .eq. 0) .and. (read_lag) ) .or. &
470  ( (have_scalar .eq. 0) .and. (read_scalar) ) ) then
471  call neko_error('Checkpoint does not match case')
472  end if
473  nel = msh%nelv
474  this%sim_Xh => u%Xh
475  if (gdim .eq. 3) then
476  call this%chkp_Xh%init(gll, lx, lx, lx)
477  else
478  call this%chkp_Xh%init(gll, lx, lx)
479  end if
480  if (this%mesh2mesh) then
481  dof = dofmap_t(msh, this%chkp_Xh)
482  allocate(x_coord(u%Xh%lx,u%Xh%ly,u%Xh%lz,u%msh%nelv))
483  allocate(y_coord(u%Xh%lx,u%Xh%ly,u%Xh%lz,u%msh%nelv))
484  allocate(z_coord(u%Xh%lx,u%Xh%ly,u%Xh%lz,u%msh%nelv))
489  do e = 1, u%dof%msh%nelv
490  center_x = 0d0
491  center_y = 0d0
492  center_z = 0d0
493  do i = 1,u%dof%Xh%lxyz
494  center_x = center_x + u%dof%x(i,1,1,e)
495  center_y = center_y + u%dof%y(i,1,1,e)
496  center_z = center_z + u%dof%z(i,1,1,e)
497  end do
498  center_x = center_x/u%Xh%lxyz
499  center_y = center_y/u%Xh%lxyz
500  center_z = center_z/u%Xh%lxyz
501  do i = 1,u%dof%Xh%lxyz
502  x_coord(i,1,1,e) = u%dof%x(i,1,1,e) - tol*(u%dof%x(i,1,1,e)-center_x)
503  y_coord(i,1,1,e) = u%dof%y(i,1,1,e) - tol*(u%dof%y(i,1,1,e)-center_y)
504  z_coord(i,1,1,e) = u%dof%z(i,1,1,e) - tol*(u%dof%z(i,1,1,e)-center_z)
505  end do
506  end do
507  call this%global_interp%init(dof,tol=tol)
508  call this%global_interp%find_points(x_coord,y_coord,z_coord,u%dof%size())
509  deallocate(x_coord)
510  deallocate(y_coord)
511  deallocate(z_coord)
512  else
513  call this%space_interp%init(this%sim_Xh, this%chkp_Xh)
514  end if
515  dof_offset = int(msh%offset_el, i8) * int(this%chkp_Xh%lxyz, i8)
516  n_glb_dofs = int(this%chkp_Xh%lxyz, i8) * int(msh%glb_nelv, i8)
517 
518  !
519  ! Read mandatory checkpoint data
520  !
521 
522  byte_offset = 4_i8 * int(mpi_integer_size,i8) + int(mpi_double_precision_size,i8)
523  byte_offset = byte_offset + &
524  dof_offset * int(mpi_real_prec_size, i8)
525  call this%read_field(fh, byte_offset, u%x, nel)
526  mpi_offset = 4_i8 * int(mpi_integer_size,i8) + int(mpi_double_precision_size,i8)
527  mpi_offset = mpi_offset +&
528  n_glb_dofs * int(mpi_real_prec_size, i8)
529 
530  byte_offset = mpi_offset + &
531  dof_offset * int(mpi_real_prec_size, i8)
532  call this%read_field(fh, byte_offset, v%x, nel)
533  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
534 
535  byte_offset = mpi_offset + &
536  dof_offset * int(mpi_real_prec_size, i8)
537  call this%read_field(fh, byte_offset, w%x, nel)
538  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
539 
540  byte_offset = mpi_offset + &
541  dof_offset * int(mpi_real_prec_size, i8)
542  call this%read_field(fh, byte_offset, p%x, nel)
543  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
544 
545  !
546  ! Read optional payload
547  !
548 
549  if (read_lag) then
550  do i = 1, ulag%size()
551  byte_offset = mpi_offset + &
552  dof_offset * int(mpi_real_prec_size, i8)
553  call this%read_field(fh, byte_offset, ulag%lf(i)%x, nel)
554  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
555  end do
556 
557  do i = 1, vlag%size()
558  byte_offset = mpi_offset + &
559  dof_offset * int(mpi_real_prec_size, i8)
560  call this%read_field(fh, byte_offset, vlag%lf(i)%x, nel)
561  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
562  end do
563 
564  do i = 1, wlag%size()
565  byte_offset = mpi_offset + &
566  dof_offset * int(mpi_real_prec_size, i8)
567  call this%read_field(fh, byte_offset, wlag%lf(i)%x, nel)
568  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
569  end do
570  end if
571 
572  if (read_scalar) then
573  byte_offset = mpi_offset + &
574  dof_offset * int(mpi_real_prec_size, i8)
575  call this%read_field(fh, byte_offset, s%x, nel)
576  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
577  end if
578 
579  if (read_dtlag .and. have_dtlag .eq. 1) then
580  call mpi_file_read_at_all(fh, mpi_offset, tlag, 10, mpi_real_precision, status, ierr)
581  mpi_offset = mpi_offset + 10_i8 * int(mpi_real_prec_size, i8)
582  call mpi_file_read_at_all(fh, mpi_offset, dtlag, 10, mpi_real_precision, status, ierr)
583  mpi_offset = mpi_offset + 10_i8 * int(mpi_real_prec_size, i8)
584  end if
585 
586  if (read_abvel .and. have_abvel .eq. 1) then
587  byte_offset = mpi_offset + &
588  dof_offset * int(mpi_real_prec_size, i8)
589  call this%read_field(fh, byte_offset, abx1%x, nel)
590  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
591  byte_offset = mpi_offset + &
592  dof_offset * int(mpi_real_prec_size, i8)
593  call this%read_field(fh, byte_offset, abx2%x, nel)
594  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
595  byte_offset = mpi_offset + &
596  dof_offset * int(mpi_real_prec_size, i8)
597  call this%read_field(fh, byte_offset, aby1%x, nel)
598  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
599  byte_offset = mpi_offset + &
600  dof_offset * int(mpi_real_prec_size, i8)
601  call this%read_field(fh, byte_offset, aby2%x, nel)
602  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
603  byte_offset = mpi_offset + &
604  dof_offset * int(mpi_real_prec_size, i8)
605  call this%read_field(fh, byte_offset, abz1%x, nel)
606  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
607  byte_offset = mpi_offset + &
608  dof_offset * int(mpi_real_prec_size, i8)
609  call this%read_field(fh, byte_offset, abz2%x, nel)
610  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
611  end if
612  if (read_scalarlag .and. have_scalarlag .eq. 1) then
613  do i = 1, slag%size()
614  byte_offset = mpi_offset + &
615  dof_offset * int(mpi_real_prec_size, i8)
616  call this%read_field(fh, byte_offset, slag%lf(i)%x, nel)
617  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
618  end do
619  byte_offset = mpi_offset + &
620  dof_offset * int(mpi_real_prec_size, i8)
621  call this%read_field(fh, byte_offset, abs1%x, nel)
622  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
623  byte_offset = mpi_offset + &
624  dof_offset * int(mpi_real_prec_size, i8)
625  call this%read_field(fh, byte_offset, abs2%x, nel)
626  mpi_offset = mpi_offset + n_glb_dofs * int(mpi_real_prec_size, i8)
627  end if
628 
629  call mpi_file_close(fh, ierr)
630 
631  call this%global_interp%free()
632  call this%space_interp%free()
633 
634  end subroutine chkp_file_read
635 
636  subroutine chkp_read_field(this, fh, byte_offset, x, nel)
637  class(chkp_file_t) :: this
638  type(mpi_file) :: fh
639  integer(kind=MPI_OFFSET_KIND) :: byte_offset
640  integer, intent(in) :: nel
641  real(kind=rp) :: x(this%sim_Xh%lxyz, nel)
642  real(kind=rp), allocatable :: read_array(:)
643  integer :: nel_stride, frac_space
644  type(mpi_status) :: status
645  integer :: ierr
646 
647  allocate(read_array(this%chkp_Xh%lxyz*nel))
648 
649  call rzero(read_array,this%chkp_xh%lxyz*nel)
650  call mpi_file_read_at_all(fh, byte_offset, read_array, &
651  nel*this%chkp_Xh%lxyz, mpi_real_precision, status, ierr)
652  if (this%mesh2mesh) then
653  x = 0.0_rp
654  call this%global_interp%evaluate(x,read_array)
655 
656  else
657  call this%space_interp%map_host(x, read_array, nel, this%sim_Xh)
658  end if
659  deallocate(read_array)
660  end subroutine chkp_read_field
661 
662 end module chkp_file
double real
Definition: device_config.h:12
Defines a checkpoint.
Definition: checkpoint.f90:34
Neko checkpoint file format.
Definition: chkp_file.f90:35
subroutine chkp_file_write(this, data, t)
Write a Neko checkpoint.
Definition: chkp_file.f90:71
subroutine chkp_file_read(this, data)
Load a checkpoint from file.
Definition: chkp_file.f90:347
subroutine chkp_read_field(this, fh, byte_offset, x, nel)
Definition: chkp_file.f90:637
Definition: comm.F90:1
type(mpi_comm) neko_comm
MPI communicator.
Definition: comm.F90:16
type(mpi_datatype) mpi_real_precision
MPI type for working precision of REAL types.
Definition: comm.F90:22
Defines a mapping of the degrees of freedom.
Definition: dofmap.f90:35
Stores a series fields.
Defines a field.
Definition: field.f90:34
Implements global_interpolation given a dofmap.
Routines to interpolate between different spaces.
Definition: math.f90:60
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:61
integer, public mpi_real_prec_size
Size of working precision REAL types.
Definition: mpi_types.f90:65
integer, public mpi_integer_size
Size of MPI type integer.
Definition: mpi_types.f90:63
integer, parameter, public i8
Definition: num_types.f90:7
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
Utilities.
Definition: utils.f90:35
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition: utils.f90:55
Interface for Neko checkpoint files.
Definition: chkp_file.f90:55
A generic file handler.
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:62