35 use num_types,
only: rp, sp
36 use field,
only: field_t
37 use json_module,
only: json_file
39 use coefs,
only: coef_t
41 use scratch_registry,
only: neko_scratch_registry
42 use fld_file_output,
only: fld_file_output_t
43 use point_zone_registry,
only: neko_point_zone_registry
44 use point_zone,
only: point_zone_t
46 use neko_config,
only: neko_bcknd_device
47 use device,
only: device_memcpy, host_to_device
51 use json_module,
only: json_file
53 use vector,
only: vector_t
55 use device_math,
only: device_copy
56 use field_registry,
only: neko_field_registry
59 use field_math,
only: field_rzero
60 use json_utils,
only: json_get, json_get_or_default, json_extract_object
61 use utils,
only: neko_error
73 type(field_t),
pointer :: design_indicator
83 type(field_t),
pointer :: brinkman_amplitude
115 type(field_t),
pointer :: sensitivity
171 class(point_zone_t),
pointer :: optimization_domain
180 type(fld_file_output_t),
private :: output
188 generic,
public :: init => init_from_json_sim, init_from_components
190 procedure, pass(this),
public :: init_from_json_sim => &
191 brinkman_design_init_from_json_sim
193 procedure, pass(this),
public :: init_from_components => &
194 brinkman_design_init_from_components
197 procedure, pass(this) :: get_values => brinkman_design_get_design
200 procedure, pass(this) :: design_get_x => brinkman_design_get_x
202 procedure, pass(this) :: design_get_x_i => brinkman_design_get_x_i
204 procedure, pass(this) :: design_get_y => brinkman_design_get_y
206 procedure, pass(this) :: design_get_y_i => brinkman_design_get_y_i
208 procedure, pass(this) :: design_get_z => brinkman_design_get_z
210 procedure, pass(this) :: design_get_z_i => brinkman_design_get_z_i
213 procedure, pass(this) :: update_design => brinkman_design_update_design
218 procedure, pass(this) :: map_forward => brinkman_design_map_forward
222 procedure, pass(this) :: map_backward => brinkman_design_map_backward
230 procedure, pass(this) :: write => brinkman_design_write
233 procedure, pass(this) :: free => brinkman_design_free
244 subroutine brinkman_design_init_from_json_sim(this, parameters, simulation)
246 type(json_file),
intent(inout) :: parameters
248 type(json_file) :: json_subdict
249 character(len=:),
allocatable :: domain_name, domain_type, name
251 call json_get_or_default(parameters,
'name', name,
'Brinkman Design')
252 call json_get_or_default(parameters,
'domain.type', domain_type,
'full')
254 select case (trim(domain_type))
256 this%has_mask = .false.
258 this%has_mask = .true.
259 call json_get(parameters,
'domain.zone_name', domain_name)
260 this%optimization_domain => &
261 neko_point_zone_registry%get_point_zone(domain_name)
264 call neko_error(
'brinkman design only supports point_zones for ' // &
265 'optimization domain types')
270 call this%init_from_components(name, simulation)
273 associate(coef => simulation%neko_case%fluid%c_Xh, &
274 gs => simulation%neko_case%fluid%gs_Xh)
276 if (
'mapping' .in. parameters)
then
277 call json_extract_object(parameters,
'mapping', json_subdict)
278 call this%mapping%init_base(coef)
279 call this%mapping%add(parameters,
'mapping')
282 if (
'initial_distribution' .in. parameters)
then
283 call json_extract_object(parameters,
'initial_distribution', json_subdict)
287 call field_rzero(this%design_indicator)
292 call this%map_forward()
294 end subroutine brinkman_design_init_from_json_sim
297 subroutine brinkman_design_free(this)
300 call this%free_base()
301 call this%brinkman_amplitude%free()
302 call this%design_indicator%free()
303 call this%sensitivity%free()
305 end subroutine brinkman_design_free
307 subroutine brinkman_design_init_from_components(this, name, simulation)
309 character(len=*),
intent(in) :: name
310 type(simulation_t),
intent(inout) :: simulation
312 type(simple_brinkman_source_term_t) :: forward_brinkman, adjoint_brinkman
314 associate(dof => simulation%neko_case%fluid%dm_Xh)
316 call neko_field_registry%add_field(dof,
"design_indicator", .true.)
317 call neko_field_registry%add_field(dof,
"brinkman_amplitude", .true.)
318 call neko_field_registry%add_field(dof,
"sensitivity", .true.)
322 this%design_indicator => &
323 neko_field_registry%get_field(
"design_indicator")
324 this%brinkman_amplitude => &
325 neko_field_registry%get_field(
"brinkman_amplitude")
326 this%sensitivity => &
327 neko_field_registry%get_field(
"sensitivity")
333 this%design_indicator = 0.0_rp
334 this%brinkman_amplitude = 0.0_rp
335 this%design_indicator%x = 0.0_rp
337 n = this%design_indicator%dof%size()
340 this%design_indicator%x(i,1,1,1) = 0.0_rp
344 if (neko_bcknd_device .eq. 1)
then
345 call device_memcpy(this%design_indicator%x, &
346 this%design_indicator%x_d, n, &
347 host_to_device, sync = .false.)
378 if (this%has_mask)
then
379 call mask_exterior_const(this%design_indicator, &
380 this%optimization_domain, 0.0_rp)
392 call this%output%init(sp,
'design', 3)
393 call this%output%fields%assign_to_field(1, this%design_indicator)
394 call this%output%fields%assign_to_field(2, this%brinkman_amplitude)
395 call this%output%fields%assign_to_field(3, this%sensitivity)
397 call this%init_base(name, n)
400 call forward_brinkman%init_from_components( &
401 simulation%fluid%f_x, &
402 simulation%fluid%f_y, &
403 simulation%fluid%f_z, &
404 this%brinkman_amplitude, &
405 simulation%fluid%u, &
406 simulation%fluid%v, &
407 simulation%fluid%w, &
408 simulation%fluid%c_Xh)
410 call simulation%fluid%source_term%add(forward_brinkman)
413 call adjoint_brinkman%init_from_components( &
414 simulation%adjoint_fluid%f_adj_x, &
415 simulation%adjoint_fluid%f_adj_y, &
416 simulation%adjoint_fluid%f_adj_z, &
417 this%brinkman_amplitude, &
418 simulation%adjoint_fluid%u_adj, &
419 simulation%adjoint_fluid%v_adj, &
420 simulation%adjoint_fluid%w_adj, &
421 simulation%adjoint_fluid%c_Xh)
424 select type (f => simulation%adjoint_fluid)
425 type is (adjoint_fluid_pnpn_t)
426 call f%source_term%add(adjoint_brinkman)
430 end subroutine brinkman_design_init_from_components
433 subroutine brinkman_design_map_forward(this)
437 if (this%has_mask)
then
438 call mask_exterior_const(this%design_indicator, &
439 this%optimization_domain, 0.0_rp)
442 call this%mapping%apply_forward(this%brinkman_amplitude, &
443 this%design_indicator)
445 end subroutine brinkman_design_map_forward
447 subroutine brinkman_design_get_design(this, values)
449 type(vector_t),
intent(inout) :: values
454 call copy(values%x, this%design_indicator%x, n)
455 if (neko_bcknd_device .eq. 1)
then
456 call device_copy(values%x_d, this%design_indicator%x_d, n)
459 end subroutine brinkman_design_get_design
461 subroutine brinkman_design_get_x(this, x)
463 type(vector_t),
intent(inout) :: x
468 call copy(x%x, this%design_indicator%dof%x, n)
469 if (neko_bcknd_device .eq. 1)
then
470 call device_copy(x%x_d, this%design_indicator%dof%x_d, n)
473 end subroutine brinkman_design_get_x
475 function brinkman_design_get_x_i(this, i)
result(x_i)
477 integer,
intent(in) :: i
482 if (i .lt. 1 .or. i .gt. n)
then
483 call neko_error(
'brinkman_design_get_x_i: index out of bounds')
486 x_i = this%design_indicator%dof%x(i,1,1,1)
488 end function brinkman_design_get_x_i
490 subroutine brinkman_design_get_y(this, y)
492 type(vector_t),
intent(inout) :: y
497 call copy(y%x, this%design_indicator%dof%y, n)
498 if (neko_bcknd_device .eq. 1)
then
499 call device_copy(y%x_d, this%design_indicator%dof%y_d, n)
502 end subroutine brinkman_design_get_y
504 function brinkman_design_get_y_i(this, i)
result(y_i)
506 integer,
intent(in) :: i
511 if (i .lt. 1 .or. i .gt. n)
then
512 call neko_error(
'brinkman_design_get_y_i: index out of bounds')
515 y_i = this%design_indicator%dof%y(i,1,1,1)
517 end function brinkman_design_get_y_i
519 subroutine brinkman_design_get_z(this, z)
521 type(vector_t),
intent(inout) :: z
526 call copy(z%x, this%design_indicator%dof%z, n)
527 if (neko_bcknd_device .eq. 1)
then
528 call device_copy(z%x_d, this%design_indicator%dof%z_d, n)
531 end subroutine brinkman_design_get_z
533 function brinkman_design_get_z_i(this, i)
result(z_i)
535 integer,
intent(in) :: i
540 if (i .lt. 1 .or. i .gt. n)
then
541 call neko_error(
'brinkman_design_get_z_i: index out of bounds')
544 z_i = this%design_indicator%dof%z(i,1,1,1)
546 end function brinkman_design_get_z_i
548 subroutine brinkman_design_update_design(this, values)
550 type(vector_t),
intent(inout) :: values
554 call copy(this%design_indicator%x, values%x, n)
555 if (neko_bcknd_device .eq. 1)
then
556 call device_copy(this%design_indicator%x_d, values%x_d, n)
559 call this%map_forward()
561 call copy(values%x, this%design_indicator%x, n)
562 if (neko_bcknd_device .eq. 1)
then
563 call device_copy(values%x_d, this%design_indicator%x_d, n)
566 end subroutine brinkman_design_update_design
568 subroutine brinkman_design_map_backward(this, sensitivity)
570 type(vector_t),
intent(in) :: sensitivity
571 type(field_t),
pointer :: tmp_fld
572 integer :: temp_indices(1)
574 call neko_scratch_registry%request_field(tmp_fld, temp_indices(1))
576 call vector_to_field(tmp_fld, sensitivity)
578 call this%mapping%apply_backward(this%sensitivity, tmp_fld)
590 if (this%has_mask)
then
591 call mask_exterior_const(this%sensitivity, this%optimization_domain, &
595 call neko_scratch_registry%relinquish_field(temp_indices)
597 end subroutine brinkman_design_map_backward
599 subroutine brinkman_design_write(this, idx)
601 integer,
intent(in) :: idx
603 call this%output%sample(real(idx, kind=rp))
605 end subroutine brinkman_design_write
607end module brinkman_design
Adjoint Pn/Pn formulation.
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.
subroutine, public vector_to_field(field, vector)
Vector to field.
Optimization initial condition.
Implements the simple_brinkman_source_term_t type.
Implements the steady_problem_t type.
A topology optimization design variable.
Abstract class for handling mapping_cascade.
A simple Brinkman source term.