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
50 use device_mathops,
only: device_opcolv, device_opadd2cm
51 use fluid_aux,
only: fluid_step_info
52 use time_scheme_controller,
only: time_scheme_controller_t
53 use projection,
only: projection_t
54 use device,
only : device_memcpy, host_to_device, device_event_sync,&
55 device_event_create, device_event_destroy, device_stream_wait_event, &
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 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, opcolv
77 use bc_list,
only: bc_list_t
78 use zero_dirichlet,
only: zero_dirichlet_t
79 use utils,
only: neko_error, neko_type_error
80 use field_math,
only: field_add2, field_copy
82 use file,
only: file_t
83 use operators,
only: ortho
84 use vector,
only: vector_t
85 use device_math,
only: device_vlsc3, device_cmult
86 use math,
only: vlsc3, cmult
87 use json_utils_ext,
only: json_key_fallback
88 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_associated
89 use comm,
only: neko_comm, mpi_real_precision
90 use mpi_f08,
only: mpi_sum, mpi_max, mpi_allreduce, mpi_comm_world, &
91 mpi_integer, mpi_logical, mpi_lor
100 type(field_t) :: p_res, u_res, v_res, w_res
104 type(field_t) :: dp, du, dv, dw
106 type(field_t),
pointer :: u_b => null()
107 type(field_t),
pointer :: v_b => null()
108 type(field_t),
pointer :: w_b => null()
109 type(field_t),
pointer :: p_b => null()
116 class(ax_t),
allocatable :: ax_vel
118 class(ax_t),
allocatable :: ax_prs
125 type(projection_t) :: proj_prs
127 type(projection_t) :: proj_u
129 type(projection_t) :: proj_v
131 type(projection_t) :: proj_w
138 type(facet_normal_t) :: bc_prs_surface
141 type(facet_normal_t) :: bc_sym_surface
148 type(zero_dirichlet_t) :: bc_vel_res
150 type(zero_dirichlet_t) :: bc_du
152 type(zero_dirichlet_t) :: bc_dv
154 type(zero_dirichlet_t) :: bc_dw
156 type(zero_dirichlet_t) :: bc_dp
159 type(bc_list_t) :: bclst_vel_res
160 type(bc_list_t) :: bclst_du
161 type(bc_list_t) :: bclst_dv
162 type(bc_list_t) :: bclst_dw
163 type(bc_list_t) :: bclst_dp
168 logical :: prs_dirichlet = .false.
178 type(field_t) :: abx1, aby1, abz1
179 type(field_t) :: abx2, aby2, abz2
182 type(field_t) :: advx, advy, advz
185 class(pnpn_prs_res_t),
allocatable :: prs_res
188 class(pnpn_vel_res_t),
allocatable :: vel_res
191 class(rhs_maker_sumab_t),
allocatable :: sumab
194 class(rhs_maker_ext_t),
allocatable :: makeabf
197 class(rhs_maker_bdf_t),
allocatable :: makebdf
200 class(rhs_maker_oifs_t),
allocatable :: makeoifs
205 type(c_ptr) :: event = c_null_ptr
210 real(kind=rp) :: norm_scaling
211 real(kind=rp) :: norm_target
212 real(kind=rp) :: norm_tolerance
218 real(kind=rp) :: norm_l2_base
221 real(kind=rp) :: norm_l2_upper
223 real(kind=rp) :: norm_l2_lower
226 type(file_t) :: file_output
230 procedure, pass(this) :: init => adjoint_fluid_pnpn_init
232 procedure, pass(this) :: free => adjoint_fluid_pnpn_free
234 procedure, pass(this) :: step => adjoint_fluid_pnpn_step
236 procedure, pass(this) :: restart => adjoint_fluid_pnpn_restart
238 procedure, pass(this) :: setup_bcs => adjoint_fluid_pnpn_setup_bcs
240 procedure, pass(this) :: write_boundary_conditions => &
241 adjoint_fluid_pnpn_write_boundary_conditions
244 procedure,
public, pass(this) :: pw_compute_ => power_iterations_compute
256 module subroutine pressure_bc_factory(object, scheme, json, coef, user)
257 class(bc_t),
pointer,
intent(inout) :: object
258 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
259 type(json_file),
intent(inout) :: json
260 type(coef_t),
intent(in) :: coef
261 type(user_t),
intent(in) :: user
262 end subroutine pressure_bc_factory
263 end interface pressure_bc_factory
272 interface velocity_bc_factory
273 module subroutine velocity_bc_factory(object, scheme, json, coef, user)
274 class(bc_t),
pointer,
intent(inout) :: object
275 type(adjoint_fluid_pnpn_t),
intent(in) :: scheme
276 type(json_file),
intent(inout) :: json
277 type(coef_t),
intent(in) :: coef
278 type(user_t),
intent(in) :: user
279 end subroutine velocity_bc_factory
280 end interface velocity_bc_factory
284 subroutine adjoint_fluid_pnpn_init(this, msh, lx, params, user, time_scheme)
285 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
286 type(mesh_t),
target,
intent(inout) :: msh
287 integer,
intent(in) :: lx
288 type(json_file),
target,
intent(inout) :: params
289 type(user_t),
target,
intent(in) :: user
290 type(time_scheme_controller_t),
target,
intent(in) :: time_scheme
291 character(len=15),
parameter :: scheme =
'Adjoint (Pn/Pn)'
292 real(kind=rp) :: abs_tol
293 character(len=LOG_SIZE) :: log_buf
294 integer :: solver_maxiter
295 character(len=:),
allocatable :: solver_type, precon_type
296 logical :: monitor, found
298 type(json_file) :: precon_params
301 character(len=:),
allocatable :: file_name
302 character(len=256) :: header_line
307 call this%init_base(msh, lx, params, scheme, user, .true.)
311 call neko_field_registry%add_field(this%dm_Xh,
'p_adj')
312 this%p_adj => neko_field_registry%get_field(
'p_adj')
318 if (this%variable_material_properties .eqv. .true.)
then
320 call ax_helm_factory(this%Ax_vel, full_formulation = .true.)
323 call pnpn_prs_res_stress_factory(this%prs_res)
326 call pnpn_vel_res_stress_factory(this%vel_res)
329 call ax_helm_factory(this%Ax_vel, full_formulation = .false.)
332 call pnpn_prs_res_factory(this%prs_res)
335 call pnpn_vel_res_factory(this%vel_res)
339 call ax_helm_factory(this%Ax_prs, full_formulation = .false.)
343 call rhs_maker_sumab_fctry(this%sumab)
346 call rhs_maker_ext_fctry(this%makeabf)
349 call rhs_maker_bdf_fctry(this%makebdf)
352 call rhs_maker_oifs_fctry(this%makeoifs)
355 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
356 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
358 call this%p_res%init(dm_xh,
"p_res")
359 call this%u_res%init(dm_xh,
"u_res")
360 call this%v_res%init(dm_xh,
"v_res")
361 call this%w_res%init(dm_xh,
"w_res")
362 call this%abx1%init(dm_xh,
"abx1")
363 call this%aby1%init(dm_xh,
"aby1")
364 call this%abz1%init(dm_xh,
"abz1")
365 call this%abx2%init(dm_xh,
"abx2")
366 call this%aby2%init(dm_xh,
"aby2")
367 call this%abz2%init(dm_xh,
"abz2")
368 call this%advx%init(dm_xh,
"advx")
369 call this%advy%init(dm_xh,
"advy")
370 call this%advz%init(dm_xh,
"advz")
373 call this%du%init(this%dm_Xh,
'du')
374 call this%dv%init(this%dm_Xh,
'dv')
375 call this%dw%init(this%dm_Xh,
'dw')
376 call this%dp%init(this%dm_Xh,
'dp')
379 call this%setup_bcs(user, params)
382 call json_get_or_default(params,
'case.output_boundary', found, .false.)
383 if (found)
call this%write_boundary_conditions()
386 if (this%variable_material_properties .and. &
387 this%vel_projection_dim .gt. 0)
then
388 call neko_error(
"Velocity projection not available for full stress &
393 call this%proj_prs%init(this%dm_Xh%size(), this%pr_projection_dim, &
394 this%pr_projection_activ_step)
396 call this%proj_u%init(this%dm_Xh%size(), this%vel_projection_dim, &
397 this%vel_projection_activ_step)
398 call this%proj_v%init(this%dm_Xh%size(), this%vel_projection_dim, &
399 this%vel_projection_activ_step)
400 call this%proj_w%init(this%dm_Xh%size(), this%vel_projection_dim, &
401 this%vel_projection_activ_step)
405 call this%chkp%add_lag(this%ulag, this%vlag, this%wlag)
408 call json_get_or_default(params,
'case.numerics.oifs', this%oifs, .false.)
411 call json_get_or_default(params,
'case.fluid.advection', advection, .true.)
414 call advection_adjoint_factory(this%adv, params, this%c_Xh)
416 if (params%valid_path(
'case.fluid.flow_rate_force'))
then
417 call neko_error(
"Flow rate forcing not available for adjoint_fluid_pnpn")
422 call neko_log%section(
"Pressure solver")
424 call json_get_or_default(params, &
425 'case.fluid.pressure_solver.max_iterations', &
427 call json_get(params,
'case.fluid.pressure_solver.type', solver_type)
428 call json_get(params,
'case.fluid.pressure_solver.preconditioner.type', &
430 call json_extract_object(params, &
431 'case.fluid.pressure_solver.preconditioner', precon_params)
432 call json_get(params,
'case.fluid.pressure_solver.absolute_tolerance', &
434 call json_get_or_default(params,
'case.fluid.velocity_solver.monitor', &
436 call neko_log%message(
'Type : ('// trim(solver_type) // &
437 ', ' // trim(precon_type) //
')')
438 write(log_buf,
'(A,ES13.6)')
'Abs tol :', abs_tol
439 call neko_log%message(log_buf)
441 call this%solver_factory(this%ksp_prs, this%dm_Xh%size(), &
442 solver_type, solver_maxiter, abs_tol, monitor)
443 call this%precon_factory_(this%pc_prs, this%ksp_prs, &
444 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_prs, &
445 precon_type, precon_params)
447 call neko_log%end_section()
450 if (neko_bcknd_device .eq. 1)
then
451 call device_event_create(this%event, 2)
458 call json_get_or_default(params,
'norm_scaling', &
459 this%norm_scaling, 0.5_rp)
467 this%u_b => neko_field_registry%get_field(
'u')
468 this%v_b => neko_field_registry%get_field(
'v')
469 this%w_b => neko_field_registry%get_field(
'w')
470 this%p_b => neko_field_registry%get_field(
'p')
473 call json_get_or_default(params,
'norm_target', &
474 this%norm_target, -1.0_rp)
475 call json_get_or_default(params,
'norm_tolerance', &
476 this%norm_tolerance, 10.0_rp)
479 call json_get_or_default(params,
'output_file', &
480 file_name,
'power_iterations.csv')
481 this%file_output = file_t(trim(file_name))
482 write(header_line,
'(A)')
'Time, Norm, Scaling'
483 call this%file_output%set_header(header_line)
485 end subroutine adjoint_fluid_pnpn_init
487 subroutine adjoint_fluid_pnpn_restart(this, dtlag, tlag)
488 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
489 real(kind=rp) :: dtlag(10), tlag(10)
492 n = this%u_adj%dof%size()
493 if (
allocated(this%chkp%previous_mesh%elements) .or. &
494 this%chkp%previous_Xh%lx .ne. this%Xh%lx)
then
495 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
496 p => this%p_adj, c_xh => this%c_Xh, ulag => this%ulag, &
497 vlag => this%vlag, wlag => this%wlag)
498 do concurrent(j = 1:n)
499 u%x(j,1,1,1) = u%x(j,1,1,1) * c_xh%mult(j,1,1,1)
500 v%x(j,1,1,1) = v%x(j,1,1,1) * c_xh%mult(j,1,1,1)
501 w%x(j,1,1,1) = w%x(j,1,1,1) * c_xh%mult(j,1,1,1)
502 p%x(j,1,1,1) = p%x(j,1,1,1) * c_xh%mult(j,1,1,1)
504 do i = 1, this%ulag%size()
505 do concurrent(j = 1:n)
506 ulag%lf(i)%x(j,1,1,1) = ulag%lf(i)%x(j,1,1,1) &
508 vlag%lf(i)%x(j,1,1,1) = vlag%lf(i)%x(j,1,1,1) &
510 wlag%lf(i)%x(j,1,1,1) = wlag%lf(i)%x(j,1,1,1) &
517 if (neko_bcknd_device .eq. 1)
then
518 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
519 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag,&
521 call device_memcpy(u%x, u%x_d, u%dof%size(), &
522 host_to_device, sync = .false.)
523 call device_memcpy(v%x, v%x_d, v%dof%size(), &
524 host_to_device, sync = .false.)
525 call device_memcpy(w%x, w%x_d, w%dof%size(), &
526 host_to_device, sync = .false.)
527 call device_memcpy(p%x, p%x_d, p%dof%size(), &
528 host_to_device, sync = .false.)
529 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, &
530 u%dof%size(), host_to_device, sync = .false.)
531 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, &
532 u%dof%size(), host_to_device, sync = .false.)
534 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, &
535 v%dof%size(), host_to_device, sync = .false.)
536 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, &
537 v%dof%size(), host_to_device, sync = .false.)
539 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, &
540 w%dof%size(), host_to_device, sync = .false.)
541 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, &
542 w%dof%size(), host_to_device, sync = .false.)
543 call device_memcpy(this%abx1%x, this%abx1%x_d, &
544 w%dof%size(), host_to_device, sync = .false.)
545 call device_memcpy(this%abx2%x, this%abx2%x_d, &
546 w%dof%size(), host_to_device, sync = .false.)
547 call device_memcpy(this%aby1%x, this%aby1%x_d, &
548 w%dof%size(), host_to_device, sync = .false.)
549 call device_memcpy(this%aby2%x, this%aby2%x_d, &
550 w%dof%size(), host_to_device, sync = .false.)
551 call device_memcpy(this%abz1%x, this%abz1%x_d, &
552 w%dof%size(), host_to_device, sync = .false.)
553 call device_memcpy(this%abz2%x, this%abz2%x_d, &
554 w%dof%size(), host_to_device, sync = .false.)
555 call device_memcpy(this%advx%x, this%advx%x_d, &
556 w%dof%size(), host_to_device, sync = .false.)
557 call device_memcpy(this%advy%x, this%advy%x_d, &
558 w%dof%size(), host_to_device, sync = .false.)
559 call device_memcpy(this%advz%x, this%advz%x_d, &
560 w%dof%size(), host_to_device, sync = .false.)
568 if (
allocated(this%chkp%previous_mesh%elements) &
569 .or. this%chkp%previous_Xh%lx .ne. this%Xh%lx)
then
570 call this%gs_Xh%op(this%u_adj, gs_op_add)
571 call this%gs_Xh%op(this%v_adj, gs_op_add)
572 call this%gs_Xh%op(this%w_adj, gs_op_add)
573 call this%gs_Xh%op(this%p_adj, gs_op_add)
575 do i = 1, this%ulag%size()
576 call this%gs_Xh%op(this%ulag%lf(i), gs_op_add)
577 call this%gs_Xh%op(this%vlag%lf(i), gs_op_add)
578 call this%gs_Xh%op(this%wlag%lf(i), gs_op_add)
638 end subroutine adjoint_fluid_pnpn_restart
640 subroutine adjoint_fluid_pnpn_free(this)
641 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
644 call this%scheme_free()
646 call this%bc_prs_surface%free()
647 call this%bc_sym_surface%free()
648 call this%bclst_vel_res%free()
649 call this%bclst_dp%free()
650 call this%proj_prs%free()
651 call this%proj_u%free()
652 call this%proj_v%free()
653 call this%proj_w%free()
655 call this%p_res%free()
656 call this%u_res%free()
657 call this%v_res%free()
658 call this%w_res%free()
665 call this%abx1%free()
666 call this%aby1%free()
667 call this%abz1%free()
669 call this%abx2%free()
670 call this%aby2%free()
671 call this%abz2%free()
673 call this%advx%free()
674 call this%advy%free()
675 call this%advz%free()
677 if (
allocated(this%Ax_vel))
then
678 deallocate(this%Ax_vel)
681 if (
allocated(this%Ax_prs))
then
682 deallocate(this%Ax_prs)
685 if (
allocated(this%prs_res))
then
686 deallocate(this%prs_res)
689 if (
allocated(this%vel_res))
then
690 deallocate(this%vel_res)
693 if (
allocated(this%sumab))
then
694 deallocate(this%sumab)
697 if (
allocated(this%makeabf))
then
698 deallocate(this%makeabf)
701 if (
allocated(this%makebdf))
then
702 deallocate(this%makebdf)
705 if (
allocated(this%makeoifs))
then
706 deallocate(this%makeoifs)
710 if (neko_bcknd_device .eq. 1)
then
711 if (c_associated(this%event))
then
712 call device_event_destroy(this%event)
716 end subroutine adjoint_fluid_pnpn_free
725 subroutine adjoint_fluid_pnpn_step(this, t, tstep, dt, ext_bdf, dt_controller)
726 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
727 real(kind=rp),
intent(in) :: t
728 integer,
intent(in) :: tstep
729 real(kind=rp),
intent(in) :: dt
730 type(time_scheme_controller_t),
intent(in) :: ext_bdf
731 type(time_step_controller_t),
intent(in) :: dt_controller
735 type(ksp_monitor_t) :: ksp_results(4)
737 type(field_t),
pointer :: u_e, v_e, w_e
739 integer :: temp_indices(3)
741 if (this%freeze)
return
743 n = this%dm_Xh%size()
745 call profiler_start_region(
'Adjoint', 1)
746 associate(u => this%u_adj, v => this%v_adj, w => this%w_adj, &
748 du => this%du, dv => this%dv, dw => this%dw, dp => this%dp, &
749 u_b => this%u_b, v_b => this%v_b, w_b => this%w_b, &
750 u_res => this%u_res, v_res => this%v_res, w_res => this%w_res, &
751 p_res => this%p_res, ax_vel => this%Ax_vel, ax_prs => this%Ax_prs, &
753 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
754 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
755 msh => this%msh, prs_res => this%prs_res, &
756 source_term => this%source_term, &
757 vel_res => this%vel_res, sumab => this%sumab, &
758 makeabf => this%makeabf, makebdf => this%makebdf, &
759 vel_projection_dim => this%vel_projection_dim, &
760 pr_projection_dim => this%pr_projection_dim, &
761 rho => this%rho, mu => this%mu, oifs => this%oifs, &
762 rho_field => this%rho, mu_field => this%mu, &
763 f_x => this%f_adj_x, f_y => this%f_adj_y, f_z => this%f_adj_z, &
764 if_variable_dt => dt_controller%if_variable_dt, &
765 dt_last_change => dt_controller%dt_last_change, &
769 call this%scratch%request_field(u_e, temp_indices(1))
770 call this%scratch%request_field(v_e, temp_indices(2))
771 call this%scratch%request_field(w_e, temp_indices(3))
772 call sumab%compute_fluid(u_e, v_e, w_e, u, v, w, &
773 ulag, vlag, wlag, ext_bdf%advection_coeffs, ext_bdf%nadv)
776 call this%source_term%compute(t, tstep)
779 call this%bcs_vel%apply_vector(f_x%x, f_y%x, f_z%x, &
780 this%dm_Xh%size(), t, tstep, strong = .false.)
783 call neko_error(
"OIFS not implemented for adjoint")
804 call this%adv%compute_adjoint(u, v, w, u_b, v_b, w_b, &
806 xh, this%c_Xh, dm_xh%size())
812 call makeabf%compute_fluid(this%abx1, this%aby1, this%abz1,&
813 this%abx2, this%aby2, this%abz2, &
814 f_x%x, f_y%x, f_z%x, &
815 rho%x(1,1,1,1), ext_bdf%advection_coeffs, n)
818 call makebdf%compute_fluid(ulag, vlag, wlag, f_x%x, f_y%x, f_z%x, &
819 u, v, w, c_xh%B, rho%x(1,1,1,1), dt, &
820 ext_bdf%diffusion_coeffs, ext_bdf%ndiff, n)
827 call this%bc_apply_vel(t, tstep, strong = .true.)
828 call this%bc_apply_prs(t, tstep)
831 call this%update_material_properties(t, tstep)
834 call profiler_start_region(
'Pressure_residual', 18)
836 call prs_res%compute(p, p_res, &
841 this%bc_prs_surface, this%bc_sym_surface, &
842 ax_prs, ext_bdf%diffusion_coeffs(1), dt, &
843 mu_field, rho_field, event)
846 if (.not. this%prs_dirichlet)
call ortho(p_res%x, this%glb_n_points, n)
848 call gs_xh%op(p_res, gs_op_add, event)
849 if (neko_bcknd_device .eq. 1)
then
850 call device_stream_wait_event(glb_cmd_queue, event, 0)
854 call this%bclst_dp%apply_scalar(p_res%x, p%dof%size(), t, tstep)
857 call profiler_end_region(
'Pressure_residual', 18)
860 call this%proj_prs%pre_solving(p_res%x, tstep, c_xh, n, dt_controller, &
863 call this%pc_prs%update()
865 call profiler_start_region(
'Pressure_solve', 3)
868 ksp_results(1) = this%ksp_prs%solve(ax_prs, dp, p_res%x, n, c_xh, &
869 this%bclst_dp, gs_xh)
872 call profiler_end_region(
'Pressure_solve', 3)
874 call this%proj_prs%post_solving(dp%x, ax_prs, c_xh, &
875 this%bclst_dp, gs_xh, n, tstep, dt_controller)
878 call field_add2(p, dp, n)
879 if (.not. this%prs_dirichlet)
call ortho(p%x, this%glb_n_points, n)
882 call profiler_start_region(
'Velocity_residual', 19)
883 call vel_res%compute(ax_vel, u, v, w, &
884 u_res, v_res, w_res, &
888 mu_field, rho_field, ext_bdf%diffusion_coeffs(1), &
891 call gs_xh%op(u_res, gs_op_add, event)
892 call gs_xh%op(v_res, gs_op_add, event)
893 call gs_xh%op(w_res, gs_op_add, event)
894 if (neko_bcknd_device .eq. 1)
then
895 call device_stream_wait_event(glb_cmd_queue, event, 0)
899 call this%bclst_vel_res%apply(u_res, v_res, w_res, t, tstep)
902 call profiler_end_region(
'Velocity_residual', 19)
904 call this%proj_u%pre_solving(u_res%x, tstep, c_xh, n, dt_controller)
905 call this%proj_v%pre_solving(v_res%x, tstep, c_xh, n, dt_controller)
906 call this%proj_w%pre_solving(w_res%x, tstep, c_xh, n, dt_controller)
908 call this%pc_vel%update()
910 call profiler_start_region(
"Velocity_solve", 4)
911 ksp_results(2:4) = this%ksp_vel%solve_coupled(ax_vel, du, dv, dw, &
912 u_res%x, v_res%x, w_res%x, n, c_xh, &
913 this%bclst_du, this%bclst_dv, this%bclst_dw, gs_xh, &
914 this%ksp_vel%max_iter)
915 call profiler_end_region(
"Velocity_solve", 4)
917 call this%proj_u%post_solving(du%x, ax_vel, c_xh, &
918 this%bclst_du, gs_xh, n, tstep, dt_controller)
919 call this%proj_v%post_solving(dv%x, ax_vel, c_xh, &
920 this%bclst_dv, gs_xh, n, tstep, dt_controller)
921 call this%proj_w%post_solving(dw%x, ax_vel, c_xh, &
922 this%bclst_dw, gs_xh, n, tstep, dt_controller)
924 if (neko_bcknd_device .eq. 1)
then
925 call device_opadd2cm(u%x_d, v%x_d, w%x_d, &
926 du%x_d, dv%x_d, dw%x_d, 1.0_rp, n, msh%gdim)
928 call opadd2cm(u%x, v%x, w%x, du%x, dv%x, dw%x, 1.0_rp, n, msh%gdim)
931 if (this%forced_flow_rate)
then
932 call neko_error(
'Forced flow rate is not implemented for the adjoint')
941 call fluid_step_info(tstep, t, dt, ksp_results, this%strict_convergence)
943 call this%scratch%relinquish_field(temp_indices)
946 call profiler_end_region(
'Adjoint', 1)
955 end subroutine adjoint_fluid_pnpn_step
963 subroutine adjoint_fluid_pnpn_setup_bcs(this, user, params)
964 use mpi_f08,
only: mpi_in_place
966 class(adjoint_fluid_pnpn_t),
intent(inout) :: this
967 type(user_t),
target,
intent(in) :: user
968 type(json_file),
intent(inout) :: params
969 integer :: i, n_bcs, j, zone_size, global_zone_size, ierr
970 class(bc_t),
pointer :: bc_i
971 type(json_core) :: core
972 type(json_value),
pointer :: bc_object
973 type(json_file) :: bc_subdict
976 logical,
allocatable :: marked_zones(:)
977 integer,
allocatable :: zone_indices(:)
978 character(len=:),
allocatable :: json_key
981 call this%bclst_vel_res%init()
982 call this%bclst_du%init()
983 call this%bclst_dv%init()
984 call this%bclst_dw%init()
985 call this%bclst_dp%init()
987 call this%bc_vel_res%init_from_components(this%c_Xh)
988 call this%bc_du%init_from_components(this%c_Xh)
989 call this%bc_dv%init_from_components(this%c_Xh)
990 call this%bc_dw%init_from_components(this%c_Xh)
991 call this%bc_dp%init_from_components(this%c_Xh)
994 call this%bc_prs_surface%init_from_components(this%c_Xh)
995 call this%bc_sym_surface%init_from_components(this%c_Xh)
997 json_key =
'case.adjoint_fluid.boundary_conditions'
1000 if (params%valid_path(json_key))
then
1001 call params%info(json_key, n_children = n_bcs)
1002 call params%get_core(core)
1003 call params%get(json_key, bc_object, found)
1008 call this%bcs_vel%init(n_bcs)
1010 allocate(marked_zones(
size(this%msh%labeled_zones)))
1011 marked_zones = .false.
1015 call json_extract_item(core, bc_object, i, bc_subdict)
1017 call json_get(bc_subdict,
"zone_indices", zone_indices)
1022 do j = 1,
size(zone_indices)
1023 zone_size = this%msh%labeled_zones(zone_indices(j))%size
1024 call mpi_allreduce(zone_size, global_zone_size, 1, &
1025 mpi_integer, mpi_max, neko_comm, ierr)
1027 if (global_zone_size .eq. 0)
then
1028 write(error_unit,
'(A, A, I0, A, A, I0, A)')
"*** ERROR ***: ",&
1029 "Zone index ", zone_indices(j), &
1030 " is invalid as this zone has 0 size, meaning it does ", &
1031 "not in the mesh. Check adjoint boundary condition ", &
1036 if (marked_zones(zone_indices(j)) .eqv. .true.)
then
1037 write(error_unit,
'(A, A, I0, A, A, A, A)')
"*** ERROR ***: ", &
1038 "Zone with index ", zone_indices(j), &
1039 " has already been assigned a boundary condition. ", &
1040 "Please check your boundary_conditions entry for the ", &
1041 "adjoint and make sure that each zone index appears ", &
1042 "only in a single boundary condition."
1045 marked_zones(zone_indices(j)) = .true.
1050 call velocity_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1054 if (
associated(bc_i))
then
1060 type is (symmetry_t)
1068 call this%bclst_vel_res%append(bc_i)
1069 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
1070 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
1071 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
1073 call this%bcs_vel%append(bc_i)
1075 call this%bc_sym_surface%mark_facets(bc_i%marked_facet)
1076 type is (non_normal_t)
1079 call this%bclst_vel_res%append(bc_i)
1080 call this%bc_du%mark_facets(bc_i%bc_x%marked_facet)
1081 call this%bc_dv%mark_facets(bc_i%bc_y%marked_facet)
1082 call this%bc_dw%mark_facets(bc_i%bc_z%marked_facet)
1083 type is (shear_stress_t)
1085 call this%bclst_vel_res%append(bc_i%symmetry)
1086 call this%bclst_du%append(bc_i%symmetry%bc_x)
1087 call this%bclst_dv%append(bc_i%symmetry%bc_y)
1088 call this%bclst_dw%append(bc_i%symmetry%bc_z)
1090 call this%bcs_vel%append(bc_i)
1091 type is (wall_model_bc_t)
1093 call this%bclst_vel_res%append(bc_i%symmetry)
1094 call this%bclst_du%append(bc_i%symmetry%bc_x)
1095 call this%bclst_dv%append(bc_i%symmetry%bc_y)
1096 call this%bclst_dw%append(bc_i%symmetry%bc_z)
1098 call this%bcs_vel%append(bc_i)
1105 if (bc_i%strong .eqv. .true.)
then
1106 call this%bc_vel_res%mark_facets(bc_i%marked_facet)
1107 call this%bc_du%mark_facets(bc_i%marked_facet)
1108 call this%bc_dv%mark_facets(bc_i%marked_facet)
1109 call this%bc_dw%mark_facets(bc_i%marked_facet)
1111 call this%bc_prs_surface%mark_facets(bc_i%marked_facet)
1114 call this%bcs_vel%append(bc_i)
1120 do i = 1,
size(this%msh%labeled_zones)
1121 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
1122 (marked_zones(i) .eqv. .false.))
then
1123 write(error_unit,
'(A, A, I0)')
"*** ERROR ***: ", &
1124 "No adjoint boundary condition assigned to zone ", i
1132 call this%bcs_prs%init(n_bcs)
1136 call json_extract_item(core, bc_object, i, bc_subdict)
1138 call pressure_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1142 if (
associated(bc_i))
then
1143 call this%bcs_prs%append(bc_i)
1146 if (bc_i%strong .eqv. .true.)
then
1147 call this%bc_dp%mark_facets(bc_i%marked_facet)
1155 call this%bc_prs_surface%finalize()
1156 call this%bc_sym_surface%finalize()
1158 call this%bc_vel_res%finalize()
1159 call this%bc_du%finalize()
1160 call this%bc_dv%finalize()
1161 call this%bc_dw%finalize()
1162 call this%bc_dp%finalize()
1164 call this%bclst_vel_res%append(this%bc_vel_res)
1165 call this%bclst_du%append(this%bc_du)
1166 call this%bclst_dv%append(this%bc_dv)
1167 call this%bclst_dw%append(this%bc_dw)
1168 call this%bclst_dp%append(this%bc_dp)
1171 this%prs_dirichlet = .not. this%bclst_dp%is_empty()
1172 call mpi_allreduce(mpi_in_place, this%prs_dirichlet, 1, &
1173 mpi_logical, mpi_lor, neko_comm)
1175 end subroutine adjoint_fluid_pnpn_setup_bcs
1178 subroutine adjoint_fluid_pnpn_write_boundary_conditions(this)
1179 use inflow,
only: inflow_t
1180 use field_dirichlet,
only: field_dirichlet_t
1181 use blasius,
only: blasius_t
1182 use field_dirichlet_vector,
only: field_dirichlet_vector_t
1183 use usr_inflow,
only: usr_inflow_t
1184 use dong_outflow,
only: dong_outflow_t
1185 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1186 type(dirichlet_t) :: bdry_mask
1187 type(field_t),
pointer :: bdry_field
1188 type(file_t) :: bdry_file
1189 integer :: temp_index, i
1190 class(bc_t),
pointer :: bci
1191 character(len=LOG_SIZE) :: log_buf
1193 call neko_log%section(
"Adjoint boundary conditions")
1194 write(log_buf,
'(A)') &
1195 'Marking using integer keys in boundary_adjoint0.f00000'
1196 call neko_log%message(log_buf)
1197 write(log_buf,
'(A)')
'Condition-value pairs: '
1198 call neko_log%message(log_buf)
1199 write(log_buf,
'(A)')
' no_slip = 1'
1200 call neko_log%message(log_buf)
1201 write(log_buf,
'(A)')
' velocity_value = 2'
1202 call neko_log%message(log_buf)
1203 write(log_buf,
'(A)')
' outflow, normal_outflow (+dong) = 3'
1204 call neko_log%message(log_buf)
1205 write(log_buf,
'(A)')
' symmetry = 4'
1206 call neko_log%message(log_buf)
1207 write(log_buf,
'(A)')
' user_velocity_pointwise = 5'
1208 call neko_log%message(log_buf)
1209 write(log_buf,
'(A)')
' periodic = 6'
1210 call neko_log%message(log_buf)
1211 write(log_buf,
'(A)')
' user_velocity = 7'
1212 call neko_log%message(log_buf)
1213 write(log_buf,
'(A)')
' user_pressure = 8'
1214 call neko_log%message(log_buf)
1215 write(log_buf,
'(A)')
' shear_stress = 9'
1216 call neko_log%message(log_buf)
1217 write(log_buf,
'(A)')
' wall_modelling = 10'
1218 call neko_log%message(log_buf)
1219 write(log_buf,
'(A)')
' blasius_profile = 11'
1220 call neko_log%message(log_buf)
1221 call neko_log%end_section()
1223 call this%scratch%request_field(bdry_field, temp_index)
1228 call bdry_mask%init_from_components(this%c_Xh, 6.0_rp)
1229 call bdry_mask%mark_zone(this%msh%periodic)
1230 call bdry_mask%finalize()
1231 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1232 call bdry_mask%free()
1234 do i = 1, this%bcs_prs%size()
1235 bci => this%bcs_prs%get(i)
1236 select type (bc => bci)
1237 type is (zero_dirichlet_t)
1238 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1239 call bdry_mask%mark_facets(bci%marked_facet)
1240 call bdry_mask%finalize()
1241 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1242 call bdry_mask%free()
1243 type is (dong_outflow_t)
1244 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1245 call bdry_mask%mark_facets(bci%marked_facet)
1246 call bdry_mask%finalize()
1247 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1248 call bdry_mask%free()
1249 type is (field_dirichlet_t)
1250 call bdry_mask%init_from_components(this%c_Xh, 8.0_rp)
1251 call bdry_mask%mark_facets(bci%marked_facet)
1252 call bdry_mask%finalize()
1253 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1254 call bdry_mask%free()
1258 do i = 1, this%bcs_vel%size()
1259 bci => this%bcs_vel%get(i)
1260 select type (bc => bci)
1261 type is (zero_dirichlet_t)
1262 call bdry_mask%init_from_components(this%c_Xh, 1.0_rp)
1263 call bdry_mask%mark_facets(bci%marked_facet)
1264 call bdry_mask%finalize()
1265 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1266 call bdry_mask%free()
1268 call bdry_mask%init_from_components(this%c_Xh, 2.0_rp)
1269 call bdry_mask%mark_facets(bci%marked_facet)
1270 call bdry_mask%finalize()
1271 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1272 call bdry_mask%free()
1273 type is (symmetry_t)
1274 call bdry_mask%init_from_components(this%c_Xh, 4.0_rp)
1275 call bdry_mask%mark_facets(bci%marked_facet)
1276 call bdry_mask%finalize()
1277 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1278 call bdry_mask%free()
1279 type is (usr_inflow_t)
1280 call bdry_mask%init_from_components(this%c_Xh, 5.0_rp)
1281 call bdry_mask%mark_facets(bci%marked_facet)
1282 call bdry_mask%finalize()
1283 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1284 call bdry_mask%free()
1285 type is (field_dirichlet_vector_t)
1286 call bdry_mask%init_from_components(this%c_Xh, 7.0_rp)
1287 call bdry_mask%mark_facets(bci%marked_facet)
1288 call bdry_mask%finalize()
1289 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1290 call bdry_mask%free()
1291 type is (shear_stress_t)
1292 call bdry_mask%init_from_components(this%c_Xh, 9.0_rp)
1293 call bdry_mask%mark_facets(bci%marked_facet)
1294 call bdry_mask%finalize()
1295 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1296 call bdry_mask%free()
1297 type is (wall_model_bc_t)
1298 call bdry_mask%init_from_components(this%c_Xh, 10.0_rp)
1299 call bdry_mask%mark_facets(bci%marked_facet)
1300 call bdry_mask%finalize()
1301 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1302 call bdry_mask%free()
1304 call bdry_mask%init_from_components(this%c_Xh, 11.0_rp)
1305 call bdry_mask%mark_facets(bci%marked_facet)
1306 call bdry_mask%finalize()
1307 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1308 call bdry_mask%free()
1313 bdry_file = file_t(
'boundary_adjoint.fld')
1314 call bdry_file%write(bdry_field)
1316 call this%scratch%relinquish_field(temp_index)
1317 end subroutine adjoint_fluid_pnpn_write_boundary_conditions
1322 subroutine rescale_fluid(fluid_data, scale)
1324 class(adjoint_fluid_pnpn_t),
intent(inout) :: fluid_data
1326 real(kind=rp),
intent(in) :: scale
1332 if (neko_bcknd_device .eq. 1)
then
1333 call device_cmult(fluid_data%u_adj%x_d, scale, fluid_data%u_adj%size())
1334 call device_cmult(fluid_data%v_adj%x_d, scale, fluid_data%v_adj%size())
1335 call device_cmult(fluid_data%w_adj%x_d, scale, fluid_data%w_adj%size())
1337 call cmult(fluid_data%u_adj%x, scale, fluid_data%u_adj%size())
1338 call cmult(fluid_data%v_adj%x, scale, fluid_data%v_adj%size())
1339 call cmult(fluid_data%w_adj%x, scale, fluid_data%w_adj%size())
1343 if (neko_bcknd_device .eq. 1)
then
1344 call device_cmult(fluid_data%f_adj_x%x_d, scale, &
1345 fluid_data%f_adj_x%size())
1346 call device_cmult(fluid_data%f_adj_y%x_d, scale, &
1347 fluid_data%f_adj_y%size())
1348 call device_cmult(fluid_data%f_adj_z%x_d, scale, &
1349 fluid_data%f_adj_z%size())
1352 call device_cmult(fluid_data%abx1%x_d, scale, fluid_data%abx1%size())
1353 call device_cmult(fluid_data%aby1%x_d, scale, fluid_data%aby1%size())
1354 call device_cmult(fluid_data%abz1%x_d, scale, fluid_data%abz1%size())
1355 call device_cmult(fluid_data%abx2%x_d, scale, fluid_data%abx2%size())
1356 call device_cmult(fluid_data%aby2%x_d, scale, fluid_data%aby2%size())
1357 call device_cmult(fluid_data%abz2%x_d, scale, fluid_data%abz2%size())
1360 call cmult(fluid_data%f_adj_x%x, scale, fluid_data%f_adj_x%size())
1361 call cmult(fluid_data%f_adj_y%x, scale, fluid_data%f_adj_y%size())
1362 call cmult(fluid_data%f_adj_z%x, scale, fluid_data%f_adj_z%size())
1364 call cmult(fluid_data%abx1%x, scale, fluid_data%abx1%size())
1365 call cmult(fluid_data%aby1%x, scale, fluid_data%aby1%size())
1366 call cmult(fluid_data%abz1%x, scale, fluid_data%abz1%size())
1368 call cmult(fluid_data%abx2%x, scale, fluid_data%abx2%size())
1369 call cmult(fluid_data%aby2%x, scale, fluid_data%aby2%size())
1370 call cmult(fluid_data%abz2%x, scale, fluid_data%abz2%size())
1374 if (neko_bcknd_device .eq. 1)
then
1375 do i = 1, fluid_data%ulag%size()
1376 call device_cmult(fluid_data%ulag%lf(i)%x_d, &
1377 scale, fluid_data%ulag%lf(i)%size())
1380 do i = 1, fluid_data%vlag%size()
1381 call device_cmult(fluid_data%vlag%lf(i)%x_d, &
1382 scale, fluid_data%vlag%lf(i)%size())
1385 do i = 1, fluid_data%wlag%size()
1386 call device_cmult(fluid_data%wlag%lf(i)%x_d, &
1387 scale, fluid_data%wlag%lf(i)%size())
1390 do i = 1, fluid_data%ulag%size()
1391 call cmult(fluid_data%ulag%lf(i)%x, &
1392 scale, fluid_data%ulag%lf(i)%size())
1395 do i = 1, fluid_data%vlag%size()
1396 call cmult(fluid_data%vlag%lf(i)%x, &
1397 scale, fluid_data%vlag%lf(i)%size())
1400 do i = 1, fluid_data%wlag%size()
1401 call cmult(fluid_data%wlag%lf(i)%x, &
1402 scale, fluid_data%wlag%lf(i)%size())
1406 end subroutine rescale_fluid
1408 function norm(x, y, z, B, volume, n)
1409 use mpi_f08,
only: mpi_in_place
1411 integer,
intent(in) :: n
1412 real(kind=rp),
dimension(n),
intent(in) :: x, y, z
1413 real(kind=rp),
dimension(n),
intent(in) :: b
1414 real(kind=rp),
intent(in) :: volume
1416 real(kind=rp) :: norm
1418 norm = vlsc3(x, x, b, n) + vlsc3(y, y, b, n) + vlsc3(z, z, b, n)
1420 call mpi_allreduce(mpi_in_place, norm, 1, &
1421 mpi_real_precision, mpi_sum, mpi_comm_world)
1423 norm = sqrt(norm / volume)
1426 function device_norm(x_d, y_d, z_d, B_d, volume, n)
1427 use mpi_f08,
only: mpi_in_place
1429 type(c_ptr),
intent(in) :: x_d, y_d, z_d
1430 type(c_ptr),
intent(in) :: B_d
1431 real(kind=rp),
intent(in) :: volume
1432 integer,
intent(in) :: n
1434 real(kind=rp) :: device_norm
1436 device_norm = device_vlsc3(x_d, x_d, b_d, n) + &
1437 device_vlsc3(y_d, y_d, b_d, n) + &
1438 device_vlsc3(z_d, z_d, b_d, n)
1440 call mpi_allreduce(mpi_in_place, device_norm, 1, &
1441 mpi_real_precision, mpi_sum, mpi_comm_world)
1443 device_norm = sqrt(device_norm / volume)
1445 end function device_norm
1451 subroutine power_iterations_compute(this, t, tstep)
1452 class(adjoint_fluid_pnpn_t),
target,
intent(inout) :: this
1453 real(kind=rp),
intent(in) :: t
1454 integer,
intent(in) :: tstep
1457 real(kind=rp) :: scaling_factor
1458 real(kind=rp) :: norm_l2, norm_l2_base
1459 character(len=256) :: log_message
1460 type(vector_t) :: data_line
1463 n = this%c_Xh%dof%size()
1464 if (tstep .eq. 1)
then
1465 if (neko_bcknd_device .eq. 1)
then
1466 norm_l2_base = device_norm(this%u_adj%x_d, this%v_adj%x_d, &
1468 this%c_Xh%B_d, this%c_Xh%volume, n)
1470 norm_l2_base = this%norm_scaling * norm(this%u_adj%x, this%v_adj%x, &
1472 this%c_Xh%B, this%c_Xh%volume, n)
1474 if (this%norm_target .lt. 0.0_rp)
then
1475 this%norm_target = norm_l2_base
1478 this%norm_l2_upper = this%norm_tolerance * this%norm_target
1479 this%norm_l2_lower = this%norm_target / this%norm_tolerance
1484 if (neko_bcknd_device .eq. 1)
then
1485 norm_l2 = device_norm(this%u_adj%x_d, this%v_adj%x_d, this%w_adj%x_d, &
1486 this%c_Xh%B_d, this%c_Xh%volume, n)
1488 norm_l2 = norm(this%u_adj%x, this%v_adj%x, this%w_adj%x, &
1489 this%c_Xh%B, this%c_Xh%volume, n)
1491 norm_l2 = sqrt(this%norm_scaling) * norm_l2
1492 scaling_factor = 1.0_rp
1495 if (norm_l2 .gt. this%norm_l2_upper &
1496 .or. norm_l2 .lt. this%norm_l2_lower)
then
1497 scaling_factor = this%norm_target / norm_l2
1498 call rescale_fluid(this, scaling_factor)
1499 norm_l2 = this%norm_target
1501 if (tstep .eq. 1)
then
1502 scaling_factor = 1.0_rp
1508 call neko_log%section(
'Power Iterations')
1510 write (log_message,
'(A7,E20.14)')
'Norm: ', norm_l2
1511 call neko_log%message(log_message, lvl = neko_log_debug)
1512 write (log_message,
'(A7,E20.14)')
'Scaling: ', scaling_factor
1513 call neko_log%message(log_message, lvl = neko_log_debug)
1516 call data_line%init(2)
1517 data_line%x = [norm_l2, scaling_factor]
1518 call this%file_output%write(data_line, t)
1521 call neko_log%end_section(
'Power Iterations')
1522 end subroutine power_iterations_compute
Boundary condition factory for pressure.
Adjoint Pn/Pn formulation.
Contains the factory routine for advection_t children.
Subroutines to add advection terms to the RHS of a transport equation.
Base type of all fluid formulations.
Base abstract type for computing the advection operator.