37 use,
intrinsic :: iso_fortran_env, only: error_unit
38 use coefs,
only: coef_t
39 use symmetry,
only: symmetry_t
40 use registry,
only: neko_registry
41 use logger,
only: neko_log, log_size, neko_log_debug
42 use num_types,
only: rp
43 use krylov,
only: ksp_monitor_t
46 adjoint_pnpn_vel_res_factory
47 use rhs_maker,
only: rhs_maker_sumab_t, rhs_maker_bdf_t, rhs_maker_ext_t, &
48 rhs_maker_oifs_t, rhs_maker_sumab_fctry, rhs_maker_bdf_fctry, &
49 rhs_maker_ext_fctry, rhs_maker_oifs_fctry
52 use device_mathops,
only: device_opadd2cm
53 use fluid_aux,
only: fluid_step_info
54 use scratch_registry,
only: neko_scratch_registry
55 use projection,
only: projection_t
56 use projection_vel,
only: projection_vel_t
57 use device,
only: device_memcpy, host_to_device, device_event_sync, &
60 use profiler,
only: profiler_start_region, profiler_end_region
61 use json_module,
only: json_file, json_core, json_value
62 use json_utils,
only: json_get, json_get_or_default, json_extract_item
63 use ax_product,
only: ax_t, ax_helm_factory
64 use field,
only: field_t
65 use dirichlet,
only: dirichlet_t
66 use shear_stress,
only: shear_stress_t
67 use wall_model_bc,
only: wall_model_bc_t
68 use facet_normal,
only: facet_normal_t
69 use non_normal,
only: non_normal_t
70 use checkpoint,
only: chkp_t
71 use mesh,
only: mesh_t
72 use user_intf,
only: user_t
73 use time_step_controller,
only: time_step_controller_t
74 use gs_ops,
only: gs_op_add
75 use neko_config,
only: neko_bcknd_device
76 use mathops,
only: opadd2cm
77 use bc_list,
only: bc_list_t
78 use zero_dirichlet,
only: zero_dirichlet_t
79 use utils,
only: neko_error
80 use field_math,
only: field_add2, field_copy, &
83 use file,
only: file_t
84 use operators,
only: ortho
85 use opr_device,
only: device_ortho
86 use inflow,
only: inflow_t
87 use field_dirichlet,
only: field_dirichlet_t
88 use blasius,
only: blasius_t
89 use field_dirichlet_vector,
only: field_dirichlet_vector_t
90 use dong_outflow,
only: dong_outflow_t
91 use time_state,
only: time_state_t
92 use vector,
only: vector_t
93 use device_math,
only: device_vlsc3, device_cmult, device_col2
94 use math,
only: vlsc3, cmult, col2
95 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_associated
96 use comm,
only: neko_comm, mpi_real_precision
97 use mpi_f08,
only: mpi_sum, mpi_max, mpi_allreduce, mpi_integer, &
99 use operators,
only : opgrad, curl, grad
109 type(field_t) :: p_res, u_res, v_res, w_res
113 type(field_t) :: dp, du, dv, dw
120 class(ax_t),
allocatable :: ax_vel
122 class(ax_t),
allocatable :: ax_prs
129 type(projection_t) :: proj_prs
130 type(projection_vel_t) :: proj_vel
137 type(facet_normal_t) :: bc_prs_surface
140 type(facet_normal_t) :: bc_sym_surface
150 type(zero_dirichlet_t) :: bc_vel_res
152 type(zero_dirichlet_t) :: bc_du
154 type(zero_dirichlet_t) :: bc_dv
156 type(zero_dirichlet_t) :: bc_dw
158 type(zero_dirichlet_t) :: bc_dp
161 type(bc_list_t) :: bclst_vel_res
162 type(bc_list_t) :: bclst_du
163 type(bc_list_t) :: bclst_dv
164 type(bc_list_t) :: bclst_dw
165 type(bc_list_t) :: bclst_dp
170 logical :: prs_dirichlet = .false.
180 type(field_t) :: abx1, aby1, abz1
181 type(field_t) :: abx2, aby2, abz2
184 type(field_t) :: advx, advy, advz
193 class(rhs_maker_sumab_t),
allocatable :: sumab
196 class(rhs_maker_ext_t),
allocatable :: makeabf
199 class(rhs_maker_bdf_t),
allocatable :: makebdf
202 class(rhs_maker_oifs_t),
allocatable :: makeoifs
208 logical :: full_stress_formulation = .false.
213 real(kind=rp) :: norm_scaling
214 real(kind=rp) :: norm_target
215 real(kind=rp) :: norm_tolerance
221 real(kind=rp) :: norm_l2_base
224 real(kind=rp) :: norm_l2_upper
226 real(kind=rp) :: norm_l2_lower
229 type(file_t) :: file_output
233 procedure, pass(this) :: init => adjoint_fluid_pnpn_init
235 procedure, pass(this) :: free => adjoint_fluid_pnpn_free
237 procedure, pass(this) :: step => adjoint_fluid_pnpn_step
239 procedure, pass(this) :: restart => adjoint_fluid_pnpn_restart
241 procedure, pass(this) :: setup_bcs => adjoint_fluid_pnpn_setup_bcs
243 procedure, pass(this) :: write_boundary_conditions => &
244 adjoint_fluid_pnpn_write_boundary_conditions
247 procedure,
public, pass(this) :: pw_compute_ => power_iterations_compute
259 module subroutine pressure_bc_factory(object, scheme, json, coef, user)
260 class(bc_t),
pointer,
intent(inout) :: object
261 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
262 type(json_file),
intent(inout) :: json
263 type(coef_t),
intent(in) :: coef
264 type(user_t),
intent(in) :: user
265 end subroutine pressure_bc_factory
266 end interface pressure_bc_factory
275 interface velocity_bc_factory
276 module subroutine velocity_bc_factory(object, scheme, json, coef, user)
277 class(bc_t),
pointer,
intent(inout) :: object
278 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
279 type(json_file),
intent(inout) :: json
280 type(coef_t),
intent(in) :: coef
281 type(user_t),
intent(in) :: user
282 end subroutine velocity_bc_factory
283 end interface velocity_bc_factory
287 subroutine adjoint_fluid_pnpn_init(this, msh, lx, params, user, chkp)
288 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
289 type(mesh_t),
target,
intent(inout) :: msh
290 integer,
intent(in) :: lx
291 type(json_file),
target,
intent(inout) :: params
292 type(user_t),
target,
intent(in) :: user
293 type(chkp_t),
target,
intent(inout) :: chkp
294 character(len=15),
parameter :: scheme =
'Adjoint (Pn/Pn)'
295 real(kind=rp) :: abs_tol
296 character(len=LOG_SIZE) :: log_buf
297 integer :: integer_val, solver_maxiter
298 character(len=:),
allocatable :: solver_type, precon_type
299 logical :: monitor, found
301 type(json_file) :: numerics_params, precon_params
304 character(len=:),
allocatable :: file_name
305 character(len=256) :: header_line
310 call this%init_base(msh, lx, params, scheme, user, .true.)
314 call neko_registry%add_field(this%dm_Xh,
'p_adj')
315 this%p_adj => neko_registry%get_field(
'p_adj')
321 call json_get(params,
'case.numerics.time_order', integer_val)
322 allocate(this%ext_bdf)
323 call this%ext_bdf%init(integer_val)
325 call json_get_or_default(params,
"case.fluid.full_stress_formulation", &
326 this%full_stress_formulation, .false.)
328 if (this%full_stress_formulation .eqv. .true.)
then
330 "Full stress formulation is not supported in the adjoint module.")
341 call ax_helm_factory(this%Ax_vel, full_formulation = .false.)
344 call adjoint_pnpn_prs_res_factory(this%prs_res)
347 call adjoint_pnpn_vel_res_factory(this%vel_res)
350 if (params%valid_path(
'case.fluid.nut_field'))
then
351 if (this%full_stress_formulation .eqv. .false.)
then
352 call neko_error(
"You need to set full_stress_formulation to " // &
353 "true for the fluid to have a spatially varying " // &
356 call json_get(params,
'case.fluid.nut_field', this%nut_field_name)
358 this%nut_field_name =
""
362 call ax_helm_factory(this%Ax_prs, full_formulation = .false.)
366 call rhs_maker_sumab_fctry(this%sumab)
369 call rhs_maker_ext_fctry(this%makeabf)
372 call rhs_maker_bdf_fctry(this%makebdf)
375 call rhs_maker_oifs_fctry(this%makeoifs)
378 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
379 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
381 call this%p_res%init(dm_xh,
"p_res")
382 call this%u_res%init(dm_xh,
"u_res")
383 call this%v_res%init(dm_xh,
"v_res")
384 call this%w_res%init(dm_xh,
"w_res")
385 call this%abx1%init(dm_xh,
"abx1")
386 call this%aby1%init(dm_xh,
"aby1")
387 call this%abz1%init(dm_xh,
"abz1")
388 call this%abx2%init(dm_xh,
"abx2")
389 call this%aby2%init(dm_xh,
"aby2")
390 call this%abz2%init(dm_xh,
"abz2")
391 call this%advx%init(dm_xh,
"advx")
392 call this%advy%init(dm_xh,
"advy")
393 call this%advz%init(dm_xh,
"advz")
396 call this%du%init(this%dm_Xh,
'du')
397 call this%dv%init(this%dm_Xh,
'dv')
398 call this%dw%init(this%dm_Xh,
'dw')
399 call this%dp%init(this%dm_Xh,
'dp')
402 call this%setup_bcs(user, params)
405 call json_get_or_default(params,
'case.output_boundary', found, .false.)
406 if (found)
call this%write_boundary_conditions()
408 call this%proj_prs%init(this%dm_Xh%size(), this%pr_projection_dim, &
409 this%pr_projection_activ_step)
411 call this%proj_vel%init(this%dm_Xh%size(), this%vel_projection_dim, &
412 this%vel_projection_activ_step)
415 call json_get_or_default(params,
'case.numerics.oifs', this%oifs, .false.)
416 if (params%valid_path(
'case.fluid.flow_rate_force'))
then
417 call neko_error(
"Flow rate forcing not available for adjoint_fluid_pnpn")
421 call neko_log%section(
"Pressure solver")
423 call json_get_or_default(params, &
424 'case.fluid.pressure_solver.max_iterations', &
426 call json_get(params,
'case.fluid.pressure_solver.type', solver_type)
427 call json_get(params,
'case.fluid.pressure_solver.preconditioner.type', &
429 call json_get(params, &
430 'case.fluid.pressure_solver.preconditioner', precon_params)
431 call json_get(params,
'case.fluid.pressure_solver.absolute_tolerance', &
433 call json_get_or_default(params,
'case.fluid.pressure_solver.monitor', &
435 call neko_log%message(
'Type : ('// trim(solver_type) // &
436 ', ' // trim(precon_type) //
')')
437 write(log_buf,
'(A,ES13.6)')
'Abs tol :', abs_tol
438 call neko_log%message(log_buf)
440 call this%solver_factory(this%ksp_prs, this%dm_Xh%size(), &
441 solver_type, solver_maxiter, abs_tol, monitor)
442 call this%precon_factory_(this%pc_prs, this%ksp_prs, &
443 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_prs, &
444 precon_type, precon_params)
445 call neko_log%end_section()
448 call neko_log%section(
"Advection factory")
449 call json_get_or_default(params,
'case.fluid.advection', advection, .true.)
450 call json_get(params,
'case.numerics', numerics_params)
451 call advection_adjoint_factory(this%adv, numerics_params, this%c_Xh, &
452 this%ulag, this%vlag, this%wlag, &
453 chkp%dtlag, chkp%tlag, this%ext_bdf, &
459 call this%chkp%add_fluid(this%u_adj, this%v_adj, this%w_adj, this%p_adj)
461 this%chkp%abx1 => this%abx1
462 this%chkp%abx2 => this%abx2
463 this%chkp%aby1 => this%aby1
464 this%chkp%aby2 => this%aby2
465 this%chkp%abz1 => this%abz1
466 this%chkp%abz2 => this%abz2
467 call this%chkp%add_lag(this%ulag, this%vlag, this%wlag)
469 call neko_log%end_section()
475 call json_get_or_default(params,
'norm_scaling', &
476 this%norm_scaling, 0.5_rp)
484 this%u_b => neko_registry%get_field(
'u')
485 this%v_b => neko_registry%get_field(
'v')
486 this%w_b => neko_registry%get_field(
'w')
487 this%p_b => neko_registry%get_field(
'p')
490 call json_get_or_default(params,
'norm_target', &
491 this%norm_target, -1.0_rp)
492 call json_get_or_default(params,
'norm_tolerance', &
493 this%norm_tolerance, 10.0_rp)
496 call json_get_or_default(params,
'output_file', &
497 file_name,
'power_iterations.csv')
498 call this%file_output%init(trim(file_name))
499 write(header_line,
'(A)')
'Time, Norm, Scaling'
500 call this%file_output%set_header(header_line)
502 end subroutine adjoint_fluid_pnpn_init
504 subroutine adjoint_fluid_pnpn_restart(this, chkp)
505 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
506 type(chkp_t),
intent(inout) :: chkp
507 real(kind=rp) :: dtlag(10), tlag(10)
513 n = this%u_adj%dof%size()
514 if (
allocated(this%chkp%previous_mesh%elements) .or. &
515 chkp%previous_Xh%lx .ne. this%Xh%lx)
then
516 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
517 p => this%p_adj, c_xh => this%c_Xh, ulag => this%ulag, &
518 vlag => this%vlag, wlag => this%wlag)
519 call col2(u%x, c_xh%mult, n)
520 call col2(v%x, c_xh%mult, n)
521 call col2(w%x, c_xh%mult, n)
522 call col2(p%x, c_xh%mult, n)
523 do i = 1, this%ulag%size()
524 call col2(ulag%lf(i)%x, c_xh%mult, n)
525 call col2(vlag%lf(i)%x, c_xh%mult, n)
526 call col2(wlag%lf(i)%x, c_xh%mult, n)
531 if (neko_bcknd_device .eq. 1)
then
532 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
533 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag,&
535 call device_memcpy(u%x, u%x_d, u%dof%size(), &
536 host_to_device, sync = .false.)
537 call device_memcpy(v%x, v%x_d, v%dof%size(), &
538 host_to_device, sync = .false.)
539 call device_memcpy(w%x, w%x_d, w%dof%size(), &
540 host_to_device, sync = .false.)
541 call device_memcpy(p%x, p%x_d, p%dof%size(), &
542 host_to_device, sync = .false.)
543 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, &
544 u%dof%size(), host_to_device, sync = .false.)
545 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, &
546 u%dof%size(), host_to_device, sync = .false.)
548 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, &
549 v%dof%size(), host_to_device, sync = .false.)
550 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, &
551 v%dof%size(), host_to_device, sync = .false.)
553 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, &
554 w%dof%size(), host_to_device, sync = .false.)
555 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, &
556 w%dof%size(), host_to_device, sync = .false.)
557 call device_memcpy(this%abx1%x, this%abx1%x_d, &
558 w%dof%size(), host_to_device, sync = .false.)
559 call device_memcpy(this%abx2%x, this%abx2%x_d, &
560 w%dof%size(), host_to_device, sync = .false.)
561 call device_memcpy(this%aby1%x, this%aby1%x_d, &
562 w%dof%size(), host_to_device, sync = .false.)
563 call device_memcpy(this%aby2%x, this%aby2%x_d, &
564 w%dof%size(), host_to_device, sync = .false.)
565 call device_memcpy(this%abz1%x, this%abz1%x_d, &
566 w%dof%size(), host_to_device, sync = .false.)
567 call device_memcpy(this%abz2%x, this%abz2%x_d, &
568 w%dof%size(), host_to_device, sync = .false.)
569 call device_memcpy(this%advx%x, this%advx%x_d, &
570 w%dof%size(), host_to_device, sync = .false.)
571 call device_memcpy(this%advy%x, this%advy%x_d, &
572 w%dof%size(), host_to_device, sync = .false.)
573 call device_memcpy(this%advz%x, this%advz%x_d, &
574 w%dof%size(), host_to_device, sync = .false.)
581 if (
allocated(this%chkp%previous_mesh%elements) &
582 .or. this%chkp%previous_Xh%lx .ne. this%Xh%lx)
then
583 call this%gs_Xh%op(this%u_adj, gs_op_add)
584 call this%gs_Xh%op(this%v_adj, gs_op_add)
585 call this%gs_Xh%op(this%w_adj, gs_op_add)
586 call this%gs_Xh%op(this%p_adj, gs_op_add)
588 do i = 1, this%ulag%size()
589 call this%gs_Xh%op(this%ulag%lf(i), gs_op_add)
590 call this%gs_Xh%op(this%vlag%lf(i), gs_op_add)
591 call this%gs_Xh%op(this%wlag%lf(i), gs_op_add)
595 end subroutine adjoint_fluid_pnpn_restart
597 subroutine adjoint_fluid_pnpn_free(this)
598 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
601 call this%scheme_free()
603 call this%bc_prs_surface%free()
604 call this%bc_sym_surface%free()
605 call this%bc_curl_curl%free()
607 call this%bc_vel_res%free()
608 call this%bc_du%free()
609 call this%bc_dv%free()
610 call this%bc_dw%free()
611 call this%bc_dp%free()
613 call this%bclst_vel_res%free()
614 call this%bclst_du%free()
615 call this%bclst_dv%free()
616 call this%bclst_dw%free()
617 call this%bclst_dp%free()
618 call this%proj_prs%free()
619 call this%proj_vel%free()
621 call this%p_res%free()
622 call this%u_res%free()
623 call this%v_res%free()
624 call this%w_res%free()
631 call this%abx1%free()
632 call this%aby1%free()
633 call this%abz1%free()
635 call this%abx2%free()
636 call this%aby2%free()
637 call this%abz2%free()
639 call this%advx%free()
640 call this%advy%free()
641 call this%advz%free()
643 if (
allocated(this%Ax_vel))
then
644 deallocate(this%Ax_vel)
647 if (
allocated(this%Ax_prs))
then
648 deallocate(this%Ax_prs)
651 if (
allocated(this%prs_res))
then
652 deallocate(this%prs_res)
655 if (
allocated(this%vel_res))
then
656 deallocate(this%vel_res)
659 if (
allocated(this%sumab))
then
660 deallocate(this%sumab)
663 if (
allocated(this%makeabf))
then
664 deallocate(this%makeabf)
667 if (
allocated(this%makebdf))
then
668 deallocate(this%makebdf)
671 if (
allocated(this%makeoifs))
then
672 deallocate(this%makeoifs)
675 if (
allocated(this%ext_bdf))
then
676 deallocate(this%ext_bdf)
681 end subroutine adjoint_fluid_pnpn_free
687 subroutine adjoint_fluid_pnpn_step(this, time, dt_controller)
688 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
689 type(time_state_t),
intent(in) :: time
690 type(time_step_controller_t),
intent(in) :: dt_controller
694 type(ksp_monitor_t) :: ksp_results(4)
695 type(field_t),
pointer :: dx_p_adj, dy_p_adj, dz_p_adj, nx1, nx2, nx3, &
697 integer :: temp_indices(3)
698 integer :: cc_indices(8)
699 real(kind=rp) :: rho_val, mu_val
701 if (this%freeze)
return
703 n = this%dm_Xh%size()
705 call profiler_start_region(
'Adjoint')
706 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
708 u_e => this%u_adj_e, v_e => this%v_adj_e, w_e => this%w_adj_e, &
709 du => this%du, dv => this%dv, dw => this%dw, dp => this%dp, &
710 u_b => this%u_b, v_b => this%v_b, w_b => this%w_b, &
711 u_res => this%u_res, v_res => this%v_res, w_res => this%w_res, &
712 p_res => this%p_res, ax_vel => this%Ax_vel, ax_prs => this%Ax_prs, &
714 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
715 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
716 msh => this%msh, prs_res => this%prs_res, &
717 source_term => this%source_term, vel_res => this%vel_res, &
718 sumab => this%sumab, &
719 makeabf => this%makeabf, makebdf => this%makebdf, &
720 vel_projection_dim => this%vel_projection_dim, &
721 pr_projection_dim => this%pr_projection_dim, &
723 rho => this%rho, mu => this%mu, &
724 f_x => this%f_adj_x, f_y => this%f_adj_y, f_z => this%f_adj_z, &
725 t => time%t, tstep => time%tstep, dt => time%dt, &
726 ext_bdf => this%ext_bdf, event => glb_cmd_event)
729 call sumab%compute_fluid(u_e, v_e, w_e, u, v, w, &
730 ulag, vlag, wlag, ext_bdf%advection_coeffs%x, ext_bdf%nadv)
733 call this%source_term%compute(time)
736 call this%bcs_vel%apply_vector(f_x%x, f_y%x, f_z%x, &
737 this%dm_Xh%size(), time, strong = .false.)
740 call neko_error(
"OIFS not implemented for adjoint")
744 call this%adv%compute_adjoint(u, v, w, u_b, v_b, w_b, &
746 xh, this%c_Xh, dm_xh%size())
752 call makeabf%compute_fluid(this%abx1, this%aby1, this%abz1,&
753 this%abx2, this%aby2, this%abz2, &
754 f_x%x, f_y%x, f_z%x, &
755 rho%x(1,1,1,1), ext_bdf%advection_coeffs%x, n)
758 call makebdf%compute_fluid(ulag, vlag, wlag, f_x%x, f_y%x, f_z%x, &
759 u, v, w, c_xh%B, c_xh%Blag, c_xh%Blaglag, rho%x(1,1,1,1), dt, &
760 ext_bdf%diffusion_coeffs%x, ext_bdf%ndiff, n)
767 call this%bc_apply_vel(time, strong = .true.)
768 call this%bc_apply_prs(time)
771 call neko_scratch_registry%request_field(dx_p_adj, cc_indices(1), .false.)
772 call neko_scratch_registry%request_field(dy_p_adj, cc_indices(2), .false.)
773 call neko_scratch_registry%request_field(dz_p_adj, cc_indices(3), .false.)
776 call neko_scratch_registry%request_field(nx1, cc_indices(4), .true.)
777 call neko_scratch_registry%request_field(nx2, cc_indices(5), .true.)
778 call neko_scratch_registry%request_field(nx3, cc_indices(6), .true.)
780 call neko_scratch_registry%request_field(work1, cc_indices(7), .false.)
781 call neko_scratch_registry%request_field(work2, cc_indices(8), .false.)
784 call grad(dx_p_adj%x, dy_p_adj%x, dz_p_adj%x, this%p_adj%x, c_xh)
787 call this%bc_curl_curl%apply_n_cross(nx1%x, nx2%x, nx3%x, dx_p_adj%x, &
788 dy_p_adj%x, dz_p_adj%x, dx_p_adj%size())
793 call curl(dx_p_adj, dy_p_adj, dz_p_adj, nx1, nx2, nx3, work1, work2, c_xh)
796 call gs_xh%op(dx_p_adj, gs_op_add, event)
797 call device_event_sync(event)
798 call gs_xh%op(dy_p_adj, gs_op_add, event)
799 call device_event_sync(event)
800 call gs_xh%op(dz_p_adj, gs_op_add, event)
801 call device_event_sync(event)
804 if (neko_bcknd_device .eq. 1)
then
805 call device_col2(dx_p_adj%x_d, c_xh%mult_d, dx_p_adj%size())
806 call device_col2(dy_p_adj%x_d, c_xh%mult_d, dx_p_adj%size())
807 call device_col2(dz_p_adj%x_d, c_xh%mult_d, dx_p_adj%size())
809 call col2(dx_p_adj%x, c_xh%mult, dx_p_adj%size())
810 call col2(dy_p_adj%x, c_xh%mult, dx_p_adj%size())
811 call col2(dz_p_adj%x, c_xh%mult, dx_p_adj%size())
814 rho_val = rho%x(1,1,1,1)
815 mu_val = mu%x(1,1,1,1)
816 call field_add2s2(f_x, dx_p_adj, -mu_val / rho_val)
817 call field_add2s2(f_y, dy_p_adj, -mu_val / rho_val)
818 call field_add2s2(f_z, dz_p_adj, -mu_val / rho_val)
820 call neko_scratch_registry%relinquish_field(cc_indices)
823 call this%update_material_properties(time)
827 call profiler_start_region(
'Adjoint_velocity_residual')
829 call vel_res%compute(ax_vel, u, v, w, &
830 u_res, v_res, w_res, &
834 mu, rho, ext_bdf%diffusion_coeffs%x(1), &
837 call gs_xh%op(u_res, gs_op_add, event)
838 call device_event_sync(event)
839 call gs_xh%op(v_res, gs_op_add, event)
840 call device_event_sync(event)
841 call gs_xh%op(w_res, gs_op_add, event)
842 call device_event_sync(event)
845 call this%bclst_vel_res%apply(u_res, v_res, w_res, time)
847 call profiler_end_region(
'Adjoint_velocity_residual')
849 call this%proj_vel%pre_solving(u_res%x, v_res%x, w_res%x, &
850 tstep, c_xh, n, dt_controller,
'Velocity')
852 call this%pc_vel%update()
854 call profiler_start_region(
"Adjoint_velocity_solve")
855 ksp_results(1:3) = this%ksp_vel%solve_coupled(ax_vel, du, dv, dw, &
856 u_res%x, v_res%x, w_res%x, n, c_xh, &
857 this%bclst_du, this%bclst_dv, this%bclst_dw, gs_xh, &
858 this%ksp_vel%max_iter)
860 call this%proj_vel%post_solving(du%x, dv%x, dw%x, ax_vel, c_xh, &
861 this%bclst_du, this%bclst_dv, this%bclst_dw, gs_xh, n, tstep, &
864 if (neko_bcknd_device .eq. 1)
then
865 call device_opadd2cm(u%x_d, v%x_d, w%x_d, &
866 du%x_d, dv%x_d, dw%x_d, 1.0_rp, n, msh%gdim)
868 call opadd2cm(u%x, v%x, w%x, du%x, dv%x, dw%x, 1.0_rp, n, msh%gdim)
870 call profiler_end_region(
"Adjoint_velocity_solve")
876 call field_copy(f_x, u)
877 call field_copy(f_y, v)
878 call field_copy(f_z, w)
880 call profiler_start_region(
'Adjoint_pressure_residual')
882 call prs_res%compute(p, p_res, &
886 this%bc_prs_surface, this%bc_sym_surface, &
887 ax_prs, ext_bdf%diffusion_coeffs%x(1), dt, &
891 if (.not. this%prs_dirichlet .and. neko_bcknd_device .eq. 1)
then
892 call device_ortho(p_res%x_d, this%glb_n_points, n)
893 else if (.not. this%prs_dirichlet)
then
894 call ortho(p_res%x, this%glb_n_points, n)
897 call gs_xh%op(p_res, gs_op_add, event)
898 call device_event_sync(event)
901 call this%bclst_dp%apply_scalar(p_res%x, p%dof%size(), time)
904 call profiler_end_region(
'Adjoint_pressure_residual')
907 call this%proj_prs%pre_solving(p_res%x, tstep, c_xh, n, dt_controller, &
910 call this%pc_prs%update()
912 call profiler_start_region(
'Adjoint_pressure_solve')
916 this%ksp_prs%solve(ax_prs, dp, p_res%x, n, c_xh, &
917 this%bclst_dp, gs_xh)
920 call profiler_end_region(
'Adjoint_pressure_solve')
922 call this%proj_prs%post_solving(dp%x, ax_prs, c_xh, &
923 this%bclst_dp, gs_xh, n, tstep, dt_controller)
926 call field_add2(p, dp, n)
927 if (.not. this%prs_dirichlet .and. neko_bcknd_device .eq. 1)
then
928 call device_ortho(p%x_d, this%glb_n_points, n)
929 else if (.not. this%prs_dirichlet)
then
930 call ortho(p%x, this%glb_n_points, n)
933 ksp_results(4)%name =
'Adjoint Pressure'
934 ksp_results(1)%name =
'Adjoint Velocity U'
935 ksp_results(2)%name =
'Adjoint Velocity V'
936 ksp_results(3)%name =
'Adjoint Velocity W'
938 if (this%forced_flow_rate)
then
939 call neko_error(
'Forced flow rate is not implemented for the adjoint')
945 call neko_scratch_registry%request_field(dx_p_adj, temp_indices(1), &
947 call neko_scratch_registry%request_field(dy_p_adj, temp_indices(2), &
949 call neko_scratch_registry%request_field(dz_p_adj, temp_indices(3), &
953 call opgrad(dx_p_adj%x, dy_p_adj%x, dz_p_adj%x, this%p_adj%x, c_xh)
956 call gs_xh%op(dx_p_adj, gs_op_add, event)
957 call device_event_sync(event)
958 call gs_xh%op(dy_p_adj, gs_op_add, event)
959 call device_event_sync(event)
960 call gs_xh%op(dz_p_adj, gs_op_add, event)
961 call device_event_sync(event)
964 if (neko_bcknd_device .eq. 1)
then
965 call device_col2(dx_p_adj%x_d, c_xh%Binv_d, dx_p_adj%size())
966 call device_col2(dy_p_adj%x_d, c_xh%Binv_d, dx_p_adj%size())
967 call device_col2(dz_p_adj%x_d, c_xh%Binv_d, dx_p_adj%size())
971 call col2(dx_p_adj%x, c_xh%Binv, dx_p_adj%size())
972 call col2(dy_p_adj%x, c_xh%Binv, dx_p_adj%size())
973 call col2(dz_p_adj%x, c_xh%Binv, dx_p_adj%size())
976 if (neko_bcknd_device .eq. 1)
then
977 call device_opadd2cm(u%x_d, v%x_d, w%x_d, dx_p_adj%x_d, &
978 dy_p_adj%x_d, dz_p_adj%x_d, -1.0_rp, n, msh%gdim)
980 call opadd2cm(u%x, v%x, w%x, dx_p_adj%x, dy_p_adj%x, dz_p_adj%x, &
981 -1.0_rp, n, msh%gdim)
984 call neko_scratch_registry%relinquish_field(temp_indices)
987 call fluid_step_info(time, ksp_results, &
988 this%full_stress_formulation, this%strict_convergence)
991 call profiler_end_region(
'Adjoint')
993 end subroutine adjoint_fluid_pnpn_step
999 subroutine adjoint_fluid_pnpn_setup_bcs(this, user, params)
1000 use mpi_f08,
only: mpi_in_place
1001 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
1002 type(user_t),
target,
intent(in) :: user
1003 type(json_file),
intent(inout) :: params
1004 integer :: i, n_bcs, j, zone_size, global_zone_size, ierr
1005 class(bc_t),
pointer :: bc_i
1006 type(json_core) :: core
1007 type(json_value),
pointer :: bc_object
1008 type(json_file) :: bc_subdict
1011 logical,
allocatable :: marked_zones(:)
1012 integer,
allocatable :: zone_indices(:)
1013 character(len=:),
allocatable :: json_key
1016 call this%bclst_vel_res%init()
1017 call this%bclst_du%init()
1018 call this%bclst_dv%init()
1019 call this%bclst_dw%init()
1020 call this%bclst_dp%init()
1022 call this%bc_vel_res%init_from_components(this%c_Xh)
1023 call this%bc_du%init_from_components(this%c_Xh)
1024 call this%bc_dv%init_from_components(this%c_Xh)
1025 call this%bc_dw%init_from_components(this%c_Xh)
1026 call this%bc_dp%init_from_components(this%c_Xh)
1029 call this%bc_prs_surface%init_from_components(this%c_Xh)
1030 call this%bc_sym_surface%init_from_components(this%c_Xh)
1031 call this%bc_curl_curl%init_from_components(this%c_Xh)
1033 json_key =
'case.adjoint_fluid.boundary_conditions'
1036 if (params%valid_path(json_key))
then
1037 call params%info(json_key, n_children = n_bcs)
1038 call params%get_core(core)
1039 call params%get(json_key, bc_object, found)
1044 call this%bcs_vel%init(n_bcs)
1046 allocate(marked_zones(
size(this%msh%labeled_zones)))
1047 marked_zones = .false.
1051 call json_extract_item(core, bc_object, i, bc_subdict)
1053 call json_get(bc_subdict,
"zone_indices", zone_indices)
1058 do j = 1,
size(zone_indices)
1059 zone_size = this%msh%labeled_zones(zone_indices(j))%size
1060 call mpi_allreduce(zone_size, global_zone_size, 1, &
1061 mpi_integer, mpi_max, neko_comm, ierr)
1063 if (global_zone_size .eq. 0)
then
1064 write(error_unit,
'(A, A, I0, A, A, I0, A)')
"*** ERROR ***: ",&
1065 "Zone index ", zone_indices(j), &
1066 " is invalid as this zone has 0 size, meaning it does ", &
1067 "not in the mesh. Check adjoint boundary condition ", &
1072 if (marked_zones(zone_indices(j)) .eqv. .true.)
then
1073 write(error_unit,
'(A, A, I0, A, A, A, A)')
"*** ERROR ***: ", &
1074 "Zone with index ", zone_indices(j), &
1075 " has already been assigned a boundary condition. ", &
1076 "Please check your boundary_conditions entry for the ", &
1077 "adjoint and make sure that each zone index appears ", &
1078 "only in a single boundary condition."
1081 marked_zones(zone_indices(j)) = .true.
1086 call velocity_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1090 if (
associated(bc_i))
then
1096 type is (symmetry_t)
1104 call this%bclst_vel_res%append(bc_i)
1105 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
1106 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
1107 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
1109 call this%bcs_vel%append(bc_i)
1111 call this%bc_sym_surface%mark_facets(bc_i%marked_facet)
1112 type is (non_normal_t)
1115 call this%bclst_vel_res%append(bc_i)
1116 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
1117 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
1118 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
1119 type is (shear_stress_t)
1121 call this%bclst_vel_res%append(bc_i%symmetry)
1122 call this%bclst_du%append(bc_i%symmetry%bc_x)
1123 call this%bclst_dv%append(bc_i%symmetry%bc_y)
1124 call this%bclst_dw%append(bc_i%symmetry%bc_z)
1126 call this%bcs_vel%append(bc_i)
1127 type is (wall_model_bc_t)
1129 call this%bclst_vel_res%append(bc_i%symmetry)
1130 call this%bclst_du%append(bc_i%symmetry%bc_x)
1131 call this%bclst_dv%append(bc_i%symmetry%bc_y)
1132 call this%bclst_dw%append(bc_i%symmetry%bc_z)
1134 call this%bcs_vel%append(bc_i)
1141 if (bc_i%strong .eqv. .true.)
then
1142 call this%bc_vel_res%mark_facets(bc_i%marked_facet)
1143 call this%bc_du%mark_facets(bc_i%marked_facet)
1144 call this%bc_dv%mark_facets(bc_i%marked_facet)
1145 call this%bc_dw%mark_facets(bc_i%marked_facet)
1147 call this%bc_prs_surface%mark_facets(bc_i%marked_facet)
1151 call this%bc_curl_curl%mark_facets(bc_i%marked_facet)
1153 call this%bcs_vel%append(bc_i)
1159 do i = 1,
size(this%msh%labeled_zones)
1160 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
1161 (marked_zones(i) .eqv. .false.))
then
1162 write(error_unit,
'(A, A, I0)')
"*** ERROR ***: ", &
1163 "No adjoint boundary condition assigned to zone ", i
1171 call this%bcs_prs%init(n_bcs)
1175 call json_extract_item(core, bc_object, i, bc_subdict)
1177 call pressure_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1181 if (
associated(bc_i))
then
1182 call this%bcs_prs%append(bc_i)
1185 if (bc_i%strong .eqv. .true.)
then
1186 call this%bc_dp%mark_facets(bc_i%marked_facet)
1194 do i = 1,
size(this%msh%labeled_zones)
1195 if (this%msh%labeled_zones(i)%size .gt. 0)
then
1196 call neko_error(
"No boundary_conditions entry in the case file!")
1202 call this%bc_prs_surface%finalize()
1203 call this%bc_sym_surface%finalize()
1204 call this%bc_curl_curl%finalize()
1206 call this%bc_vel_res%finalize()
1207 call this%bc_du%finalize()
1208 call this%bc_dv%finalize()
1209 call this%bc_dw%finalize()
1210 call this%bc_dp%finalize()
1212 call this%bclst_vel_res%append(this%bc_vel_res)
1213 call this%bclst_du%append(this%bc_du)
1214 call this%bclst_dv%append(this%bc_dv)
1215 call this%bclst_dw%append(this%bc_dw)
1216 call this%bclst_dp%append(this%bc_dp)
1219 this%prs_dirichlet = .not. this%bclst_dp%is_empty()
1220 call mpi_allreduce(mpi_in_place, this%prs_dirichlet, 1, &
1221 mpi_logical, mpi_lor, neko_comm)
1223 end subroutine adjoint_fluid_pnpn_setup_bcs
1226 subroutine adjoint_fluid_pnpn_write_boundary_conditions(this)
1227 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1228 type(dirichlet_t) :: bdry_mask
1229 type(field_t),
pointer :: bdry_field
1230 type(file_t) :: bdry_file
1231 integer :: temp_index, i
1232 class(bc_t),
pointer :: bci
1233 character(len=LOG_SIZE) :: log_buf
1235 call neko_log%section(
"Adjoint boundary conditions")
1236 write(log_buf,
'(A)') &
1237 'Marking using integer keys in boundary_adjoint0.f00000'
1238 call neko_log%message(log_buf)
1239 write(log_buf,
'(A)')
'Condition-value pairs: '
1240 call neko_log%message(log_buf)
1241 write(log_buf,
'(A)')
' no_slip = 1'
1242 call neko_log%message(log_buf)
1243 write(log_buf,
'(A)')
' velocity_value = 2'
1244 call neko_log%message(log_buf)
1245 write(log_buf,
'(A)')
' outflow, normal_outflow (+dong) = 3'
1246 call neko_log%message(log_buf)
1247 write(log_buf,
'(A)')
' symmetry = 4'
1248 call neko_log%message(log_buf)
1249 write(log_buf,
'(A)')
' user_velocity_pointwise = 5'
1250 call neko_log%message(log_buf)
1251 write(log_buf,
'(A)')
' periodic = 6'
1252 call neko_log%message(log_buf)
1253 write(log_buf,
'(A)')
' user_velocity = 7'
1254 call neko_log%message(log_buf)
1255 write(log_buf,
'(A)')
' user_pressure = 8'
1256 call neko_log%message(log_buf)
1257 write(log_buf,
'(A)')
' shear_stress = 9'
1258 call neko_log%message(log_buf)
1259 write(log_buf,
'(A)')
' wall_modelling = 10'
1260 call neko_log%message(log_buf)
1261 write(log_buf,
'(A)')
' blasius_profile = 11'
1262 call neko_log%message(log_buf)
1263 call neko_log%end_section()
1265 call neko_scratch_registry%request_field(bdry_field, temp_index, .true.)
1269 call bdry_mask%init_from_components(this%c_Xh, 6.0_rp)
1270 call bdry_mask%mark_zone(this%msh%periodic)
1271 call bdry_mask%finalize()
1272 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1273 call bdry_mask%free()
1275 do i = 1, this%bcs_prs%size()
1276 bci => this%bcs_prs%get(i)
1277 select type (bc => bci)
1278 type is (zero_dirichlet_t)
1279 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1280 call bdry_mask%mark_facets(bci%marked_facet)
1281 call bdry_mask%finalize()
1282 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1283 call bdry_mask%free()
1284 type is (dong_outflow_t)
1285 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1286 call bdry_mask%mark_facets(bci%marked_facet)
1287 call bdry_mask%finalize()
1288 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1289 call bdry_mask%free()
1290 type is (field_dirichlet_t)
1291 call bdry_mask%init_from_components(this%c_Xh, 8.0_rp)
1292 call bdry_mask%mark_facets(bci%marked_facet)
1293 call bdry_mask%finalize()
1294 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1295 call bdry_mask%free()
1299 do i = 1, this%bcs_vel%size()
1300 bci => this%bcs_vel%get(i)
1301 select type (bc => bci)
1302 type is (zero_dirichlet_t)
1303 call bdry_mask%init_from_components(this%c_Xh, 1.0_rp)
1304 call bdry_mask%mark_facets(bci%marked_facet)
1305 call bdry_mask%finalize()
1306 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1307 call bdry_mask%free()
1309 call bdry_mask%init_from_components(this%c_Xh, 2.0_rp)
1310 call bdry_mask%mark_facets(bci%marked_facet)
1311 call bdry_mask%finalize()
1312 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1313 call bdry_mask%free()
1314 type is (symmetry_t)
1315 call bdry_mask%init_from_components(this%c_Xh, 4.0_rp)
1316 call bdry_mask%mark_facets(bci%marked_facet)
1317 call bdry_mask%finalize()
1318 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1319 call bdry_mask%free()
1320 type is (field_dirichlet_vector_t)
1321 call bdry_mask%init_from_components(this%c_Xh, 7.0_rp)
1322 call bdry_mask%mark_facets(bci%marked_facet)
1323 call bdry_mask%finalize()
1324 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1325 call bdry_mask%free()
1326 type is (shear_stress_t)
1327 call bdry_mask%init_from_components(this%c_Xh, 9.0_rp)
1328 call bdry_mask%mark_facets(bci%marked_facet)
1329 call bdry_mask%finalize()
1330 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1331 call bdry_mask%free()
1332 type is (wall_model_bc_t)
1333 call bdry_mask%init_from_components(this%c_Xh, 10.0_rp)
1334 call bdry_mask%mark_facets(bci%marked_facet)
1335 call bdry_mask%finalize()
1336 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1337 call bdry_mask%free()
1339 call bdry_mask%init_from_components(this%c_Xh, 11.0_rp)
1340 call bdry_mask%mark_facets(bci%marked_facet)
1341 call bdry_mask%finalize()
1342 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1343 call bdry_mask%free()
1348 call bdry_file%init(
'boundary_adjoint.fld')
1349 call bdry_file%write(bdry_field)
1351 call neko_scratch_registry%relinquish_field(temp_index)
1352 end subroutine adjoint_fluid_pnpn_write_boundary_conditions
1357 subroutine rescale_fluid(fluid_data, scale)
1359 class(adjoint_fluid_pnpn_t),
intent(inout) :: fluid_data
1361 real(kind=rp),
intent(in) :: scale
1367 if (neko_bcknd_device .eq. 1)
then
1368 call device_cmult(fluid_data%u_adj%x_d, scale, fluid_data%u_adj%size())
1369 call device_cmult(fluid_data%v_adj%x_d, scale, fluid_data%v_adj%size())
1370 call device_cmult(fluid_data%w_adj%x_d, scale, fluid_data%w_adj%size())
1372 call cmult(fluid_data%u_adj%x, scale, fluid_data%u_adj%size())
1373 call cmult(fluid_data%v_adj%x, scale, fluid_data%v_adj%size())
1374 call cmult(fluid_data%w_adj%x, scale, fluid_data%w_adj%size())
1378 if (neko_bcknd_device .eq. 1)
then
1379 call device_cmult(fluid_data%f_adj_x%x_d, scale, &
1380 fluid_data%f_adj_x%size())
1381 call device_cmult(fluid_data%f_adj_y%x_d, scale, &
1382 fluid_data%f_adj_y%size())
1383 call device_cmult(fluid_data%f_adj_z%x_d, scale, &
1384 fluid_data%f_adj_z%size())
1387 call device_cmult(fluid_data%abx1%x_d, scale, fluid_data%abx1%size())
1388 call device_cmult(fluid_data%aby1%x_d, scale, fluid_data%aby1%size())
1389 call device_cmult(fluid_data%abz1%x_d, scale, fluid_data%abz1%size())
1390 call device_cmult(fluid_data%abx2%x_d, scale, fluid_data%abx2%size())
1391 call device_cmult(fluid_data%aby2%x_d, scale, fluid_data%aby2%size())
1392 call device_cmult(fluid_data%abz2%x_d, scale, fluid_data%abz2%size())
1395 call cmult(fluid_data%f_adj_x%x, scale, fluid_data%f_adj_x%size())
1396 call cmult(fluid_data%f_adj_y%x, scale, fluid_data%f_adj_y%size())
1397 call cmult(fluid_data%f_adj_z%x, scale, fluid_data%f_adj_z%size())
1399 call cmult(fluid_data%abx1%x, scale, fluid_data%abx1%size())
1400 call cmult(fluid_data%aby1%x, scale, fluid_data%aby1%size())
1401 call cmult(fluid_data%abz1%x, scale, fluid_data%abz1%size())
1403 call cmult(fluid_data%abx2%x, scale, fluid_data%abx2%size())
1404 call cmult(fluid_data%aby2%x, scale, fluid_data%aby2%size())
1405 call cmult(fluid_data%abz2%x, scale, fluid_data%abz2%size())
1409 if (neko_bcknd_device .eq. 1)
then
1410 do i = 1, fluid_data%ulag%size()
1411 call device_cmult(fluid_data%ulag%lf(i)%x_d, &
1412 scale, fluid_data%ulag%lf(i)%size())
1415 do i = 1, fluid_data%vlag%size()
1416 call device_cmult(fluid_data%vlag%lf(i)%x_d, &
1417 scale, fluid_data%vlag%lf(i)%size())
1420 do i = 1, fluid_data%wlag%size()
1421 call device_cmult(fluid_data%wlag%lf(i)%x_d, &
1422 scale, fluid_data%wlag%lf(i)%size())
1425 do i = 1, fluid_data%ulag%size()
1426 call cmult(fluid_data%ulag%lf(i)%x, &
1427 scale, fluid_data%ulag%lf(i)%size())
1430 do i = 1, fluid_data%vlag%size()
1431 call cmult(fluid_data%vlag%lf(i)%x, &
1432 scale, fluid_data%vlag%lf(i)%size())
1435 do i = 1, fluid_data%wlag%size()
1436 call cmult(fluid_data%wlag%lf(i)%x, &
1437 scale, fluid_data%wlag%lf(i)%size())
1441 end subroutine rescale_fluid
1443 function norm(x, y, z, B, volume, n)
1444 use mpi_f08,
only: mpi_in_place
1446 integer,
intent(in) :: n
1447 real(kind=rp),
dimension(n),
intent(in) :: x, y, z
1448 real(kind=rp),
dimension(n),
intent(in) :: b
1449 real(kind=rp),
intent(in) :: volume
1451 real(kind=rp) :: norm
1453 norm = vlsc3(x, x, b, n) + vlsc3(y, y, b, n) + vlsc3(z, z, b, n)
1455 call mpi_allreduce(mpi_in_place, norm, 1, &
1456 mpi_real_precision, mpi_sum, neko_comm)
1458 norm = sqrt(norm / volume)
1461 function device_norm(x_d, y_d, z_d, B_d, volume, n)
1462 use mpi_f08,
only: mpi_in_place
1464 type(c_ptr),
intent(in) :: x_d, y_d, z_d
1465 type(c_ptr),
intent(in) :: B_d
1466 real(kind=rp),
intent(in) :: volume
1467 integer,
intent(in) :: n
1469 real(kind=rp) :: device_norm
1471 device_norm = device_vlsc3(x_d, x_d, b_d, n) + &
1472 device_vlsc3(y_d, y_d, b_d, n) + &
1473 device_vlsc3(z_d, z_d, b_d, n)
1475 call mpi_allreduce(mpi_in_place, device_norm, 1, &
1476 mpi_real_precision, mpi_sum, neko_comm)
1478 device_norm = sqrt(device_norm / volume)
1480 end function device_norm
1486 subroutine power_iterations_compute(this, t, tstep)
1487 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1488 real(kind=rp),
intent(in) :: t
1489 integer,
intent(in) :: tstep
1492 real(kind=rp) :: scaling_factor
1493 real(kind=rp) :: norm_l2, norm_l2_base
1494 character(len=256) :: log_message
1495 type(vector_t) :: data_line
1498 n = this%c_Xh%dof%size()
1499 if (tstep .eq. 1)
then
1500 if (neko_bcknd_device .eq. 1)
then
1501 norm_l2_base = device_norm(this%u_adj%x_d, this%v_adj%x_d, &
1503 this%c_Xh%B_d, this%c_Xh%volume, n)
1505 norm_l2_base = this%norm_scaling * norm(this%u_adj%x, this%v_adj%x, &
1507 this%c_Xh%B, this%c_Xh%volume, n)
1509 if (this%norm_target .lt. 0.0_rp)
then
1510 this%norm_target = norm_l2_base
1513 this%norm_l2_upper = this%norm_tolerance * this%norm_target
1514 this%norm_l2_lower = this%norm_target / this%norm_tolerance
1519 if (neko_bcknd_device .eq. 1)
then
1520 norm_l2 = device_norm(this%u_adj%x_d, this%v_adj%x_d, this%w_adj%x_d, &
1521 this%c_Xh%B_d, this%c_Xh%volume, n)
1523 norm_l2 = norm(this%u_adj%x, this%v_adj%x, this%w_adj%x, &
1524 this%c_Xh%B, this%c_Xh%volume, n)
1526 norm_l2 = sqrt(this%norm_scaling) * norm_l2
1527 scaling_factor = 1.0_rp
1530 if (norm_l2 .gt. this%norm_l2_upper &
1531 .or. norm_l2 .lt. this%norm_l2_lower)
then
1532 scaling_factor = this%norm_target / norm_l2
1533 call rescale_fluid(this, scaling_factor)
1534 norm_l2 = this%norm_target
1536 if (tstep .eq. 1)
then
1537 scaling_factor = 1.0_rp
1543 call neko_log%section(
'Power Iterations')
1545 write (log_message,
'(A7,E20.14)')
'Norm: ', norm_l2
1546 call neko_log%message(log_message, lvl = neko_log_debug)
1547 write (log_message,
'(A7,E20.14)')
'Scaling: ', scaling_factor
1548 call neko_log%message(log_message, lvl = neko_log_debug)
1551 call data_line%init(2)
1552 data_line%x = [norm_l2, scaling_factor]
1553 call this%file_output%write(data_line, t)
1556 call neko_log%end_section(
'Power Iterations')
1557 end subroutine power_iterations_compute
Boundary condition factory for pressure.
Adjoint Pn/Pn formulation.
Subroutines to add advection terms to the RHS of a transport equation.
Base type of all fluid formulations.
Abstract type to compute pressure residual.
Abstract type to compute velocity residual.
Base abstract type for computing the advection operator.
Dirichlet condition in facet normal direction.