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 if (neko_bcknd_device .eq. 1) then
197 call device_unmap(this%x, this%x_d)
198 end if
199 deallocate(this%x)
200 end if
201
202 if (this%internal_dofmap) then
203 call this%dof%free()
204 deallocate(this%dof)
205 this%internal_dofmap = .false.
206 end if
207
208 nullify(this%msh)
209 nullify(this%Xh)
210 nullify(this%dof)
211
212 end subroutine field_free
213
218 subroutine field_copy_from(this, memdir, sync)
219 class(field_t), intent(inout) :: this
220 integer, intent(in) :: memdir
221 logical, intent(in) :: sync
222
223 if (neko_bcknd_device .eq. 1) then
224 call device_memcpy(this%x, this%x_d, this%size(), memdir, sync)
225 end if
226
227 end subroutine field_copy_from
228
229
233 subroutine field_assign_field(this, g)
234 class(field_t), intent(inout) :: this
235 type(field_t), intent(in) :: g
236
237 if (allocated(this%x)) then
238 if (.not. associated(this%Xh, g%Xh)) then
239 call this%free()
240 end if
241 end if
242
243 this%Xh => g%Xh
244 this%msh => g%msh
245 if (len_trim(this%name) == 0) then
246 this%name = g%name
247 end if
248
249 if (.not. g%internal_dofmap) then
250 this%dof => g%dof
251 else
252 if (this%internal_dofmap) then
253 call this%dof%free()
254 else
255 allocate(this%dof)
256 this%internal_dofmap = .true.
257 end if
258 call this%dof%init(this%msh, this%Xh)
259 end if
260
261 if (.not. allocated(this%x)) then
262
263 allocate(this%x(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
264
265 if (neko_bcknd_device .eq. 1) then
266 call device_map(this%x, this%x_d, this%size())
267 end if
268
269 end if
270
271 if (neko_bcknd_device .eq. 1) then
272 call device_copy(this%x_d, g%x_d, this%size())
273 else
274 call copy(this%x, g%x, this%dof%size())
275 end if
276
277 end subroutine field_assign_field
278
280 subroutine field_assign_scalar(this, a)
281 class(field_t), intent(inout) :: this
282 real(kind=rp), intent(in) :: a
283
284 if (neko_bcknd_device .eq. 1) then
285 call device_cfill(this%x_d, a, this%size())
286 else
287 call cfill(this%x, a, this%size())
288 end if
289
290 end subroutine field_assign_scalar
291
295 subroutine field_add_field(this, g)
296 class(field_t), intent(inout) :: this
297 type(field_t), intent(in) :: g
298
299 if (neko_bcknd_device .eq. 1) then
300 call device_add2(this%x_d, g%x_d, this%size())
301 else
302 call add2(this%x, g%x, this%size())
303 end if
304
305 end subroutine field_add_field
306
307
310 subroutine field_add_scalar(this, a)
311 class(field_t), intent(inout) :: this
312 real(kind=rp), intent(in) :: a
313
314 if (neko_bcknd_device .eq. 1) then
315 call device_cadd(this%x_d, a, this%size())
316 else
317 call cadd(this%x, a, this%size())
318 end if
319
320 end subroutine field_add_scalar
321
323 pure function field_size(this) result(size)
324 class(field_t), intent(in) :: this
325 integer :: size
326
327 size = this%dof%size()
328 end function field_size
329
330 ! ========================================================================== !
331 ! Field pointer type subroutines
332
333 subroutine field_ptr_init(this, ptr)
334 class(field_ptr_t), intent(inout) :: this
335 type(field_t), target, intent(in) :: ptr
336
337 call this%free()
338
339 this%ptr => ptr
340
341 end subroutine field_ptr_init
342
343 subroutine field_ptr_free(this)
344 class(field_ptr_t), intent(inout) :: this
345
346 if (associated(this%ptr)) then
347 nullify(this%ptr)
348 end if
349
350 end subroutine field_ptr_free
351
352 ! ========================================================================== !
353 ! Field wrapper type subroutines
354
355 subroutine field_wrapper_init_field(this, f)
356 class(field_wrapper_t), intent(inout) :: this
357 type(field_t), intent(in) :: f
358
359 call this%free()
360 allocate(this%field)
361 this%field = f
362
363 end subroutine field_wrapper_init_field
364
365 subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
366 class(field_wrapper_t), intent(inout) :: this
367 type(mesh_t), target, intent(in) :: msh
368 type(space_t), target, intent(in) :: space
369 character(len=*), optional :: fld_name
370
371 call this%free()
372 allocate(this%field)
373 call this%field%init(msh, space, fld_name)
374
376
377 subroutine field_wrapper_init_external_dof(this, dof, fld_name)
378 class(field_wrapper_t), intent(inout) :: this
379 type(dofmap_t), target, intent(in) :: dof
380 character(len=*), optional :: fld_name
381
382 call this%free()
383 allocate(this%field)
384 call this%field%init(dof, fld_name)
385
387
388 subroutine field_wrapper_free(this)
389 class(field_wrapper_t), intent(inout) :: this
390
391 if (associated(this%field)) then
392 call this%field%free()
393 deallocate(this%field)
394 end if
395
396 end subroutine field_wrapper_free
397
398end 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:296
pure integer function field_size(this)
Return the size of the field based on the underlying dofmap.
Definition field.f90:324
subroutine field_assign_field(this, g)
Assignment .
Definition field.f90:234
subroutine field_wrapper_free(this)
Definition field.f90:389
subroutine field_add_scalar(this, a)
Add .
Definition field.f90:311
subroutine field_copy_from(this, memdir, sync)
Easy way to copy between host and device.
Definition field.f90:219
subroutine field_assign_scalar(this, a)
Assignment .
Definition field.f90:281
subroutine field_ptr_init(this, ptr)
Definition field.f90:334
subroutine field_ptr_free(this)
Definition field.f90:344
subroutine field_wrapper_init_internal_dof(this, msh, space, fld_name)
Definition field.f90:366
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:378
subroutine field_wrapper_init_field(this, f)
Definition field.f90:356
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