Neko 1.99.6
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 if (this%internal_dofmap) then
252 call this%dof%free()
253 deallocate(this%dof)
254 this%internal_dofmap = .false.
255 end if
256 this%dof => g%dof
257 else
258 if (this%internal_dofmap) then
259 call this%dof%free()
260 else
261 allocate(this%dof)
262 this%internal_dofmap = .true.
263 end if
264 call this%dof%init(this%msh, this%Xh)
265 end if
266
267 if (.not. allocated(this%x)) then
268
269 allocate(this%x(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
270
271 if (neko_bcknd_device .eq. 1) then
272 call device_map(this%x, this%x_d, this%size())
273 end if
274
275 end if
276
277 if (neko_bcknd_device .eq. 1) then
278 call device_copy(this%x_d, g%x_d, this%size())
279 else
280 call copy(this%x, g%x, this%dof%size())
281 end if
282
283 end subroutine field_assign_field
284
286 subroutine field_assign_scalar(this, a)
287 class(field_t), intent(inout) :: this
288 real(kind=rp), intent(in) :: a
289
290 if (neko_bcknd_device .eq. 1) then
291 call device_cfill(this%x_d, a, this%size())
292 else
293 call cfill(this%x, a, this%size())
294 end if
295
296 end subroutine field_assign_scalar
297
301 subroutine field_add_field(this, g)
302 class(field_t), intent(inout) :: this
303 type(field_t), intent(in) :: g
304
305 if (neko_bcknd_device .eq. 1) then
306 call device_add2(this%x_d, g%x_d, this%size())
307 else
308 call add2(this%x, g%x, this%size())
309 end if
310
311 end subroutine field_add_field
312
313
316 subroutine field_add_scalar(this, a)
317 class(field_t), intent(inout) :: this
318 real(kind=rp), intent(in) :: a
319
320 if (neko_bcknd_device .eq. 1) then
321 call device_cadd(this%x_d, a, this%size())
322 else
323 call cadd(this%x, a, this%size())
324 end if
325
326 end subroutine field_add_scalar
327
329 pure function field_size(this) result(size)
330 class(field_t), intent(in) :: this
331 integer :: size
332
333 size = this%dof%size()
334 end function field_size
335
336 ! ========================================================================== !
337 ! Field pointer type subroutines
338
339 subroutine field_ptr_init(this, ptr)
340 class(field_ptr_t), intent(inout) :: this
341 type(field_t), target, intent(in) :: ptr
342
343 call this%free()
344
345 this%ptr => ptr
346
347 end subroutine field_ptr_init
348
349 subroutine field_ptr_free(this)
350 class(field_ptr_t), intent(inout) :: this
351
352 if (associated(this%ptr)) then
353 nullify(this%ptr)
354 end if
355
356 end subroutine field_ptr_free
357
358 ! ========================================================================== !
359 ! Field wrapper type subroutines
360
361 subroutine field_wrapper_init_field(this, f)
362 class(field_wrapper_t), intent(inout) :: this
363 type(field_t), intent(in) :: f
364
365 call this%free()
366 allocate(this%field)
367 this%field = f
368
369 end subroutine field_wrapper_init_field
370
371 subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
372 class(field_wrapper_t), intent(inout) :: this
373 type(mesh_t), target, intent(in) :: msh
374 type(space_t), target, intent(in) :: space
375 character(len=*), optional :: fld_name
376
377 call this%free()
378 allocate(this%field)
379 call this%field%init(msh, space, fld_name)
380
382
383 subroutine field_wrapper_init_external_dof(this, dof, fld_name)
384 class(field_wrapper_t), intent(inout) :: this
385 type(dofmap_t), target, intent(in) :: dof
386 character(len=*), optional :: fld_name
387
388 call this%free()
389 allocate(this%field)
390 call this%field%init(dof, fld_name)
391
393
394 subroutine field_wrapper_free(this)
395 class(field_wrapper_t), intent(inout) :: this
396
397 if (associated(this%field)) then
398 call this%field%free()
399 deallocate(this%field)
400 end if
401
402 end subroutine field_wrapper_free
403
404end module field
Map a Fortran array to a device (allocate and associate)
Definition device.F90:78
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:84
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:261
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:302
pure integer function field_size(this)
Return the size of the field based on the underlying dofmap.
Definition field.f90:330
subroutine field_assign_field(this, g)
Assignment .
Definition field.f90:235
subroutine field_wrapper_free(this)
Definition field.f90:395
subroutine field_add_scalar(this, a)
Add .
Definition field.f90:317
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:287
subroutine field_ptr_init(this, ptr)
Definition field.f90:340
subroutine field_ptr_free(this)
Definition field.f90:350
subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
Definition field.f90:372
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:384
subroutine field_wrapper_init_field(this, f)
Definition field.f90:362
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:566
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:900
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:597
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:291
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:43
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:64