6 use global_interpolation,
only: global_interpolation_t
7 use json_utils,
only: json_get_or_default
8 use logger,
only: neko_log, log_size
9 use num_types,
only: rp
10 use tuple,
only: tuple4_i4_t
11 use utils,
only: neko_error
15 integer,
public,
parameter :: facet_type_interior = 0
16 integer,
public,
parameter :: facet_type_outlet = 1
17 integer,
public,
parameter :: facet_type_inlet = 2
18 integer,
public,
parameter :: facet_type_wall = 3
19 integer,
public,
parameter :: facet_type_sympln = 4
27 pure function cross(a, b)
result(c)
28 real(kind=rp),
dimension(3),
intent(in) :: a
29 real(kind=rp),
dimension(3),
intent(in) :: b
30 real(kind=rp),
dimension(3) :: c
32 c(1) = a(2) * b(3) - a(3) * b(2)
33 c(2) = a(3) * b(1) - a(1) * b(3)
34 c(3) = a(1) * b(2) - a(2) * b(1)
42 pure function dot(a, b)
result(d)
43 real(kind=rp),
dimension(3),
intent(in) :: a(3)
44 real(kind=rp),
dimension(3),
intent(in) :: b(3)
47 d = a(1) * b(1) + a(2) * b(2) + a(3) * b(3)
57 pure function area(nv, vertices)
result(a)
58 integer,
intent(in) :: nv
59 real(kind=rp),
dimension(3, nv),
intent(in) :: vertices
63 real(kind=rp),
dimension(3) :: v1, e1, e2, tmp
64 real(kind=rp) :: cp(3)
73 e1 = (vertices(:, v) - v1)
74 e2 = (vertices(:, v + 1) - v1)
89 subroutine get_facets(C, out, facet_type)
90 type(case_t),
intent(in) :: C
91 integer,
dimension(:, :),
allocatable,
intent(out) :: out
92 integer,
intent(in),
optional :: facet_type
95 integer :: e, f, facet_id
96 integer :: N_elem, N_facets
97 integer :: facet_type_
99 if (
present(facet_type))
then
100 facet_type_ = facet_type
112 if (c%msh%facet_type(f, e) .eq. facet_type_)
then
113 n_facets = n_facets + 1
119 allocate (out(2, n_facets))
125 if (c%msh%facet_type(f, e) .eq. facet_type_)
then
128 facet_id = facet_id + 1
133 end subroutine get_facets
139 subroutine get_facets_outlet(C, out)
140 type(case_t),
intent(in) :: C
141 integer,
dimension(:, :),
allocatable,
intent(out) :: out
143 call get_facets(c, out, facet_type_outlet)
144 end subroutine get_facets_outlet
153 pure function sum_weighted(a, w)
result(s)
154 real(kind=rp),
dimension(:),
intent(in) :: a
155 real(kind=rp),
dimension(:),
intent(in),
optional :: w
164 end function sum_weighted
172 pure function average_weighted(a, w)
result(m)
173 real(kind=rp),
dimension(:),
intent(in) :: a
174 real(kind=rp),
dimension(:),
intent(in),
optional :: w
178 m = sum_weighted(a, w) / sum(w)
183 end function average_weighted
190 subroutine get_facet_nodes(C, element_id, facet_id, nodes)
191 type(case_t),
intent(in) :: C
192 integer,
intent(in) :: element_id
193 integer,
intent(in) :: facet_id
194 real(kind=rp),
dimension(:, :),
allocatable,
intent(out) :: nodes
199 type(tuple4_i4_t) :: t_hex
203 select type (ele => c%msh%elements(element_id)%e)
208 if (n_nodes .eq. 0)
then
209 call neko_error(
"Error: the facet shape is not supported.")
213 if (
allocated(nodes) .and.
size(nodes, 2) .eq. n_nodes)
then
215 else if (.not.
allocated(nodes))
then
216 allocate (nodes(3, n_nodes))
218 call neko_error(
"Error: the nodes array is not the correct size.")
222 select type (ele => c%msh%elements(element_id)%e)
224 call ele%facet_order(t_hex, facet_id)
227 nodes(:, n) = c%msh%points(v)%x
231 end subroutine get_facet_nodes
233 subroutine estimate_temperature(neko_case)
234 type(case_t),
intent(inout) :: neko_case
235 type(global_interpolation_t) :: interpolator
237 real(kind=rp) :: target_temperature
238 real(kind=rp) :: temperature_mean
239 real(kind=rp),
dimension(:),
allocatable :: temperature_local
241 integer,
allocatable :: facet_list(:, :)
243 real(kind=rp),
dimension(:, :),
allocatable :: facet_nodes
244 real(kind=rp),
dimension(:, :),
allocatable :: facet_centers
245 real(kind=rp),
dimension(:),
allocatable :: facet_area
247 integer :: element_id, facet_id
251 character(len=LOG_SIZE) :: log_buf
254 call json_get_or_default(neko_case%params,
'topopt.target_temperature', &
255 target_temperature, 0.5_rp)
258 call interpolator%init(neko_case%scalar%dm_xh)
261 call get_facets(neko_case, facet_list)
264 n_facets =
size(facet_list, 2)
265 allocate (facet_centers(3, n_facets))
266 allocate (facet_area(n_facets))
267 allocate (temperature_local(n_facets))
271 element_id = facet_list(1, f)
272 facet_id = facet_list(2, f)
275 call get_facet_nodes(neko_case, element_id, facet_id, facet_nodes)
278 facet_centers(:, f) = 0.0
279 do n = 1,
size(facet_nodes, 2)
280 facet_centers(:, f) = facet_centers(:, f) + facet_nodes(:, n)
282 facet_centers(:, f) = facet_centers(:, f) /
size(facet_nodes, 2)
285 facet_area(f) = area(
size(facet_nodes, 2), facet_nodes)
289 call interpolator%find_points_xyz(facet_centers, n_facets)
290 call interpolator%evaluate(temperature_local, neko_case%scalar%s%x)
292 temperature_local = temperature_local - target_temperature
293 temperature_mean = average_weighted(temperature_local, facet_area)
295 write (log_buf,
'(a,f15.7)') &
296 "Outlet area-weighted average temperature deviation: ", &
298 call neko_log%message(log_buf)
300 call interpolator%free()
302 end subroutine estimate_temperature