Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
mask.f90
Go to the documentation of this file.
1! Copyright (c) 2020-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 mask
35 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, &
36 c_size_t
40 use device_math, only : device_cadd
41 use utils, only : neko_error
42
43 implicit none
44 private
45
51 type, public :: mask_t
52 private
53 integer :: n_elements = 0 ! Number of elements in the mask
54 integer, allocatable :: mask(:) ! The mask array
55 type(c_ptr) :: mask_d = c_null_ptr ! Pointer to the device mask array
56 logical :: is_set_ = .false. ! Flag to indicate if the mask is set
57
58 contains
59 ! Public interface for the mask type
60 generic, public :: init => init_from_array, init_from_array_device, &
62 procedure, public, pass(this) :: free => mask_free
63
64 procedure, public, pass(this) :: invert_from => invert_mask
65 procedure, public, pass(this) :: size => mask_size
66 procedure, public, pass(this) :: is_set => mask_is_set
67 procedure, public, pass(this) :: get_d => mask_get_d
68
69 generic, public :: set => mask_set, mask_set_d
70 generic, public :: get => mask_get, mask_get_i
71
72 ! Private procedures
73 procedure, pass(this) :: allocate => mask_allocate
74 procedure, pass(this) :: init_from_array
75 procedure, pass(this) :: init_from_array_device
76 procedure, pass(this) :: init_from_mask
77 procedure, pass(this) :: invert_mask
78
79 ! Setters
80 procedure, pass(this) :: mask_set
81 procedure, pass(this) :: mask_set_d
82
83 ! Getters
84 procedure, pass(this) :: mask_get
85 procedure, pass(this) :: mask_get_i
86
87 end type mask_t
88
89contains
90
92 subroutine mask_allocate(this, n_elements)
93 class(mask_t), intent(inout) :: this
94 integer, intent(in) :: n_elements
95
96 this%is_set_ = .false.
97 if (n_elements .eq. this%n_elements) return
98 call this%free()
99
100 allocate(this%mask(n_elements))
101
102 if (neko_bcknd_device .eq. 1) then
103 call device_map(this%mask, this%mask_d, n_elements)
104 end if
105
106 this%n_elements = n_elements
107 end subroutine mask_allocate
108
110 subroutine mask_free(this)
111 class(mask_t), intent(inout) :: this
112
113 if (allocated(this%mask)) then
114 if (neko_bcknd_device .eq. 1) then
115 call device_unmap(this%mask, this%mask_d)
116 end if
117 deallocate(this%mask)
118 end if
119
120 this%n_elements = 0
121 this%mask_d = c_null_ptr
122 this%is_set_ = .false.
123 end subroutine mask_free
124
126 subroutine init_from_array(this, mask_array, n_elements)
127 class(mask_t), intent(inout) :: this
128 integer, intent(in) :: n_elements
129 integer, intent(in) :: mask_array(n_elements)
130
131 call this%allocate(n_elements)
132
133 this%mask = mask_array
134 if (neko_bcknd_device .eq. 1) then
135 call device_memcpy(this%mask, this%mask_d, this%n_elements, &
136 host_to_device, sync = .true.)
137 call device_cadd(this%mask_d, -1, this%n_elements)
138 end if
139
140 this%is_set_ = .true.
141 end subroutine init_from_array
142
144 subroutine init_from_array_device(this, mask_array_d, n_elements)
145 class(mask_t), intent(inout) :: this
146 integer, intent(in) :: n_elements
147 type(c_ptr), intent(inout):: mask_array_d
148 integer(kind=c_size_t) :: size_c
149
150 size_c = n_elements * int(4, c_size_t)
151
152 call this%allocate(n_elements)
153 call device_memcpy(this%mask_d, mask_array_d, size_c, &
154 device_to_device, sync = .false.)
155 call device_memcpy(this%mask, mask_array_d, n_elements, &
156 device_to_host, sync = .true.)
157 this%mask = this%mask - 1 ! Adjust for 0-based indexing
158
159 this%is_set_ = .true.
160 end subroutine init_from_array_device
161
163 subroutine init_from_mask(this, other)
164 class(mask_t), intent(inout) :: this
165 class(mask_t), intent(inout) :: other
166 integer(kind=c_size_t) :: size_c
167
168 call this%allocate(other%n_elements)
169
170 size_c = other%n_elements * int(4, c_size_t)
171
172 this%mask = other%mask
173 if (neko_bcknd_device .eq. 1) then
174 call device_memcpy(this%mask_d, other%mask_d, size_c, &
175 device_to_device, sync = .true.)
176 end if
177
178 this%n_elements = other%n_elements
179 this%is_set_ = other%is_set_
180 end subroutine init_from_mask
181
183 subroutine invert_mask(this, other, total_elements)
184 class(mask_t), intent(inout) :: this
185 class(mask_t), intent(in) :: other
186 integer, intent(in) :: total_elements
187
188 logical, allocatable :: found(:)
189 integer, allocatable :: new_mask(:)
190 integer :: i, j, k, v, new_size
191
192 allocate(found(total_elements))
193 found = .false.
194
195 ! mark present
196 do i = 1, other%size()
197 v = other%mask(i)
198 if (v >= 1 .and. v <= total_elements) found(v) = .true.
199 end do
200
201 ! count complement
202 new_size = 0
203 do j = 1, total_elements
204 if (.not. found(j)) new_size = new_size + 1
205 end do
206
207 allocate(new_mask(new_size))
208
209 ! fill complement
210 k = 1
211 do j = 1, total_elements
212 if (.not. found(j)) then
213 new_mask(k) = j
214 k = k + 1
215 end if
216 end do
217
218 call this%init_from_array(new_mask, new_size)
219 end subroutine invert_mask
220
222 pure function mask_size(this) result(n_elements)
223 class(mask_t), intent(in) :: this
224 integer :: n_elements
225
226 n_elements = this%n_elements
227 end function mask_size
228
230 pure function mask_is_set(this) result(is_set)
231 class(mask_t), intent(in) :: this
232 logical :: is_set
233
234 is_set = this%is_set_
235 end function mask_is_set
236
238 function mask_get(this) result(mask_array)
239 class(mask_t), intent(in), target :: this
240 integer, pointer :: mask_array(:)
241
242 if (.not. this%is_set()) call neko_error("Mask is not set.")
243
244 mask_array => this%mask
245 end function mask_get
246
248 function mask_get_i(this, index) result(mask_value)
249 class(mask_t), intent(in), target :: this
250 integer, intent(in) :: index
251 integer :: mask_value
252
253 if (.not. this%is_set()) call neko_error("Mask is not set.")
254 if (index < 1 .or. index > this%n_elements) then
255 call neko_error("Index out of bounds in mask_get_i")
256 end if
257
258 mask_value = this%mask(index)
259 end function mask_get_i
260
262 function mask_get_d(this) result(mask_array_d)
263 class(mask_t), intent(in) :: this
264 type(c_ptr) :: mask_array_d
265
266 if (.not. this%is_set()) call neko_error("Mask is not set.")
267
268 mask_array_d = this%mask_d
269 end function mask_get_d
270
272 subroutine mask_set(this, mask_array, n_elements)
273 class(mask_t), intent(inout) :: this
274 integer, intent(in) :: n_elements
275 integer, intent(in) :: mask_array(n_elements)
276
277 call this%allocate(n_elements)
278
279 this%mask = mask_array
280 if (neko_bcknd_device .eq. 1) then
281 call device_memcpy(this%mask, this%mask_d, n_elements, &
282 host_to_device, sync = .true.)
283 call device_cadd(this%mask_d, -1, n_elements)
284 end if
285
286 this%is_set_ = .true.
287 end subroutine mask_set
288
290 subroutine mask_set_d(this, mask_array_d, n_elements)
291 class(mask_t), intent(inout) :: this
292 integer, intent(in) :: n_elements
293 type(c_ptr), intent(inout) :: mask_array_d
294 integer(kind=c_size_t) :: size_c
295
296 call this%allocate(n_elements)
297 size_c = n_elements * int(4, c_size_t)
298
299 call device_memcpy(this%mask_d, mask_array_d, size_c, &
300 device_to_device, sync = .false.)
301 call device_memcpy(this%mask, mask_array_d, n_elements, &
302 device_to_host, sync = .true.)
303 this%mask = this%mask - 1 ! Adjust for 0-based indexing
304
305 this%is_set_ = .true.
306 end subroutine mask_set_d
307
308
309end module mask
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
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public device_to_device
Definition device.F90:47
integer, parameter, public host_to_device
Definition device.F90:47
integer, parameter, public device_to_host
Definition device.F90:47
Object for handling masks in Neko.
Definition mask.f90:34
subroutine invert_mask(this, other, total_elements)
Invert the contents of another mask object.
Definition mask.f90:184
pure logical function mask_is_set(this)
Check if the mask is set.
Definition mask.f90:231
integer function, dimension(:), pointer mask_get(this)
Get the mask array.
Definition mask.f90:239
subroutine init_from_array(this, mask_array, n_elements)
Initialize the mask from a 1-indexed host array.
Definition mask.f90:127
subroutine init_from_mask(this, other)
Initialize the mask from another mask object.
Definition mask.f90:164
pure integer function mask_size(this)
Get the size of the mask.
Definition mask.f90:223
subroutine mask_allocate(this, n_elements)
Allocate the mask object.
Definition mask.f90:93
integer function mask_get_i(this, index)
Get the mask array.
Definition mask.f90:249
subroutine mask_set_d(this, mask_array_d, n_elements)
Set the mask from a 0-indexed device array.
Definition mask.f90:291
subroutine mask_free(this)
Free the mask object.
Definition mask.f90:111
subroutine mask_set(this, mask_array, n_elements)
Set the mask from a 1-indexed host array.
Definition mask.f90:273
type(c_ptr) function mask_get_d(this)
Get the device pointer to the mask array.
Definition mask.f90:263
subroutine init_from_array_device(this, mask_array_d, n_elements)
Initialize the mask from a 0-indexed device array.
Definition mask.f90:145
Build configurations.
integer, parameter neko_bcknd_device
Utilities.
Definition utils.f90:35
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51