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