Neko 1.99.1
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!
35 use neko_config
36 use num_types, only : rp, dp
39 use space, only : space_t, operator(.ne.)
42 use field, only : field_t, field_ptr_t
44 use mesh, only: mesh_t
45 use math, only : neko_eps
46 implicit none
47 private
48
49 type, public :: chkp_t
50 type(field_t), pointer :: u => null()
51 type(field_t), pointer :: v => null()
52 type(field_t), pointer :: w => null()
53 type(field_t), pointer :: p => null()
54
55
56 !
57 ! Optional payload
58 !
59 type(field_series_t), pointer :: ulag => null()
60 type(field_series_t), pointer :: vlag => null()
61 type(field_series_t), pointer :: wlag => null()
62
63 real(kind=rp), pointer :: tlag(:) => null()
64 real(kind=rp), pointer :: dtlag(:) => null()
65
67 type(field_t), pointer :: abx1 => null()
68 type(field_t), pointer :: abx2 => null()
69 type(field_t), pointer :: aby1 => null()
70 type(field_t), pointer :: aby2 => null()
71 type(field_t), pointer :: abz1 => null()
72 type(field_t), pointer :: abz2 => null()
73
74 type(field_t), pointer :: s => null()
75 type(field_series_t), pointer :: slag => null()
76 type(field_t), pointer :: abs1 => null()
77 type(field_t), pointer :: abs2 => null()
78
79 type(field_series_list_t) :: scalar_lags
80
82 type(field_ptr_t), allocatable :: scalar_abx1(:)
83 type(field_ptr_t), allocatable :: scalar_abx2(:)
84
85 real(kind=dp) :: t
86 type(mesh_t) :: previous_mesh
87 type(space_t) :: previous_xh
88 real(kind=rp) :: mesh2mesh_tol = neko_eps*1e3_rp
89
90 contains
91 procedure, pass(this) :: init => chkp_init
92 procedure, pass(this) :: sync_host => chkp_sync_host
93 procedure, pass(this) :: sync_device => chkp_sync_device
94 procedure, pass(this) :: add_lag => chkp_add_lag
95 procedure, pass(this) :: add_scalar => chkp_add_scalar
96 procedure, pass(this) :: restart_time => chkp_restart_time
97 final :: chkp_free
98 end type chkp_t
99
100contains
101
103 subroutine chkp_init(this, u, v, w, p)
104 class(chkp_t), intent(inout) :: this
105 type(field_t), intent(in), target :: u
106 type(field_t), intent(in), target :: v
107 type(field_t), intent(in), target :: w
108 type(field_t), intent(in), target :: p
109
110 ! Check that all velocity components are defined on the same
111 ! function space
112 if ( u%Xh .ne. v%Xh .or. &
113 u%Xh .ne. w%Xh ) then
114 call neko_error('Different function spaces for each velocity component')
115 end if
116
117 ! Check that both velocity and pressure is defined on the same mesh
118 if ( u%msh%nelv .ne. p%msh%nelv ) then
119 call neko_error('Velocity and pressure defined on different meshes')
120 end if
121
122 this%u => u
123 this%v => v
124 this%w => w
125 this%p => p
126
127 this%t = 0d0
128
129 end subroutine chkp_init
130
132 subroutine chkp_free(this)
133 type(chkp_t), intent(inout) :: this
134
135 nullify(this%u)
136 nullify(this%v)
137 nullify(this%w)
138 nullify(this%p)
139
140 nullify(this%ulag)
141 nullify(this%vlag)
142 nullify(this%wlag)
143
144 ! Scalar cleanup
145 nullify(this%s)
146 nullify(this%slag)
147 nullify(this%abs1)
148 nullify(this%abs2)
149
150 ! Free scalar lag list if it was initialized
151 if (allocated(this%scalar_lags%items)) then
152 call this%scalar_lags%free()
153 end if
154
155 ! Free multi-scalar ABX field arrays
156 if (allocated(this%scalar_abx1)) then
157 deallocate(this%scalar_abx1)
158 end if
159 if (allocated(this%scalar_abx2)) then
160 deallocate(this%scalar_abx2)
161 end if
162
163 end subroutine chkp_free
164
166 subroutine chkp_sync_host(this)
167 class(chkp_t), intent(inout) :: this
168 integer :: i, j
169
170 if (neko_bcknd_device .eq. 1) then
171 associate(u=>this%u, v=>this%v, w=>this%w, &
172 ulag=>this%ulag, vlag=>this%vlag, wlag=>this%wlag, &
173 p=>this%p)
174
175 if (associated(this%u) .and. associated(this%v) .and. &
176 associated(this%w) .and. associated(this%p)) then
177 call device_memcpy(u%x, u%x_d, u%dof%size(), device_to_host, sync=.false.)
178 call device_memcpy(v%x, v%x_d, v%dof%size(), device_to_host, sync=.false.)
179 call device_memcpy(w%x, w%x_d, w%dof%size(), device_to_host, sync=.false.)
180 call device_memcpy(p%x, p%x_d, p%dof%size(), device_to_host, sync=.false.)
181 end if
182
183 if (associated(this%ulag) .and. associated(this%vlag) .and. &
184 associated(this%wlag)) then
185 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, &
186 u%dof%size(), device_to_host, sync=.false.)
187 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, &
188 u%dof%size(), device_to_host, sync=.false.)
189
190 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, &
191 v%dof%size(), device_to_host, sync=.false.)
192 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, &
193 v%dof%size(), device_to_host, sync=.false.)
194
195 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, &
196 w%dof%size(), device_to_host, sync=.false.)
197 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, &
198 w%dof%size(), device_to_host, sync=.false.)
199 call device_memcpy(this%abx1%x, this%abx1%x_d, &
200 w%dof%size(), device_to_host, sync=.false.)
201 call device_memcpy(this%abx2%x, this%abx2%x_d, &
202 w%dof%size(), device_to_host, sync=.false.)
203 call device_memcpy(this%aby1%x, this%aby1%x_d, &
204 w%dof%size(), device_to_host, sync=.false.)
205 call device_memcpy(this%aby2%x, this%aby2%x_d, &
206 w%dof%size(), device_to_host, sync=.false.)
207 call device_memcpy(this%abz1%x, this%abz1%x_d, &
208 w%dof%size(), device_to_host, sync=.false.)
209 call device_memcpy(this%abz2%x, this%abz2%x_d, &
210 w%dof%size(), device_to_host, sync=.false.)
211 end if
212 if (associated(this%s)) then
213 call device_memcpy(this%s%x, this%s%x_d, &
214 this%s%dof%size(), device_to_host, sync=.false.)
215 call device_memcpy(this%slag%lf(1)%x, this%slag%lf(1)%x_d, &
216 this%s%dof%size(), device_to_host, sync=.false.)
217 call device_memcpy(this%slag%lf(2)%x, this%slag%lf(2)%x_d, &
218 this%s%dof%size(), device_to_host, sync=.false.)
219 call device_memcpy(this%abs1%x, this%abs1%x_d, &
220 w%dof%size(), device_to_host, sync=.false.)
221 call device_memcpy(this%abs2%x, this%abs2%x_d, &
222 w%dof%size(), device_to_host, sync=.false.)
223 end if
224
225 ! Multi-scalar lag field synchronization
226 if (allocated(this%scalar_lags%items) .and. this%scalar_lags%size() > 0) then
227 do i = 1, this%scalar_lags%size()
228 block
229 type(field_series_t), pointer :: slag
230 integer :: slag_size, dof_size
231 slag => this%scalar_lags%get(i)
232 slag_size = slag%size()
233 dof_size = slag%f%dof%size()
234 do j = 1, slag_size
235 call device_memcpy(slag%lf(j)%x, slag%lf(j)%x_d, &
236 dof_size, device_to_host, sync=.false.)
237 end do
238 end block
239 end do
240 end if
241
242 ! Multi-scalar ABX field synchronization
243 if (allocated(this%scalar_abx1) .and. allocated(this%scalar_abx2)) then
244 do i = 1, size(this%scalar_abx1)
245 call device_memcpy(this%scalar_abx1(i)%ptr%x, this%scalar_abx1(i)%ptr%x_d, &
246 this%scalar_abx1(i)%ptr%dof%size(), device_to_host, sync=.false.)
247 call device_memcpy(this%scalar_abx2(i)%ptr%x, this%scalar_abx2(i)%ptr%x_d, &
248 this%scalar_abx2(i)%ptr%dof%size(), device_to_host, sync=.false.)
249 end do
250 end if
251 end associate
252 call device_sync(glb_cmd_queue)
253 end if
254
255 end subroutine chkp_sync_host
256
258 subroutine chkp_sync_device(this)
259 class(chkp_t), intent(inout) :: this
260 integer :: i, j
261
262 if (neko_bcknd_device .eq. 1) then
263 associate(u=>this%u, v=>this%v, w=>this%w, &
264 ulag=>this%ulag, vlag=>this%vlag, wlag=>this%wlag,&
265 p=>this%p)
266
267 if (associated(this%u) .and. associated(this%v) .and. &
268 associated(this%w)) then
269 call device_memcpy(u%x, u%x_d, u%dof%size(), &
270 host_to_device, sync=.false.)
271 call device_memcpy(v%x, v%x_d, v%dof%size(), &
272 host_to_device, sync=.false.)
273 call device_memcpy(w%x, w%x_d, w%dof%size(), &
274 host_to_device, sync=.false.)
275 call device_memcpy(p%x, p%x_d, p%dof%size(), &
276 host_to_device, sync=.false.)
277 end if
278
279 if (associated(this%ulag) .and. associated(this%vlag) .and. &
280 associated(this%wlag)) then
281 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, u%dof%size(), &
282 host_to_device, sync=.false.)
283 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, u%dof%size(), &
284 host_to_device, sync=.false.)
285
286 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, v%dof%size(), &
287 host_to_device, sync=.false.)
288 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, v%dof%size(), &
289 host_to_device, sync=.false.)
290
291 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, w%dof%size(), &
292 host_to_device, sync=.false.)
293 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, w%dof%size(), &
294 host_to_device, sync=.false.)
295 end if
296 if (associated(this%s)) then
297 call device_memcpy(this%s%x, this%s%x_d, this%s%dof%size(), &
298 host_to_device, sync=.false.)
299
300 call device_memcpy(this%slag%lf(1)%x, this%slag%lf(1)%x_d, &
301 this%s%dof%size(), host_to_device, sync=.false.)
302 call device_memcpy(this%slag%lf(2)%x, this%slag%lf(2)%x_d, &
303 this%s%dof%size(), host_to_device, sync=.false.)
304 call device_memcpy(this%abs1%x, this%abs1%x_d, &
305 w%dof%size(), host_to_device, sync=.false.)
306 call device_memcpy(this%abs2%x, this%abs2%x_d, &
307 w%dof%size(), host_to_device, sync=.false.)
308 end if
309
310 ! Multi-scalar lag field synchronization
311 if (allocated(this%scalar_lags%items) .and. this%scalar_lags%size() > 0) then
312 do i = 1, this%scalar_lags%size()
313 block
314 type(field_series_t), pointer :: slag
315 integer :: slag_size, dof_size
316 slag => this%scalar_lags%get(i)
317 slag_size = slag%size()
318 dof_size = slag%f%dof%size()
319 do j = 1, slag_size
320 call device_memcpy(slag%lf(j)%x, slag%lf(j)%x_d, &
321 dof_size, host_to_device, sync=.false.)
322 end do
323 end block
324 end do
325 end if
326
327 ! Multi-scalar ABX field synchronization
328 if (allocated(this%scalar_abx1) .and. allocated(this%scalar_abx2)) then
329 do i = 1, size(this%scalar_abx1)
330 call device_memcpy(this%scalar_abx1(i)%ptr%x, this%scalar_abx1(i)%ptr%x_d, &
331 this%scalar_abx1(i)%ptr%dof%size(), host_to_device, sync=.false.)
332 call device_memcpy(this%scalar_abx2(i)%ptr%x, this%scalar_abx2(i)%ptr%x_d, &
333 this%scalar_abx2(i)%ptr%dof%size(), host_to_device, sync=.false.)
334 end do
335 end if
336 end associate
337 end if
338
339 end subroutine chkp_sync_device
340
342 subroutine chkp_add_lag(this, ulag, vlag, wlag)
343 class(chkp_t), intent(inout) :: this
344 type(field_series_t), target :: ulag
345 type(field_series_t), target :: vlag
346 type(field_series_t), target :: wlag
347
348 this%ulag => ulag
349 this%vlag => vlag
350 this%wlag => wlag
351
352 end subroutine chkp_add_lag
353
354
355
357 subroutine chkp_add_scalar(this, s, slag, abs1, abs2)
358 class(chkp_t), intent(inout) :: this
359 type(field_t), target, intent(in) :: s
360 type(field_series_t), target, intent(in) :: slag
361 type(field_t), target, intent(in), optional :: abs1, abs2
362
363 this%s => s
364 this%slag => slag
365
366 if (present(abs1)) this%abs1 => abs1
367 if (present(abs2)) this%abs2 => abs2
368
369 end subroutine chkp_add_scalar
370
371
373 pure function chkp_restart_time(this) result(rtime)
374 class(chkp_t), intent(in) :: this
375 real(kind=dp) :: rtime
376
377 rtime = this%t
378 end function chkp_restart_time
379
380end module checkpoint
Copy data between host and device (or device and device)
Definition device.F90:71
Synchronize a device or stream.
Definition device.F90:107
Defines a checkpoint.
subroutine chkp_sync_host(this)
Synchronize checkpoint with device.
subroutine chkp_init(this, u, v, w, p)
Initialize checkpoint structure with mandatory data.
subroutine chkp_sync_device(this)
Synchronize device with checkpoint.
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_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
Definition math.f90:60
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.f90:69
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
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:58
field_ptr_t, To easily obtain a pointer to a field
Definition field.f90:82
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