37 use neko_config,
only: neko_bcknd_device
38 use num_types,
only: rp, sp, dp
41 use field,
only: field_t
42 use field_output,
only: field_output_t
43 use json_utils,
only: json_extract_item
44 use json_module,
only: json_file
45 use coefs,
only: coef_t
46 use field_math,
only: field_copy
48 use device_math,
only: device_col2
49 use scratch_registry,
only: neko_scratch_registry
50 use utils,
only: neko_warning, neko_error
51 use vector,
only:vector_t
53 use gather_scatter,
only : gs_op_add
69 type(coef_t),
pointer :: coef
71 type(field_output_t) :: design_output
73 type(field_output_t) :: sensitivity_output
75 type(field_t),
pointer :: design_in => null()
76 type(field_t),
pointer :: design_out => null()
77 type(field_t),
pointer :: sensitivity_out => null()
79 type(field_t),
allocatable :: sensitivity_stages(:)
81 logical :: output_fields_set = .false.
82 logical :: outputs_initialized = .false.
84 logical :: verbose_design = .false.
86 logical :: verbose_sensitivity = .false.
88 integer :: output_precision = sp
90 character(len=32) :: output_format =
'fld'
92 character(len=80) :: forward_file_name =
''
94 character(len=80) :: sensitivity_file_name =
''
98 procedure, pass(this) :: init_base => mapping_handler_init_base
100 procedure, pass(this) :: free => mapping_handler_free
102 generic :: apply_forward => mapping_handler_apply_forward_field, &
103 mapping_handler_apply_forward_vector
104 procedure, pass(this) :: mapping_handler_apply_forward_field
105 procedure, pass(this) :: mapping_handler_apply_forward_vector
108 generic :: apply_backward => mapping_handler_apply_backward_field, &
109 mapping_handler_apply_backward_vector
110 procedure, pass(this) :: mapping_handler_apply_backward_field
111 procedure, pass(this) :: mapping_handler_apply_backward_vector
113 generic :: add => add_mapping, add_json_mappings
115 procedure, pass(this) :: add_mapping => &
116 mapping_handler_add_mapping
118 procedure, pass(this) :: add_json_mappings => &
119 mapping_handler_add_json_mappings
121 procedure, pass(this) :: set_stage_names => &
122 mapping_handler_set_stage_names
124 procedure, pass(this) :: make_cts => mapping_handler_make_cts
126 procedure, pass(this) :: init_output_fields => &
127 mapping_handler_init_output_fields
129 procedure, pass(this) :: write_design => mapping_handler_write_design
131 procedure, pass(this) :: write_sensitivity => &
132 mapping_handler_write_sensitivity
134 procedure, pass(this) :: set_output_counter => &
135 mapping_handler_set_output_counter
144 integer :: i, n_mappings, n_fields
146 if (.not. this%output_fields_set)
then
147 call neko_error(
'Mapping output fields have not been configured')
149 if (.not.
associated(this%coef))
then
150 call neko_error(
'Mapping handler coefficients are not initialized')
152 if (.not.
associated(this%design_out))
then
153 call neko_error(
'Mapped design output field is not associated')
155 if (.not.
associated(this%design_in))
then
156 call neko_error(
'Unmapped design input field is not associated')
158 if (.not.
associated(this%sensitivity_out))
then
159 call neko_error(
'Sensitivity output field is not associated')
162 call this%design_output%free()
163 call this%sensitivity_output%free()
165 if (
allocated(this%sensitivity_stages))
then
166 do i = 1,
size(this%sensitivity_stages)
167 call this%sensitivity_stages(i)%free()
169 deallocate(this%sensitivity_stages)
173 if (
allocated(this%mapping_cascade)) n_mappings =
size(this%mapping_cascade)
175 if (this%verbose_design)
then
177 n_fields = n_mappings + 1
178 if (n_fields .le. 0) n_fields = 1
181 if (n_mappings .gt. 0)
then
188 call this%design_output%init(trim(this%forward_file_name), n_fields, &
189 precision = this%output_precision, &
190 format = trim(this%output_format))
191 if (this%verbose_design .and. n_mappings .gt. 0)
then
193 call this%design_output%fields%assign_to_field(i, &
194 this%mapping_cascade(i)%mapping%X_in)
196 call this%design_output%fields%assign_to_field(n_fields, this%design_out)
197 else if (n_mappings .gt. 0)
then
198 call this%design_output%fields%assign_to_field(1, &
199 this%mapping_cascade(1)%mapping%X_in)
200 call this%design_output%fields%assign_to_field(2, this%design_out)
202 call this%design_output%fields%assign_to_field(1, this%design_out)
205 if (this%verbose_sensitivity)
then
207 n_fields = n_mappings + 2
208 allocate(this%sensitivity_stages(n_mappings + 1))
209 do i = 1, n_mappings + 1
210 call this%sensitivity_stages(i)%init(this%coef%dof)
212 call this%set_stage_names()
213 call this%sensitivity_output%init( &
214 trim(this%sensitivity_file_name), n_fields, &
215 precision = this%output_precision, &
216 format = trim(this%output_format))
217 do i = 1, n_mappings + 1
218 call this%sensitivity_output%fields%assign_to_field(i, &
219 this%sensitivity_stages(i))
221 call this%sensitivity_output%fields%assign_to_field(n_fields, &
222 this%sensitivity_out)
224 call this%set_stage_names()
225 call this%sensitivity_output%init( &
226 trim(this%sensitivity_file_name), 1, &
227 precision = this%output_precision, &
228 format = trim(this%output_format))
229 call this%sensitivity_output%fields%assign_to_field(1, &
230 this%sensitivity_out)
233 this%outputs_initialized = .true.
238 subroutine mapping_handler_init_base(this, coef)
240 type(coef_t),
target,
intent(in) :: coef
246 end subroutine mapping_handler_init_base
250 subroutine mapping_handler_free(this)
254 if (
allocated(this%mapping_cascade))
then
255 do i = 1,
size(this%mapping_cascade)
256 call this%mapping_cascade(i)%free()
258 deallocate(this%mapping_cascade)
260 if (
allocated(this%sensitivity_stages))
then
261 do i = 1,
size(this%sensitivity_stages)
262 call this%sensitivity_stages(i)%free()
264 deallocate(this%sensitivity_stages)
266 if (this%outputs_initialized)
then
267 call this%design_output%free()
268 call this%sensitivity_output%free()
270 this%outputs_initialized = .false.
271 this%output_fields_set = .false.
272 this%output_precision = sp
273 this%output_format =
'fld'
274 this%forward_file_name =
''
275 this%sensitivity_file_name =
''
276 if (
associated(this%design_in))
nullify(this%design_in)
277 if (
associated(this%design_out))
nullify(this%design_out)
278 if (
associated(this%sensitivity_out))
nullify(this%sensitivity_out)
279 if (
associated(this%coef))
nullify(this%coef)
281 end subroutine mapping_handler_free
287 subroutine mapping_handler_apply_forward_field(this, X_out, X_in)
289 type(field_t),
intent(in) :: X_in
290 type(field_t),
intent(inout) :: X_out
292 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
293 integer :: temp_indices(2)
295 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
297 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
302 call field_copy(tmp_fld_out, x_in)
305 call this%make_cts(tmp_fld_out)
308 if (
allocated(this%mapping_cascade))
then
309 do i = 1,
size(this%mapping_cascade)
311 call field_copy(tmp_fld_in, tmp_fld_out)
313 call this%mapping_cascade(i)%mapping%apply_forward(tmp_fld_out, &
321 call field_copy(x_out, tmp_fld_out)
324 call neko_scratch_registry%relinquish_field(temp_indices)
326 end subroutine mapping_handler_apply_forward_field
332 subroutine mapping_handler_apply_forward_vector(this, X_out, X_in)
334 type(vector_t),
intent(in) :: X_in
335 type(vector_t),
intent(inout) :: X_out
336 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
337 integer :: temp_indices(2)
339 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
341 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
345 call mapping_handler_apply_forward_field(this, tmp_fld_out, tmp_fld_in)
349 call neko_scratch_registry%relinquish_field(temp_indices)
351 end subroutine mapping_handler_apply_forward_vector
359 subroutine mapping_handler_apply_backward_field(this, sens_out, sens_in)
361 type(field_t),
intent(inout) :: sens_out
362 type(field_t),
intent(in) :: sens_in
364 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
365 integer :: temp_indices(2)
367 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
369 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
374 call field_copy(tmp_fld_out, sens_in)
375 if (
allocated(this%sensitivity_stages))
then
376 call field_copy(this%sensitivity_stages(1), sens_in)
380 call this%make_cts(tmp_fld_out)
383 if (
allocated(this%mapping_cascade))
then
384 do i =
size(this%mapping_cascade), 1, -1
386 call field_copy(tmp_fld_in, tmp_fld_out)
391 call this%mapping_cascade(i)%mapping%apply_backward(tmp_fld_out, &
393 if (
allocated(this%sensitivity_stages))
then
394 call field_copy(this%sensitivity_stages( &
395 size(this%mapping_cascade) - i + 2), tmp_fld_out)
403 call field_copy(sens_out, tmp_fld_out)
406 call neko_scratch_registry%relinquish_field(temp_indices)
409 end subroutine mapping_handler_apply_backward_field
417 subroutine mapping_handler_apply_backward_vector(this, X_out, X_in)
419 type(vector_t),
intent(in) :: X_in
420 type(vector_t),
intent(inout) :: X_out
421 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
422 integer :: temp_indices(2)
424 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
426 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
430 call mapping_handler_apply_backward_field(this, tmp_fld_out, tmp_fld_in)
434 call neko_scratch_registry%relinquish_field(temp_indices)
436 end subroutine mapping_handler_apply_backward_vector
439 subroutine mapping_handler_add_json_mappings(this, json, name)
441 type(json_file),
intent(inout) :: json
442 character(len=*),
intent(in) :: name
447 type(json_file) :: mapping_subdict
448 integer :: n_mappings, i, i0
450 if (json%valid_path(name))
then
452 call json%info(name, n_children = n_mappings)
454 if (
allocated(this%mapping_cascade))
then
455 i0 =
size(this%mapping_cascade)
456 call move_alloc(this%mapping_cascade, temp)
457 allocate(this%mapping_cascade(i0 + n_mappings))
458 if (
allocated(temp))
then
460 call move_alloc(temp(i)%mapping, &
461 this%mapping_cascade(i)%mapping)
466 allocate(this%mapping_cascade(n_mappings))
471 call json_extract_item(json, name, i, mapping_subdict)
473 mapping_subdict, this%coef)
478 call neko_warning(
"No mappings selected")
481 end subroutine mapping_handler_add_json_mappings
486 subroutine mapping_handler_add_mapping(this, mapping)
491 integer :: n_mappings, i
493 if (
allocated(this%mapping_cascade))
then
494 n_mappings =
size(this%mapping_cascade)
499 call move_alloc(this%mapping_cascade, temp)
500 allocate(this%mapping_cascade(n_mappings + 1))
502 if (
allocated(temp))
then
504 call move_alloc(temp(i)%mapping, this%mapping_cascade(i)%mapping)
508 this%mapping_cascade(n_mappings + 1)%mapping =
mapping
511 end subroutine mapping_handler_add_mapping
514 pure function mapping_handler_derivative_name(field_name)
result(name)
515 character(len=*),
intent(in) :: field_name
516 character(len=80) :: name
518 name =
'dFd_' // trim(field_name)
520 end function mapping_handler_derivative_name
524 subroutine mapping_handler_set_stage_names(this)
527 character(len=80) :: previous_name
532 previous_name = trim(this%design_in%name)
533 if (
allocated(this%mapping_cascade))
then
534 do i = 1,
size(this%mapping_cascade)
535 this%mapping_cascade(i)%mapping%X_in%name = trim(previous_name)
536 previous_name = trim(this%mapping_cascade(i)%mapping%fld_name)
541 this%sensitivity_out%name = mapping_handler_derivative_name( &
543 if (
allocated(this%sensitivity_stages))
then
544 this%sensitivity_stages(1)%name = mapping_handler_derivative_name( &
545 this%design_out%name)
546 if (
allocated(this%mapping_cascade))
then
547 do i =
size(this%mapping_cascade), 1, -1
548 j =
size(this%mapping_cascade) - i + 2
549 this%sensitivity_stages(j)%name = &
550 mapping_handler_derivative_name( &
551 this%mapping_cascade(i)%mapping%X_in%name)
556 end subroutine mapping_handler_set_stage_names
569 subroutine mapping_handler_init_output_fields(this, design_in, design_out, &
570 sensitivity_out, verbose_design, verbose_sensitivity, &
571 output_precision, output_format, forward_file_name, &
572 sensitivity_file_name)
574 type(field_t),
target,
intent(inout) :: design_in
575 type(field_t),
target,
intent(inout) :: design_out
576 type(field_t),
target,
intent(inout) :: sensitivity_out
577 logical,
intent(in) :: verbose_design
578 logical,
intent(in) :: verbose_sensitivity
579 integer,
intent(in) :: output_precision
580 character(len=*),
intent(in) :: output_format
581 character(len=*),
intent(in) :: forward_file_name
582 character(len=*),
intent(in) :: sensitivity_file_name
584 this%design_in => design_in
585 this%design_out => design_out
586 this%sensitivity_out => sensitivity_out
587 this%verbose_design = verbose_design
588 this%verbose_sensitivity = verbose_sensitivity
589 if (output_precision .ne. sp .and. output_precision .ne. dp)
then
590 call neko_error(
'output_precision must be either sp or dp')
592 this%output_precision = output_precision
593 this%output_format = trim(output_format)
594 this%forward_file_name = trim(forward_file_name)
595 this%sensitivity_file_name = trim(sensitivity_file_name)
596 this%output_fields_set = .true.
600 end subroutine mapping_handler_init_output_fields
605 subroutine mapping_handler_write_design(this, idx)
607 integer,
intent(in) :: idx
609 if (.not. this%outputs_initialized)
then
610 call neko_error(
'Mapping design output is not initialized')
612 call this%design_output%sample(real(idx, kind=rp))
614 end subroutine mapping_handler_write_design
619 subroutine mapping_handler_write_sensitivity(this, idx)
621 integer,
intent(in) :: idx
623 if (.not. this%outputs_initialized)
then
624 call neko_error(
'Mapping sensitivity output is not initialized')
626 call this%sensitivity_output%sample(real(idx, kind=rp))
628 end subroutine mapping_handler_write_sensitivity
633 subroutine mapping_handler_set_output_counter(this, idx)
635 integer,
intent(in) :: idx
637 if (.not. this%outputs_initialized)
return
639 call this%design_output%set_counter(idx)
640 call this%sensitivity_output%set_counter(idx)
642 end subroutine mapping_handler_set_output_counter
648 subroutine mapping_handler_make_cts(this, fld)
650 type(field_t),
intent(inout) :: fld
652 call this%coef%gs_h%op(fld, gs_op_add)
653 if (neko_bcknd_device .eq. 1)
then
654 call device_col2(fld%x_d, this%coef%mult_d, fld%size())
656 call col2(fld%x, this%coef%mult, fld%size())
659 end subroutine mapping_handler_make_cts
mapping factory. Both constructs and initializes the object.
Implements the mapping_handler_t type.
subroutine mapping_handler_setup_outputs(this)
Setup output objects after mappings are known.
Mappings to be applied to a scalar field.
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.
Base abstract class for mapping.
A helper type that is needed to have an array of polymorphic objects.
Abstract class for handling mapping_cascade.