37 use num_types,
only: rp, sp, dp
38 use field,
only: field_t
39 use json_module,
only: json_file
41 use coefs,
only: coef_t
43 use scratch_registry,
only: neko_scratch_registry
44 use point_zone_registry,
only: neko_point_zone_registry
45 use point_zone,
only: point_zone_t
47 use neko_config,
only: neko_bcknd_device
48 use device,
only: device_memcpy, host_to_device
52 use json_module,
only: json_file
54 use vector,
only: vector_t
56 use device_math,
only: device_copy
57 use registry,
only: neko_registry
60 use field_math,
only: field_rzero
61 use json_utils,
only: json_get, json_get_or_default, json_get
62 use utils,
only: neko_error
63 use comm,
only: neko_comm
75 type(field_t),
pointer :: design_indicator
85 type(field_t),
pointer :: brinkman_amplitude
117 type(field_t),
pointer :: sensitivity
173 class(point_zone_t),
pointer :: optimization_domain
187 generic,
public :: init => init_from_json_sim, init_from_components
189 procedure, pass(this),
public :: init_from_json_sim => &
190 brinkman_design_init_from_json_sim
192 procedure, pass(this),
public :: init_from_components => &
193 brinkman_design_init_from_components
196 procedure, pass(this) :: get_values => brinkman_design_get_design
198 procedure, pass(this) :: get_sensitivity => brinkman_design_get_sensitivity
201 procedure, pass(this) :: design_get_x => brinkman_design_get_x
203 procedure, pass(this) :: design_get_x_i => brinkman_design_get_x_i
205 procedure, pass(this) :: design_get_y => brinkman_design_get_y
207 procedure, pass(this) :: design_get_y_i => brinkman_design_get_y_i
209 procedure, pass(this) :: design_get_z => brinkman_design_get_z
211 procedure, pass(this) :: design_get_z_i => brinkman_design_get_z_i
214 procedure, pass(this) :: update_design => brinkman_design_update_design
219 procedure, pass(this) :: map_forward => brinkman_design_map_forward
223 procedure, pass(this) :: map_backward => brinkman_design_map_backward
231 procedure, pass(this) :: write => brinkman_design_write
233 procedure, pass(this) :: set_output_counter => &
234 brinkman_design_set_output_counter
237 procedure, pass(this) :: free => brinkman_design_free
248 subroutine brinkman_design_init_from_json_sim(this, parameters, simulation)
250 type(json_file),
intent(inout) :: parameters
252 type(json_file) :: json_subdict
253 character(len=:),
allocatable :: domain_name, domain_type, name
254 character(len=:),
allocatable :: output_precision_str
255 logical :: dealias, verbose_design, verbose_sensitivity
256 integer :: output_precision
258 call json_get_or_default(parameters,
'name', name,
'Brinkman Design')
259 call json_get_or_default(parameters,
'domain.type', domain_type,
'full')
260 call json_get_or_default(parameters,
'dealias', dealias, .true.)
261 call json_get_or_default(parameters,
'verbose_design', verbose_design, &
263 call json_get_or_default(parameters,
'verbose_sensitivity', &
264 verbose_sensitivity, .false.)
265 call json_get_or_default(parameters,
'output_precision', &
266 output_precision_str,
'sp')
268 select case (trim(output_precision_str))
270 output_precision = sp
272 output_precision = dp
274 call neko_error(
'Invalid output_precision in design.brinkman. ' // &
275 'Expected ''sp'' or ''dp''.')
278 select case (trim(domain_type))
280 this%has_mask = .false.
282 this%has_mask = .true.
283 call json_get(parameters,
'domain.zone_name', domain_name)
284 this%optimization_domain => &
285 neko_point_zone_registry%get_point_zone(domain_name)
288 call neko_error(
'brinkman design only supports point_zones for ' // &
289 'optimization domain types')
294 call this%init_from_components(name, simulation, dealias)
297 associate(coef => simulation%neko_case%fluid%c_Xh, &
298 gs => simulation%neko_case%fluid%gs_Xh)
300 if (
'mapping' .in. parameters)
then
301 call this%mapping%init_base(coef)
302 call this%mapping%add(parameters,
'mapping')
303 call this%mapping%init_output_fields(this%brinkman_amplitude, &
304 this%sensitivity, verbose_design, verbose_sensitivity, &
308 if (
'initial_distribution' .in. parameters)
then
309 call json_get(parameters,
'initial_distribution', json_subdict)
313 call field_rzero(this%design_indicator)
318 call this%map_forward()
320 end subroutine brinkman_design_init_from_json_sim
323 subroutine brinkman_design_free(this)
326 call this%free_base()
327 nullify(this%brinkman_amplitude)
328 nullify(this%design_indicator)
329 nullify(this%sensitivity)
331 end subroutine brinkman_design_free
333 subroutine brinkman_design_init_from_components(this, name, simulation, &
336 character(len=*),
intent(in) :: name
337 type(simulation_t),
intent(inout) :: simulation
338 logical,
intent(in) :: dealias
340 type(simple_brinkman_source_term_t) :: forward_brinkman, adjoint_brinkman
342 associate(dof => simulation%neko_case%fluid%dm_Xh)
344 call neko_registry%add_field(dof,
"design_indicator", .true.)
345 call neko_registry%add_field(dof,
"brinkman_amplitude", .true.)
346 call neko_registry%add_field(dof,
"sensitivity", .true.)
350 this%design_indicator => neko_registry%get_field(
"design_indicator")
351 this%brinkman_amplitude => neko_registry%get_field(
"brinkman_amplitude")
352 this%sensitivity => neko_registry%get_field(
"sensitivity")
358 this%design_indicator = 0.0_rp
359 this%brinkman_amplitude = 0.0_rp
360 this%design_indicator = 0.0_rp
390 if (this%has_mask)
then
391 call mask_exterior_const(this%design_indicator, &
392 this%optimization_domain, 0.0_rp)
395 n = this%design_indicator%dof%size()
396 call this%init_base(name, n)
399 call forward_brinkman%init_from_components( &
400 simulation%fluid%f_x, &
401 simulation%fluid%f_y, &
402 simulation%fluid%f_z, &
403 this%brinkman_amplitude, &
404 simulation%fluid%u, &
405 simulation%fluid%v, &
406 simulation%fluid%w, &
407 simulation%fluid%c_Xh, &
408 simulation%adjoint_fluid%c_Xh_GL, &
409 simulation%adjoint_fluid%GLL_to_GL, &
410 dealias, simulation%adjoint_fluid%scratch_GL)
412 call simulation%fluid%source_term%add(forward_brinkman)
415 call adjoint_brinkman%init_from_components( &
416 simulation%adjoint_fluid%f_adj_x, &
417 simulation%adjoint_fluid%f_adj_y, &
418 simulation%adjoint_fluid%f_adj_z, &
419 this%brinkman_amplitude, &
420 simulation%adjoint_fluid%u_adj, &
421 simulation%adjoint_fluid%v_adj, &
422 simulation%adjoint_fluid%w_adj, &
423 simulation%adjoint_fluid%c_Xh, &
424 simulation%adjoint_fluid%c_Xh_GL, &
425 simulation%adjoint_fluid%GLL_to_GL, &
426 dealias, simulation%adjoint_fluid%scratch_GL)
429 select type (f => simulation%adjoint_fluid)
430 type is (adjoint_fluid_pnpn_t)
431 call f%source_term%add(adjoint_brinkman)
435 end subroutine brinkman_design_init_from_components
438 subroutine brinkman_design_map_forward(this)
442 if (this%has_mask)
then
443 call mask_exterior_const(this%design_indicator, &
444 this%optimization_domain, 0.0_rp)
447 call this%mapping%apply_forward(this%brinkman_amplitude, &
448 this%design_indicator)
450 end subroutine brinkman_design_map_forward
452 subroutine brinkman_design_get_design(this, values)
454 type(vector_t),
intent(inout) :: values
458 if (n .ne. values%size())
then
459 call neko_error(
'Get design: size mismatch')
462 if (neko_bcknd_device .eq. 1)
then
463 call device_copy(values%x_d, this%design_indicator%x_d, n)
465 call copy(values%x, this%design_indicator%x, n)
468 end subroutine brinkman_design_get_design
470 subroutine brinkman_design_get_sensitivity(this, values)
472 type(vector_t),
intent(inout) :: values
476 if (n .ne. values%size())
then
477 call neko_error(
'Get design: size mismatch')
480 if (neko_bcknd_device .eq. 1)
then
481 call device_copy(values%x_d, this%sensitivity%x_d, n)
483 call copy(values%x, this%sensitivity%x, n)
486 end subroutine brinkman_design_get_sensitivity
488 subroutine brinkman_design_get_x(this, x)
490 type(vector_t),
intent(inout) :: x
494 if (n .ne. x%size())
then
495 call neko_error(
'Get x: size mismatch')
498 if (neko_bcknd_device .eq. 1)
then
499 call device_copy(x%x_d, this%design_indicator%dof%x_d, n)
501 call copy(x%x, this%design_indicator%dof%x, n)
504 end subroutine brinkman_design_get_x
506 function brinkman_design_get_x_i(this, i)
result(x_i)
508 integer,
intent(in) :: i
513 if (i .lt. 1 .or. i .gt. n)
then
514 call neko_error(
'brinkman_design_get_x_i: index out of bounds')
517 x_i = this%design_indicator%dof%x(i,1,1,1)
519 end function brinkman_design_get_x_i
521 subroutine brinkman_design_get_y(this, y)
523 type(vector_t),
intent(inout) :: y
527 if (n .ne. y%size())
then
528 call neko_error(
'Get y: size mismatch')
531 if (neko_bcknd_device .eq. 1)
then
532 call device_copy(y%x_d, this%design_indicator%dof%y_d, n)
534 call copy(y%x, this%design_indicator%dof%y, n)
537 end subroutine brinkman_design_get_y
539 function brinkman_design_get_y_i(this, i)
result(y_i)
541 integer,
intent(in) :: i
546 if (i .lt. 1 .or. i .gt. n)
then
547 call neko_error(
'brinkman_design_get_y_i: index out of bounds')
550 y_i = this%design_indicator%dof%y(i,1,1,1)
552 end function brinkman_design_get_y_i
554 subroutine brinkman_design_get_z(this, z)
556 type(vector_t),
intent(inout) :: z
560 if (n .ne. z%size())
then
561 call neko_error(
'Get z: size mismatch')
564 if (neko_bcknd_device .eq. 1)
then
565 call device_copy(z%x_d, this%design_indicator%dof%z_d, n)
567 call copy(z%x, this%design_indicator%dof%z, n)
570 end subroutine brinkman_design_get_z
572 function brinkman_design_get_z_i(this, i)
result(z_i)
574 integer,
intent(in) :: i
579 if (i .lt. 1 .or. i .gt. n)
then
580 call neko_error(
'brinkman_design_get_z_i: index out of bounds')
583 z_i = this%design_indicator%dof%z(i,1,1,1)
585 end function brinkman_design_get_z_i
587 subroutine brinkman_design_update_design(this, values)
589 type(vector_t),
intent(inout) :: values
593 if (neko_bcknd_device .eq. 1)
then
594 call device_copy(this%design_indicator%x_d, values%x_d, n)
596 call copy(this%design_indicator%x, values%x, n)
599 call this%map_forward()
601 if (neko_bcknd_device .eq. 1)
then
602 call device_copy(values%x_d, this%design_indicator%x_d, n)
604 call copy(values%x, this%design_indicator%x, n)
607 end subroutine brinkman_design_update_design
609 subroutine brinkman_design_map_backward(this, sensitivity)
611 type(vector_t),
intent(in) :: sensitivity
612 type(field_t),
pointer :: tmp_fld
613 integer :: temp_index
615 call neko_scratch_registry%request(tmp_fld, temp_index, .false.)
617 call vector_to_field(tmp_fld, sensitivity)
619 call this%mapping%apply_backward(this%sensitivity, tmp_fld)
621 if (this%has_mask)
then
622 call mask_exterior_const(this%sensitivity, this%optimization_domain, &
626 call neko_scratch_registry%relinquish_field(temp_index)
628 end subroutine brinkman_design_map_backward
630 subroutine brinkman_design_write(this, idx)
632 integer,
intent(in) :: idx
634 call this%mapping%write_design(idx)
635 call this%mapping%write_sensitivity(idx)
637 end subroutine brinkman_design_write
639 subroutine brinkman_design_set_output_counter(this, idx)
641 integer,
intent(in) :: idx
643 call this%mapping%set_output_counter(idx)
645 end subroutine brinkman_design_set_output_counter
647end 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.