Neko 1.99.3
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 utils, only : neko_varname_len
44 use, intrinsic :: iso_c_binding
45 implicit none
46 private
47
48 type, public :: field_t
49 real(kind=rp), allocatable :: x(:,:,:,:)
50
51 type(space_t), pointer :: xh
52 type(mesh_t), pointer :: msh
53 type(dofmap_t), pointer :: dof
54
55 logical :: internal_dofmap = .false.
56 character(len=NEKO_VARNAME_LEN) :: name = ""
57 type(c_ptr) :: x_d = c_null_ptr
58 contains
59 procedure, private, pass(this) :: init_common => field_init_common
60 procedure, private, pass(this) :: init_external_dof => &
62 procedure, private, pass(this) :: init_internal_dof => &
64 procedure, private, pass(this) :: assign_field => field_assign_field
65 procedure, private, pass(this) :: assign_scalar => field_assign_scalar
66 procedure, private, pass(this) :: add_field => field_add_field
67 procedure, private, pass(this) :: add_scalar => field_add_scalar
68 procedure, pass(this) :: copy_from => field_copy_from
69 procedure, pass(this) :: free => field_free
71 procedure, pass(this) :: size => field_size
73 generic :: init => init_external_dof, init_internal_dof
75 generic :: assignment(=) => assign_field, assign_scalar
79 generic :: add => add_field, add_scalar
80 end type field_t
81
83 type, public :: field_ptr_t
84 type(field_t), pointer :: ptr => null()
85 contains
87 procedure, pass(this) :: init => field_ptr_init
89 procedure, pass(this) :: free => field_ptr_free
90 end type field_ptr_t
91
93 type, public :: field_wrapper_t
94 type(field_t), pointer :: field => null()
95 contains
97 generic :: init => init_field, init_internal_dof, init_external_dof
99 procedure, pass(this) :: init_field => field_wrapper_init_field
101 procedure, pass(this) :: init_internal_dof => &
104 procedure, pass(this) :: init_external_dof => &
107 procedure, pass(this) :: free => field_wrapper_free
108 end type field_wrapper_t
109
110contains
111
113 subroutine field_init_internal_dof(this, msh, space, fld_name)
114 class(field_t), intent(inout) :: this
115 type(mesh_t), target, intent(in) :: msh
116 type(space_t), target, intent(in) :: space
117 character(len=*), optional :: fld_name
118
119 call this%free()
120
121 this%Xh => space
122 this%msh => msh
123
124 allocate(this%dof)
125 call this%dof%init(this%msh, this%Xh)
126 this%internal_dofmap = .true.
127
128 if (present(fld_name)) then
129 call this%init_common(fld_name)
130 else
131 call this%init_common()
132 end if
133
134 end subroutine field_init_internal_dof
135
137 subroutine field_init_external_dof(this, dof, fld_name)
138 class(field_t), intent(inout) :: this
139 type(dofmap_t), target, intent(in) :: dof
140 character(len=*), optional :: fld_name
141
142 call this%free()
143
144 this%dof => dof
145 this%Xh => dof%Xh
146 this%msh => dof%msh
147
148 if (present(fld_name)) then
149 call this%init_common(fld_name)
150 else
151 call this%init_common()
152 end if
153
154 end subroutine field_init_external_dof
155
157 subroutine field_init_common(this, fld_name)
158 class(field_t), intent(inout) :: this
159 character(len=*), optional :: fld_name
160 integer :: ierr
161 integer :: n
162
163 associate(lx => this%Xh%lx, ly => this%Xh%ly, &
164 lz => this%Xh%lz, nelv => this%msh%nelv)
165
166 if (.not. allocated(this%x)) then
167 allocate(this%x(lx, ly, lz, nelv), stat = ierr)
168 this%x = 0.0_rp
169 end if
170
171 if (present(fld_name)) then
172 this%name = fld_name
173 else
174 this%name = "Field"
175 end if
176
177 if (neko_bcknd_device .eq. 1) then
178 n = lx * ly * lz * nelv
179 call device_map(this%x, this%x_d, n)
180 block
181 real(c_rp) :: rp_dummy
182 integer(c_size_t) :: s
183 s = c_sizeof(rp_dummy) * n
184 call device_memset(this%x_d, 0, s, sync = .true.)
185 end block
186 end if
187 end associate
188
189 end subroutine field_init_common
190
192 subroutine field_free(this)
193 class(field_t), intent(inout) :: this
194
195 this%name = ""
196 if (allocated(this%x)) then
197 if (neko_bcknd_device .eq. 1) then
198 call device_unmap(this%x, this%x_d)
199 end if
200 deallocate(this%x)
201 end if
202
203 if (this%internal_dofmap) then
204 call this%dof%free()
205 deallocate(this%dof)
206 this%internal_dofmap = .false.
207 end if
208
209 nullify(this%msh)
210 nullify(this%Xh)
211 nullify(this%dof)
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
285 if (neko_bcknd_device .eq. 1) then
286 call device_cfill(this%x_d, a, this%size())
287 else
288 call cfill(this%x, a, this%size())
289 end if
290
291 end subroutine field_assign_scalar
292
296 subroutine field_add_field(this, g)
297 class(field_t), intent(inout) :: this
298 type(field_t), intent(in) :: g
299
300 if (neko_bcknd_device .eq. 1) then
301 call device_add2(this%x_d, g%x_d, this%size())
302 else
303 call add2(this%x, g%x, this%size())
304 end if
305
306 end subroutine field_add_field
307
308
311 subroutine field_add_scalar(this, a)
312 class(field_t), intent(inout) :: this
313 real(kind=rp), intent(in) :: a
314
315 if (neko_bcknd_device .eq. 1) then
316 call device_cadd(this%x_d, a, this%size())
317 else
318 call cadd(this%x, a, this%size())
319 end if
320
321 end subroutine field_add_scalar
322
324 pure function field_size(this) result(size)
325 class(field_t), intent(in) :: this
326 integer :: size
327
328 size = this%dof%size()
329 end function field_size
330
331 ! ========================================================================== !
332 ! Field pointer type subroutines
333
334 subroutine field_ptr_init(this, ptr)
335 class(field_ptr_t), intent(inout) :: this
336 type(field_t), target, intent(in) :: ptr
337
338 call this%free()
339
340 this%ptr => ptr
341
342 end subroutine field_ptr_init
343
344 subroutine field_ptr_free(this)
345 class(field_ptr_t), intent(inout) :: this
346
347 if (associated(this%ptr)) then
348 nullify(this%ptr)
349 end if
350
351 end subroutine field_ptr_free
352
353 ! ========================================================================== !
354 ! Field wrapper type subroutines
355
356 subroutine field_wrapper_init_field(this, f)
357 class(field_wrapper_t), intent(inout) :: this
358 type(field_t), intent(in) :: f
359
360 call this%free()
361 allocate(this%field)
362 this%field = f
363
364 end subroutine field_wrapper_init_field
365
366 subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
367 class(field_wrapper_t), intent(inout) :: this
368 type(mesh_t), target, intent(in) :: msh
369 type(space_t), target, intent(in) :: space
370 character(len=*), optional :: fld_name
371
372 call this%free()
373 allocate(this%field)
374 call this%field%init(msh, space, fld_name)
375
377
378 subroutine field_wrapper_init_external_dof(this, dof, fld_name)
379 class(field_wrapper_t), intent(inout) :: this
380 type(dofmap_t), target, intent(in) :: dof
381 character(len=*), optional :: fld_name
382
383 call this%free()
384 allocate(this%field)
385 call this%field%init(dof, fld_name)
386
388
389 subroutine field_wrapper_free(this)
390 class(field_wrapper_t), intent(inout) :: this
391
392 if (associated(this%field)) then
393 call this%field%free()
394 deallocate(this%field)
395 end if
396
397 end subroutine field_wrapper_free
398
399end 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
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:83
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_memset(x_d, v, s, sync, strm)
Set memory on the device to a value.
Definition device.F90:244
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:297
pure integer function field_size(this)
Return the size of the field based on the underlying dofmap.
Definition field.f90:325
subroutine field_assign_field(this, g)
Assignment .
Definition field.f90:235
subroutine field_wrapper_free(this)
Definition field.f90:390
subroutine field_add_scalar(this, a)
Add .
Definition field.f90:312
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:335
subroutine field_ptr_free(this)
Definition field.f90:345
subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
Definition field.f90:367
subroutine field_init_common(this, fld_name)
Initialize a field this.
Definition field.f90:158
subroutine field_wrapper_init_external_dof(this, dof, fld_name)
Definition field.f90:379
subroutine field_wrapper_init_field(this, f)
Definition field.f90:357
subroutine field_init_external_dof(this, dof, fld_name)
Initialize a field this on the mesh msh using an internal dofmap.
Definition field.f90:138
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:114
subroutine field_free(this)
Deallocate a field f.
Definition field.f90:193
Definition math.f90:60
subroutine, public cadd(a, s, n)
Add a scalar to vector .
Definition math.f90:498
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:776
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:523
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:252
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
Utilities.
Definition utils.f90:35
integer, parameter, public neko_varname_len
Definition utils.f90:42
field_ptr_t, To easily obtain a pointer to a field
Definition field.f90:83
field_wrapper_t, used to wrap an allocated field for use in a field list
Definition field.f90:93
The function space for the SEM solution fields.
Definition space.f90:63