Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
field.f90
Go to the documentation of this file.
1! Copyright (c) 2018-2025, 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!
34module field
37 use num_types, only : rp, c_rp
39 use math, only : add2, copy, cadd, cfill
40 use mesh, only : mesh_t
41 use space, only : space_t, operator(.ne.)
42 use dofmap, only : dofmap_t
43 use, intrinsic :: iso_c_binding
44 implicit none
45 private
46
47 type, public :: field_t
48 real(kind=rp), allocatable :: x(:,:,:,:)
49
50 type(space_t), pointer :: xh
51 type(mesh_t), pointer :: msh
52 type(dofmap_t), pointer :: dof
53
54 logical :: internal_dofmap = .false.
55 character(len=80) :: name = ""
56 type(c_ptr) :: x_d = c_null_ptr
57 contains
58 procedure, private, pass(this) :: init_common => field_init_common
59 procedure, private, pass(this) :: init_external_dof => &
61 procedure, private, pass(this) :: init_internal_dof => &
63 procedure, private, pass(this) :: assign_field => field_assign_field
64 procedure, private, pass(this) :: assign_scalar => field_assign_scalar
65 procedure, private, pass(this) :: add_field => field_add_field
66 procedure, private, pass(this) :: add_scalar => field_add_scalar
67 procedure, pass(this) :: copy_from => field_copy_from
68 procedure, pass(this) :: free => field_free
70 procedure, pass(this) :: size => field_size
72 generic :: init => init_external_dof, init_internal_dof
74 generic :: assignment(=) => assign_field, assign_scalar
78 generic :: add => add_field, add_scalar
79 end type field_t
80
82 type, public :: field_ptr_t
83 type(field_t), pointer :: ptr => null()
84 contains
86 procedure, pass(this) :: init => field_ptr_init
88 procedure, pass(this) :: free => field_ptr_free
89 end type field_ptr_t
90
92 type, public :: field_wrapper_t
93 type(field_t), pointer :: field => null()
94 contains
96 generic :: init => init_field, init_internal_dof, init_external_dof
98 procedure, pass(this) :: init_field => field_wrapper_init_field
100 procedure, pass(this) :: init_internal_dof => &
103 procedure, pass(this) :: init_external_dof => &
106 procedure, pass(this) :: free => field_wrapper_free
107 end type field_wrapper_t
108
109contains
110
112 subroutine field_init_internal_dof(this, msh, space, fld_name)
113 class(field_t), intent(inout) :: this
114 type(mesh_t), target, intent(in) :: msh
115 type(space_t), target, intent(in) :: space
116 character(len=*), optional :: fld_name
117
118 call this%free()
119
120 this%Xh => space
121 this%msh => msh
122
123 allocate(this%dof)
124 call this%dof%init(this%msh, this%Xh)
125 this%internal_dofmap = .true.
126
127 if (present(fld_name)) then
128 call this%init_common(fld_name)
129 else
130 call this%init_common()
131 end if
132
133 end subroutine field_init_internal_dof
134
136 subroutine field_init_external_dof(this, dof, fld_name)
137 class(field_t), intent(inout) :: this
138 type(dofmap_t), target, intent(in) :: dof
139 character(len=*), optional :: fld_name
140
141 call this%free()
142
143 this%dof => dof
144 this%Xh => dof%Xh
145 this%msh => dof%msh
146
147 if (present(fld_name)) then
148 call this%init_common(fld_name)
149 else
150 call this%init_common()
151 end if
152
153 end subroutine field_init_external_dof
154
156 subroutine field_init_common(this, fld_name)
157 class(field_t), intent(inout) :: this
158 character(len=*), optional :: fld_name
159 integer :: ierr
160 integer :: n
161
162 associate(lx => this%Xh%lx, ly => this%Xh%ly, &
163 lz => this%Xh%lz, nelv => this%msh%nelv)
164
165 if (.not. allocated(this%x)) then
166 allocate(this%x(lx, ly, lz, nelv), stat = ierr)
167 this%x = 0.0_rp
168 end if
169
170 if (present(fld_name)) then
171 this%name = fld_name
172 else
173 this%name = "Field"
174 end if
175
176 if (neko_bcknd_device .eq. 1) then
177 n = lx * ly * lz * nelv
178 call device_map(this%x, this%x_d, n)
179 block
180 real(c_rp) :: rp_dummy
181 integer(c_size_t) :: s
182 s = c_sizeof(rp_dummy) * n
183 call device_memset(this%x_d, 0, s, sync = .true.)
184 end block
185 end if
186 end associate
187
188 end subroutine field_init_common
189
191 subroutine field_free(this)
192 class(field_t), intent(inout) :: this
193
194 this%name = ""
195 if (allocated(this%x)) then
196 deallocate(this%x)
197 end if
198
199 if (this%internal_dofmap) then
200 call this%dof%free()
201 deallocate(this%dof)
202 this%internal_dofmap = .false.
203 end if
204
205 nullify(this%msh)
206 nullify(this%Xh)
207 nullify(this%dof)
208
209 if (c_associated(this%x_d)) then
210 call device_free(this%x_d)
211 end if
212
213 end subroutine field_free
214
219 subroutine field_copy_from(this, memdir, sync)
220 class(field_t), intent(inout) :: this
221 integer, intent(in) :: memdir
222 logical, intent(in) :: sync
223
224 if (neko_bcknd_device .eq. 1) then
225 call device_memcpy(this%x, this%x_d, this%size(), memdir, sync)
226 end if
227
228 end subroutine field_copy_from
229
230
234 subroutine field_assign_field(this, g)
235 class(field_t), intent(inout) :: this
236 type(field_t), intent(in) :: g
237
238 if (allocated(this%x)) then
239 if (.not. associated(this%Xh, g%Xh)) then
240 call this%free()
241 end if
242 end if
243
244 this%Xh => g%Xh
245 this%msh => g%msh
246 if (len_trim(this%name) == 0) then
247 this%name = g%name
248 end if
249
250 if (.not. g%internal_dofmap) then
251 this%dof => g%dof
252 else
253 if (this%internal_dofmap) then
254 call this%dof%free()
255 else
256 allocate(this%dof)
257 this%internal_dofmap = .true.
258 end if
259 call this%dof%init(this%msh, this%Xh)
260 end if
261
262 if (.not. allocated(this%x)) then
263
264 allocate(this%x(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
265
266 if (neko_bcknd_device .eq. 1) then
267 call device_map(this%x, this%x_d, this%size())
268 end if
269
270 end if
271
272 if (neko_bcknd_device .eq. 1) then
273 call device_copy(this%x_d, g%x_d, this%size())
274 else
275 call copy(this%x, g%x, this%dof%size())
276 end if
277
278 end subroutine field_assign_field
279
281 subroutine field_assign_scalar(this, a)
282 class(field_t), intent(inout) :: this
283 real(kind=rp), intent(in) :: a
284 integer :: i, j, k, l
285
286 if (neko_bcknd_device .eq. 1) then
287 call device_cfill(this%x_d, a, this%size())
288 else
289 call cfill(this%x, a, this%size())
290 end if
291
292 end subroutine field_assign_scalar
293
297 subroutine field_add_field(this, g)
298 class(field_t), intent(inout) :: this
299 type(field_t), intent(in) :: g
300
301 if (neko_bcknd_device .eq. 1) then
302 call device_add2(this%x_d, g%x_d, this%size())
303 else
304 call add2(this%x, g%x, this%size())
305 end if
306
307 end subroutine field_add_field
308
309
312 subroutine field_add_scalar(this, a)
313 class(field_t), intent(inout) :: this
314 real(kind=rp), intent(in) :: a
315
316 if (neko_bcknd_device .eq. 1) then
317 call device_cadd(this%x_d, a, this%size())
318 else
319 call cadd(this%x, a, this%size())
320 end if
321
322 end subroutine field_add_scalar
323
325 pure function field_size(this) result(size)
326 class(field_t), intent(in) :: this
327 integer :: size
328
329 size = this%dof%size()
330 end function field_size
331
332 ! ========================================================================== !
333 ! Field pointer type subroutines
334
335 subroutine field_ptr_init(this, ptr)
336 class(field_ptr_t), intent(inout) :: this
337 type(field_t), target, intent(in) :: ptr
338
339 call this%free()
340
341 this%ptr => ptr
342
343 end subroutine field_ptr_init
344
345 subroutine field_ptr_free(this)
346 class(field_ptr_t), intent(inout) :: this
347
348 if (associated(this%ptr)) then
349 nullify(this%ptr)
350 end if
351
352 end subroutine field_ptr_free
353
354 ! ========================================================================== !
355 ! Field wrapper type subroutines
356
357 subroutine field_wrapper_init_field(this, f)
358 class(field_wrapper_t), intent(inout) :: this
359 type(field_t), intent(in) :: f
360
361 call this%free()
362 allocate(this%field)
363 this%field = f
364
365 end subroutine field_wrapper_init_field
366
367 subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
368 class(field_wrapper_t), intent(inout) :: this
369 type(mesh_t), target, intent(in) :: msh
370 type(space_t), target, intent(in) :: space
371 character(len=*), optional :: fld_name
372
373 call this%free()
374 allocate(this%field)
375 call this%field%init(msh, space, fld_name)
376
378
379 subroutine field_wrapper_init_external_dof(this, dof, fld_name)
380 class(field_wrapper_t), intent(inout) :: this
381 type(dofmap_t), target, intent(in) :: dof
382 character(len=*), optional :: fld_name
383
384 call this%free()
385 allocate(this%field)
386 call this%field%init(dof, fld_name)
387
389
390 subroutine field_wrapper_free(this)
391 class(field_wrapper_t), intent(inout) :: this
392
393 if (associated(this%field)) then
394 call this%field%free()
395 deallocate(this%field)
396 end if
397
398 end subroutine field_wrapper_free
399
400end module field
Map a Fortran array to a device (allocate and associate)
Definition device.F90:77
Copy data between host and device (or device and device)
Definition device.F90:71
subroutine, public device_add2(a_d, b_d, n, strm)
Vector addition .
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
subroutine, public device_cfill(a_d, c, n, strm)
Set all elements to a constant c .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition device.F90:219
subroutine, public device_memset(x_d, v, s, sync, strm)
Set memory on the device to a value.
Definition device.F90:238
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
subroutine field_add_field(this, g)
Add .
Definition field.f90:298
pure integer function field_size(this)
Return the size of the field based on the underlying dofmap.
Definition field.f90:326
subroutine field_assign_field(this, g)
Assignment .
Definition field.f90:235
subroutine field_wrapper_free(this)
Definition field.f90:391
subroutine field_add_scalar(this, a)
Add .
Definition field.f90:313
subroutine field_copy_from(this, memdir, sync)
Easy way to copy between host and device.
Definition field.f90:220
subroutine field_assign_scalar(this, a)
Assignment .
Definition field.f90:282
subroutine field_ptr_init(this, ptr)
Definition field.f90:336
subroutine field_ptr_free(this)
Definition field.f90:346
subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
Definition field.f90:368
subroutine field_init_common(this, fld_name)
Initialize a field this.
Definition field.f90:157
subroutine field_wrapper_init_external_dof(this, dof, fld_name)
Definition field.f90:380
subroutine field_wrapper_init_field(this, f)
Definition field.f90:358
subroutine field_init_external_dof(this, dof, fld_name)
Initialize a field this on the mesh msh using an internal dofmap.
Definition field.f90:137
subroutine field_init_internal_dof(this, msh, space, fld_name)
Initialize a field this on the mesh msh using an internal dofmap.
Definition field.f90:113
subroutine field_free(this)
Deallocate a field f.
Definition field.f90:192
Definition math.f90:60
subroutine, public cadd(a, s, n)
Add a scalar to vector .
Definition math.f90:462
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:726
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:487
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:249
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public c_rp
Definition num_types.f90:13
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a function space.
Definition space.f90:34
field_ptr_t, To easily obtain a pointer to a field
Definition field.f90:82
field_wrapper_t, used to wrap an allocated field for use in a field list
Definition field.f90:92
The function space for the SEM solution fields.
Definition space.f90:63