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, copy, cmult
55 use device_math,
only: device_glsc2, device_copy, device_cmult
56 use vector_math,
only: vector_cmult
57 use math_ext,
only: glsc2_mask
58 use field_math,
only: field_rone, field_copy, field_cmult, field_cfill
59 use utils,
only: neko_error
60 use vector,
only: vector_t
74 real(kind=rp) :: limit
76 real(kind=rp) :: volume_domain
78 class(coef_t),
pointer :: c_xh => null()
82 logical :: if_mapping = .false.
87 procedure,
public, pass(this) :: init_json_sim => &
88 volume_constraint_init_json_sim
90 procedure,
public, pass(this) :: init_from_components => &
91 volume_constraint_init_from_components
93 procedure,
public, pass(this) :: free => volume_constraint_free
95 procedure,
public, pass(this) :: update_value => &
96 volume_constraint_update_value
98 procedure,
public, pass(this) :: update_sensitivity => &
99 volume_constraint_update_sensitivity
102 procedure,
private, pass(this) :: compute_volume
113 subroutine volume_constraint_init_json_sim(this, json, design, simulation)
115 type(json_file),
intent(inout) :: json
116 class(
design_t),
intent(in) :: design
119 character(len=:),
allocatable :: mask_name
120 character(len=:),
allocatable :: name
122 real(kind=rp) :: limit
124 call json_get_or_default(json,
"name", name,
"Volume constraint")
125 call json_get_or_default(json,
"mask_name", mask_name,
"")
126 call json_get_or_default(json,
"is_max", is_max, .false.)
127 call json_get(json,
"limit", limit)
129 call this%init_from_components(
design, simulation, name, mask_name, &
133 if (
'mapping' .in. json)
then
135 call this%mapping%init_base(this%c_Xh)
136 call this%mapping%add(json,
'mapping')
137 this%if_mapping = .true.
139 call this%update_value(
design)
142 end subroutine volume_constraint_init_json_sim
152 subroutine volume_constraint_init_from_components(this, design, simulation, &
153 name, mask_name, is_max, limit)
155 class(
design_t),
intent(in) :: design
157 character(len=*),
intent(in) :: mask_name
158 character(len=*),
intent(in) :: name
159 logical,
intent(in) :: is_max
160 real(kind=rp),
intent(in) :: limit
162 type(field_t),
pointer :: work
163 integer :: temp_indices(1)
166 call this%init_base(name,
design%size(), mask_name)
171 this%c_Xh => simulation%neko_case%fluid%c_Xh
174 if (this%has_mask)
then
177 call neko_scratch_registry%request_field(work, temp_indices(1))
178 call field_rone(work)
181 if (neko_bcknd_device .eq. 1)
then
182 this%volume_domain = device_glsc2(work%x_d, this%c_xh%B_d, &
185 this%volume_domain = glsc2_mask(work%x, this%c_Xh%B, &
186 design%size(), this%mask%mask%get(), this%mask%size)
189 call neko_scratch_registry%relinquish_field(temp_indices)
191 this%volume_domain = this%c_Xh%volume
197 call this%update_value(
design)
202 if (neko_bcknd_device .eq. 1)
then
203 call device_copy(this%sensitivity%x_d, this%c_xh%B_d,
design%size())
204 call device_cmult(this%sensitivity%x_d, -1.0_rp / this%volume_domain, &
207 if (this%is_max)
then
208 call device_cmult(this%sensitivity%x_d, -1.0_rp,
design%size())
211 call copy(this%sensitivity%x, this%c_Xh%B,
design%size())
212 call cmult(this%sensitivity%x, -1.0_rp / this%volume_domain, &
215 if (this%is_max)
then
216 call vector_cmult(this%sensitivity, -1.0_rp)
220 if (this%has_mask)
then
224 end subroutine volume_constraint_init_from_components
227 subroutine volume_constraint_free(this)
230 call this%free_base()
231 end subroutine volume_constraint_free
236 subroutine volume_constraint_update_value(this, design)
238 class(
design_t),
intent(in) :: design
239 real(kind=rp) :: volume
241 volume = this%compute_volume(
design)
244 this%value = this%limit - volume / this%volume_domain
247 if (this%is_max) this%value = -this%value
249 end subroutine volume_constraint_update_value
254 subroutine volume_constraint_update_sensitivity(this, design)
256 class(
design_t),
intent(in) :: design
258 type(field_t),
pointer :: unmapped, mapped
259 integer :: temp_indices(2)
261 if (this%if_mapping)
then
263 call neko_scratch_registry%request_field(unmapped, temp_indices(1))
264 call neko_scratch_registry%request_field(mapped, temp_indices(2))
266 call field_cfill(unmapped, -1.0_rp / this%volume_domain)
267 if (this%is_max)
then
268 call field_cmult(unmapped, -1.0_rp)
271 if (this%has_mask)
then
275 call this%mapping%apply_backward(mapped, unmapped)
278 call neko_scratch_registry%relinquish_field(temp_indices)
284 end subroutine volume_constraint_update_sensitivity
294 function compute_volume(this, design)
result(volume)
296 class(
design_t),
intent(in) :: design
297 real(kind=rp) :: volume
302 volume = volume_brinkman_design(this,
design)
305 call neko_error(
'Volume constraint only works with brinkman_design')
308 end function compute_volume
313 function volume_brinkman_design(this, design)
result(volume)
316 real(kind=rp) :: volume
317 type(field_t),
pointer :: work
318 type(vector_t) :: values, unmapped_values
319 integer :: temp_indices(1)
322 if (this%if_mapping)
then
323 call design%get_values(unmapped_values)
324 call values%init(unmapped_values%size())
325 call this%mapping%apply_forward(values, unmapped_values)
326 call unmapped_values%free()
328 call design%get_values(values)
331 if (this%has_mask)
then
333 if (neko_bcknd_device .eq. 1)
then
334 call neko_scratch_registry%request_field(work, temp_indices(1))
335 call device_copy(work%x_d, values%x_d,
design%size())
338 volume = device_glsc2(work%x_d, this%c_xh%B_d,
design%size())
340 call neko_scratch_registry%relinquish_field(temp_indices)
342 volume = glsc2_mask(values%x, this%c_Xh%B,
design%size(), &
343 this%mask%mask%get(), this%mask%size)
348 if (neko_bcknd_device .eq. 1)
then
349 volume = device_glsc2(values%x_d, this%c_xh%B_d,
design%size())
351 volume = glsc2(values%x, this%c_Xh%B,
design%size())
358 end function volume_brinkman_design
Implements the constraint_t type.
Implements the mapping_handler_t type.
Mappings to be applied to a scalar field.
Some common Masking operations we may need.
Contains extensions to the neko library required to run the topology optimization code.
subroutine, public field_to_vector(vector, field)
Field to vector.
Implements the steady_problem_t type.
Implements the volume_constraint_t type. Either .
A topology optimization design variable.
The abstract constraint type.
Abstract class for handling mapping_cascade.
A constraint on the volume of the design.