Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
spectral_vanishing_viscosity.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 disclaimer
13! in the documentation and/or other materials provided with the
14! distribution.
15!
16! * Neither the name of the authors nor the names of its contributors may
17! be used to endorse or promote products derived from this software
18! without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30! POSSIBILITY OF SUCH DAMAGE.
31!
34 use num_types, only : rp
36 use registry, only : neko_registry
37 use field, only : field_t
39 use json_module, only : json_file
41 use coefs, only : coef_t
42 use math, only : cfill, copy, rzero, col2
45 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr
47 implicit none
48 private
49
50 character(len=3), parameter :: known_directions(7) = [character(len=3) :: &
51 "rst", "rs", "rt", "st", "r", "s", "t"]
52 character(len=9), parameter :: known_formulations(1) = [character(len=9) :: &
53 "one-sided"]
54 character(len=5), parameter :: known_nu_types(2) = [character(len=5) :: &
55 "value", "field"]
56 character(len=5), parameter :: known_kernel_types(1) = [character(len=5) :: &
57 "power"]
58
59
61 type, public :: svv_t
65 character(len=:), allocatable :: direction
67 character(len=:), allocatable :: kernel_type
69 type(coef_t), pointer :: coef => null()
71 real(kind=rp), allocatable :: h1(:,:,:,:)
72 type(c_ptr) :: h1_d = c_null_ptr
74 real(kind=rp), allocatable :: ident(:,:)
75 type(c_ptr) :: ident_d = c_null_ptr
77 character(len=:), allocatable :: nue_field_name
78 type(field_t), pointer :: nue => null()
80 logical :: tvar_h1 = .false.
81 contains
82 procedure, pass(this) :: init => svv_init_from_json
83 procedure, pass(this) :: free => svv_free
84 procedure, pass(this) :: update => svv_update_h1
85 end type svv_t
86
87contains
88
94 subroutine svv_init_from_json(this, json, coef, rho)
95 class(svv_t), intent(inout) :: this
96 type(json_file), intent(inout) :: json
97 type(coef_t), intent(in), target :: coef
98 type(field_t), intent(in) :: rho
99 real(kind=rp), allocatable :: transfer(:)
100 real(kind=rp) :: nu_val, power_coef
101 character(len=:), allocatable :: nu_type, direction, formulation
102 integer :: i, lx
103
104
105 call this%free()
106 this%coef => coef
107 lx = coef%Xh%lx
108
109 call json_get_or_default(json, "svv.formulation", formulation, &
110 "one-sided")
111 if (trim(formulation) .ne. "one-sided") then
112 call neko_error("This SVV operator only supports the one-sided " // &
113 "formulation")
114 end if
115
116 call json_get_or_default(json, "svv.direction", direction, "rst")
117 this%direction = trim(direction)
118 if (all(trim(this%direction) .ne. known_directions)) then
119 call neko_type_error("The SVV direction", this%direction, &
121 end if
122
123 allocate(transfer(lx))
124
125 call json_get(json, "svv.kernel.type", this%kernel_type)
126 select case (trim(this%kernel_type))
127 case ("power")
128 call json_get_or_lookup(json, "svv.kernel.power_coefficient", power_coef)
129 if (power_coef .eq. 0.0_rp) then
130 transfer = 0.0_rp
131 else
132 do i = 1, lx
133 transfer(i) = 1.0_rp - ((i - 1.0_rp) / (lx - 1.0_rp)) ** &
134 ((lx - 1.0_rp) * power_coef)
135 end do
136 end if
137 case default
138 call neko_type_error("The SVV kernel type `", &
139 trim(this%kernel_type), known_kernel_types)
140 end select
141
142 call this%filter%init_from_components(coef, "nonBoyd", transfer)
143 deallocate(transfer)
144
145 allocate(this%ident(lx, lx))
146 this%ident = 0.0_rp
147 do i = 1, lx
148 this%ident(i, i) = 1.0_rp
149 end do
150
151 allocate(this%h1(lx, lx, lx, coef%msh%nelv))
152 if (neko_bcknd_device .eq. 1) then
153 call device_map(this%ident, this%ident_d, lx * lx)
154 call device_memcpy(this%ident, this%ident_d, lx * lx, &
155 host_to_device, sync = .false.)
156 call device_map(this%h1, this%h1_d, coef%dof%size())
157 call device_rzero(this%h1_d, coef%dof%size())
158 else
159 call rzero(this%h1, coef%dof%size())
160 end if
161
162 call json_get(json, "svv.nu.type", nu_type)
163 select case (trim(nu_type))
164 case ("value")
165 call json_get_or_lookup(json, "svv.nu.value", nu_val)
166 if (neko_bcknd_device .eq. 1) then
167 call device_cfill(this%h1_d, nu_val, coef%dof%size())
168 call device_col2(this%h1_d, rho%x_d, coef%dof%size())
169 else
170 call cfill(this%h1, nu_val, coef%dof%size())
171 call col2(this%h1, rho%x, coef%dof%size())
172 end if
173 case ("field")
174 call json_get_or_default(json, "svv.nu.time_variable", &
175 this%tvar_h1, .true.)
176 call json_get(json, "svv.nu.field_name", this%nue_field_name)
177 if (neko_registry%field_exists(this%nue_field_name)) then
178 this%nue => neko_registry%get_field(this%nue_field_name)
179 call svv_copy_viscosity(this, rho)
180 else if (.not. this%tvar_h1) then
181 call neko_error("The static SVV viscosity field `" // &
182 this%nue_field_name // "` does not exist")
183 end if
184 case default
185 call neko_error("Invalid svv.nu.type: " // trim(nu_type))
186 end select
187
188 if (allocated(nu_type)) deallocate(nu_type)
189 if (allocated(direction)) deallocate(direction)
190 if (allocated(formulation)) deallocate(formulation)
191 end subroutine svv_init_from_json
192
197 subroutine svv_update_h1(this, rho, tstep)
198 class(svv_t), intent(inout) :: this
199 type(field_t), intent(in) :: rho
200 integer, intent(in) :: tstep
201
202 if (.not. this%tvar_h1) return
203 if (.not. associated(this%nue)) then
204 if (.not. neko_registry%field_exists(this%nue_field_name)) then
205 call neko_error("The SVV viscosity field `" // &
206 this%nue_field_name // "` does not exist at time step " // &
207 trim(adjustl(to_string(tstep))))
208 end if
209 this%nue => neko_registry%get_field(this%nue_field_name)
210 end if
211 call svv_copy_viscosity(this, rho)
212 end subroutine svv_update_h1
213
217 subroutine svv_copy_viscosity(this, rho)
218 class(svv_t), intent(inout) :: this
219 type(field_t), intent(in) :: rho
220
221 if (neko_bcknd_device .eq. 1) then
222 call device_copy(this%h1_d, this%nue%x_d, this%coef%dof%size())
223 call device_col2(this%h1_d, rho%x_d, this%coef%dof%size())
224 else
225 call copy(this%h1, this%nue%x, this%coef%dof%size())
226 call col2(this%h1, rho%x, this%coef%dof%size())
227 end if
228 end subroutine svv_copy_viscosity
229
232 subroutine svv_free(this)
233 class(svv_t), intent(inout) :: this
234
235 call this%filter%free()
236 if (allocated(this%h1)) then
237 if (neko_bcknd_device .eq. 1) then
238 call device_unmap(this%h1, this%h1_d)
239 end if
240 deallocate(this%h1)
241 end if
242 if (allocated(this%ident)) then
243 if (neko_bcknd_device .eq. 1) then
244 call device_unmap(this%ident, this%ident_d)
245 end if
246 deallocate(this%ident)
247 end if
248 if (allocated(this%direction)) deallocate(this%direction)
249 if (allocated(this%kernel_type)) deallocate(this%kernel_type)
250 if (allocated(this%nue_field_name)) deallocate(this%nue_field_name)
251 nullify(this%coef)
252 nullify(this%nue)
253 this%h1_d = c_null_ptr
254 this%ident_d = c_null_ptr
255 this%tvar_h1 = .false.
256 end subroutine svv_free
257
260 function to_string(value) result(string)
261 integer, intent(in) :: value
262 character(len=32) :: string
263 write(string, '(I0)') value
264 end function to_string
265
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
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Coefficients.
Definition coef.f90:34
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
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
integer, parameter, public host_to_device
Definition device.F90:48
Implements elementwise_filter_t.
Defines a field.
Definition field.f90:34
Filter to be applied to a scalar field.
Definition filter.f90:38
Utilities for retrieving parameters from the case files.
Definition math.f90:60
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:600
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1049
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:294
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:238
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:158
Data and filter construction for spectral vanishing viscosity.
subroutine svv_free(this)
Release all resources owned by an SVV object.
subroutine svv_update_h1(this, rho, tstep)
Update a time-varying, field-valued SVV viscosity.
character(len=9), dimension(1), parameter known_formulations
subroutine svv_copy_viscosity(this, rho)
Copy the configured viscosity field and multiply it by density.
subroutine svv_init_from_json(this, json, coef, rho)
Construct an SVV object from case parameters.
character(len=5), dimension(1), parameter known_kernel_types
character(len=5), dimension(2), parameter known_nu_types
character(len=3), dimension(7), parameter known_directions
character(len=32) function to_string(value)
Convert an integer to a compact string.
Utilities.
Definition utils.f90:35
subroutine, public neko_type_error(base_type, wrong_type, known_types)
Reports an error allocating a type for a particular base pointer class.
Definition utils.f90:376
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Implements the elementwise filter for SEM.
Spectral vanishing viscosity configuration and coefficients.