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, vector_cfill
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)
211 call vector_cfill(this%sensitivity, -1.0_rp / this%volume_domain)
212 if (this%is_max)
then
213 call vector_cmult(this%sensitivity, -1.0_rp)
216 if (this%has_mask)
then
220 end subroutine volume_constraint_init_from_components
223 subroutine volume_constraint_free(this)
226 call this%free_base()
227 end subroutine volume_constraint_free
232 subroutine volume_constraint_update_value(this, design)
234 class(
design_t),
intent(in) :: design
235 real(kind=rp) :: volume
237 volume = this%compute_volume(
design)
240 this%value = this%limit - volume / this%volume_domain
243 if (this%is_max) this%value = -this%value
245 end subroutine volume_constraint_update_value
250 subroutine volume_constraint_update_sensitivity(this, design)
252 class(
design_t),
intent(in) :: design
254 type(field_t),
pointer :: unmapped, mapped
255 integer :: temp_indices(2)
257 if (this%if_mapping)
then
259 call neko_scratch_registry%request(unmapped, temp_indices(1), &
261 call neko_scratch_registry%request(mapped, temp_indices(2), &
263 call field_cfill(unmapped, -1.0_rp / this%volume_domain)
264 if (this%is_max)
then
265 call field_cmult(unmapped, -1.0_rp)
268 if (this%has_mask)
then
272 call this%mapping%apply_backward(mapped, unmapped)
275 call neko_scratch_registry%relinquish(temp_indices)
281 end subroutine volume_constraint_update_sensitivity
291 function compute_volume(this, design)
result(volume)
293 class(
design_t),
intent(in) :: design
294 real(kind=rp) :: volume
299 volume = volume_brinkman_design(this,
design)
302 call neko_error(
'Volume constraint only works with brinkman_design')
305 end function compute_volume
310 function volume_brinkman_design(this, design)
result(volume)
313 real(kind=rp) :: volume
314 type(field_t),
pointer :: work
315 type(vector_t),
pointer :: values, unmapped_values
316 integer :: temp_indices, ind_value, ind_um_value
318 call neko_scratch_registry%request(values, ind_value,
design%size(), &
322 if (this%if_mapping)
then
323 call neko_scratch_registry%request(unmapped_values, ind_um_value, &
325 call design%get_values(unmapped_values)
326 call this%mapping%apply_forward(values, unmapped_values)
327 call neko_scratch_registry%relinquish(ind_um_value)
329 call design%get_values(values)
332 if (this%has_mask)
then
334 if (neko_bcknd_device .eq. 1)
then
335 call neko_scratch_registry%request(work, temp_indices, .false.)
336 call device_copy(work%x_d, values%x_d,
design%size())
339 volume = device_glsc2(work%x_d, this%c_xh%B_d,
design%size())
341 call neko_scratch_registry%relinquish(temp_indices)
343 volume = glsc2_mask(values%x, this%c_Xh%B,
design%size(), &
344 this%mask%mask%get(), this%mask%size)
349 if (neko_bcknd_device .eq. 1)
then
350 volume = device_glsc2(values%x_d, this%c_xh%B_d,
design%size())
352 volume = glsc2(values%x, this%c_Xh%B,
design%size())
357 call neko_scratch_registry%relinquish(ind_value)
359 end function volume_brinkman_design
364 function volume_constraint_get_log_size(this)
result(n)
369 end function volume_constraint_get_log_size
374 subroutine volume_constraint_get_log_headers(this, headers)
376 character(len=*),
intent(out) :: headers(:)
377 character(len=64) :: prefix
379 if (
size(headers) .lt. 1)
return
380 prefix = trim(this%name)
382 if (
size(headers) .lt. 2)
return
383 headers(2) = trim(prefix) //
'.volume'
385 end subroutine volume_constraint_get_log_headers
390 subroutine volume_constraint_get_log_values(this, values)
392 real(kind=rp),
intent(out) :: values(:)
393 real(kind=rp) :: volume_ratio
395 if (
size(values) .lt. 1)
return
396 if (this%is_max)
then
397 volume_ratio = this%limit + this%value
399 volume_ratio = this%limit - this%value
402 values(1) = this%value
403 if (
size(values) .lt. 2)
return
404 values(2) = volume_ratio
406 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.