36 use gather_scatter,
only: gs_t, gs_op_min, gs_op_max
37 use neko_config,
only: neko_bcknd_device
38 use num_types,
only: rp, i8
40 use field,
only: field_t
41 use space,
only: space_t, gll, gl
42 use dofmap,
only: dofmap_t
43 use krylov,
only: ksp_t, krylov_solver_factory, ksp_max_iter
44 use coefs,
only: coef_t
45 use jacobi,
only: jacobi_t
46 use sx_jacobi,
only: sx_jacobi_t
47 use device_jacobi,
only: device_jacobi_t
48 use hsmg,
only: hsmg_t
49 use phmg,
only: phmg_t
50 use precon,
only: pc_t, precon_factory, precon_destroy
51 use fluid_stats,
only: fluid_stats_t
53 use bc_list,
only: bc_list_t
54 use mesh,
only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
55 use operators,
only: cfl
56 use logger,
only: neko_log, log_size, neko_log_verbose
57 use field_registry,
only: neko_field_registry
58 use json_utils,
only: json_get, json_get_or_default
59 use json_module,
only: json_file
60 use scratch_registry,
only: scratch_registry_t
61 use user_intf,
only: user_t, dummy_user_material_properties, &
62 user_material_properties_intf
63 use utils,
only: neko_error
64 use time_state,
only: time_state_t
67 use device_math,
only: device_cfill, device_add2s2
68 use field_math,
only: field_cfill, field_add2s2, field_addcol3
71 use device,
only : device_event_sync, glb_cmd_event, device_to_host, &
81 class(ksp_t),
allocatable :: ksp_vel
82 class(ksp_t),
allocatable :: ksp_prs
83 class(pc_t),
allocatable :: pc_vel
84 class(pc_t),
allocatable :: pc_prs
85 integer :: vel_projection_dim
86 integer :: pr_projection_dim
87 integer :: vel_projection_activ_step
88 integer :: pr_projection_activ_step
89 logical :: strict_convergence
92 type(field_t),
pointer :: u_adj_e => null()
93 type(field_t),
pointer :: v_adj_e => null()
94 type(field_t),
pointer :: w_adj_e => null()
96 type(fluid_stats_t) :: stats
97 logical :: forced_flow_rate = .false.
100 character(len=:),
allocatable :: nut_field_name
103 integer(kind=i8) :: glb_n_points
105 integer(kind=i8) :: glb_unique_points
106 type(scratch_registry_t) :: scratch
109 procedure, pass(this) :: init_base => adjoint_fluid_scheme_init_base
110 procedure, pass(this) :: scheme_free => adjoint_fluid_scheme_free
112 procedure, pass(this) :: validate => adjoint_fluid_scheme_validate
114 procedure, pass(this) :: bc_apply_vel => adjoint_fluid_scheme_bc_apply_vel
116 procedure, pass(this) :: bc_apply_prs => adjoint_fluid_scheme_bc_apply_prs
118 procedure, pass(this) :: compute_cfl => adjoint_compute_cfl
120 procedure, pass(this) :: set_material_properties => &
121 adjoint_fluid_scheme_set_material_properties
124 procedure, pass(this) :: update_material_properties => &
125 adjoint_fluid_scheme_update_material_properties
127 procedure,
nopass :: solver_factory => adjoint_fluid_scheme_solver_factory
129 procedure, pass(this) :: precon_factory_ => &
130 adjoint_fluid_scheme_precon_factory
135 module subroutine adjoint_fluid_scheme_factory(object, type_name)
137 character(len=*) :: type_name
138 end subroutine adjoint_fluid_scheme_factory
141 public :: adjoint_fluid_scheme_incompressible_t, adjoint_fluid_scheme_factory
146 subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, &
148 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
149 type(mesh_t),
target,
intent(inout) :: msh
150 integer,
intent(in) :: lx
151 character(len=*),
intent(in) :: scheme
152 type(json_file),
target,
intent(inout) :: params
153 type(user_t),
target,
intent(in) :: user
154 logical,
intent(in) :: kspv_init
155 character(len=LOG_SIZE) :: log_buf
156 real(kind=rp) :: real_val
157 logical :: logical_val
158 integer :: integer_val
159 character(len=:),
allocatable :: string_val1, string_val2
160 character(len=:),
allocatable :: json_key
161 type(json_file) :: json_subdict
171 lxd = (3 * (lx + 1)) / 2
172 if (msh%gdim .eq. 2)
then
173 call this%Xh%init(gll, lx, lx)
175 call this%Xh%init(gll, lx, lx, lx)
177 call this%Xh_GL%init(gl, lxd, lxd, lxd)
182 call this%dm_Xh%init(msh, this%Xh)
183 call this%dm_Xh_GL%init(msh, this%Xh_GL)
185 call this%gs_Xh%init(this%dm_Xh)
186 call this%gs_Xh_GL%init(this%dm_Xh_GL)
188 call this%c_Xh%init(this%gs_Xh)
189 call this%c_Xh_GL%init(this%gs_Xh_GL)
191 call this%GLL_to_GL%init(this%Xh_GL, this%Xh)
194 call this%scratch_GL%init(this%dm_Xh_GL, 5, 2)
197 call this%scratch%init(this%dm_Xh, 10, 2)
200 call json_get_or_default(params,
'case.fluid.name', this%name,
"fluid")
206 call neko_log%section(
'Adjoint fluid')
207 write(log_buf,
'(A, A)')
'Type : ', trim(scheme)
208 call neko_log%message(log_buf)
209 write(log_buf,
'(A, A)')
'Name : ', trim(this%name)
210 call neko_log%message(log_buf)
213 call neko_field_registry%add_field(this%dm_Xh,
'u_adj')
214 call neko_field_registry%add_field(this%dm_Xh,
'v_adj')
215 call neko_field_registry%add_field(this%dm_Xh,
'w_adj')
216 this%u_adj => neko_field_registry%get_field(
'u_adj')
217 this%v_adj => neko_field_registry%get_field(
'v_adj')
218 this%w_adj => neko_field_registry%get_field(
'w_adj')
223 call this%set_material_properties(params, user)
227 'case.adjoint_fluid.velocity_solver.projection_space_size', &
228 'case.fluid.velocity_solver.projection_space_size')
229 call json_get_or_default(params, json_key, this%vel_projection_dim, 0)
231 'case.adjoint_fluid.pressure_solver.projection_space_size', &
232 'case.fluid.pressure_solver.projection_space_size')
233 call json_get_or_default(params, json_key, this%pr_projection_dim, 0)
236 'case.adjoint_fluid.velocity_solver.projection_hold_steps', &
237 'case.fluid.velocity_solver.projection_hold_steps')
238 call json_get_or_default(params, json_key, &
239 this%vel_projection_activ_step, 5)
241 'case.adjoint_fluid.pressure_solver.projection_hold_steps', &
242 'case.fluid.pressure_solver.projection_hold_steps')
243 call json_get_or_default(params, json_key, &
244 this%pr_projection_activ_step, 5)
248 call json_get_or_default(params, json_key, this%freeze, .false.)
257 if (params%valid_path(
"case.fluid.flow_rate_force"))
then
258 call neko_error(
'Flow rate forcing not yet implemented')
259 this%forced_flow_rate = .true.
264 write(log_buf,
'(A, I1)')
'Poly order : ', lx-1
265 else if (lx .ge. 10)
then
266 write(log_buf,
'(A, I2)')
'Poly order : ', lx-1
268 write(log_buf,
'(A, I3)')
'Poly order : ', lx-1
270 call neko_log%message(log_buf)
271 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
272 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
274 write(log_buf,
'(A, I0)')
'GLL points : ', this%glb_n_points
275 call neko_log%message(log_buf)
276 write(log_buf,
'(A, I0)')
'Unique pts.: ', this%glb_unique_points
277 call neko_log%message(log_buf)
279 call json_get(params,
'case.numerics.dealias', logical_val)
280 write(log_buf,
'(A, L1)')
'Dealias : ', logical_val
281 call neko_log%message(log_buf)
283 call json_get_or_default(params,
'case.output_boundary', logical_val, &
285 write(log_buf,
'(A, L1)')
'Save bdry : ', logical_val
286 call neko_log%message(log_buf)
288 call json_get_or_default(params,
"case.fluid.full_stress_formulation", &
289 logical_val, .false.)
290 write(log_buf,
'(A, L1)')
'Full stress: ', logical_val
291 call neko_log%message(log_buf)
296 allocate(this%f_adj_x)
297 allocate(this%f_adj_y)
298 allocate(this%f_adj_z)
299 call this%f_adj_x%init(this%dm_Xh, fld_name =
"adjoint_rhs_x")
300 call this%f_adj_y%init(this%dm_Xh, fld_name =
"adjoint_rhs_y")
301 call this%f_adj_z%init(this%dm_Xh, fld_name =
"adjoint_rhs_z")
321 call neko_log%section(
"Adjoint Velocity solver")
324 'case.adjoint_fluid.velocity_solver.max_iterations', &
325 'case.fluid.velocity_solver.max_iterations')
326 call json_get_or_default(params, json_key, integer_val, ksp_max_iter)
329 'case.adjoint_fluid.velocity_solver.type', &
330 'case.fluid.velocity_solver.type')
331 call json_get(params, json_key, string_val1)
334 'case.adjoint_fluid.velocity_solver.preconditioner.type', &
335 'case.fluid.velocity_solver.preconditioner.type')
336 call json_get(params, json_key, string_val2)
339 'case.adjoint_fluid.velocity_solver.preconditioner', &
340 'case.fluid.velocity_solver.preconditioner')
341 call json_get(params, json_key, json_subdict)
344 'case.adjoint_fluid.velocity_solver.absolute_tolerance', &
345 'case.fluid.velocity_solver.absolute_tolerance')
346 call json_get(params, json_key, real_val)
349 'case.adjoint_fluid.velocity_solver.monitor', &
350 'case.fluid.velocity_solver.monitor')
351 call json_get_or_default(params, json_key, logical_val, .false.)
353 call neko_log%message(
'Type : (' // trim(string_val1) // &
354 ', ' // trim(string_val2) //
')')
356 write(log_buf,
'(A,ES13.6)')
'Abs tol :', real_val
357 call neko_log%message(log_buf)
358 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
359 string_val1, integer_val, real_val, logical_val)
360 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
361 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_vel, &
362 string_val2, json_subdict)
363 call neko_log%end_section()
367 call json_get_or_default(params,
'case.fluid.strict_convergence', &
368 this%strict_convergence, .false.)
371 call this%ulag%init(this%u_adj, 2)
372 call this%vlag%init(this%v_adj, 2)
373 call this%wlag%init(this%w_adj, 2)
375 call neko_field_registry%add_field(this%dm_Xh,
'u_adj_e')
376 call neko_field_registry%add_field(this%dm_Xh,
'v_adj_e')
377 call neko_field_registry%add_field(this%dm_Xh,
'w_adj_e')
378 this%u_adj_e => neko_field_registry%get_field(
'u_adj_e')
379 this%v_adj_e => neko_field_registry%get_field(
'v_adj_e')
380 this%w_adj_e => neko_field_registry%get_field(
'w_adj_e')
383 call this%source_term%init(this%f_adj_x, this%f_adj_y, this%f_adj_z, &
384 this%c_Xh, user, this%name)
385 call this%source_term%add(params,
'case.adjoint_fluid.source_term')
387 call neko_log%end_section()
389 end subroutine adjoint_fluid_scheme_init_base
392 subroutine adjoint_fluid_scheme_free(this)
393 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
397 if (
allocated(this%ksp_vel))
then
398 call this%ksp_vel%free()
399 deallocate(this%ksp_vel)
402 if (
allocated(this%ksp_prs))
then
403 call this%ksp_prs%free()
404 deallocate(this%ksp_prs)
407 if (
allocated(this%pc_vel))
then
408 call precon_destroy(this%pc_vel)
409 deallocate(this%pc_vel)
412 if (
allocated(this%pc_prs))
then
413 call precon_destroy(this%pc_prs)
414 deallocate(this%pc_prs)
417 call this%source_term%free()
419 call this%gs_Xh%free()
421 call this%c_Xh%free()
423 call this%scratch%free()
424 call this%scratch_GL%free()
431 nullify(this%u_adj_e)
432 nullify(this%v_adj_e)
433 nullify(this%w_adj_e)
435 call this%ulag%free()
436 call this%vlag%free()
437 call this%wlag%free()
440 if (
associated(this%f_adj_x))
then
441 call this%f_adj_x%free()
444 if (
associated(this%f_adj_y))
then
445 call this%f_adj_y%free()
448 if (
associated(this%f_adj_z))
then
449 call this%f_adj_z%free()
452 nullify(this%f_adj_x)
453 nullify(this%f_adj_y)
454 nullify(this%f_adj_z)
459 end subroutine adjoint_fluid_scheme_free
463 subroutine adjoint_fluid_scheme_validate(this)
464 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
467 if ((.not.
associated(this%u_adj)) .or. &
468 (.not.
associated(this%v_adj)) .or. &
469 (.not.
associated(this%w_adj)) .or. &
470 (.not.
associated(this%p_adj)))
then
471 call neko_error(
'Fields are not registered')
474 if ((.not.
allocated(this%u_adj%x)) .or. &
475 (.not.
allocated(this%v_adj%x)) .or. &
476 (.not.
allocated(this%w_adj%x)) .or. &
477 (.not.
allocated(this%p_adj%x)))
then
478 call neko_error(
'Fields are not allocated')
481 if (.not.
allocated(this%ksp_vel))
then
482 call neko_error(
'No Krylov solver for velocity defined')
485 if (.not.
allocated(this%ksp_prs))
then
486 call neko_error(
'No Krylov solver for pressure defined')
492 call this%chkp%init(this%u_adj, this%v_adj, this%w_adj, this%p_adj)
494 end subroutine adjoint_fluid_scheme_validate
500 subroutine adjoint_fluid_scheme_bc_apply_vel(this, time, strong)
501 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
502 type(time_state_t),
intent(in) :: time
503 logical,
intent(in) :: strong
506 class(bc_t),
pointer :: b => null()
508 call this%bcs_vel%apply_vector(&
509 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
511 call this%gs_Xh%op(this%u_adj, gs_op_min, glb_cmd_event)
512 call this%gs_Xh%op(this%v_adj, gs_op_min, glb_cmd_event)
513 call this%gs_Xh%op(this%w_adj, gs_op_min, glb_cmd_event)
514 call device_event_sync(glb_cmd_event)
516 call this%bcs_vel%apply_vector(&
517 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
519 call this%gs_Xh%op(this%u_adj, gs_op_max, glb_cmd_event)
520 call this%gs_Xh%op(this%v_adj, gs_op_max, glb_cmd_event)
521 call this%gs_Xh%op(this%w_adj, gs_op_max, glb_cmd_event)
522 call device_event_sync(glb_cmd_event)
524 do i = 1, this%bcs_vel%size()
525 b => this%bcs_vel%get(i)
531 end subroutine adjoint_fluid_scheme_bc_apply_vel
535 subroutine adjoint_fluid_scheme_bc_apply_prs(this, time)
536 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
537 type(time_state_t),
intent(in) :: time
540 class(bc_t),
pointer :: b => null()
542 call this%bcs_prs%apply(this%p_adj, time)
543 call this%gs_Xh%op(this%p_adj, gs_op_min, glb_cmd_event)
544 call device_event_sync(glb_cmd_event)
546 call this%bcs_prs%apply(this%p_adj, time)
547 call this%gs_Xh%op(this%p_adj, gs_op_max, glb_cmd_event)
548 call device_event_sync(glb_cmd_event)
550 do i = 1, this%bcs_prs%size()
551 b => this%bcs_prs%get(i)
556 end subroutine adjoint_fluid_scheme_bc_apply_prs
560 subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, &
561 max_iter, abstol, monitor)
562 class(ksp_t),
allocatable,
target,
intent(inout) :: ksp
563 integer,
intent(in),
value :: n
564 character(len=*),
intent(in) :: solver
565 integer,
intent(in) :: max_iter
566 real(kind=rp),
intent(in) :: abstol
567 logical,
intent(in) :: monitor
569 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
572 end subroutine adjoint_fluid_scheme_solver_factory
575 subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, dof, gs, &
576 bclst, pctype, pcparams)
577 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
578 class(pc_t),
allocatable,
target,
intent(inout) :: pc
579 class(ksp_t),
target,
intent(inout) :: ksp
580 type(coef_t),
target,
intent(in) :: coef
581 type(dofmap_t),
target,
intent(in) :: dof
582 type(gs_t),
target,
intent(inout) :: gs
583 type(bc_list_t),
target,
intent(inout) :: bclst
584 character(len=*) :: pctype
585 type(json_file),
intent(inout) :: pcparams
587 call precon_factory(pc, pctype)
589 select type (pcp => pc)
591 call pcp%init(coef, dof, gs)
592 type is (sx_jacobi_t)
593 call pcp%init(coef, dof, gs)
594 type is (device_jacobi_t)
595 call pcp%init(coef, dof, gs)
597 call pcp%init(coef, bclst, pcparams)
599 call pcp%init(coef, bclst, pcparams)
604 end subroutine adjoint_fluid_scheme_precon_factory
623 function adjoint_compute_cfl(this, dt)
result(c)
624 class(adjoint_fluid_scheme_incompressible_t),
intent(in) :: this
625 real(kind=rp),
intent(in) :: dt
628 c = cfl(dt, this%u_adj%x, this%v_adj%x, this%w_adj%x, &
629 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
631 end function adjoint_compute_cfl
637 subroutine adjoint_fluid_scheme_update_material_properties(this, time)
638 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
639 type(time_state_t),
intent(in) :: time
640 type(field_t),
pointer :: nut
642 call this%user_material_properties(this%name, &
643 this%material_properties, time)
645 if (len(trim(this%nut_field_name)) > 0)
then
646 nut => neko_field_registry%get_field(this%nut_field_name)
647 call field_addcol3(this%mu, nut, this%rho)
654 if (neko_bcknd_device .eq. 1)
then
655 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
656 device_to_host, sync=.false.)
657 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
658 device_to_host, sync=.false.)
660 end subroutine adjoint_fluid_scheme_update_material_properties
666 subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
667 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
668 type(json_file),
intent(inout) :: params
669 type(user_t),
target,
intent(in) :: user
670 character(len=LOG_SIZE) :: log_buf
672 procedure(user_material_properties_intf),
pointer :: dummy_mp_ptr
673 real(kind=rp) :: const_mu, const_rho
674 type(time_state_t) :: time
677 dummy_mp_ptr => dummy_user_material_properties
679 call this%mu%init(this%dm_Xh,
"mu")
680 call this%rho%init(this%dm_Xh,
"rho")
681 call this%material_properties%init(2)
682 call this%material_properties%assign_to_field(1, this%rho)
683 call this%material_properties%assign_to_field(2, this%mu)
685 if (.not.
associated(user%material_properties, dummy_mp_ptr))
then
687 write(log_buf,
'(A)')
"Material properties must be set in the user&
689 call neko_log%message(log_buf)
690 this%user_material_properties => user%material_properties
692 call user%material_properties(this%name, &
693 this%material_properties, time)
696 this%user_material_properties => dummy_user_material_properties
698 if (params%valid_path(
'case.fluid.Re') .and. &
699 (params%valid_path(
'case.fluid.mu') .or. &
700 params%valid_path(
'case.fluid.rho')))
then
701 call neko_error(
"To set the material properties for the fluid, " // &
702 "either provide Re OR mu and rho in the case file.")
704 else if (params%valid_path(
'case.fluid.Re'))
then
706 write(log_buf,
'(A)')
'Non-dimensional fluid material properties &
708 call neko_log%message(log_buf, lvl = neko_log_verbose)
709 write(log_buf,
'(A)')
'Density will be set to 1, dynamic viscosity to&
711 call neko_log%message(log_buf, lvl = neko_log_verbose)
714 call json_get(params,
'case.fluid.Re', const_mu)
715 write(log_buf,
'(A)')
'Read non-dimensional material properties'
716 call neko_log%message(log_buf)
717 write(log_buf,
'(A,ES13.6)')
'Re :', const_mu
718 call neko_log%message(log_buf)
723 const_mu = 1.0_rp/const_mu
726 call json_get(params,
'case.fluid.mu', const_mu)
727 call json_get(params,
'case.fluid.rho', const_rho)
733 if (
associated(user%material_properties, dummy_mp_ptr))
then
735 call field_cfill(this%mu, const_mu)
736 call field_cfill(this%rho, const_rho)
739 write(log_buf,
'(A,ES13.6)')
'rho :', const_rho
740 call neko_log%message(log_buf)
741 write(log_buf,
'(A,ES13.6)')
'mu :', const_mu
742 call neko_log%message(log_buf)
749 if (neko_bcknd_device .eq. 1)
then
750 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
751 device_to_host, sync=.false.)
752 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
753 device_to_host, sync=.false.)
755 end subroutine adjoint_fluid_scheme_set_material_properties
Implements the adjoint_source_term_t type.
Base type of all fluid formulations.
Base type of all fluid formulations.
Wrapper contaning and executing the adjoint source terms.