Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
lube_term_objective.f90
Go to the documentation of this file.
1
34!
36!
37! I promise I'll write this document properly in the future...
38!
39! But the Borval Peterson (I think) paper had an objective function
40! that had 2 terms, dissipation and this term they claimed represented
41! out of plane stresses.
42! I never really understood that extra term, I also don't think it
43! applies to 3D cases, but everyone includes it anyway.
44!
45! It appears to me to be basically a heuristic penality that targets
46! non-binary designs
47!
48! so let's call
49!
50! F = \int |\nabla u|^2 + K \int \chi \u^2
51!
52! | dissipation | |"lube term"|
53!
54! I say "lube term" because they said it came from lubrication theory...
55! Anyway, we can change all this later (especially the names!)
56
57! If the objective function \int |\nabla u|^2,
58! the corresponding adjoint forcing is \int \nabla v \cdot \nabla u
59!
60! for the lube term, the adjoint forcing is \chi u
61!
62! This has always annoyed me...
63! because now I see one objective and one constraint
64!
66 use objective, only: objective_t
67 use design, only: design_t
68 use brinkman_design, only: brinkman_design_t
69 use simulation_m, only: simulation_t
72 use num_types, only: rp
73 use field, only: field_t
74 use scratch_registry, only: neko_scratch_registry, scratch_registry_t
75 use neko_config, only: neko_bcknd_device
77 use utils, only: neko_error
78 use json_module, only: json_file
79 use json_utils, only: json_get_or_default
80 use registry, only: neko_registry
81 use interpolation, only: interpolator_t
82 use space, only: space_t, gl
83 use coefs, only: coef_t
84 use math, only: glsc2, copy, col2, invcol2
85 use device_math, only: device_copy, device_glsc2, device_col2, device_invcol2
86 use math_ext, only: glsc2_mask
87 use field_math, only: field_col3, field_addcol3, field_cmult, field_col2
88 implicit none
89 private
90
93 type, public, extends(objective_t) :: lube_term_objective_t
94 private
95
97 type(field_t), pointer :: u => null()
99 type(field_t), pointer :: v => null()
101 type(field_t), pointer :: w => null()
103 type(field_t), pointer :: brinkman_amplitude => null()
105 logical :: dealias_sensitivity
107 logical :: dealias_forcing
109 real(kind=rp) :: volume
110
111 ! ---- everything GLL ----
113 type(coef_t), pointer :: c_xh_gll
115 type(space_t), pointer :: xh_gll
116
117 ! ---- everything for GL ----
119 type(space_t), pointer :: xh_gl
121 type(coef_t), pointer :: c_xh_gl
123 type(interpolator_t), pointer :: gll_to_gl
125 type(scratch_registry_t), pointer :: scratch_gl
127 integer :: gdim
128
129
130 contains
131
133 procedure, public, pass(this) :: init_json_sim => lube_term_init_json_sim
135 procedure, public, pass(this) :: init_from_attributes => &
136 lube_term_init_attributes
138 procedure, public, pass(this) :: free => lube_term_free
140 procedure, public, pass(this) :: update_value => &
141 lube_term_update_value
143 procedure, public, pass(this) :: update_sensitivity => &
144 lube_term_update_sensitivity
145
146 end type lube_term_objective_t
147
148contains
149
155 subroutine lube_term_init_json_sim(this, json, design, simulation)
156 class(lube_term_objective_t), intent(inout) :: this
157 type(json_file), intent(inout) :: json
158 class(design_t), intent(in) :: design
159 type(simulation_t), target, intent(inout) :: simulation
160
161 character(len=:), allocatable :: mask_name
162 character(len=:), allocatable :: name
163 real(kind=rp) :: weight
164 logical :: dealias_sensitivity, dealias_forcing
165
166 call json_get_or_default(json, "weight", weight, 1.0_rp)
167 call json_get_or_default(json, "mask_name", mask_name, "")
168 call json_get_or_default(json, "name", name, "Out of plane stresses")
169 call json_get_or_default(json, "dealias_sensitivity", &
170 dealias_sensitivity, .true.)
171 call json_get_or_default(json, "dealias_forcing", &
172 dealias_forcing, .true.)
173
174 call this%init_from_attributes(design, simulation, weight, name, &
175 mask_name, dealias_sensitivity, dealias_forcing)
176 end subroutine lube_term_init_json_sim
177
187 subroutine lube_term_init_attributes(this, design, simulation, weight, &
188 name, mask_name, dealias_sensitivity, dealias_forcing)
189 class(lube_term_objective_t), intent(inout) :: this
190 class(design_t), intent(in) :: design
191 type(simulation_t), target, intent(inout) :: simulation
192 real(kind=rp), intent(in) :: weight
193 character(len=*), intent(in) :: mask_name
194 character(len=*), intent(in) :: name
195 logical, intent(in) :: dealias_sensitivity
196 logical, intent(in) :: dealias_forcing
197 type(adjoint_lube_source_term_t) :: lube_term
198
199 ! Call the base initializer
200 call this%init_base(name, design%size(), weight, mask_name)
201
202 this%dealias_forcing = dealias_forcing
203 this%dealias_sensitivity = dealias_sensitivity
204
205 ! Grab the brinkman amplitude for the lube term
206 select type (design)
207 type is (brinkman_design_t)
208 this%brinkman_amplitude => &
209 neko_registry%get_field("brinkman_amplitude")
210
211
212 class default
213 call neko_error('Minimum dissipation only works with brinkman_design')
214 end select
215
216 this%u => neko_registry%get_field('u')
217 this%v => neko_registry%get_field('v')
218 this%w => neko_registry%get_field('w')
219
220 ! GLL
221 this%c_Xh_GLL => simulation%neko_case%fluid%c_Xh
222 this%Xh_GLL => simulation%neko_case%fluid%c_Xh%Xh
223 this%gdim = this%c_Xh_GLL%msh%gdim
224
225 ! GL
226 this%c_Xh_GL => simulation%adjoint_case%fluid_adj%c_Xh_GL
227 this%Xh_GL => this%c_Xh_GL%Xh
228
229 ! GLL to GL
230 this%GLL_to_GL => simulation%adjoint_case%fluid_adj%GLL_to_GL
231
232 this%scratch_GL => simulation%adjoint_case%fluid_adj%scratch_GL
233
234 ! compute the volume of the objective domain
235 if (this%has_mask) then
236 this%volume = compute_masked_volume(this%mask, this%c_Xh_GLL)
237 else
238 this%volume = this%c_Xh_GLL%volume
239 end if
240
241 ! if we have the lube term we need to initialize and append that too
242
243 associate(f_adj_x => simulation%adjoint_fluid%f_adj_x, &
244 f_adj_y => simulation%adjoint_fluid%f_adj_y, &
245 f_adj_z => simulation%adjoint_fluid%f_adj_z)
246
247 call lube_term%init_from_components(f_adj_x, f_adj_y, f_adj_z, design, &
248 this%weight, this%u, this%v, this%w, this%mask, &
249 this%has_mask, this%c_Xh_GLL, this%c_Xh_GL, this%GLL_to_GL, &
250 this%dealias_forcing, this%volume, &
251 this%scratch_GL, this%gdim)
252
253 end associate
254
255 ! append adjoint forcing term based on objective function
256 select type (f => simulation%adjoint_fluid)
257 type is (adjoint_fluid_pnpn_t)
258 call f%source_term%add_source_term(lube_term)
259 end select
260
261 end subroutine lube_term_init_attributes
262
264 subroutine lube_term_free(this)
265 class(lube_term_objective_t), intent(inout) :: this
266 call this%free_base()
267
268 this%u => null()
269 this%v => null()
270 this%w => null()
271 this%c_Xh_GLL => null()
272 this%brinkman_amplitude => null()
273 nullify(this%c_Xh_GL)
274 nullify(this%Xh_GL)
275 nullify(this%Xh_GLL)
276 nullify(this%GLL_to_GL)
277 nullify(this%scratch_GL)
278
279 end subroutine lube_term_free
280
284 subroutine lube_term_update_value(this, design)
285 class(lube_term_objective_t), intent(inout) :: this
286 class(design_t), intent(in) :: design
287 type(field_t), pointer :: work
288 integer :: temp_indices(1)
289
290 call neko_scratch_registry%request_field(work, temp_indices(1), .false.)
291
292 call field_col3(work, this%u, this%u)
293 call field_addcol3(work, this%v, this%v)
294 if (this%gdim .eq. 3) then
295 call field_addcol3(work, this%w, this%w)
296 end if
297 call field_col2(work, this%brinkman_amplitude)
298
299 if (this%has_mask) then
300 if (neko_bcknd_device .eq. 1) then
301 ! note, this could be done more elagantly by writing
302 ! device_glsc2_mask
303 call mask_exterior_const(work, this%mask, 0.0_rp)
304 this%value = device_glsc2(work%x_d, this%c_Xh_GLL%B_d, design%size())
305 else
306 this%value = glsc2_mask(work%x, this%c_Xh_GLL%B, design%size(), &
307 this%mask%mask%get(), this%mask%size)
308 end if
309 else
310 if (neko_bcknd_device .eq. 1) then
311 this%value = device_glsc2(work%x_d, this%c_Xh_GLL%B_d, design%size())
312 else
313 this%value = glsc2(work%x, this%c_Xh_GLL%B, design%size())
314 end if
315 end if
316 this%value = 0.5_rp * this%value / this%volume
317
318 call neko_scratch_registry%relinquish_field(temp_indices)
319
320 end subroutine lube_term_update_value
321
326 subroutine lube_term_update_sensitivity(this, design)
327 class(lube_term_objective_t), intent(inout) :: this
328 class(design_t), intent(in) :: design
329 type(field_t), pointer :: work
330 integer :: temp_indices(1)
331 integer :: n_GL, nel
332 type(field_t), pointer :: accumulate, fld_GL
333 integer :: temp_indices_GL(2)
334
335 ! if we have the lube term we also get an extra term in the sensitivity
336
337 call neko_scratch_registry%request_field(work, temp_indices(1), .false.)
338
339 if(this%dealias_sensitivity) then
340 nel = this%c_Xh_GLL%msh%nelv
341 n_gl = nel * this%Xh_GL%lxyz
342 call this%scratch_GL%request_field(accumulate, temp_indices_gl(1), &
343 .false.)
344 call this%scratch_GL%request_field(fld_gl, temp_indices_gl(2), .false.)
345
346 call this%GLL_to_GL%map(fld_gl%x, this%u%x, nel, this%Xh_GL)
347 call field_col3(accumulate, fld_gl, fld_gl)
348 call this%GLL_to_GL%map(fld_gl%x, this%v%x, nel, this%Xh_GL)
349 call field_addcol3(accumulate, fld_gl, fld_gl)
350 if (this%gdim .eq. 3) then
351 call this%GLL_to_GL%map(fld_gl%x, this%w%x, nel, this%Xh_GL)
352 call field_addcol3(accumulate, fld_gl, fld_gl)
353 end if
354 ! scale
355 call field_cmult(accumulate, this%weight * 0.5_rp / this%volume)
356
357 ! Evaluate term on GL and preempt the GLL premultiplication
358 if (neko_bcknd_device .eq. 1) then
359 call device_col2(accumulate%x_d, this%c_Xh_GL%B_d, n_gl)
360 call this%GLL_to_GL%map(work%x, accumulate%x, nel, this%Xh_GLL)
361 call device_invcol2(work%x_d, this%c_Xh_GLL%B_d, work%size())
362 else
363 call col2(accumulate%x, this%c_Xh_GL%B, n_gl)
364 call this%GLL_to_GL%map(work%x, accumulate%x, nel, this%Xh_GLL)
365 call invcol2(work%x, this%c_Xh_GLL%B, work%size())
366 end if
367
368 call this%scratch_GL%relinquish_field(temp_indices_gl)
369
370 else
371 call field_col3(work, this%u, this%u)
372 call field_addcol3(work, this%v, this%v)
373 if (this%gdim .eq. 3) then
374 call field_addcol3(work, this%w, this%w)
375 end if
376 ! scale
377 call field_cmult(work, this%weight * 0.5_rp / this%volume)
378 end if
379
380 if (neko_bcknd_device .eq. 1) then
381 call device_copy(this%sensitivity%x_d, work%x_d, this%sensitivity%size())
382 else
383 call copy(this%sensitivity%x, work%x, this%sensitivity%size())
384 end if
385
386 call neko_scratch_registry%relinquish_field(temp_indices)
387
388 end subroutine lube_term_update_sensitivity
389
390end module lube_term_objective
Adjoint Pn/Pn formulation.
Implements the adjoint_lube_source_term_t type.
Implements the design_t.
Definition design.f90:36
Implements the lube_term_objective_t type.
subroutine lube_term_init_json_sim(this, json, design, simulation)
The common constructor using a JSON object.
Some common Masking operations we may need.
Definition mask_ops.f90:36
real(kind=rp) function, public compute_masked_volume(mask, coef)
Compute the volume of the domain contained within the mask.
Definition mask_ops.f90:182
Implements the objective_t type.
Definition objective.f90:36
Implements the steady_problem_t type.
A adjoint source term corresponding to an objective of.
A topology optimization design variable.
An abstract design type.
Definition design.f90:54
An objective function corresponding to out of plane stresses .
The abstract objective type.
Definition objective.f90:52