Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
adjoint_minimum_dissipation_source_term.f90
1! Copyright (c) 2023, 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!
34!
35!
36! If the objective function $\int |\nabla u|^2$,
37! the corresponding adjoint forcing is $ \int \nabla v \cdot \nabla u $ in weak
38! form.
40 use num_types, only: rp
41 use field_list, only: field_list_t
42 use json_module, only: json_file
43 use json_utils, only: json_get, json_get_or_default
44 use source_term, only: source_term_t
45 use coefs, only: coef_t
46 use neko_config, only: neko_bcknd_device
47 use utils, only: neko_error
48 use field, only: field_t
49 use field_math, only: field_subcol3, field_add2, field_add2s2
50 use json_module, only: json_file
52 use simcomp_executor, only: neko_simcomps
53 use fluid_user_source_term, only: fluid_user_source_term_t
54 use num_types, only: rp
55 use field, only: field_t
56 use field_registry, only: neko_field_registry
57 use math, only: rzero, copy, chsign
58 use device_math, only: device_copy, device_cmult
59 use neko_config, only: neko_bcknd_device
60 use operators, only: curl
61 use scratch_registry, only: neko_scratch_registry
63 use point_zone, only: point_zone_t
64 implicit none
65 private
66
68 ! $\int \nabla v \cdot \nabla u $
69 type, public, extends(source_term_t) :: &
72 type(field_t), pointer :: u => null()
74 type(field_t), pointer :: v => null()
76 type(field_t), pointer :: w => null()
78 real(kind=rp) :: obj_scale
80 class(point_zone_t), pointer :: mask => null()
82 logical :: if_mask
83
84 contains
86 procedure, pass(this) :: init => &
87 adjoint_minimum_dissipation_source_term_init_from_json
89 procedure, pass(this) :: init_from_components => &
90 adjoint_minimum_dissipation_source_term_init_from_components
92 procedure, pass(this) :: free => &
93 adjoint_minimum_dissipation_source_term_free
95 procedure, pass(this) :: compute_ => &
96 adjoint_minimum_dissipation_source_term_compute
98
99contains
106 subroutine adjoint_minimum_dissipation_source_term_init_from_json(this, &
107 json, fields, coef, variable_name)
108 class(adjoint_minimum_dissipation_source_term_t), intent(inout) :: this
109 type(json_file), intent(inout) :: json
110 type(field_list_t), intent(in), target :: fields
111 type(coef_t), intent(in), target :: coef
112 character(len=*), intent(in) :: variable_name
113
114 ! we shouldn't be initializing this from JSON
115 ! maybe throw an error?
116
117
118 end subroutine adjoint_minimum_dissipation_source_term_init_from_json
119
128 subroutine adjoint_minimum_dissipation_source_term_init_from_components(this,&
129 f_x, f_y, f_z, &
130 u, v, w, obj_scale, &
131 mask, if_mask, &
132 coef)
133 class(adjoint_minimum_dissipation_source_term_t), intent(inout) :: this
134 type(field_t), pointer, intent(in) :: f_x, f_y, f_z
135 type(field_list_t) :: fields
136 type(coef_t) :: coef
137 real(kind=rp) :: start_time
138 real(kind=rp) :: end_time
139 real(kind=rp) :: obj_scale
140 type(field_t), intent(in), target :: u, v, w
141 class(point_zone_t), intent(in), target :: mask
142 logical :: if_mask
143
144 ! I wish you didn't need a start time and end time...
145 ! but I'm just going to set a super big number...
146 start_time = 0.0_rp
147 end_time = 100000000.0_rp
148
149 call this%free()
150
151 ! this is copying the fluid source term init
152 ! We package the fields for the source term to operate on in a field list.
153 call fields%init(3)
154 call fields%assign(1, f_x)
155 call fields%assign(2, f_y)
156 call fields%assign(3, f_z)
157
158 call this%init_base(fields, coef, start_time, end_time)
159
160 ! point everything in the correct places
161 this%u => u
162 this%v => v
163 this%w => w
164
165 this%obj_scale = obj_scale
166
167 this%if_mask = if_mask
168 if (this%if_mask) then
169 this%mask => mask
170 end if
171
172 end subroutine adjoint_minimum_dissipation_source_term_init_from_components
173
175 subroutine adjoint_minimum_dissipation_source_term_free(this)
176 class(adjoint_minimum_dissipation_source_term_t), intent(inout) :: this
177
178 call this%free_base()
179 end subroutine adjoint_minimum_dissipation_source_term_free
180
185 subroutine adjoint_minimum_dissipation_source_term_compute(this, t, tstep)
186 class(adjoint_minimum_dissipation_source_term_t), intent(inout) :: this
187 real(kind=rp), intent(in) :: t
188 integer, intent(in) :: tstep
189 type(field_t), pointer :: u, v, w
190 type(field_t), pointer :: fu, fv, fw
191 !type(field_t), pointer :: dudx, dudy, dudz
192 !type(field_t), pointer :: dvdx, dvdy, dvdz
193 !type(field_t), pointer :: dwdx, dwdy, dwdz
194 type(field_t), pointer :: wo1, wo2, wo3, wo4, wo5, wo6
195 type(field_t), pointer :: t1 , t2
196 integer :: temp_indices(8)
197 integer n
198
199
200 fu => this%fields%get_by_index(1)
201 fv => this%fields%get_by_index(2)
202 fw => this%fields%get_by_index(3)
203
204 n = fu%size()
205
206 ! fuck I'm not sure about this... I need a pen and paper
207 ! also there should be a way to pre-process this forcing term...
208 ! instead of recalculating it every time
209 u => this%u
210 v => this%v
211 w => this%w
212 call neko_scratch_registry%request_field(wo1, temp_indices(1))
213 call neko_scratch_registry%request_field(wo2, temp_indices(2))
214 call neko_scratch_registry%request_field(wo3, temp_indices(3))
215 call neko_scratch_registry%request_field(wo4, temp_indices(4))
216 call neko_scratch_registry%request_field(wo5, temp_indices(5))
217 call neko_scratch_registry%request_field(wo6, temp_indices(6))
218 call neko_scratch_registry%request_field(t1 , temp_indices(7))
219 call neko_scratch_registry%request_field(t2 , temp_indices(8))
220
221 ! TODO
222 ! ok we're computing gradients at every timestep... which is stupid...
223 ! BUT
224 ! if this was unsteady we would have to do this.
225
226 ! TODO
227 ! this is cheating a little bit...
228 ! in strong form, \nabla u . \nabla v => - v . \nabla^2 u + bdry
229 !
230 ! we can do this properly later in weak form, ideally using ax_helm or so
231 !
232 ! for now we'll work in strong form and ignore the bdry
233 ! and suffer the double derivative :/
234 !
235 ! in fact, we'll go even quicker and use
236 ! \nabla ^2 u = grad (div (u)) - curl ( curl (u ))
237 ! and assume divergence free u
238
239 ! => - \nabla ^2 u = curl ( curl (u ))
240
241 call curl(wo1, wo2, wo3, u, v, w, t1, t2, this%coef)
242 call curl(wo4, wo5, wo6, wo1, wo2, wo3, t1, t2, this%coef)
243
244 ! mask
245 if (this%if_mask) then
246 call mask_exterior_const(wo4, this%mask, 0.0_rp)
247 call mask_exterior_const(wo5, this%mask, 0.0_rp)
248 call mask_exterior_const(wo6, this%mask, 0.0_rp)
249 end if
250
251 call field_add2s2(fu, wo4, this%obj_scale)
252 call field_add2s2(fv, wo5, this%obj_scale)
253 call field_add2s2(fw, wo6, this%obj_scale)
254
255 ! don't worry... we'll write this MUCH cleaner in the final version
256
257 call neko_scratch_registry%relinquish_field(temp_indices)
258
259 end subroutine adjoint_minimum_dissipation_source_term_compute
260
Implements the adjoint_minimum_dissipation_source_term_t type.
Some common Masking operations we may need.
Definition mask_ops.f90:34
Implements the steady_simcomp_t type.
The steady_simcomp_t type is a simulation component that terminates a simulation when the normed diff...