Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
volume_constraint.f90
Go to the documentation of this file.
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! $V = \frac{1}{|\Omega_O|}\int_{\Omega_O} \tilde{\rho} d\Omega$
35! Either
36! $V < V_\text{max}$
37! $V > V_\text{min}$
39 use constraint, only: constraint_t
40
41 use design, only: design_t
43 use simulation, only: simulation_t
44
45 use num_types, only: rp
46 use coefs, only: coef_t
47 use json_module, only: json_file
48 use json_utils, only: json_get, json_get_or_default
49 use field, only: field_t
50 use field_registry, only: neko_field_registry
51 use scratch_registry, only: neko_scratch_registry
52 use neko_config, only: neko_bcknd_device
54 use math, only: glsc2
55 use device_math, only: device_glsc2
56 use math_ext, only: glsc2_mask
57 use field_math, only: field_rone, field_copy
58 use utils, only: neko_error
59 implicit none
60 private
61
63 type, public, extends(constraint_t) :: volume_constraint_t
64 private
65
69 logical :: is_max
71 real(kind=rp) :: limit
73 real(kind=rp) :: volume_domain
74
76 class(coef_t), pointer :: c_xh => null()
77
78 contains
80 procedure, public, pass(this) :: init_json => volume_constraint_init_json
82 procedure, public, pass(this) :: init_from_attributes => &
85 procedure, public, pass(this) :: free => volume_constraint_free
87 procedure, public, pass(this) :: update_value => &
90 procedure, public, pass(this) :: update_sensitivity => &
92
94 procedure, private, pass(this) :: compute_volume
95
96 end type volume_constraint_t
97
98contains
99
104 subroutine volume_constraint_init_json(this, json, design, simulation)
105 class(volume_constraint_t), intent(inout) :: this
106 type(json_file), intent(inout) :: json
107 class(design_t), intent(in) :: design
108 type(simulation_t), target, intent(inout) :: simulation
109
110 character(len=:), allocatable :: mask_name
111 character(len=:), allocatable :: name
112 logical :: is_max
113 real(kind=rp) :: limit
114
115 call json_get_or_default(json, "mask_name", mask_name, "")
116 call json_get_or_default(json, "name", name, "Volume constraint")
117 call json_get_or_default(json, "is_max", is_max, .false.)
118 call json_get(json, "limit", limit)
119
120 call this%init_from_attributes(design, simulation, name, mask_name, &
121 is_max, limit)
122 end subroutine volume_constraint_init_json
123
130 subroutine volume_constraint_init_attributes(this, design, simulation, &
131 name, mask_name, is_max, limit)
132 class(volume_constraint_t), intent(inout) :: this
133 class(design_t), intent(in) :: design
134 type(simulation_t), target, intent(inout) :: simulation
135 character(len=*), intent(in) :: mask_name
136 character(len=*), intent(in) :: name
137 logical, intent(in) :: is_max
138 real(kind=rp), intent(in) :: limit
139
140 real(kind=rp) :: volume
141 type(field_t), pointer :: work
142 integer :: temp_indices(1)
143
144 ! Initialize the base class
145 call this%init_base(name, design%size(), mask_name)
146
147 ! Store the attributes
148 this%is_max = is_max
149 this%limit = limit
150 this%c_Xh => simulation%neko_case%fluid%c_Xh
151
152 ! Now we can extract the mask/has_mask from the design
153 if (this%has_mask) then
154
155 ! calculate the volume of the optimization domain
156 call neko_scratch_registry%request_field(work, temp_indices(1))
157 call field_rone(work)
158
159 if (neko_bcknd_device .eq. 1) then
160 call mask_exterior_const(work, this%mask, 0.0_rp)
161 this%volume_domain = device_glsc2(work%x_d, this%c_xh%B_d, &
162 work%size())
163 else
164 this%volume_domain = glsc2_mask(work%x, this%c_Xh%B, &
165 design%size(), this%mask%mask, this%mask%size)
166 end if
167
168 call neko_scratch_registry%relinquish_field(temp_indices)
169 else
170 this%volume_domain = this%c_Xh%volume
171 end if
172
173 ! ------------------------------------------------------------------------ !
174 ! Initialize the value of constraint
175
176 ! Compute the volume of the design
177 volume = this%compute_volume(design)
178
179 ! Compute the distance to the target volume
180 this%value = this%limit - volume / this%volume_domain
181
182 ! Invert the sign if it is a maximum constraint
183 if (this%is_max) this%value = - ( this%value )
184
185 ! ------------------------------------------------------------------------ !
186 ! Initialize the sensitivity value
187
188 this%sensitivity = 1.0_rp / this%volume_domain
189
190 ! Invert the sign if it is a maximum constraint
191 if (.not. this%is_max) this%sensitivity = (-1.0_rp) * this%sensitivity
192
193 if (this%has_mask) then
194 call mask_exterior_const(this%sensitivity, this%mask, 0.0_rp)
195 end if
196
198
200 subroutine volume_constraint_free(this)
201 class(volume_constraint_t), intent(inout) :: this
202
203 call this%free_base()
204 end subroutine volume_constraint_free
205
209 subroutine volume_constraint_update_value(this, design)
210 class(volume_constraint_t), intent(inout) :: this
211 class(design_t), intent(in) :: design
212 real(kind=rp) :: volume
213
214 volume = this%compute_volume(design)
215
216 ! Compute the distance to the target volume
217 this%value = this%limit - volume / this%volume_domain
218
219 ! Invert the sign if it is a maximum constraint
220 if (this%is_max) this%value = - ( this%value )
221
222 end subroutine volume_constraint_update_value
223
229 class(volume_constraint_t), intent(inout) :: this
230 class(design_t), intent(in) :: design
231
232 ! Sensitivity is just a constant so it should not be updated
233
235
236
237 ! ========================================================================== !
238 ! The actual volume computations for different types of designs
239
240
245 function compute_volume(this, design) result(volume)
246 class(volume_constraint_t), intent(inout) :: this
247 class(design_t), intent(in) :: design
248 real(kind=rp) :: volume
249
250 volume = 0.0_rp
251 select type (design)
252 type is (brinkman_design_t)
253 volume = volume_brinkman_design(this, design)
254
255 class default
256 call neko_error('Volume constraint only works with brinkman_design')
257 end select
258
259 end function compute_volume
260
263 function volume_brinkman_design(this, design) result(volume)
264 class(volume_constraint_t), intent(inout) :: this
265 type(brinkman_design_t), intent(in) :: design
266 real(kind=rp) :: volume
267 type(field_t), pointer :: work, design_indicator
268 integer :: temp_indices(1)
269
270 volume = 0.0_rp
271 design_indicator => neko_field_registry%get_field("design_indicator")
272
273 ! in the future we should be using the mapped design variable
274 ! corresponding to this constraint!!!
275 if (this%has_mask) then
276
277 if (neko_bcknd_device .eq. 1) then
278 call neko_scratch_registry%request_field(work, temp_indices(1))
279 call field_copy(work, design_indicator)
280 call mask_exterior_const(work, this%mask, 0.0_rp)
281 volume = device_glsc2(work%x_d, this%c_xh%B_d, design%size())
282 call neko_scratch_registry%relinquish_field(temp_indices)
283 else
284 volume = glsc2_mask(design_indicator%x, &
285 this%c_Xh%B, design%size(), this%mask%mask, this%mask%size)
286 end if
287
288 else
289
290 if (neko_bcknd_device .eq. 1) then
291 volume = device_glsc2(design_indicator%x_d, &
292 this%c_xh%B_d, design%size())
293 else
294 volume = glsc2(design_indicator%x, &
295 this%c_Xh%B, design%size())
296 end if
297
298 end if
299
300 end function volume_brinkman_design
301
302end module volume_constraint
Implements the constraint_t type.
Implements the design_t.
Definition design.f90:34
Some common Masking operations we may need.
Definition mask_ops.f90:34
real(kind=rp) function glsc2_mask(a, b, size, mask, mask_size)
Weighted inner product for indices in the mask.
Definition math_ext.f90:117
Implements the steady_problem_t type.
Implements the volume_constraint_t type.
real(kind=rp) function compute_volume(this, design)
Computes the volume of the design.
subroutine volume_constraint_init_json(this, json, design, simulation)
The common constructor using a JSON object.
subroutine volume_constraint_init_attributes(this, design, simulation, name, mask_name, is_max, limit)
The direct initializer from attributes.
real(kind=rp) function volume_brinkman_design(this, design)
Computes the volume of the brinkman_design.
subroutine volume_constraint_update_sensitivity(this, design)
The computation of the sensitivity.
subroutine volume_constraint_update_value(this, design)
The computation of the constraint.
subroutine volume_constraint_free(this)
Destructor.
A topology optimization design variable.
The abstract constraint type.
An abstract design type.
Definition design.f90:48
A constraint on the volume of the design.