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, 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
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
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: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:157
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: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