Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
viscous_dissipation_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 | |"Brinkman dissipation"|
53!
54! I say "Brinkman dissipation" because they said it came from lubrication
55! theory...
56! Anyway, we can change all this later (especially the names!)
57
58! If the objective function \frac{\mu}{2} \int |\nabla u|^2,
59! the corresponding adjoint forcing is \mu \int \nabla v \cdot \nabla u
60!
61! for the Brinkman dissipation, the adjoint forcing is \chi u
62!
63! This has always annoyed me...
64! because now I see one objective and one constraint
65!
67 use num_types, only: rp
68 use field, only: field_t
69 use field_math, only: field_col3, field_addcol3, field_cmult, field_add2s2, &
70 field_copy
71 use operators, only: grad
73 use scratch_registry, only: neko_scratch_registry
76 use objective, only: objective_t
77 use simulation_m, only: simulation_t
78 use adjoint_fluid_scheme, only: adjoint_fluid_scheme_t
79 use coefs, only: coef_t
80 use registry, only: neko_registry
81 use neko_config, only: neko_bcknd_device
82 use math, only: glsc2, copy
83 use device_math, only: device_copy, device_glsc2
84 use design, only: design_t
85 use brinkman_design, only: brinkman_design_t
86 use point_zone, only: point_zone_t
88 use math_ext, only: glsc2_mask
89 use utils, only: neko_error
90 use json_module, only: json_file
91 use json_utils, only: json_get_or_default
92 use continuation_scheduler, only: nekotop_continuation
93 implicit none
94 private
95
99 private
100
102 type(field_t), pointer :: u => null()
104 type(field_t), pointer :: v => null()
106 type(field_t), pointer :: w => null()
108 type(coef_t), pointer :: c_xh => null()
110 type(field_t), pointer :: adjoint_u => null()
112 type(field_t), pointer :: adjoint_v => null()
114 type(field_t), pointer :: adjoint_w => null()
116 real(kind=rp) :: volume
118 real(kind=rp) :: viscosity
119
120 contains
122 procedure, public, pass(this) :: init_json_sim => &
125 procedure, public, pass(this) :: init_from_attributes => &
126 viscous_dissipation_init_attributes
128 procedure, public, pass(this) :: free => viscous_dissipation_free
130 procedure, public, pass(this) :: update_value => &
131 viscous_dissipation_update_value
133 procedure, public, pass(this) :: update_sensitivity => &
134 viscous_dissipation_update_sensitivity
135
137
138contains
139
145 subroutine viscous_dissipation_init_json_sim(this, json, design, simulation)
146 class(viscous_dissipation_objective_t), intent(inout) :: this
147 type(json_file), intent(inout) :: json
148 class(design_t), intent(in) :: design
149 type(simulation_t), target, intent(inout) :: simulation
150
151 character(len=:), allocatable :: name
152 character(len=:), allocatable :: mask_name
153 real(kind=rp) :: weight
154 real(kind=rp) :: start_time, end_time
155
156 call nekotop_continuation%json_get_or_register(json, 'weight', &
157 this%weight, weight, 1.0_rp)
158 call json_get_or_default(json, "mask_name", mask_name, "")
159 call json_get_or_default(json, "name", name, "Dissipation")
160 call json_get_or_default(json, "start_time", start_time, 0.0_rp)
161 call json_get_or_default(json, "end_time", end_time, huge(0.0_rp))
162
163 call this%init_from_attributes(design, simulation, weight, name, &
164 mask_name, start_time, end_time)
166
176 subroutine viscous_dissipation_init_attributes(this, design, simulation, &
177 weight, name, mask_name, start_time, end_time)
178 class(viscous_dissipation_objective_t), intent(inout) :: this
179 class(design_t), intent(in) :: design
180 type(simulation_t), target, intent(inout) :: simulation
181 real(kind=rp), intent(in) :: weight
182 character(len=*), intent(in) :: name
183 character(len=*), intent(in) :: mask_name
184 real(kind=rp), intent(in) :: start_time
185 real(kind=rp), intent(in) :: end_time
186
187 type(adjoint_viscous_dissipation_source_term_t) :: adjoint_forcing
188
189 call this%init_base(name, design%size(), weight, mask_name, &
190 start_time, end_time)
191
192 ! Save the simulation and design
193 this%u => neko_registry%get_field('u')
194 this%v => neko_registry%get_field('v')
195 this%w => neko_registry%get_field('w')
196 this%c_Xh => simulation%fluid%c_Xh
197 this%adjoint_u => neko_registry%get_field('u_adj')
198 this%adjoint_v => neko_registry%get_field('v_adj')
199 this%adjoint_w => neko_registry%get_field('w_adj')
200 this%viscosity = simulation%fluid%mu%x(1,1,1,1)
201
202 ! compute the volume of the objective domain
203 if (this%has_mask) then
204 this%volume = compute_masked_volume(this%mask, this%c_Xh)
205 else
206 this%volume = this%c_Xh%volume
207 end if
208
209 ! you will need to init this!
210 ! append a source term based on the viscous dissipation
211 ! init the adjoint forcing term for the adjoint
212 call adjoint_forcing%init_from_components( &
213 simulation%adjoint_fluid%f_adj_x, &
214 simulation%adjoint_fluid%f_adj_y, &
215 simulation%adjoint_fluid%f_adj_z, &
216 this%u, this%v, this%w, this%weight * this%viscosity, &
217 this%mask, this%has_mask, &
218 this%c_Xh, this%volume, this%start_time, this%end_time)
219
220 ! append adjoint forcing term based on objective function
221 select type (f => simulation%adjoint_fluid)
222 type is (adjoint_fluid_pnpn_t)
223 call f%source_term%add_source_term(adjoint_forcing)
224 end select
225
226 end subroutine viscous_dissipation_init_attributes
227
229 subroutine viscous_dissipation_free(this)
230 class(viscous_dissipation_objective_t), intent(inout) :: this
231 call this%free_base()
232
233 if (associated(this%u)) nullify(this%u)
234 if (associated(this%v)) nullify(this%v)
235 if (associated(this%w)) nullify(this%w)
236 if (associated(this%c_Xh)) nullify(this%c_Xh)
237
238 if (associated(this%adjoint_u)) nullify(this%adjoint_u)
239 if (associated(this%adjoint_v)) nullify(this%adjoint_v)
240 if (associated(this%adjoint_w)) nullify(this%adjoint_w)
241
242 end subroutine viscous_dissipation_free
243
247 subroutine viscous_dissipation_update_value(this, design)
248 class(viscous_dissipation_objective_t), intent(inout) :: this
249 class(design_t), intent(in) :: design
250 type(field_t), pointer :: wo1, wo2, wo3, work
251 type(field_t), pointer :: objective_field
252 integer :: temp_indices(5)
253 integer n
254
255 call neko_scratch_registry%request_field(wo1, temp_indices(1), .false.)
256 call neko_scratch_registry%request_field(wo2, temp_indices(2), .false.)
257 call neko_scratch_registry%request_field(wo3, temp_indices(3), .false.)
258 call neko_scratch_registry%request_field(objective_field, temp_indices(4), &
259 .false.)
260 call neko_scratch_registry%request_field(work, temp_indices(5), .false.)
261
262 ! update_value the objective function.
263 call grad(wo1%x, wo2%x, wo3%x, this%u%x, this%c_Xh)
264 call field_col3(objective_field, wo1, wo1)
265 call field_addcol3(objective_field, wo2, wo2)
266 call field_addcol3(objective_field, wo3, wo3)
267
268 call grad(wo1%x, wo2%x, wo3%x, this%v%x, this%c_Xh)
269 call field_addcol3(objective_field, wo1, wo1)
270 call field_addcol3(objective_field, wo2, wo2)
271 call field_addcol3(objective_field, wo3, wo3)
272
273 call grad(wo1%x, wo2%x, wo3%x, this%w%x, this%c_Xh)
274 call field_addcol3(objective_field, wo1, wo1)
275 call field_addcol3(objective_field, wo2, wo2)
276 call field_addcol3(objective_field, wo3, wo3)
277
278 ! integrate the field
279 n = wo1%size()
280 if (this%has_mask) then
281 if (neko_bcknd_device .eq. 1) then
282 ! note, this could be done more elagantly by writing
283 ! device_glsc2_mask
284 call field_copy(work, objective_field)
285 call mask_exterior_const(work, this%mask, 0.0_rp)
286 this%value = device_glsc2(work%x_d, this%c_xh%B_d, n)
287 else
288 this%value = glsc2_mask(objective_field%x, this%c_Xh%b, &
289 n, this%mask%mask%get(), this%mask%size)
290 end if
291 else
292 if (neko_bcknd_device .eq. 1) then
293 this%value = device_glsc2(objective_field%x_d, &
294 this%c_Xh%b_d, n)
295 else
296 this%value = glsc2(objective_field%x, this%c_Xh%b, n)
297 end if
298 end if
299
300 this%value = this%value * 0.5_rp * this%viscosity / this%volume
301
302 call neko_scratch_registry%relinquish_field(temp_indices)
303
304 end subroutine viscous_dissipation_update_value
305
309 subroutine viscous_dissipation_update_sensitivity(this, design)
310 class(viscous_dissipation_objective_t), intent(inout) :: this
311 class(design_t), intent(in) :: design
312
313 end subroutine viscous_dissipation_update_sensitivity
314
Adjoint Pn/Pn formulation.
Implements the adjoint_viscous_dissipation_source_term_t type.
Continuation scheduler for the optimization loop.
Implements the design_t.
Definition design.f90:36
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.
Implements the viscous_dissipation_objective_t type.
subroutine viscous_dissipation_init_json_sim(this, json, design, simulation)
The common constructor using a JSON object.
A topology optimization design variable.
An abstract design type.
Definition design.f90:53
The abstract objective type.
Definition objective.f90:52
An objective function corresponding to viscous dissipation .