Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
tensor3.f90
Go to the documentation of this file.
1! Copyright (c) 2026, 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 tensor3
36 use num_types, only : rp
38 use math, only : cfill
41 use, intrinsic :: iso_c_binding
42 implicit none
43 private
44
45 type, public :: tensor3_t
46 real(kind=rp), allocatable :: x(:,:,:)
47 character(len=NEKO_VARNAME_LEN) :: name = ""
48 type(c_ptr) :: x_d = c_null_ptr
49 integer, private :: n1 = 0
50 integer, private :: n2 = 0
51 integer, private :: n3 = 0
52 integer, private :: n = 0
53 contains
55 procedure, pass(t) :: init => tensor3_init
57 procedure, pass(t) :: free => tensor3_free
59 procedure, pass(t) :: size => tensor3_size
61 procedure, pass(t) :: copy_from => tensor3_copy_from
63 procedure, pass(t) :: get_n1 => tensor3_n1
65 procedure, pass(t) :: get_n2 => tensor3_n2
67 procedure, pass(t) :: get_n3 => tensor3_n3
69 procedure, pass(t) :: tensor3_assign_tensor3
71 procedure, pass(t) :: tensor3_assign_scalar
72
73 generic :: assignment(=) => tensor3_assign_tensor3, &
75
77 procedure, pass(t), private :: alloc => tensor3_allocate
78 end type tensor3_t
79
80 type, public :: tensor3_ptr_t
81 type(tensor3_t), pointer :: ptr => null()
82 contains
84 procedure, pass(this) :: init => tensor3_ptr_init
86 procedure, pass(this) :: free => tensor3_ptr_free
87 end type tensor3_ptr_t
88
89contains
90
97 subroutine tensor3_init(t, n1, n2, n3, name)
98 class(tensor3_t), intent(inout) :: t
99 integer, intent(in) :: n1
100 integer, intent(in) :: n2
101 integer, intent(in) :: n3
102 character(len=*), intent(in), optional :: name
103
104 ! t%alloc zeroes the device side (and synchronizes) before any
105 ! host-side touch: under zero-copy the device then faults the
106 ! pages first (device first touch), which gives contiguous
107 ! physical mappings and thus better GPU TLB utilisation; rewriting
108 ! the zeros on the host afterwards is benign.
109 call t%alloc(n1, n2, n3)
110
111 if (present(name)) then
112 t%name = name
113 end if
114
115 end subroutine tensor3_init
116
122 subroutine tensor3_allocate(t, n1, n2, n3)
123 class(tensor3_t), intent(inout) :: t
124 integer, intent(in) :: n1
125 integer, intent(in) :: n2
126 integer, intent(in) :: n3
127
128 call t%free()
129
130 allocate(t%x(n1, n2, n3))
131 t%n1 = n1
132 t%n2 = n2
133 t%n3 = n3
134 t%n = n1*n2*n3
135
136 if (neko_bcknd_device .eq. 1) then
137 call device_map(t%x, t%x_d, t%n)
138 call device_cfill(t%x_d, 0.0_rp, t%n)
139 call device_sync()
140 end if
141 call cfill(t%x, 0.0_rp, t%n)
142
143 end subroutine tensor3_allocate
144
147 subroutine tensor3_free(t)
148 class(tensor3_t), intent(inout) :: t
149
150 if (allocated(t%x)) then
151 if (neko_bcknd_device .eq. 1) then
152 call device_unmap(t%x, t%x_d)
153 end if
154 deallocate(t%x)
155 end if
156
157 t%n1 = 0
158 t%n2 = 0
159 t%n3 = 0
160 t%n = 0
161 t%name = ""
162
163 end subroutine tensor3_free
164
167 pure function tensor3_size(t) result(s)
168 class(tensor3_t), intent(in) :: t
169 integer :: s
170 s = t%n
171 end function tensor3_size
172
177 subroutine tensor3_copy_from(t, memdir, sync)
178 class(tensor3_t), intent(inout) :: t
179 integer, intent(in) :: memdir
180 logical, intent(in) :: sync
181
182 if (neko_bcknd_device .eq. 1) then
183 call device_memcpy(t%x, t%x_d, t%n, memdir, sync)
184 end if
185
186 end subroutine tensor3_copy_from
187
190 pure function tensor3_n1(t) result(n1)
191 class(tensor3_t), intent(in) :: t
192 integer :: n1
193 n1 = t%n1
194 end function tensor3_n1
195
198 pure function tensor3_n2(t) result(n2)
199 class(tensor3_t), intent(in) :: t
200 integer :: n2
201 n2 = t%n2
202 end function tensor3_n2
203
206 pure function tensor3_n3(t) result(n3)
207 class(tensor3_t), intent(in) :: t
208 integer :: n3
209 n3 = t%n3
210 end function tensor3_n3
211
215 subroutine tensor3_assign_tensor3(t, w)
216 class(tensor3_t), intent(inout) :: t
217 type(tensor3_t), intent(in) :: w
218
219 if (allocated(t%x)) then
220 call t%free()
221 end if
222
223 if (.not. allocated(t%x)) then
224
225 t%n1 = w%n1
226 t%n2 = w%n2
227 t%n3 = w%n3
228 t%n = w%n
229 allocate(t%x(t%n1, t%n2, t%n3))
230
231 if (neko_bcknd_device .eq. 1) then
232 call device_map(t%x, t%x_d, t%n)
233 end if
234
235 end if
236
237 if (neko_bcknd_device .eq. 1) then
238 call device_copy(t%x_d, w%x_d, t%n)
239 else
240 t%x = w%x
241 end if
242
243 t%name = w%name
244
245 end subroutine tensor3_assign_tensor3
246
250 subroutine tensor3_assign_scalar(t, s)
251 class(tensor3_t), intent(inout) :: t
252 real(kind=rp), intent(in) :: s
253
254 if (.not. allocated(t%x)) then
255 call neko_error('tensor3 not allocated')
256 end if
257
258 if (neko_bcknd_device .eq. 1) then
259 call device_cfill(t%x_d, s, t%n)
260 else
261 t%x = s
262 end if
263
264 end subroutine tensor3_assign_scalar
265
266 ! ========================================================================== !
267 ! tensor3 pointer type subroutines
268
272 subroutine tensor3_ptr_init(this, ptr)
273 class(tensor3_ptr_t), intent(inout) :: this
274 type(tensor3_t), target, intent(in) :: ptr
275
276 call this%free()
277 this%ptr => ptr
278 end subroutine tensor3_ptr_init
279
282 subroutine tensor3_ptr_free(this)
283 class(tensor3_ptr_t), intent(inout) :: this
284
285 if (associated(this%ptr)) then
286 nullify(this%ptr)
287 end if
288
289 end subroutine tensor3_ptr_free
290
291end module tensor3
Map a Fortran array to a device (allocate and associate)
Definition device.F90:83
Copy data between host and device (or device and device)
Definition device.F90:72
Synchronize a device or stream.
Definition device.F90:119
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
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
Definition math.f90:60
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:600
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a rank-3 tensor.
Definition tensor3.f90:34
subroutine tensor3_ptr_free(this)
Destructor. Just nullifies the pointer.
Definition tensor3.f90:283
subroutine tensor3_init(t, n1, n2, n3, name)
Initialise a tensor of size n1*n2*n3.
Definition tensor3.f90:98
pure integer function tensor3_n3(t)
Returns the size of the third dimension.
Definition tensor3.f90:207
pure integer function tensor3_n2(t)
Returns the size of the second dimension.
Definition tensor3.f90:199
subroutine tensor3_assign_scalar(t, s)
Assignment .
Definition tensor3.f90:251
subroutine tensor3_ptr_init(this, ptr)
Constructor. Just assigns the pointer.
Definition tensor3.f90:273
pure integer function tensor3_size(t)
Returns the number of entries in the tensor.
Definition tensor3.f90:168
subroutine tensor3_copy_from(t, memdir, sync)
Easy way to copy between host and device.
Definition tensor3.f90:178
pure integer function tensor3_n1(t)
Returns the size of the first dimension.
Definition tensor3.f90:191
subroutine tensor3_assign_tensor3(t, w)
Assignment .
Definition tensor3.f90:216
subroutine tensor3_allocate(t, n1, n2, n3)
Allocate a tensor of size n1*n2*n3.
Definition tensor3.f90:123
subroutine tensor3_free(t)
Deallocate a tensor.
Definition tensor3.f90:148
Utilities.
Definition utils.f90:35
integer, parameter, public neko_varname_len
Definition utils.f90:43