Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
checkpoint.f90
Go to the documentation of this file.
1! Copyright (c) 2021, 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
39 use space, only : space_t, operator(.ne.)
42 use field, only : field_t, field_ptr_t
43 use utils, only : neko_error
44 use mesh, only : mesh_t
45 use math, only : neko_eps
47 use time_state, only : time_state_t
48 implicit none
49 private
50
51 type, public :: chkp_t
52 type(field_t), pointer :: u => null()
53 type(field_t), pointer :: v => null()
54 type(field_t), pointer :: w => null()
55 type(field_t), pointer :: p => null()
56
57
58 !
59 ! Optional payload
60 !
61 type(field_series_t), pointer :: ulag => null()
62 type(field_series_t), pointer :: vlag => null()
63 type(field_series_t), pointer :: wlag => null()
64
65 real(kind=rp), pointer :: tlag(:) => null()
66 real(kind=rp), pointer :: dtlag(:) => null()
67
69 type(field_t), pointer :: abx1 => null()
70 type(field_t), pointer :: abx2 => null()
71 type(field_t), pointer :: aby1 => null()
72 type(field_t), pointer :: aby2 => null()
73 type(field_t), pointer :: abz1 => null()
74 type(field_t), pointer :: abz2 => null()
75
76 type(field_t), pointer :: s => null()
77 type(field_series_t), pointer :: slag => null()
78 type(field_t), pointer :: abs1 => null()
79 type(field_t), pointer :: abs2 => null()
80
81 type(field_series_list_t) :: scalar_lags
82
84 type(field_ptr_t), allocatable :: scalar_abx1(:)
85 type(field_ptr_t), allocatable :: scalar_abx2(:)
86
87 real(kind=dp) :: t = 0d0
88 type(mesh_t) :: previous_mesh
89 type(space_t) :: previous_xh
90 real(kind=dp) :: mesh2mesh_tol = glob_interp_tol
91
93 type(field_t), pointer :: wm_x => null()
94 type(field_t), pointer :: wm_y => null()
95 type(field_t), pointer :: wm_z => null()
96 type(field_series_t), pointer :: wm_x_lag => null()
97 type(field_series_t), pointer :: wm_y_lag => null()
98 type(field_series_t), pointer :: wm_z_lag => null()
99 real(kind=rp), pointer :: msh_x(:,:,:,:) => null()
100 real(kind=rp), pointer :: msh_y(:,:,:,:) => null()
101 real(kind=rp), pointer :: msh_z(:,:,:,:) => null()
102 real(kind=rp), pointer :: pivot_pos(:) => null()
103 real(kind=rp), pointer :: pivot_vel_lag(:,:) => null()
104 real(kind=rp), pointer :: blag(:,:,:,:) => null()
105 real(kind=rp), pointer :: blaglag(:,:,:,:) => null()
106 real(kind=rp), pointer :: basis_pos(:) => null()
107 real(kind=rp), pointer :: basis_vel_lag(:,:) => null()
108 contains
109 procedure, pass(this) :: init => chkp_init
110 procedure, pass(this) :: sync_host => chkp_sync_host
111 procedure, pass(this) :: sync_device => chkp_sync_device
112 procedure, pass(this) :: add_fluid => chkp_add_fluid
113 procedure, pass(this) :: add_lag => chkp_add_lag
114 procedure, pass(this) :: add_scalar => chkp_add_scalar
115 procedure, pass(this) :: add_ale => chkp_add_ale
116 procedure, pass(this) :: restart_time => chkp_restart_time
117 procedure, pass(this) :: set_time_state => chkp_set_time_state
118 procedure, pass(this) :: free => chkp_free
119 end type chkp_t
120
121contains
122
124 subroutine chkp_init(this)
125 class(chkp_t), intent(inout) :: this
126
127 ! Make sure the object is clean
128 call this%free()
129
130 end subroutine chkp_init
131
133 subroutine chkp_free(this)
134 class(chkp_t), intent(inout) :: this
135
136 this%t = 0d0
137
138 if (associated(this%u)) nullify(this%u)
139 if (associated(this%v)) nullify(this%v)
140 if (associated(this%w)) nullify(this%w)
141 if (associated(this%p)) nullify(this%p)
142
143 if (associated(this%ulag)) nullify(this%ulag)
144 if (associated(this%vlag)) nullify(this%vlag)
145 if (associated(this%wlag)) nullify(this%wlag)
146
147 if (associated(this%tlag)) nullify(this%tlag)
148 if (associated(this%dtlag)) nullify(this%dtlag)
149
150 ! ALE cleanup
151 if (associated(this%wm_x)) nullify(this%wm_x)
152 if (associated(this%wm_y)) nullify(this%wm_y)
153 if (associated(this%wm_z)) nullify(this%wm_z)
154 if (associated(this%wm_x_lag)) nullify(this%wm_x_lag)
155 if (associated(this%wm_y_lag)) nullify(this%wm_y_lag)
156 if (associated(this%wm_z_lag)) nullify(this%wm_z_lag)
157 if (associated(this%basis_vel_lag)) nullify(this%basis_vel_lag)
158 if (associated(this%msh_x)) nullify(this%msh_x)
159 if (associated(this%msh_y)) nullify(this%msh_y)
160 if (associated(this%msh_z)) nullify(this%msh_z)
161 if (associated(this%pivot_pos)) nullify(this%pivot_pos)
162 if (associated(this%pivot_vel_lag)) nullify(this%pivot_vel_lag)
163 if (associated(this%Blag)) nullify(this%Blag)
164 if (associated(this%Blaglag)) nullify(this%Blaglag)
165 if (associated(this%basis_pos)) nullify(this%basis_pos)
166
167 if (associated(this%abx1)) nullify(this%abx1)
168 if (associated(this%abx2)) nullify(this%abx2)
169 if (associated(this%aby1)) nullify(this%aby1)
170 if (associated(this%aby2)) nullify(this%aby2)
171 if (associated(this%abz1)) nullify(this%abz1)
172 if (associated(this%abz2)) nullify(this%abz2)
173
174 if (associated(this%s)) nullify(this%s)
175 if (associated(this%slag)) nullify(this%slag)
176 if (associated(this%abs1)) nullify(this%abs1)
177 if (associated(this%abs2)) nullify(this%abs2)
178
179 call this%scalar_lags%free()
180
181 if (allocated(this%scalar_abx1)) then
182 deallocate(this%scalar_abx1)
183 end if
184
185 if (allocated(this%scalar_abx2)) then
186 deallocate(this%scalar_abx2)
187 end if
188
189 call this%previous_mesh%free()
190 call this%previous_Xh%free()
191
192 end subroutine chkp_free
193
195 subroutine chkp_sync_host(this)
196 class(chkp_t), intent(inout) :: this
197 integer :: i, j
198
199 if (neko_bcknd_device .eq. 1) then
200 associate(u => this%u, v => this%v, w => this%w, &
201 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
202 p => this%p)
203
204 if (associated(this%u) .and. associated(this%v) .and. &
205 associated(this%w) .and. associated(this%p)) then
206 call u%copy_from(device_to_host, sync = .false.)
207 call v%copy_from(device_to_host, sync = .false.)
208 call w%copy_from(device_to_host, sync = .false.)
209 call p%copy_from(device_to_host, sync = .false.)
210 end if
211
212 if (associated(this%ulag) .and. associated(this%vlag) .and. &
213 associated(this%wlag)) then
214 call ulag%lf(1)%copy_from(device_to_host, sync = .false.)
215 call ulag%lf(2)%copy_from(device_to_host, sync = .false.)
216
217 call vlag%lf(1)%copy_from(device_to_host, sync = .false.)
218 call vlag%lf(2)%copy_from(device_to_host, sync = .false.)
219
220 call wlag%lf(1)%copy_from(device_to_host, sync = .false.)
221 call wlag%lf(2)%copy_from(device_to_host, sync = .false.)
222 call this%abx1%copy_from(device_to_host, sync = .false.)
223 call this%abx2%copy_from(device_to_host, sync = .false.)
224 call this%aby1%copy_from(device_to_host, sync = .false.)
225 call this%aby2%copy_from(device_to_host, sync = .false.)
226 call this%abz1%copy_from(device_to_host, sync = .false.)
227 call this%abz2%copy_from(device_to_host, sync = .false.)
228 end if
229
230 if (associated(this%s)) then
231 call this%s%copy_from(device_to_host, sync = .false.)
232 call this%slag%lf(1)%copy_from(device_to_host, sync = .false.)
233 call this%slag%lf(2)%copy_from(device_to_host, sync = .false.)
234 call this%abs1%copy_from(device_to_host, sync = .false.)
235 call this%abs2%copy_from(device_to_host, sync = .false.)
236 end if
237
238 ! ALE field synchronization
239 if (associated(this%wm_x) .and. associated(this%wm_y) .and. &
240 associated(this%wm_z)) then
241 call this%wm_x%copy_from(device_to_host, sync = .false.)
242 call this%wm_y%copy_from(device_to_host, sync = .false.)
243 call this%wm_z%copy_from(device_to_host, sync = .false.)
244
245 if (associated(this%wm_x_lag) .and. associated(this%wm_y_lag) &
246 .and. associated(this%wm_z_lag)) then
247
248 call this%wm_x_lag%lf(1)%copy_from(device_to_host, &
249 sync = .false.)
250 call this%wm_x_lag%lf(2)%copy_from(device_to_host, &
251 sync = .false.)
252
253 call this%wm_y_lag%lf(1)%copy_from(device_to_host, &
254 sync = .false.)
255 call this%wm_y_lag%lf(2)%copy_from(device_to_host, &
256 sync = .false.)
257
258 call this%wm_z_lag%lf(1)%copy_from(device_to_host, &
259 sync = .false.)
260 call this%wm_z_lag%lf(2)%copy_from(device_to_host, &
261 sync = .false.)
262 end if
263 end if
264
265 ! Multi-scalar lag field synchronization
266 do i = 1, this%scalar_lags%size()
267 block
268 type(field_series_t), pointer :: slag
269 integer :: slag_size
270 slag => this%scalar_lags%get(i)
271 slag_size = slag%size()
272 do j = 1, slag_size
273 call slag%lf(j)%copy_from(device_to_host, sync = .false.)
274 end do
275 end block
276 end do
277
278 ! Multi-scalar ABX field synchronization
279 if (allocated(this%scalar_abx1) .and. allocated(this%scalar_abx2)) then
280 do i = 1, size(this%scalar_abx1)
281 call this%scalar_abx1(i)%ptr%copy_from(device_to_host, &
282 sync = .false.)
283 call this%scalar_abx2(i)%ptr%copy_from(device_to_host, &
284 sync = .false.)
285 end do
286 end if
287 end associate
288 call device_sync(glb_cmd_queue)
289 end if
290
291 end subroutine chkp_sync_host
292
294 subroutine chkp_sync_device(this)
295 class(chkp_t), intent(inout) :: this
296 integer :: i, j
297
298 if (neko_bcknd_device .eq. 1) then
299 associate(u => this%u, v => this%v, w => this%w, &
300 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
301 p => this%p)
302
303 if (associated(this%u) .and. associated(this%v) .and. &
304 associated(this%w)) then
305 call u%copy_from(host_to_device, sync = .false.)
306 call v%copy_from(host_to_device, sync = .false.)
307 call w%copy_from(host_to_device, sync = .false.)
308 call p%copy_from(host_to_device, sync = .false.)
309 end if
310
311 if (associated(this%ulag) .and. associated(this%vlag) .and. &
312 associated(this%wlag)) then
313 call ulag%lf(1)%copy_from(host_to_device, sync = .false.)
314 call ulag%lf(2)%copy_from(host_to_device, sync = .false.)
315
316 call vlag%lf(1)%copy_from(host_to_device, sync = .false.)
317 call vlag%lf(2)%copy_from(host_to_device, sync = .false.)
318
319 call wlag%lf(1)%copy_from(host_to_device, sync = .false.)
320 call wlag%lf(2)%copy_from(host_to_device, sync = .false.)
321 end if
322
323 if (associated(this%s)) then
324 call this%s%copy_from(host_to_device, sync = .false.)
325
326 call this%slag%lf(1)%copy_from(host_to_device, sync = .false.)
327 call this%slag%lf(2)%copy_from(host_to_device, sync = .false.)
328 call this%abs1%copy_from(host_to_device, sync = .false.)
329 call this%abs2%copy_from(host_to_device, sync = .false.)
330 end if
331
332 ! ALE field synchronization
333 if (associated(this%wm_x) .and. associated(this%wm_y) .and. &
334 associated(this%wm_z)) then
335 call this%wm_x%copy_from(host_to_device, sync = .false.)
336 call this%wm_y%copy_from(host_to_device, sync = .false.)
337 call this%wm_z%copy_from(host_to_device, sync = .false.)
338 if (associated(this%wm_x_lag) .and. associated(this%wm_y_lag) .and. &
339 associated(this%wm_z_lag)) then
340 call this%wm_x_lag%lf(1)%copy_from(host_to_device, &
341 sync = .false.)
342 call this%wm_x_lag%lf(2)%copy_from(host_to_device, &
343 sync = .false.)
344
345 call this%wm_y_lag%lf(1)%copy_from(host_to_device, &
346 sync = .false.)
347 call this%wm_y_lag%lf(2)%copy_from(host_to_device, &
348 sync = .false.)
349
350 call this%wm_z_lag%lf(1)%copy_from(host_to_device, &
351 sync = .false.)
352 call this%wm_z_lag%lf(2)%copy_from(host_to_device, &
353 sync = .false.)
354 end if
355 end if
356
357 ! Multi-scalar lag field synchronization
358 if (allocated(this%scalar_lags%items) .and. &
359 this%scalar_lags%size() > 0) then
360 do i = 1, this%scalar_lags%size()
361 block
362 type(field_series_t), pointer :: slag
363 integer :: slag_size, dof_size
364 slag => this%scalar_lags%get(i)
365 slag_size = slag%size()
366 dof_size = slag%f%dof%size()
367 do j = 1, slag_size
368 call slag%lf(j)%copy_from(host_to_device, sync = .false.)
369 end do
370 end block
371 end do
372 end if
373
374 ! Multi-scalar ABX field synchronization
375 if (allocated(this%scalar_abx1) .and. allocated(this%scalar_abx2)) then
376 do i = 1, size(this%scalar_abx1)
377 call this%scalar_abx1(i)%ptr%copy_from(host_to_device, &
378 sync = .false.)
379 call this%scalar_abx2(i)%ptr%copy_from(host_to_device, &
380 sync = .false.)
381 end do
382 end if
383 end associate
384 end if
385
386 end subroutine chkp_sync_device
387
389 subroutine chkp_add_fluid(this, u, v, w, p)
390 class(chkp_t), intent(inout) :: this
391 type(field_t), target :: u
392 type(field_t), target :: v
393 type(field_t), target :: w
394 type(field_t), target :: p
395
396 ! Check that all velocity components are defined on the same
397 ! function space
398 if ( u%Xh .ne. v%Xh .or. &
399 u%Xh .ne. w%Xh ) then
400 call neko_error('Different function spaces for each velocity component')
401 end if
402
403 ! Check that both velocity and pressure is defined on the same mesh
404 if ( u%msh%nelv .ne. p%msh%nelv ) then
405 call neko_error('Velocity and pressure defined on different meshes')
406 end if
407
408 this%u => u
409 this%v => v
410 this%w => w
411 this%p => p
412
413 end subroutine chkp_add_fluid
414
416 subroutine chkp_add_lag(this, ulag, vlag, wlag)
417 class(chkp_t), intent(inout) :: this
418 type(field_series_t), target :: ulag
419 type(field_series_t), target :: vlag
420 type(field_series_t), target :: wlag
421
422 this%ulag => ulag
423 this%vlag => vlag
424 this%wlag => wlag
425
426 end subroutine chkp_add_lag
427
428
429
431 subroutine chkp_add_scalar(this, s, slag, abs1, abs2)
432 class(chkp_t), intent(inout) :: this
433 type(field_t), target, intent(in) :: s
434 type(field_series_t), target, intent(in) :: slag
435 type(field_t), target, intent(in), optional :: abs1, abs2
436
437 this%s => s
438 this%slag => slag
439
440 if (present(abs1)) this%abs1 => abs1
441 if (present(abs2)) this%abs2 => abs2
442
443 end subroutine chkp_add_scalar
444
446 subroutine chkp_add_ale(this, x, y, z, Blag, Blaglag, wm_x, wm_y, wm_z, &
447 wm_x_lag, wm_y_lag, wm_z_lag, pivot_pos, pivot_vel_lag, basis_pos, &
448 basis_vel_lag)
449 class(chkp_t), intent(inout) :: this
450 type(field_t), target, intent(in) :: wm_x, wm_y, wm_z
451 real(kind=rp), intent(in), pointer :: pivot_pos(:), pivot_vel_lag(:,:)
452 type(field_series_t), target, intent(in) :: wm_x_lag, wm_y_lag, wm_z_lag
453 real(kind=rp), intent(in), pointer :: x(:,:,:,:), y(:,:,:,:), z(:,:,:,:)
454 real(kind=rp), pointer, intent(in) :: blag(:,:,:,:), blaglag(:,:,:,:)
455 real(kind=rp), intent(in), pointer :: basis_pos(:)
456 real(kind=rp), intent(in), pointer :: basis_vel_lag(:,:)
457
458 this%msh_x => x
459 this%msh_y => y
460 this%msh_z => z
461 this%wm_x => wm_x
462 this%wm_y => wm_y
463 this%wm_z => wm_z
464 this%wm_x_lag => wm_x_lag
465 this%wm_y_lag => wm_y_lag
466 this%wm_z_lag => wm_z_lag
467 this%Blag => blag
468 this%Blaglag => blaglag
469 this%pivot_pos => pivot_pos
470 this%pivot_vel_lag => pivot_vel_lag
471 this%basis_pos => basis_pos
472 this%basis_vel_lag => basis_vel_lag
473 end subroutine chkp_add_ale
474
476 pure function chkp_restart_time(this) result(rtime)
477 class(chkp_t), intent(in) :: this
478 real(kind=dp) :: rtime
479
480 rtime = this%t
481 end function chkp_restart_time
482
484 subroutine chkp_set_time_state(this, time_state)
485 class(chkp_t), intent(in) :: this
486 type(time_state_t), intent(inout) :: time_state
487
488 time_state%t = this%t
489 time_state%dtlag = this%dtlag
490 time_state%tlag = this%tlag
491 end subroutine chkp_set_time_state
492
493end module checkpoint
Copy data between host and device (or device and device)
Definition device.F90:71
Synchronize a device or stream.
Definition device.F90:113
Defines a checkpoint.
subroutine chkp_sync_host(this)
Synchronize checkpoint with device.
subroutine chkp_set_time_state(this, time_state)
Set time state.
subroutine chkp_sync_device(this)
Synchronize device with checkpoint.
subroutine chkp_add_ale(this, x, y, z, blag, blaglag, wm_x, wm_y, wm_z, wm_x_lag, wm_y_lag, wm_z_lag, pivot_pos, pivot_vel_lag, basis_pos, basis_vel_lag)
Add mesh velocity and other required variables to checkpointing for ALE.
pure real(kind=dp) function chkp_restart_time(this)
Return restart time from a loaded checkpoint.
subroutine chkp_free(this)
Reset checkpoint.
subroutine chkp_add_lag(this, ulag, vlag, wlag)
Add lagged velocity terms.
subroutine chkp_add_fluid(this, u, v, w, p)
Add a fluid to the checkpoint.
subroutine chkp_init(this)
Initialize checkpoint structure with mandatory data.
subroutine chkp_add_scalar(this, s, slag, abs1, abs2)
Add a scalar to checkpointing.
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:47
integer, parameter, public device_to_host
Definition device.F90:47
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
Definition device.F90:51
Contains the field_series_list_t type for managing multiple field series.
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Implements global_interpolation given a dofmap.
real(kind=dp), parameter, public glob_interp_tol
Definition math.f90:60
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.f90:70
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
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
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
field_ptr_t, To easily obtain a pointer to a field
Definition field.f90:83
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
A list of field series pointers, used for managing multiple scalar lag fields.
The function space for the SEM solution fields.
Definition space.f90:63
A struct that contains all info about the time, expand as needed.