47 use num_types,
only: rp
48 use coefs,
only: coef_t
49 use json_module,
only: json_file
50 use json_utils,
only: json_get, json_get_or_default
51 use field,
only: field_t
52 use scratch_registry,
only: neko_scratch_registry
53 use neko_config,
only: neko_bcknd_device
55 use math,
only: glsc2, copy, cmult
56 use device_math,
only: device_glsc2, device_copy, device_cmult
57 use vector_math,
only: vector_cmult
58 use math_ext,
only: glsc2_mask
59 use field_math,
only: field_rone, field_copy, field_cmult, field_cfill
60 use utils,
only: neko_error
61 use vector,
only: vector_t
75 real(kind=rp) :: limit
77 real(kind=rp) :: volume_domain
79 class(coef_t),
pointer :: c_xh => null()
83 logical :: if_mapping = .false.
88 procedure,
public, pass(this) :: init_json_sim => &
91 procedure,
public, pass(this) :: init_from_components => &
92 volume_constraint_init_from_components
94 procedure,
public, pass(this) :: free => volume_constraint_free
96 procedure,
public, pass(this) :: update_value => &
97 volume_constraint_update_value
99 procedure,
public, pass(this) :: update_sensitivity => &
100 volume_constraint_update_sensitivity
102 procedure,
public, pass(this) :: get_log_size => &
103 volume_constraint_get_log_size
105 procedure,
public, pass(this) :: get_log_headers => &
106 volume_constraint_get_log_headers
108 procedure,
public, pass(this) :: get_log_values => &
109 volume_constraint_get_log_values
112 procedure,
private, pass(this) :: compute_volume
125 type(json_file),
intent(inout) :: json
126 class(
design_t),
intent(in) :: design
129 character(len=:),
allocatable :: mask_name
130 character(len=:),
allocatable :: name
132 real(kind=rp) :: limit
134 call json_get_or_default(json,
"name", name,
"Volume constraint")
135 call json_get_or_default(json,
"mask_name", mask_name,
"")
136 call json_get_or_default(json,
"is_max", is_max, .false.)
137 call json_get(json,
"limit", limit)
139 call this%init_from_components(
design, simulation, name, mask_name, &
143 if (
'mapping' .in. json)
then
145 call this%mapping%init_base(this%c_Xh)
146 call this%mapping%add(json,
'mapping')
147 this%if_mapping = .true.
149 call this%update_value(
design)
162 subroutine volume_constraint_init_from_components(this, design, simulation, &
163 name, mask_name, is_max, limit)
165 class(
design_t),
intent(in) :: design
167 character(len=*),
intent(in) :: mask_name
168 character(len=*),
intent(in) :: name
169 logical,
intent(in) :: is_max
170 real(kind=rp),
intent(in) :: limit
172 type(field_t),
pointer :: work
173 integer :: temp_indices(1)
176 call this%init_base(name,
design%size(), mask_name)
181 this%c_Xh => simulation%neko_case%fluid%c_Xh
184 if (this%has_mask)
then
187 call neko_scratch_registry%request(work, temp_indices(1), .false.)
188 call field_rone(work)
191 if (neko_bcknd_device .eq. 1)
then
192 this%volume_domain = device_glsc2(work%x_d, this%c_xh%B_d, &
195 this%volume_domain = glsc2_mask(work%x, this%c_Xh%B, &
196 design%size(), this%mask%mask%get(), this%mask%size)
199 call neko_scratch_registry%relinquish(temp_indices)
201 this%volume_domain = this%c_Xh%volume
207 call this%update_value(
design)
212 if (neko_bcknd_device .eq. 1)
then
213 call device_copy(this%sensitivity%x_d, this%c_xh%B_d,
design%size())
214 call device_cmult(this%sensitivity%x_d, -1.0_rp / this%volume_domain, &
217 if (this%is_max)
then
218 call device_cmult(this%sensitivity%x_d, -1.0_rp,
design%size())
221 call copy(this%sensitivity%x, this%c_Xh%B,
design%size())
222 call cmult(this%sensitivity%x, -1.0_rp / this%volume_domain, &
225 if (this%is_max)
then
226 call vector_cmult(this%sensitivity, -1.0_rp)
230 if (this%has_mask)
then
234 end subroutine volume_constraint_init_from_components
237 subroutine volume_constraint_free(this)
240 call this%free_base()
241 end subroutine volume_constraint_free
246 subroutine volume_constraint_update_value(this, design)
248 class(
design_t),
intent(in) :: design
249 real(kind=rp) :: volume
251 volume = this%compute_volume(
design)
254 this%value = this%limit - volume / this%volume_domain
257 if (this%is_max) this%value = -this%value
259 end subroutine volume_constraint_update_value
264 subroutine volume_constraint_update_sensitivity(this, design)
266 class(
design_t),
intent(in) :: design
268 type(field_t),
pointer :: unmapped, mapped
269 integer :: temp_indices(2)
271 if (this%if_mapping)
then
273 call neko_scratch_registry%request(unmapped, temp_indices(1), &
275 call neko_scratch_registry%request(mapped, temp_indices(2), &
278 call field_cfill(unmapped, -1.0_rp / this%volume_domain)
279 if (this%is_max)
then
280 call field_cmult(unmapped, -1.0_rp)
283 if (this%has_mask)
then
287 call this%mapping%apply_backward(mapped, unmapped)
290 call neko_scratch_registry%relinquish(temp_indices)
296 end subroutine volume_constraint_update_sensitivity
306 function compute_volume(this, design)
result(volume)
308 class(
design_t),
intent(in) :: design
309 real(kind=rp) :: volume
314 volume = volume_brinkman_design(this,
design)
317 call neko_error(
'Volume constraint only works with brinkman_design')
320 end function compute_volume
325 function volume_brinkman_design(this, design)
result(volume)
328 real(kind=rp) :: volume
329 type(field_t),
pointer :: work
330 type(vector_t),
pointer :: values, unmapped_values
331 integer :: temp_indices, ind_value, ind_um_value
333 call neko_scratch_registry%request(values, ind_value,
design%size(), &
337 if (this%if_mapping)
then
338 call neko_scratch_registry%request(unmapped_values, ind_um_value, &
340 call design%get_values(unmapped_values)
341 call this%mapping%apply_forward(values, unmapped_values)
342 call neko_scratch_registry%relinquish(ind_um_value)
344 call design%get_values(values)
347 if (this%has_mask)
then
349 if (neko_bcknd_device .eq. 1)
then
350 call neko_scratch_registry%request(work, temp_indices, .false.)
351 call device_copy(work%x_d, values%x_d,
design%size())
354 volume = device_glsc2(work%x_d, this%c_xh%B_d,
design%size())
356 call neko_scratch_registry%relinquish(temp_indices)
358 volume = glsc2_mask(values%x, this%c_Xh%B,
design%size(), &
359 this%mask%mask%get(), this%mask%size)
364 if (neko_bcknd_device .eq. 1)
then
365 volume = device_glsc2(values%x_d, this%c_xh%B_d,
design%size())
367 volume = glsc2(values%x, this%c_Xh%B,
design%size())
372 call neko_scratch_registry%relinquish(ind_value)
374 end function volume_brinkman_design
379 function volume_constraint_get_log_size(this)
result(n)
384 end function volume_constraint_get_log_size
389 subroutine volume_constraint_get_log_headers(this, headers)
391 character(len=*),
intent(out) :: headers(:)
392 character(len=64) :: prefix
394 if (
size(headers) .lt. 1)
return
395 prefix = trim(this%name)
397 if (
size(headers) .lt. 2)
return
398 headers(2) = trim(prefix) //
'.volume'
400 end subroutine volume_constraint_get_log_headers
405 subroutine volume_constraint_get_log_values(this, values)
407 real(kind=rp),
intent(out) :: values(:)
408 real(kind=rp) :: volume_ratio
410 if (
size(values) .lt. 1)
return
411 if (this%is_max)
then
412 volume_ratio = this%limit + this%value
414 volume_ratio = this%limit - this%value
417 values(1) = this%value
418 if (
size(values) .lt. 2)
return
419 values(2) = volume_ratio
421 end subroutine volume_constraint_get_log_values
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 .
subroutine volume_constraint_init_json_sim(this, json, design, simulation)
The common constructor using a JSON object.
A topology optimization design variable.
The abstract constraint type.
Abstract class for handling mapping_cascade.
A constraint on the volume of the design.