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
51 use vector,
only: vector_t
52 use matrix,
only: matrix_t
53 use vector_math,
only: vector_cmult
54 use matrix_math,
only: matrix_cmult
55 use math,
only: copy, col2
56 use device_math,
only: device_copy, device_col2
57 use registry,
only: neko_registry
60 use field_math,
only: field_rzero
61 use json_utils,
only: json_get, json_get_or_default
62 use utils,
only: neko_error
74 type(field_t),
pointer :: design_indicator
84 type(field_t),
pointer :: brinkman_amplitude
116 type(field_t),
pointer :: sensitivity
172 class(point_zone_t),
pointer :: optimization_domain
176 class(coef_t),
pointer :: coef
178 real(kind=rp) :: avg_b
190 generic,
public :: init => init_from_json_sim, init_from_components
192 procedure, pass(this),
public :: init_from_json_sim => &
193 brinkman_design_init_from_json_sim
195 procedure, pass(this),
public :: init_from_components => &
196 brinkman_design_init_from_components
199 procedure, pass(this) :: get_values => brinkman_design_get_design
201 procedure, pass(this) :: get_sensitivity => brinkman_design_get_sensitivity
204 procedure, pass(this) :: design_get_x => brinkman_design_get_x
206 procedure, pass(this) :: design_get_x_i => brinkman_design_get_x_i
208 procedure, pass(this) :: design_get_y => brinkman_design_get_y
210 procedure, pass(this) :: design_get_y_i => brinkman_design_get_y_i
212 procedure, pass(this) :: design_get_z => brinkman_design_get_z
214 procedure, pass(this) :: design_get_z_i => brinkman_design_get_z_i
217 procedure, pass(this) :: update_design => brinkman_design_update_design
222 procedure, pass(this) :: map_forward => brinkman_design_map_forward
226 procedure, pass(this) :: map_backward => brinkman_design_map_backward
229 procedure, pass(this) :: convert_to_directional_derivative => &
230 brinkman_design_convert_to_directional_derivative
232 procedure, pass(this) :: project_sensitivity_vector => &
233 brinkman_design_project_sensitivity_vector
235 procedure, pass(this) :: project_sensitivity_matrix => &
236 brinkman_design_project_sensitivity_matrix
237 generic,
public :: project_sensitivity => &
238 project_sensitivity_vector, project_sensitivity_matrix
246 procedure, pass(this) :: write => brinkman_design_write
248 procedure, pass(this) :: set_output_counter => &
249 brinkman_design_set_output_counter
252 procedure, pass(this) :: free => brinkman_design_free
263 subroutine brinkman_design_init_from_json_sim(this, parameters, simulation)
265 type(json_file),
intent(inout) :: parameters
267 type(json_file) :: json_subdict
268 character(len=:),
allocatable :: domain_name, domain_type, name
269 character(len=:),
allocatable :: output_format_str, output_precision_str
270 logical :: dealias, verbose_design, verbose_sensitivity
271 integer :: output_precision
273 call json_get_or_default(parameters,
'name', name,
'Brinkman Design')
274 call json_get_or_default(parameters,
'domain.type', domain_type,
'full')
275 call json_get_or_default(parameters,
'dealias', dealias, .true.)
276 call json_get_or_default(parameters,
'verbose_design', verbose_design, &
278 call json_get_or_default(parameters,
'verbose_sensitivity', &
279 verbose_sensitivity, .false.)
280 call json_get_or_default(parameters,
'output_precision', &
281 output_precision_str,
'sp')
282 call json_get_or_default(parameters,
'output_format', &
283 output_format_str,
'fld')
285 select case (trim(output_precision_str))
286 case (
'sp',
'SP',
'single')
287 output_precision = sp
288 case (
'dp',
'DP',
'double')
289 output_precision = dp
291 call neko_error(
'Invalid output_precision in design.brinkman. ' // &
292 'Expected "sp" or "dp".')
295 select case (trim(domain_type))
297 this%has_mask = .false.
299 this%has_mask = .true.
300 call json_get(parameters,
'domain.zone_name', domain_name)
301 this%optimization_domain => &
302 neko_point_zone_registry%get_point_zone(domain_name)
305 call neko_error(
'brinkman design only supports point_zones for ' // &
306 'optimization domain types')
311 call this%init_from_components(name, simulation, dealias)
314 associate(coef => simulation%neko_case%fluid%c_Xh, &
315 gs => simulation%neko_case%fluid%gs_Xh)
317 if (
'mapping' .in. parameters)
then
318 call this%mapping%init_base(coef)
319 call this%mapping%add(parameters,
'mapping')
320 call this%mapping%init_output_fields(this%design_indicator, &
321 this%brinkman_amplitude, this%sensitivity, verbose_design, &
322 verbose_sensitivity, output_precision, output_format_str, &
323 'design',
'sensitivity')
326 if (
'initial_distribution' .in. parameters)
then
327 call json_get(parameters,
'initial_distribution', json_subdict)
331 call field_rzero(this%design_indicator)
336 call this%map_forward()
338 end subroutine brinkman_design_init_from_json_sim
341 subroutine brinkman_design_free(this)
344 call this%free_base()
345 call this%mapping%free()
346 nullify(this%brinkman_amplitude)
347 nullify(this%design_indicator)
348 nullify(this%sensitivity)
350 end subroutine brinkman_design_free
352 subroutine brinkman_design_init_from_components(this, name, simulation, &
355 character(len=*),
intent(in) :: name
356 type(simulation_t),
intent(inout) :: simulation
357 logical,
intent(in) :: dealias
359 type(simple_brinkman_source_term_t) :: forward_brinkman, adjoint_brinkman
361 associate(dof => simulation%neko_case%fluid%dm_Xh)
363 call neko_registry%add_field(dof,
"design_indicator", .true.)
364 call neko_registry%add_field(dof,
"brinkman_amplitude", .true.)
365 call neko_registry%add_field(dof,
"sensitivity", .true.)
369 this%design_indicator => neko_registry%get_field(
"design_indicator")
370 this%brinkman_amplitude => neko_registry%get_field(
"brinkman_amplitude")
371 this%sensitivity => neko_registry%get_field(
"sensitivity")
373 this%coef => simulation%fluid%c_Xh
379 this%design_indicator = 0.0_rp
380 this%brinkman_amplitude = 0.0_rp
381 this%design_indicator = 0.0_rp
411 if (this%has_mask)
then
412 call mask_exterior_const(this%design_indicator, &
413 this%optimization_domain, 0.0_rp)
416 n = this%design_indicator%dof%size()
417 call this%init_base(name, n)
420 this%avg_B = this%coef%volume / real(simulation%fluid%glb_unique_points)
423 call forward_brinkman%init_from_components( &
424 simulation%fluid%f_x, &
425 simulation%fluid%f_y, &
426 simulation%fluid%f_z, &
427 this%brinkman_amplitude, &
428 simulation%fluid%u, &
429 simulation%fluid%v, &
430 simulation%fluid%w, &
431 simulation%fluid%c_Xh, &
432 simulation%adjoint_fluid%c_Xh_GL, &
433 simulation%adjoint_fluid%GLL_to_GL, &
434 dealias, simulation%adjoint_fluid%scratch_GL)
436 call simulation%fluid%source_term%add(forward_brinkman)
439 call adjoint_brinkman%init_from_components( &
440 simulation%adjoint_fluid%f_adj_x, &
441 simulation%adjoint_fluid%f_adj_y, &
442 simulation%adjoint_fluid%f_adj_z, &
443 this%brinkman_amplitude, &
444 simulation%adjoint_fluid%u_adj, &
445 simulation%adjoint_fluid%v_adj, &
446 simulation%adjoint_fluid%w_adj, &
447 simulation%adjoint_fluid%c_Xh, &
448 simulation%adjoint_fluid%c_Xh_GL, &
449 simulation%adjoint_fluid%GLL_to_GL, &
450 dealias, simulation%adjoint_fluid%scratch_GL)
453 select type (f => simulation%adjoint_fluid)
454 type is (adjoint_fluid_pnpn_t)
455 call f%source_term%add(adjoint_brinkman)
459 end subroutine brinkman_design_init_from_components
462 subroutine brinkman_design_map_forward(this)
466 if (this%has_mask)
then
467 call mask_exterior_const(this%design_indicator, &
468 this%optimization_domain, 0.0_rp)
471 call this%mapping%apply_forward(this%brinkman_amplitude, &
472 this%design_indicator)
474 end subroutine brinkman_design_map_forward
476 subroutine brinkman_design_get_design(this, values)
478 type(vector_t),
intent(inout) :: values
482 if (n .ne. values%size())
then
483 call neko_error(
'Get design: size mismatch')
486 if (neko_bcknd_device .eq. 1)
then
487 call device_copy(values%x_d, this%design_indicator%x_d, n)
489 call copy(values%x, this%design_indicator%x, n)
492 end subroutine brinkman_design_get_design
494 subroutine brinkman_design_get_sensitivity(this, values)
496 type(vector_t),
intent(inout) :: values
500 if (n .ne. values%size())
then
501 call neko_error(
'Get sensitivity: size mismatch')
504 if (neko_bcknd_device .eq. 1)
then
505 call device_copy(values%x_d, this%sensitivity%x_d, n)
507 call copy(values%x, this%sensitivity%x, n)
510 end subroutine brinkman_design_get_sensitivity
516 subroutine brinkman_design_convert_to_directional_derivative(this, vec_in)
518 type(vector_t),
intent(inout) :: vec_in
522 if (n .ne. vec_in%size())
then
523 call neko_error(
'convert_to_directional_derivative: size mismatch')
526 if (neko_bcknd_device .eq. 1)
then
527 call device_col2(vec_in%x_d, this%coef%B_d, n)
529 call col2(vec_in%x, this%coef%B, n)
532 end subroutine brinkman_design_convert_to_directional_derivative
537 subroutine brinkman_design_project_sensitivity_vector(this, sensitivity)
539 type(vector_t),
intent(inout) :: sensitivity
541 call vector_cmult(sensitivity, this%avg_B)
542 end subroutine brinkman_design_project_sensitivity_vector
544 subroutine brinkman_design_project_sensitivity_matrix(this, sensitivity)
546 type(matrix_t),
intent(inout) :: sensitivity
548 call matrix_cmult(sensitivity, this%avg_B)
549 end subroutine brinkman_design_project_sensitivity_matrix
551 subroutine brinkman_design_get_x(this, x)
553 type(vector_t),
intent(inout) :: x
557 if (n .ne. x%size())
then
558 call neko_error(
'Get x: size mismatch')
561 if (neko_bcknd_device .eq. 1)
then
562 call device_copy(x%x_d, this%design_indicator%dof%x_d, n)
564 call copy(x%x, this%design_indicator%dof%x, n)
567 end subroutine brinkman_design_get_x
569 function brinkman_design_get_x_i(this, i)
result(x_i)
571 integer,
intent(in) :: i
576 if (i .lt. 1 .or. i .gt. n)
then
577 call neko_error(
'brinkman_design_get_x_i: index out of bounds')
580 x_i = this%design_indicator%dof%x(i,1,1,1)
582 end function brinkman_design_get_x_i
584 subroutine brinkman_design_get_y(this, y)
586 type(vector_t),
intent(inout) :: y
590 if (n .ne. y%size())
then
591 call neko_error(
'Get y: size mismatch')
594 if (neko_bcknd_device .eq. 1)
then
595 call device_copy(y%x_d, this%design_indicator%dof%y_d, n)
597 call copy(y%x, this%design_indicator%dof%y, n)
600 end subroutine brinkman_design_get_y
602 function brinkman_design_get_y_i(this, i)
result(y_i)
604 integer,
intent(in) :: i
609 if (i .lt. 1 .or. i .gt. n)
then
610 call neko_error(
'brinkman_design_get_y_i: index out of bounds')
613 y_i = this%design_indicator%dof%y(i,1,1,1)
615 end function brinkman_design_get_y_i
617 subroutine brinkman_design_get_z(this, z)
619 type(vector_t),
intent(inout) :: z
623 if (n .ne. z%size())
then
624 call neko_error(
'Get z: size mismatch')
627 if (neko_bcknd_device .eq. 1)
then
628 call device_copy(z%x_d, this%design_indicator%dof%z_d, n)
630 call copy(z%x, this%design_indicator%dof%z, n)
633 end subroutine brinkman_design_get_z
635 function brinkman_design_get_z_i(this, i)
result(z_i)
637 integer,
intent(in) :: i
642 if (i .lt. 1 .or. i .gt. n)
then
643 call neko_error(
'brinkman_design_get_z_i: index out of bounds')
646 z_i = this%design_indicator%dof%z(i,1,1,1)
648 end function brinkman_design_get_z_i
650 subroutine brinkman_design_update_design(this, values)
652 type(vector_t),
intent(inout) :: values
656 if (neko_bcknd_device .eq. 1)
then
657 call device_copy(this%design_indicator%x_d, values%x_d, n)
659 call copy(this%design_indicator%x, values%x, n)
662 call this%map_forward()
664 if (neko_bcknd_device .eq. 1)
then
665 call device_copy(values%x_d, this%design_indicator%x_d, n)
667 call copy(values%x, this%design_indicator%x, n)
670 end subroutine brinkman_design_update_design
672 subroutine brinkman_design_map_backward(this, sensitivity)
674 type(vector_t),
intent(in) :: sensitivity
675 type(field_t),
pointer :: tmp_fld
676 integer :: temp_index
678 call neko_scratch_registry%request(tmp_fld, temp_index, .false.)
680 call vector_to_field(tmp_fld, sensitivity)
682 call this%mapping%apply_backward(this%sensitivity, tmp_fld)
684 if (this%has_mask)
then
685 call mask_exterior_const(this%sensitivity, this%optimization_domain, &
689 call neko_scratch_registry%relinquish_field(temp_index)
691 end subroutine brinkman_design_map_backward
693 subroutine brinkman_design_write(this, idx)
695 integer,
intent(in) :: idx
697 call this%mapping%write_design(idx)
698 call this%mapping%write_sensitivity(idx)
700 end subroutine brinkman_design_write
702 subroutine brinkman_design_set_output_counter(this, idx)
704 integer,
intent(in) :: idx
706 call this%mapping%set_output_counter(idx)
708 end subroutine brinkman_design_set_output_counter
710end 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.