35 use,
intrinsic :: iso_fortran_env, only: error_unit
36 use coefs,
only: coef_t
37 use symmetry,
only: symmetry_t
38 use field_registry,
only: neko_field_registry
39 use logger,
only: neko_log, log_size, neko_log_debug
40 use num_types,
only: rp
41 use krylov,
only: ksp_monitor_t
42 use pnpn_residual,
only: pnpn_prs_res_t, pnpn_vel_res_t, &
43 pnpn_prs_res_factory, pnpn_vel_res_factory, &
44 pnpn_prs_res_stress_factory, pnpn_vel_res_stress_factory
45 use rhs_maker,
only: rhs_maker_sumab_t, rhs_maker_bdf_t, rhs_maker_ext_t, &
46 rhs_maker_oifs_t, rhs_maker_sumab_fctry, rhs_maker_bdf_fctry, &
47 rhs_maker_ext_fctry, rhs_maker_oifs_fctry
51 use device_mathops,
only: device_opcolv, device_opadd2cm
52 use fluid_aux,
only: fluid_step_info
53 use time_scheme_controller,
only: time_scheme_controller_t
54 use projection,
only: projection_t
55 use projection_vel,
only: projection_vel_t
56 use device,
only: device_memcpy, host_to_device, device_event_sync, &
59 use profiler,
only: profiler_start_region, profiler_end_region
60 use json_module,
only: json_file, json_core, json_value
61 use json_utils,
only: json_get, json_get_or_default, json_extract_item, &
63 use json_module,
only: json_file
64 use ax_product,
only: ax_t, ax_helm_factory
65 use field,
only: field_t
66 use dirichlet,
only: dirichlet_t
67 use shear_stress,
only: shear_stress_t
68 use wall_model_bc,
only: wall_model_bc_t
69 use facet_normal,
only: facet_normal_t
70 use non_normal,
only: non_normal_t
71 use checkpoint,
only: chkp_t
72 use mesh,
only: mesh_t
73 use user_intf,
only: user_t
74 use time_step_controller,
only: time_step_controller_t
75 use gs_ops,
only: gs_op_add
76 use neko_config,
only: neko_bcknd_device
77 use mathops,
only: opadd2cm, opcolv
78 use bc_list,
only: bc_list_t
79 use zero_dirichlet,
only: zero_dirichlet_t
80 use utils,
only: neko_error, neko_type_error
81 use field_math,
only: field_add2, field_copy
83 use file,
only: file_t
84 use operators,
only: ortho
85 use time_state,
only: time_state_t
86 use vector,
only: vector_t
87 use device_math,
only: device_vlsc3, device_cmult
88 use math,
only: vlsc3, cmult
90 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_associated
91 use comm,
only: neko_comm, mpi_real_precision
92 use mpi_f08,
only: mpi_sum, mpi_max, mpi_allreduce, mpi_comm_world, &
93 mpi_integer, mpi_logical, mpi_lor
101 type(field_t) :: p_res, u_res, v_res, w_res
105 type(field_t) :: dp, du, dv, dw
107 type(field_t),
pointer :: u_b => null()
108 type(field_t),
pointer :: v_b => null()
109 type(field_t),
pointer :: w_b => null()
110 type(field_t),
pointer :: p_b => null()
117 class(ax_t),
allocatable :: ax_vel
119 class(ax_t),
allocatable :: ax_prs
126 type(projection_t) :: proj_prs
127 type(projection_vel_t) :: proj_vel
134 type(facet_normal_t) :: bc_prs_surface
137 type(facet_normal_t) :: bc_sym_surface
144 type(zero_dirichlet_t) :: bc_vel_res
146 type(zero_dirichlet_t) :: bc_du
148 type(zero_dirichlet_t) :: bc_dv
150 type(zero_dirichlet_t) :: bc_dw
152 type(zero_dirichlet_t) :: bc_dp
155 type(bc_list_t) :: bclst_vel_res
156 type(bc_list_t) :: bclst_du
157 type(bc_list_t) :: bclst_dv
158 type(bc_list_t) :: bclst_dw
159 type(bc_list_t) :: bclst_dp
164 logical :: prs_dirichlet = .false.
174 type(field_t) :: abx1, aby1, abz1
175 type(field_t) :: abx2, aby2, abz2
178 type(field_t) :: advx, advy, advz
181 class(pnpn_prs_res_t),
allocatable :: prs_res
184 class(pnpn_vel_res_t),
allocatable :: vel_res
187 class(rhs_maker_sumab_t),
allocatable :: sumab
190 class(rhs_maker_ext_t),
allocatable :: makeabf
193 class(rhs_maker_bdf_t),
allocatable :: makebdf
196 class(rhs_maker_oifs_t),
allocatable :: makeoifs
202 logical :: full_stress_formulation = .false.
207 real(kind=rp) :: norm_scaling
208 real(kind=rp) :: norm_target
209 real(kind=rp) :: norm_tolerance
215 real(kind=rp) :: norm_l2_base
218 real(kind=rp) :: norm_l2_upper
220 real(kind=rp) :: norm_l2_lower
223 type(file_t) :: file_output
227 procedure, pass(this) :: init => adjoint_fluid_pnpn_init
229 procedure, pass(this) :: free => adjoint_fluid_pnpn_free
231 procedure, pass(this) :: step => adjoint_fluid_pnpn_step
233 procedure, pass(this) :: restart => adjoint_fluid_pnpn_restart
235 procedure, pass(this) :: setup_bcs => adjoint_fluid_pnpn_setup_bcs
237 procedure, pass(this) :: write_boundary_conditions => &
238 adjoint_fluid_pnpn_write_boundary_conditions
241 procedure,
public, pass(this) :: pw_compute_ => power_iterations_compute
253 module subroutine pressure_bc_factory(object, scheme, json, coef, user)
254 class(bc_t),
pointer,
intent(inout) :: object
255 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
256 type(json_file),
intent(inout) :: json
257 type(coef_t),
intent(in) :: coef
258 type(user_t),
intent(in) :: user
259 end subroutine pressure_bc_factory
260 end interface pressure_bc_factory
269 interface velocity_bc_factory
270 module subroutine velocity_bc_factory(object, scheme, json, coef, user)
271 class(bc_t),
pointer,
intent(inout) :: object
272 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
273 type(json_file),
intent(inout) :: json
274 type(coef_t),
intent(in) :: coef
275 type(user_t),
intent(in) :: user
276 end subroutine velocity_bc_factory
277 end interface velocity_bc_factory
281 subroutine adjoint_fluid_pnpn_init(this, msh, lx, params, user, chkp)
282 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
283 type(mesh_t),
target,
intent(inout) :: msh
284 integer,
intent(in) :: lx
285 type(json_file),
target,
intent(inout) :: params
286 type(user_t),
target,
intent(in) :: user
287 type(chkp_t),
target,
intent(inout) :: chkp
288 character(len=15),
parameter :: scheme =
'Adjoint (Pn/Pn)'
289 real(kind=rp) :: abs_tol
290 character(len=LOG_SIZE) :: log_buf
291 integer :: integer_val, solver_maxiter
292 character(len=:),
allocatable :: solver_type, precon_type
293 logical :: monitor, found
295 type(json_file) :: numerics_params, precon_params
298 character(len=:),
allocatable :: file_name
299 character(len=256) :: header_line
304 call this%init_base(msh, lx, params, scheme, user, .true.)
308 call neko_field_registry%add_field(this%dm_Xh,
'p_adj')
309 this%p_adj => neko_field_registry%get_field(
'p_adj')
315 call json_get(params,
'case.numerics.time_order', integer_val)
316 allocate(this%ext_bdf)
317 call this%ext_bdf%init(integer_val)
319 call json_get_or_default(params,
"case.fluid.full_stress_formulation", &
320 this%full_stress_formulation, .false.)
322 if (this%full_stress_formulation .eqv. .true.)
then
324 "Full stress formulation is not supported in the adjoint module.")
335 call ax_helm_factory(this%Ax_vel, full_formulation = .false.)
338 call pnpn_prs_res_factory(this%prs_res)
341 call pnpn_vel_res_factory(this%vel_res)
344 if (params%valid_path(
'case.fluid.nut_field'))
then
345 if (this%full_stress_formulation .eqv. .false.)
then
346 call neko_error(
"You need to set full_stress_formulation to " // &
347 "true for the fluid to have a spatially varying " // &
350 call json_get(params,
'case.fluid.nut_field', this%nut_field_name)
352 this%nut_field_name =
""
356 call ax_helm_factory(this%Ax_prs, full_formulation = .false.)
360 call rhs_maker_sumab_fctry(this%sumab)
363 call rhs_maker_ext_fctry(this%makeabf)
366 call rhs_maker_bdf_fctry(this%makebdf)
369 call rhs_maker_oifs_fctry(this%makeoifs)
372 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
373 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
375 call this%p_res%init(dm_xh,
"p_res")
376 call this%u_res%init(dm_xh,
"u_res")
377 call this%v_res%init(dm_xh,
"v_res")
378 call this%w_res%init(dm_xh,
"w_res")
379 call this%abx1%init(dm_xh,
"abx1")
380 call this%aby1%init(dm_xh,
"aby1")
381 call this%abz1%init(dm_xh,
"abz1")
382 call this%abx2%init(dm_xh,
"abx2")
383 call this%aby2%init(dm_xh,
"aby2")
384 call this%abz2%init(dm_xh,
"abz2")
385 call this%advx%init(dm_xh,
"advx")
386 call this%advy%init(dm_xh,
"advy")
387 call this%advz%init(dm_xh,
"advz")
390 call this%du%init(this%dm_Xh,
'du')
391 call this%dv%init(this%dm_Xh,
'dv')
392 call this%dw%init(this%dm_Xh,
'dw')
393 call this%dp%init(this%dm_Xh,
'dp')
396 call this%setup_bcs(user, params)
399 call json_get_or_default(params,
'case.output_boundary', found, .false.)
400 if (found)
call this%write_boundary_conditions()
402 call this%proj_prs%init(this%dm_Xh%size(), this%pr_projection_dim, &
403 this%pr_projection_activ_step)
405 call this%proj_vel%init(this%dm_Xh%size(), this%vel_projection_dim, &
406 this%vel_projection_activ_step)
409 call json_get_or_default(params,
'case.numerics.oifs', this%oifs, .false.)
410 if (params%valid_path(
'case.fluid.flow_rate_force'))
then
411 call neko_error(
"Flow rate forcing not available for adjoint_fluid_pnpn")
415 call neko_log%section(
"Pressure solver")
417 call json_get_or_default(params, &
418 'case.fluid.pressure_solver.max_iterations', &
420 call json_get(params,
'case.fluid.pressure_solver.type', solver_type)
421 call json_get(params,
'case.fluid.pressure_solver.preconditioner.type', &
423 call json_extract_object(params, &
424 'case.fluid.pressure_solver.preconditioner', precon_params)
425 call json_get(params,
'case.fluid.pressure_solver.absolute_tolerance', &
427 call json_get_or_default(params,
'case.fluid.pressure_solver.monitor', &
429 call neko_log%message(
'Type : ('// trim(solver_type) // &
430 ', ' // trim(precon_type) //
')')
431 write(log_buf,
'(A,ES13.6)')
'Abs tol :', abs_tol
432 call neko_log%message(log_buf)
434 call this%solver_factory(this%ksp_prs, this%dm_Xh%size(), &
435 solver_type, solver_maxiter, abs_tol, monitor)
436 call this%precon_factory_(this%pc_prs, this%ksp_prs, &
437 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_prs, &
438 precon_type, precon_params)
439 call neko_log%end_section()
442 call neko_log%section(
"Advection factory")
443 call json_get_or_default(params,
'case.fluid.advection', advection, .true.)
444 call json_extract_object(params,
'case.numerics', numerics_params)
445 call advection_adjoint_factory(this%adv, numerics_params, this%c_Xh, &
446 this%ulag, this%vlag, this%wlag, &
447 chkp%dtlag, chkp%tlag, this%ext_bdf, &
453 call this%chkp%init(this%u_adj, this%v_adj, this%w_adj, this%p_adj)
455 this%chkp%abx1 => this%abx1
456 this%chkp%abx2 => this%abx2
457 this%chkp%aby1 => this%aby1
458 this%chkp%aby2 => this%aby2
459 this%chkp%abz1 => this%abz1
460 this%chkp%abz2 => this%abz2
461 call this%chkp%add_lag(this%ulag, this%vlag, this%wlag)
463 call neko_log%end_section()
469 call json_get_or_default(params,
'norm_scaling', &
470 this%norm_scaling, 0.5_rp)
478 this%u_b => neko_field_registry%get_field(
'u')
479 this%v_b => neko_field_registry%get_field(
'v')
480 this%w_b => neko_field_registry%get_field(
'w')
481 this%p_b => neko_field_registry%get_field(
'p')
484 call json_get_or_default(params,
'norm_target', &
485 this%norm_target, -1.0_rp)
486 call json_get_or_default(params,
'norm_tolerance', &
487 this%norm_tolerance, 10.0_rp)
490 call json_get_or_default(params,
'output_file', &
491 file_name,
'power_iterations.csv')
492 call this%file_output%init(trim(file_name))
493 write(header_line,
'(A)')
'Time, Norm, Scaling'
494 call this%file_output%set_header(header_line)
496 end subroutine adjoint_fluid_pnpn_init
498 subroutine adjoint_fluid_pnpn_restart(this, chkp)
499 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
500 type(chkp_t),
intent(inout) :: chkp
501 real(kind=rp) :: dtlag(10), tlag(10)
507 n = this%u_adj%dof%size()
508 if (
allocated(this%chkp%previous_mesh%elements) .or. &
509 chkp%previous_Xh%lx .ne. this%Xh%lx)
then
510 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
511 p => this%p_adj, c_xh => this%c_Xh, ulag => this%ulag, &
512 vlag => this%vlag, wlag => this%wlag)
513 do concurrent(j = 1:n)
514 u%x(j,1,1,1) = u%x(j,1,1,1) * c_xh%mult(j,1,1,1)
515 v%x(j,1,1,1) = v%x(j,1,1,1) * c_xh%mult(j,1,1,1)
516 w%x(j,1,1,1) = w%x(j,1,1,1) * c_xh%mult(j,1,1,1)
517 p%x(j,1,1,1) = p%x(j,1,1,1) * c_xh%mult(j,1,1,1)
519 do i = 1, this%ulag%size()
520 do concurrent(j = 1:n)
521 ulag%lf(i)%x(j,1,1,1) = ulag%lf(i)%x(j,1,1,1) &
523 vlag%lf(i)%x(j,1,1,1) = vlag%lf(i)%x(j,1,1,1) &
525 wlag%lf(i)%x(j,1,1,1) = wlag%lf(i)%x(j,1,1,1) &
532 if (neko_bcknd_device .eq. 1)
then
533 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
534 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag,&
536 call device_memcpy(u%x, u%x_d, u%dof%size(), &
537 host_to_device, sync = .false.)
538 call device_memcpy(v%x, v%x_d, v%dof%size(), &
539 host_to_device, sync = .false.)
540 call device_memcpy(w%x, w%x_d, w%dof%size(), &
541 host_to_device, sync = .false.)
542 call device_memcpy(p%x, p%x_d, p%dof%size(), &
543 host_to_device, sync = .false.)
544 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, &
545 u%dof%size(), host_to_device, sync = .false.)
546 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, &
547 u%dof%size(), host_to_device, sync = .false.)
549 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, &
550 v%dof%size(), host_to_device, sync = .false.)
551 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, &
552 v%dof%size(), host_to_device, sync = .false.)
554 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, &
555 w%dof%size(), host_to_device, sync = .false.)
556 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, &
557 w%dof%size(), host_to_device, sync = .false.)
558 call device_memcpy(this%abx1%x, this%abx1%x_d, &
559 w%dof%size(), host_to_device, sync = .false.)
560 call device_memcpy(this%abx2%x, this%abx2%x_d, &
561 w%dof%size(), host_to_device, sync = .false.)
562 call device_memcpy(this%aby1%x, this%aby1%x_d, &
563 w%dof%size(), host_to_device, sync = .false.)
564 call device_memcpy(this%aby2%x, this%aby2%x_d, &
565 w%dof%size(), host_to_device, sync = .false.)
566 call device_memcpy(this%abz1%x, this%abz1%x_d, &
567 w%dof%size(), host_to_device, sync = .false.)
568 call device_memcpy(this%abz2%x, this%abz2%x_d, &
569 w%dof%size(), host_to_device, sync = .false.)
570 call device_memcpy(this%advx%x, this%advx%x_d, &
571 w%dof%size(), host_to_device, sync = .false.)
572 call device_memcpy(this%advy%x, this%advy%x_d, &
573 w%dof%size(), host_to_device, sync = .false.)
574 call device_memcpy(this%advz%x, this%advz%x_d, &
575 w%dof%size(), host_to_device, sync = .false.)
582 if (
allocated(this%chkp%previous_mesh%elements) &
583 .or. this%chkp%previous_Xh%lx .ne. this%Xh%lx)
then
584 call this%gs_Xh%op(this%u_adj, gs_op_add)
585 call this%gs_Xh%op(this%v_adj, gs_op_add)
586 call this%gs_Xh%op(this%w_adj, gs_op_add)
587 call this%gs_Xh%op(this%p_adj, gs_op_add)
589 do i = 1, this%ulag%size()
590 call this%gs_Xh%op(this%ulag%lf(i), gs_op_add)
591 call this%gs_Xh%op(this%vlag%lf(i), gs_op_add)
592 call this%gs_Xh%op(this%wlag%lf(i), gs_op_add)
596 end subroutine adjoint_fluid_pnpn_restart
598 subroutine adjoint_fluid_pnpn_free(this)
599 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
602 call this%scheme_free()
604 call this%bc_prs_surface%free()
605 call this%bc_sym_surface%free()
606 call this%bclst_vel_res%free()
607 call this%bclst_dp%free()
608 call this%proj_prs%free()
609 call this%proj_vel%free()
611 call this%p_res%free()
612 call this%u_res%free()
613 call this%v_res%free()
614 call this%w_res%free()
621 call this%abx1%free()
622 call this%aby1%free()
623 call this%abz1%free()
625 call this%abx2%free()
626 call this%aby2%free()
627 call this%abz2%free()
629 call this%advx%free()
630 call this%advy%free()
631 call this%advz%free()
633 if (
allocated(this%Ax_vel))
then
634 deallocate(this%Ax_vel)
637 if (
allocated(this%Ax_prs))
then
638 deallocate(this%Ax_prs)
641 if (
allocated(this%prs_res))
then
642 deallocate(this%prs_res)
645 if (
allocated(this%vel_res))
then
646 deallocate(this%vel_res)
649 if (
allocated(this%sumab))
then
650 deallocate(this%sumab)
653 if (
allocated(this%makeabf))
then
654 deallocate(this%makeabf)
657 if (
allocated(this%makebdf))
then
658 deallocate(this%makebdf)
661 if (
allocated(this%makeoifs))
then
662 deallocate(this%makeoifs)
665 if (
allocated(this%ext_bdf))
then
666 deallocate(this%ext_bdf)
671 end subroutine adjoint_fluid_pnpn_free
677 subroutine adjoint_fluid_pnpn_step(this, time, dt_controller)
678 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
679 type(time_state_t),
intent(in) :: time
680 type(time_step_controller_t),
intent(in) :: dt_controller
684 type(ksp_monitor_t) :: ksp_results(4)
686 if (this%freeze)
return
688 n = this%dm_Xh%size()
690 call profiler_start_region(
'Adjoint', 13)
691 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
693 u_e => this%u_adj_e, v_e => this%v_adj_e, w_e => this%w_adj_e, &
694 du => this%du, dv => this%dv, dw => this%dw, dp => this%dp, &
695 u_b => this%u_b, v_b => this%v_b, w_b => this%w_b, &
696 u_res => this%u_res, v_res => this%v_res, w_res => this%w_res, &
697 p_res => this%p_res, ax_vel => this%Ax_vel, ax_prs => this%Ax_prs, &
699 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
700 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
701 msh => this%msh, prs_res => this%prs_res, &
702 source_term => this%source_term, vel_res => this%vel_res, &
703 sumab => this%sumab, &
704 makeabf => this%makeabf, makebdf => this%makebdf, &
705 vel_projection_dim => this%vel_projection_dim, &
706 pr_projection_dim => this%pr_projection_dim, &
708 rho => this%rho, mu => this%mu, &
709 f_x => this%f_adj_x, f_y => this%f_adj_y, f_z => this%f_adj_z, &
710 t => time%t, tstep => time%tstep, dt => time%dt, &
711 ext_bdf => this%ext_bdf, event => glb_cmd_event)
714 call sumab%compute_fluid(u_e, v_e, w_e, u, v, w, &
715 ulag, vlag, wlag, ext_bdf%advection_coeffs, ext_bdf%nadv)
718 call this%source_term%compute(t, tstep)
721 call this%bcs_vel%apply_vector(f_x%x, f_y%x, f_z%x, &
722 this%dm_Xh%size(), t, tstep, strong = .false.)
725 call neko_error(
"OIFS not implemented for adjoint")
729 call this%adv%compute_adjoint(u, v, w, u_b, v_b, w_b, &
731 xh, this%c_Xh, dm_xh%size())
737 call makeabf%compute_fluid(this%abx1, this%aby1, this%abz1,&
738 this%abx2, this%aby2, this%abz2, &
739 f_x%x, f_y%x, f_z%x, &
740 rho%x(1,1,1,1), ext_bdf%advection_coeffs, n)
743 call makebdf%compute_fluid(ulag, vlag, wlag, f_x%x, f_y%x, f_z%x, &
744 u, v, w, c_xh%B, rho%x(1,1,1,1), dt, &
745 ext_bdf%diffusion_coeffs, ext_bdf%ndiff, n)
752 call this%bc_apply_vel(t, tstep, strong = .true.)
753 call this%bc_apply_prs(t, tstep)
756 call this%update_material_properties(t, tstep)
759 call profiler_start_region(
'Pressure_residual', 18)
761 call prs_res%compute(p, p_res, &
766 this%bc_prs_surface, this%bc_sym_surface, &
767 ax_prs, ext_bdf%diffusion_coeffs(1), dt, &
771 if (.not. this%prs_dirichlet)
call ortho(p_res%x, this%glb_n_points, n)
773 call gs_xh%op(p_res, gs_op_add, event)
774 call device_event_sync(event)
777 call this%bclst_dp%apply_scalar(p_res%x, p%dof%size(), t, tstep)
780 call profiler_end_region(
'Pressure_residual', 18)
783 call this%proj_prs%pre_solving(p_res%x, tstep, c_xh, n, dt_controller, &
786 call this%pc_prs%update()
788 call profiler_start_region(
'Pressure_solve', 3)
792 this%ksp_prs%solve(ax_prs, dp, p_res%x, n, c_xh, &
793 this%bclst_dp, gs_xh)
796 call profiler_end_region(
'Pressure_solve', 3)
798 call this%proj_prs%post_solving(dp%x, ax_prs, c_xh, &
799 this%bclst_dp, gs_xh, n, tstep, dt_controller)
802 call field_add2(p, dp, n)
803 if (.not. this%prs_dirichlet)
call ortho(p%x, this%glb_n_points, n)
806 call profiler_start_region(
'Velocity_residual', 19)
807 call vel_res%compute(ax_vel, u, v, w, &
808 u_res, v_res, w_res, &
812 mu, rho, ext_bdf%diffusion_coeffs(1), &
815 call gs_xh%op(u_res, gs_op_add, event)
816 call device_event_sync(event)
817 call gs_xh%op(v_res, gs_op_add, event)
818 call device_event_sync(event)
819 call gs_xh%op(w_res, gs_op_add, event)
820 call device_event_sync(event)
823 call this%bclst_vel_res%apply(u_res, v_res, w_res, t, tstep)
826 call profiler_end_region(
'Velocity_residual', 19)
828 call this%proj_vel%pre_solving(u_res%x, v_res%x, w_res%x, &
829 tstep, c_xh, n, dt_controller,
'Velocity')
831 call this%pc_vel%update()
833 call profiler_start_region(
"Velocity_solve", 4)
834 ksp_results(2:4) = this%ksp_vel%solve_coupled(ax_vel, du, dv, dw, &
835 u_res%x, v_res%x, w_res%x, n, c_xh, &
836 this%bclst_du, this%bclst_dv, this%bclst_dw, gs_xh, &
837 this%ksp_vel%max_iter)
838 call profiler_end_region(
"Velocity_solve", 4)
840 call this%proj_vel%post_solving(du%x, dv%x, dw%x, ax_vel, c_xh, &
841 this%bclst_du, this%bclst_dv, this%bclst_dw, gs_xh, n, tstep, &
844 if (neko_bcknd_device .eq. 1)
then
845 call device_opadd2cm(u%x_d, v%x_d, w%x_d, &
846 du%x_d, dv%x_d, dw%x_d, 1.0_rp, n, msh%gdim)
848 call opadd2cm(u%x, v%x, w%x, du%x, dv%x, dw%x, 1.0_rp, n, msh%gdim)
851 if (this%forced_flow_rate)
then
852 call neko_error(
'Forced flow rate is not implemented for the adjoint')
856 call fluid_step_info(time, ksp_results, &
857 this%full_stress_formulation, this%strict_convergence)
860 call profiler_end_region(
'Adjoint', 13)
862 end subroutine adjoint_fluid_pnpn_step
868 subroutine adjoint_fluid_pnpn_setup_bcs(this, user, params)
869 use mpi_f08,
only: mpi_in_place
870 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
871 type(user_t),
target,
intent(in) :: user
872 type(json_file),
intent(inout) :: params
873 integer :: i, n_bcs, j, zone_size, global_zone_size, ierr
874 class(bc_t),
pointer :: bc_i
875 type(json_core) :: core
876 type(json_value),
pointer :: bc_object
877 type(json_file) :: bc_subdict
880 logical,
allocatable :: marked_zones(:)
881 integer,
allocatable :: zone_indices(:)
882 character(len=:),
allocatable :: json_key
885 call this%bclst_vel_res%init()
886 call this%bclst_du%init()
887 call this%bclst_dv%init()
888 call this%bclst_dw%init()
889 call this%bclst_dp%init()
891 call this%bc_vel_res%init_from_components(this%c_Xh)
892 call this%bc_du%init_from_components(this%c_Xh)
893 call this%bc_dv%init_from_components(this%c_Xh)
894 call this%bc_dw%init_from_components(this%c_Xh)
895 call this%bc_dp%init_from_components(this%c_Xh)
898 call this%bc_prs_surface%init_from_components(this%c_Xh)
899 call this%bc_sym_surface%init_from_components(this%c_Xh)
901 json_key =
'case.adjoint_fluid.boundary_conditions'
904 if (params%valid_path(json_key))
then
905 call params%info(json_key, n_children = n_bcs)
906 call params%get_core(core)
907 call params%get(json_key, bc_object, found)
912 call this%bcs_vel%init(n_bcs)
914 allocate(marked_zones(
size(this%msh%labeled_zones)))
915 marked_zones = .false.
919 call json_extract_item(core, bc_object, i, bc_subdict)
921 call json_get(bc_subdict,
"zone_indices", zone_indices)
926 do j = 1,
size(zone_indices)
927 zone_size = this%msh%labeled_zones(zone_indices(j))%size
928 call mpi_allreduce(zone_size, global_zone_size, 1, &
929 mpi_integer, mpi_max, neko_comm, ierr)
931 if (global_zone_size .eq. 0)
then
932 write(error_unit,
'(A, A, I0, A, A, I0, A)')
"*** ERROR ***: ",&
933 "Zone index ", zone_indices(j), &
934 " is invalid as this zone has 0 size, meaning it does ", &
935 "not in the mesh. Check adjoint boundary condition ", &
940 if (marked_zones(zone_indices(j)) .eqv. .true.)
then
941 write(error_unit,
'(A, A, I0, A, A, A, A)')
"*** ERROR ***: ", &
942 "Zone with index ", zone_indices(j), &
943 " has already been assigned a boundary condition. ", &
944 "Please check your boundary_conditions entry for the ", &
945 "adjoint and make sure that each zone index appears ", &
946 "only in a single boundary condition."
949 marked_zones(zone_indices(j)) = .true.
954 call velocity_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
958 if (
associated(bc_i))
then
972 call this%bclst_vel_res%append(bc_i)
973 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
974 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
975 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
977 call this%bcs_vel%append(bc_i)
979 call this%bc_sym_surface%mark_facets(bc_i%marked_facet)
980 type is (non_normal_t)
983 call this%bclst_vel_res%append(bc_i)
984 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
985 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
986 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
987 type is (shear_stress_t)
989 call this%bclst_vel_res%append(bc_i%symmetry)
990 call this%bclst_du%append(bc_i%symmetry%bc_x)
991 call this%bclst_dv%append(bc_i%symmetry%bc_y)
992 call this%bclst_dw%append(bc_i%symmetry%bc_z)
994 call this%bcs_vel%append(bc_i)
995 type is (wall_model_bc_t)
997 call this%bclst_vel_res%append(bc_i%symmetry)
998 call this%bclst_du%append(bc_i%symmetry%bc_x)
999 call this%bclst_dv%append(bc_i%symmetry%bc_y)
1000 call this%bclst_dw%append(bc_i%symmetry%bc_z)
1002 call this%bcs_vel%append(bc_i)
1009 if (bc_i%strong .eqv. .true.)
then
1010 call this%bc_vel_res%mark_facets(bc_i%marked_facet)
1011 call this%bc_du%mark_facets(bc_i%marked_facet)
1012 call this%bc_dv%mark_facets(bc_i%marked_facet)
1013 call this%bc_dw%mark_facets(bc_i%marked_facet)
1015 call this%bc_prs_surface%mark_facets(bc_i%marked_facet)
1018 call this%bcs_vel%append(bc_i)
1024 do i = 1,
size(this%msh%labeled_zones)
1025 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
1026 (marked_zones(i) .eqv. .false.))
then
1027 write(error_unit,
'(A, A, I0)')
"*** ERROR ***: ", &
1028 "No adjoint boundary condition assigned to zone ", i
1036 call this%bcs_prs%init(n_bcs)
1040 call json_extract_item(core, bc_object, i, bc_subdict)
1042 call pressure_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1046 if (
associated(bc_i))
then
1047 call this%bcs_prs%append(bc_i)
1050 if (bc_i%strong .eqv. .true.)
then
1051 call this%bc_dp%mark_facets(bc_i%marked_facet)
1059 do i = 1,
size(this%msh%labeled_zones)
1060 if (this%msh%labeled_zones(i)%size .gt. 0)
then
1061 call neko_error(
"No boundary_conditions entry in the case file!")
1067 call this%bc_prs_surface%finalize()
1068 call this%bc_sym_surface%finalize()
1070 call this%bc_vel_res%finalize()
1071 call this%bc_du%finalize()
1072 call this%bc_dv%finalize()
1073 call this%bc_dw%finalize()
1074 call this%bc_dp%finalize()
1076 call this%bclst_vel_res%append(this%bc_vel_res)
1077 call this%bclst_du%append(this%bc_du)
1078 call this%bclst_dv%append(this%bc_dv)
1079 call this%bclst_dw%append(this%bc_dw)
1080 call this%bclst_dp%append(this%bc_dp)
1083 this%prs_dirichlet = .not. this%bclst_dp%is_empty()
1084 call mpi_allreduce(mpi_in_place, this%prs_dirichlet, 1, &
1085 mpi_logical, mpi_lor, neko_comm)
1087 end subroutine adjoint_fluid_pnpn_setup_bcs
1090 subroutine adjoint_fluid_pnpn_write_boundary_conditions(this)
1091 use inflow,
only: inflow_t
1092 use field_dirichlet,
only: field_dirichlet_t
1093 use blasius,
only: blasius_t
1094 use field_dirichlet_vector,
only: field_dirichlet_vector_t
1095 use usr_inflow,
only: usr_inflow_t
1096 use dong_outflow,
only: dong_outflow_t
1097 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1098 type(dirichlet_t) :: bdry_mask
1099 type(field_t),
pointer :: bdry_field
1100 type(file_t) :: bdry_file
1101 integer :: temp_index, i
1102 class(bc_t),
pointer :: bci
1103 character(len=LOG_SIZE) :: log_buf
1105 call neko_log%section(
"Adjoint boundary conditions")
1106 write(log_buf,
'(A)') &
1107 'Marking using integer keys in boundary_adjoint0.f00000'
1108 call neko_log%message(log_buf)
1109 write(log_buf,
'(A)')
'Condition-value pairs: '
1110 call neko_log%message(log_buf)
1111 write(log_buf,
'(A)')
' no_slip = 1'
1112 call neko_log%message(log_buf)
1113 write(log_buf,
'(A)')
' velocity_value = 2'
1114 call neko_log%message(log_buf)
1115 write(log_buf,
'(A)')
' outflow, normal_outflow (+dong) = 3'
1116 call neko_log%message(log_buf)
1117 write(log_buf,
'(A)')
' symmetry = 4'
1118 call neko_log%message(log_buf)
1119 write(log_buf,
'(A)')
' user_velocity_pointwise = 5'
1120 call neko_log%message(log_buf)
1121 write(log_buf,
'(A)')
' periodic = 6'
1122 call neko_log%message(log_buf)
1123 write(log_buf,
'(A)')
' user_velocity = 7'
1124 call neko_log%message(log_buf)
1125 write(log_buf,
'(A)')
' user_pressure = 8'
1126 call neko_log%message(log_buf)
1127 write(log_buf,
'(A)')
' shear_stress = 9'
1128 call neko_log%message(log_buf)
1129 write(log_buf,
'(A)')
' wall_modelling = 10'
1130 call neko_log%message(log_buf)
1131 write(log_buf,
'(A)')
' blasius_profile = 11'
1132 call neko_log%message(log_buf)
1133 call neko_log%end_section()
1135 call this%scratch%request_field(bdry_field, temp_index)
1140 call bdry_mask%init_from_components(this%c_Xh, 6.0_rp)
1141 call bdry_mask%mark_zone(this%msh%periodic)
1142 call bdry_mask%finalize()
1143 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1144 call bdry_mask%free()
1146 do i = 1, this%bcs_prs%size()
1147 bci => this%bcs_prs%get(i)
1148 select type (bc => bci)
1149 type is (zero_dirichlet_t)
1150 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1151 call bdry_mask%mark_facets(bci%marked_facet)
1152 call bdry_mask%finalize()
1153 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1154 call bdry_mask%free()
1155 type is (dong_outflow_t)
1156 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1157 call bdry_mask%mark_facets(bci%marked_facet)
1158 call bdry_mask%finalize()
1159 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1160 call bdry_mask%free()
1161 type is (field_dirichlet_t)
1162 call bdry_mask%init_from_components(this%c_Xh, 8.0_rp)
1163 call bdry_mask%mark_facets(bci%marked_facet)
1164 call bdry_mask%finalize()
1165 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1166 call bdry_mask%free()
1170 do i = 1, this%bcs_vel%size()
1171 bci => this%bcs_vel%get(i)
1172 select type (bc => bci)
1173 type is (zero_dirichlet_t)
1174 call bdry_mask%init_from_components(this%c_Xh, 1.0_rp)
1175 call bdry_mask%mark_facets(bci%marked_facet)
1176 call bdry_mask%finalize()
1177 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1178 call bdry_mask%free()
1180 call bdry_mask%init_from_components(this%c_Xh, 2.0_rp)
1181 call bdry_mask%mark_facets(bci%marked_facet)
1182 call bdry_mask%finalize()
1183 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1184 call bdry_mask%free()
1185 type is (symmetry_t)
1186 call bdry_mask%init_from_components(this%c_Xh, 4.0_rp)
1187 call bdry_mask%mark_facets(bci%marked_facet)
1188 call bdry_mask%finalize()
1189 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1190 call bdry_mask%free()
1191 type is (usr_inflow_t)
1192 call bdry_mask%init_from_components(this%c_Xh, 5.0_rp)
1193 call bdry_mask%mark_facets(bci%marked_facet)
1194 call bdry_mask%finalize()
1195 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1196 call bdry_mask%free()
1197 type is (field_dirichlet_vector_t)
1198 call bdry_mask%init_from_components(this%c_Xh, 7.0_rp)
1199 call bdry_mask%mark_facets(bci%marked_facet)
1200 call bdry_mask%finalize()
1201 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1202 call bdry_mask%free()
1203 type is (shear_stress_t)
1204 call bdry_mask%init_from_components(this%c_Xh, 9.0_rp)
1205 call bdry_mask%mark_facets(bci%marked_facet)
1206 call bdry_mask%finalize()
1207 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1208 call bdry_mask%free()
1209 type is (wall_model_bc_t)
1210 call bdry_mask%init_from_components(this%c_Xh, 10.0_rp)
1211 call bdry_mask%mark_facets(bci%marked_facet)
1212 call bdry_mask%finalize()
1213 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1214 call bdry_mask%free()
1216 call bdry_mask%init_from_components(this%c_Xh, 11.0_rp)
1217 call bdry_mask%mark_facets(bci%marked_facet)
1218 call bdry_mask%finalize()
1219 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1220 call bdry_mask%free()
1225 call bdry_file%init(
'boundary_adjoint.fld')
1226 call bdry_file%write(bdry_field)
1228 call this%scratch%relinquish_field(temp_index)
1229 end subroutine adjoint_fluid_pnpn_write_boundary_conditions
1234 subroutine rescale_fluid(fluid_data, scale)
1236 class(adjoint_fluid_pnpn_t),
intent(inout) :: fluid_data
1238 real(kind=rp),
intent(in) :: scale
1244 if (neko_bcknd_device .eq. 1)
then
1245 call device_cmult(fluid_data%u_adj%x_d, scale, fluid_data%u_adj%size())
1246 call device_cmult(fluid_data%v_adj%x_d, scale, fluid_data%v_adj%size())
1247 call device_cmult(fluid_data%w_adj%x_d, scale, fluid_data%w_adj%size())
1249 call cmult(fluid_data%u_adj%x, scale, fluid_data%u_adj%size())
1250 call cmult(fluid_data%v_adj%x, scale, fluid_data%v_adj%size())
1251 call cmult(fluid_data%w_adj%x, scale, fluid_data%w_adj%size())
1255 if (neko_bcknd_device .eq. 1)
then
1256 call device_cmult(fluid_data%f_adj_x%x_d, scale, &
1257 fluid_data%f_adj_x%size())
1258 call device_cmult(fluid_data%f_adj_y%x_d, scale, &
1259 fluid_data%f_adj_y%size())
1260 call device_cmult(fluid_data%f_adj_z%x_d, scale, &
1261 fluid_data%f_adj_z%size())
1264 call device_cmult(fluid_data%abx1%x_d, scale, fluid_data%abx1%size())
1265 call device_cmult(fluid_data%aby1%x_d, scale, fluid_data%aby1%size())
1266 call device_cmult(fluid_data%abz1%x_d, scale, fluid_data%abz1%size())
1267 call device_cmult(fluid_data%abx2%x_d, scale, fluid_data%abx2%size())
1268 call device_cmult(fluid_data%aby2%x_d, scale, fluid_data%aby2%size())
1269 call device_cmult(fluid_data%abz2%x_d, scale, fluid_data%abz2%size())
1272 call cmult(fluid_data%f_adj_x%x, scale, fluid_data%f_adj_x%size())
1273 call cmult(fluid_data%f_adj_y%x, scale, fluid_data%f_adj_y%size())
1274 call cmult(fluid_data%f_adj_z%x, scale, fluid_data%f_adj_z%size())
1276 call cmult(fluid_data%abx1%x, scale, fluid_data%abx1%size())
1277 call cmult(fluid_data%aby1%x, scale, fluid_data%aby1%size())
1278 call cmult(fluid_data%abz1%x, scale, fluid_data%abz1%size())
1280 call cmult(fluid_data%abx2%x, scale, fluid_data%abx2%size())
1281 call cmult(fluid_data%aby2%x, scale, fluid_data%aby2%size())
1282 call cmult(fluid_data%abz2%x, scale, fluid_data%abz2%size())
1286 if (neko_bcknd_device .eq. 1)
then
1287 do i = 1, fluid_data%ulag%size()
1288 call device_cmult(fluid_data%ulag%lf(i)%x_d, &
1289 scale, fluid_data%ulag%lf(i)%size())
1292 do i = 1, fluid_data%vlag%size()
1293 call device_cmult(fluid_data%vlag%lf(i)%x_d, &
1294 scale, fluid_data%vlag%lf(i)%size())
1297 do i = 1, fluid_data%wlag%size()
1298 call device_cmult(fluid_data%wlag%lf(i)%x_d, &
1299 scale, fluid_data%wlag%lf(i)%size())
1302 do i = 1, fluid_data%ulag%size()
1303 call cmult(fluid_data%ulag%lf(i)%x, &
1304 scale, fluid_data%ulag%lf(i)%size())
1307 do i = 1, fluid_data%vlag%size()
1308 call cmult(fluid_data%vlag%lf(i)%x, &
1309 scale, fluid_data%vlag%lf(i)%size())
1312 do i = 1, fluid_data%wlag%size()
1313 call cmult(fluid_data%wlag%lf(i)%x, &
1314 scale, fluid_data%wlag%lf(i)%size())
1318 end subroutine rescale_fluid
1320 function norm(x, y, z, B, volume, n)
1321 use mpi_f08,
only: mpi_in_place
1323 integer,
intent(in) :: n
1324 real(kind=rp),
dimension(n),
intent(in) :: x, y, z
1325 real(kind=rp),
dimension(n),
intent(in) :: b
1326 real(kind=rp),
intent(in) :: volume
1328 real(kind=rp) :: norm
1330 norm = vlsc3(x, x, b, n) + vlsc3(y, y, b, n) + vlsc3(z, z, b, n)
1332 call mpi_allreduce(mpi_in_place, norm, 1, &
1333 mpi_real_precision, mpi_sum, mpi_comm_world)
1335 norm = sqrt(norm / volume)
1338 function device_norm(x_d, y_d, z_d, B_d, volume, n)
1339 use mpi_f08,
only: mpi_in_place
1341 type(c_ptr),
intent(in) :: x_d, y_d, z_d
1342 type(c_ptr),
intent(in) :: B_d
1343 real(kind=rp),
intent(in) :: volume
1344 integer,
intent(in) :: n
1346 real(kind=rp) :: device_norm
1348 device_norm = device_vlsc3(x_d, x_d, b_d, n) + &
1349 device_vlsc3(y_d, y_d, b_d, n) + &
1350 device_vlsc3(z_d, z_d, b_d, n)
1352 call mpi_allreduce(mpi_in_place, device_norm, 1, &
1353 mpi_real_precision, mpi_sum, mpi_comm_world)
1355 device_norm = sqrt(device_norm / volume)
1357 end function device_norm
1363 subroutine power_iterations_compute(this, t, tstep)
1364 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1365 real(kind=rp),
intent(in) :: t
1366 integer,
intent(in) :: tstep
1369 real(kind=rp) :: scaling_factor
1370 real(kind=rp) :: norm_l2, norm_l2_base
1371 character(len=256) :: log_message
1372 type(vector_t) :: data_line
1375 n = this%c_Xh%dof%size()
1376 if (tstep .eq. 1)
then
1377 if (neko_bcknd_device .eq. 1)
then
1378 norm_l2_base = device_norm(this%u_adj%x_d, this%v_adj%x_d, &
1380 this%c_Xh%B_d, this%c_Xh%volume, n)
1382 norm_l2_base = this%norm_scaling * norm(this%u_adj%x, this%v_adj%x, &
1384 this%c_Xh%B, this%c_Xh%volume, n)
1386 if (this%norm_target .lt. 0.0_rp)
then
1387 this%norm_target = norm_l2_base
1390 this%norm_l2_upper = this%norm_tolerance * this%norm_target
1391 this%norm_l2_lower = this%norm_target / this%norm_tolerance
1396 if (neko_bcknd_device .eq. 1)
then
1397 norm_l2 = device_norm(this%u_adj%x_d, this%v_adj%x_d, this%w_adj%x_d, &
1398 this%c_Xh%B_d, this%c_Xh%volume, n)
1400 norm_l2 = norm(this%u_adj%x, this%v_adj%x, this%w_adj%x, &
1401 this%c_Xh%B, this%c_Xh%volume, n)
1403 norm_l2 = sqrt(this%norm_scaling) * norm_l2
1404 scaling_factor = 1.0_rp
1407 if (norm_l2 .gt. this%norm_l2_upper &
1408 .or. norm_l2 .lt. this%norm_l2_lower)
then
1409 scaling_factor = this%norm_target / norm_l2
1410 call rescale_fluid(this, scaling_factor)
1411 norm_l2 = this%norm_target
1413 if (tstep .eq. 1)
then
1414 scaling_factor = 1.0_rp
1420 call neko_log%section(
'Power Iterations')
1422 write (log_message,
'(A7,E20.14)')
'Norm: ', norm_l2
1423 call neko_log%message(log_message, lvl = neko_log_debug)
1424 write (log_message,
'(A7,E20.14)')
'Scaling: ', scaling_factor
1425 call neko_log%message(log_message, lvl = neko_log_debug)
1428 call data_line%init(2)
1429 data_line%x = [norm_l2, scaling_factor]
1430 call this%file_output%write(data_line, t)
1433 call neko_log%end_section(
'Power Iterations')
1434 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.
Base type of all fluid formulations.
Base abstract type for computing the advection operator.