Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
cylinder.f90
Go to the documentation of this file.
1module user
2 use user_intf, only: user_t
3 use field, only: field_t
4 use field_registry, only: neko_field_registry
5 use scratch_registry, only: neko_scratch_registry
6 use comm, only: neko_comm, pe_rank, mpi_real_precision
7 use mpi_f08, only: mpi_allreduce, mpi_sum
8 use num_types, only: rp
9 use coefs, only: coef_t
10 use json_module, only: json_file
11 use field_math, only: field_col3
12 use point_zone, only: point_zone_t
13 use point_zone_registry, only: neko_point_zone_registry
14 use math, only: cfill_mask, glsc2
15 implicit none
16
17 ! Global user variables
18 type(field_t) :: divergence
19
20contains
21
22 ! Register user-defined functions (see user_intf.f90)
23 subroutine user_setup(user)
24 type(user_t), intent(inout) :: user
25 user%user_check => user_calc_quantities
26 user%fluid_user_ic => user_ic
27 end subroutine user_setup
28
29 ! User-defined routine called at the end of every time step
30 subroutine user_calc_quantities(t, tstep, u, v, w, p, coef, params)
31 real(kind=rp), intent(in) :: t
32 integer, intent(in) :: tstep
33 type(coef_t), intent(inout) :: coef
34 type(json_file), intent(inout) :: params
35 type(field_t), intent(inout) :: u, v, w, p
36 type(field_t), pointer :: brinkman, mapped_brinkman
37 type(field_t), pointer :: work
38 integer :: temp_indices(2)
39
40 integer :: ntot
41 real(kind=rp) :: leakage, lift, drag
42
43 if (neko_field_registry%field_exists("brinkman_indicator")) then
44 brinkman => neko_field_registry%get_field("brinkman_indicator")
45 mapped_brinkman => neko_field_registry%get_field("brinkman")
46
47 ! Another good metric inspired by
48 ! A. Ghasemi & A. Elham (2019)
49 ! "FLOW TOPOLOGY OPTIMIZATION IN PERIODIC DOMAINS WITH APPLICATION TO
50 ! MICRO HEAT EXCHANGER OPTIMIZATION"
51 ! I think they are aluding to that: we only have one source term
52 ! (brinkman)
53 ! in the equation, so by integrating this source term we effectively are
54 ! computing the lift and drag. (without the need to know the interface
55 ! location)
56 ! I think that's quite clever!
57
58 ntot = u%dof%size()
59 call neko_scratch_registry%request_field(work, temp_indices(1))
60 call field_col3(work, mapped_brinkman, u)
61 drag = glsc2(work%x, coef%B, ntot)
62 call field_col3(work, mapped_brinkman, v)
63 lift = glsc2(work%x, coef%B, ntot)
64 call neko_scratch_registry%relinquish_field(temp_indices)
65
66 ! calculate the leakage
67 leakage = leak(brinkman%x, u%x, v%x, w%x, coef%b, ntot)
68 if (pe_rank .eq. 0) then
69 print *, 'Leakage = ', leakage, ', ', t
70 print *, 'Lift = ', lift, ', ', t
71 print *, 'Drag = ', drag, ', ', t
72 end if
73 end if
74
75 end subroutine user_calc_quantities
76
77 function leak(brink, u, v, w, B, n)
78 integer, intent(in) :: n
79 real(kind=rp), dimension(n), intent(in) :: brink
80 real(kind=rp), dimension(n), intent(in) :: u
81 real(kind=rp), dimension(n), intent(in) :: v
82 real(kind=rp), dimension(n), intent(in) :: w
83 real(kind=rp), dimension(n), intent(in) :: b
84 real(kind=rp) :: leak, tmp
85 integer :: i, ierr
86
87 tmp = 0.0_rp
88 do i = 1, n
89 tmp = tmp + brink(i) * sqrt(u(i)**2 + v(i)**2 + w(i)**2) * b(i)
90 end do
91
92 call mpi_allreduce(tmp, leak, 1, &
93 mpi_real_precision, mpi_sum, neko_comm, ierr)
94
95 end function leak
96
97 ! User-defined initial condition
98 subroutine user_ic(u, v, w, p, params)
99 type(field_t), intent(inout) :: u
100 type(field_t), intent(inout) :: v
101 type(field_t), intent(inout) :: w
102 type(field_t), intent(inout) :: p
103 type(json_file), intent(inout) :: params
104 class(point_zone_t), pointer :: zone
105 integer :: i, ntot
106
107 ntot = u%dof%size()
108 do i = 1, ntot
109 u%x(i,1,1,1) = sqrt(1.0_rp - 0.1_rp**2)
110 w%x(i,1,1,1) = 0.0_rp
111
112 ! just to break the symmetry and induce shedding quicker
113 if (abs(u%dof%y(i,1,1,1)) .lt. 4.0_rp) then
114 v%x(i,1,1,1) = 0.1_rp
115 else
116 v%x(i,1,1,1) = 0.0_rp
117 end if
118
119 end do
120 p = 0.0_rp
121
122 ! Get the cylinder mask
123 if (neko_point_zone_registry%point_zone_exists("cylinder")) then
124 zone => neko_point_zone_registry%get_point_zone("cylinder")
125
126 ! Set the velocity to zero inside the cylinder
127 call cfill_mask(u%x, 0.0_rp, u%size(), zone%mask, zone%size)
128 call cfill_mask(v%x, 0.0_rp, v%size(), zone%mask, zone%size)
129 call cfill_mask(w%x, 0.0_rp, w%size(), zone%mask, zone%size)
130 end if
131 end subroutine user_ic
132
133
134end module user
User defined user region.
Definition user.f90:2
real(kind=rp) function leak(brink, u, v, w, b, n)
Definition cylinder.f90:78
subroutine user_ic(u, v, w, p, params)
Definition cylinder.f90:99
subroutine user_calc_quantities(t, tstep, u, v, w, p, coef, params)
Definition cylinder.f90:31
subroutine user_setup(user)
Register user defined functions (see nekos user_intf.f90)
Definition user.f90:22
type(field_t) divergence
Definition cylinder.f90:18