Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
adjoint_fluid_scheme_incompressible.f90
Go to the documentation of this file.
1
34!
37 use adjoint_fluid_scheme, only: adjoint_fluid_scheme_t
38 use gather_scatter, only: gs_t, gs_op_min, gs_op_max
39 use neko_config, only: neko_bcknd_device
40 use num_types, only: rp, dp, i8
42 use field, only: field_t
43 use space, only: space_t, gll, gl, operator(.ne.)
44 use dofmap, only: dofmap_t
45 use krylov, only: ksp_t, krylov_solver_factory, ksp_max_iter
46 use coefs, only: coef_t
47 use precon, only: pc_t, precon_factory
48 use fluid_stats, only: fluid_stats_t
49 use bc, only: bc_t
50 use bc_list, only: bc_list_t
51 use mesh, only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
52 use operators, only: cfl
53 use logger, only: neko_log, log_size, neko_log_verbose
54 use registry, only: neko_registry
55 use json_utils, only: json_get, json_get_or_default
56 use json_module, only: json_file
57 use user_intf, only: user_t, dummy_user_material_properties, &
58 user_material_properties_intf
59 use utils, only: neko_error
60 use time_state, only: time_state_t
61
62 use math, only: glsum
63 use device_math, only: device_cfill, device_add2s2
64 use field_math, only: field_cfill, field_add2s2, field_addcol3
65
66 use json_utils_ext, only: json_key_fallback
67 use device, only : device_event_sync, glb_cmd_event, device_to_host, &
68 device_memcpy
69 implicit none
70 private
71
73 type, abstract, extends(adjoint_fluid_scheme_t) :: &
76 type(adjoint_source_term_t) :: source_term
77 class(ksp_t), allocatable :: ksp_vel
78 class(ksp_t), allocatable :: ksp_prs
79 class(pc_t), allocatable :: pc_vel
80 class(pc_t), allocatable :: pc_prs
81 integer :: vel_projection_dim
82 integer :: pr_projection_dim
83 integer :: vel_projection_activ_step
84 integer :: pr_projection_activ_step
85 logical :: strict_convergence
86
88 type(field_t), pointer :: u_adj_e => null()
89 type(field_t), pointer :: v_adj_e => null()
90 type(field_t), pointer :: w_adj_e => null()
91
92 type(fluid_stats_t) :: stats
93 logical :: forced_flow_rate = .false.
94
96 character(len=:), allocatable :: nut_field_name
97
99 integer(kind=i8) :: glb_n_points
101 integer(kind=i8) :: glb_unique_points
102 contains
104 procedure, pass(this) :: init_base => adjoint_fluid_scheme_init_base
105 procedure, pass(this) :: scheme_free => adjoint_fluid_scheme_free
107 procedure, pass(this) :: validate => adjoint_fluid_scheme_validate
109 procedure, pass(this) :: bc_apply_vel => adjoint_fluid_scheme_bc_apply_vel
111 procedure, pass(this) :: bc_apply_prs => adjoint_fluid_scheme_bc_apply_prs
113 procedure, pass(this) :: compute_cfl => adjoint_compute_cfl
115 procedure, pass(this) :: set_material_properties => &
116 adjoint_fluid_scheme_set_material_properties
117
119 procedure, pass(this) :: update_material_properties => &
120 adjoint_fluid_scheme_update_material_properties
122 procedure, nopass :: solver_factory => adjoint_fluid_scheme_solver_factory
124 procedure, pass(this) :: precon_factory_ => &
125 adjoint_fluid_scheme_precon_factory
127
128 interface
129
130 module subroutine adjoint_fluid_scheme_factory(object, type_name)
131 class(adjoint_fluid_scheme_t), intent(inout), allocatable :: object
132 character(len=*) :: type_name
133 end subroutine adjoint_fluid_scheme_factory
134 end interface
135
136 public :: adjoint_fluid_scheme_incompressible_t, adjoint_fluid_scheme_factory
137
138contains
139
141 subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, &
142 user, kspv_init)
143 class(adjoint_fluid_scheme_incompressible_t), target, intent(inout) :: this
144 type(mesh_t), target, intent(inout) :: msh
145 integer, intent(in) :: lx
146 character(len=*), intent(in) :: scheme
147 type(json_file), target, intent(inout) :: params
148 type(user_t), target, intent(in) :: user
149 logical, intent(in) :: kspv_init
150 character(len=LOG_SIZE) :: log_buf
151 real(kind=rp) :: real_val
152 logical :: logical_val
153 integer :: integer_val
154 character(len=:), allocatable :: string_val1, string_val2
155 character(len=:), allocatable :: json_key
156 type(json_file) :: json_subdict
157 integer :: lxd
158
159 !
160 ! SEM simulation fundamentals
161 !
162
163 this%msh => msh
164
165 ! over intergration order (hard coded now, should be optional)
166 lxd = (3 * (lx + 1)) / 2
167 if (msh%gdim .eq. 2) then
168 call this%Xh%init(gll, lx, lx)
169 else
170 call this%Xh%init(gll, lx, lx, lx)
171 end if
172 call this%Xh_GL%init(gl, lxd, lxd, lxd)
173
174 ! NOTE. This shouldn't require remaking all this stuff. What should be
175 ! changed on the neko side is a way of initializing a coef FULLY (ie, Bs)
176 ! with just a space.
177 call this%dm_Xh%init(msh, this%Xh)
178 call this%dm_Xh_GL%init(msh, this%Xh_GL)
179
180 call this%gs_Xh%init(this%dm_Xh)
181 call this%gs_Xh_GL%init(this%dm_Xh_GL)
182
183 call this%c_Xh%init(this%gs_Xh)
184 call this%c_Xh_GL%init(this%gs_Xh_GL)
185
186 call this%GLL_to_GL%init(this%Xh_GL, this%Xh)
187
188 ! Overintegration scratch registry (5 should be sufficient)
189 call this%scratch_GL%init(5, 2, this%dm_Xh_GL)
190
191 ! Assign a name
192 call json_get_or_default(params, 'case.fluid.name', this%name, "fluid")
193
194 !
195 ! First section of fluid log
196 !
197
198 call neko_log%section('Adjoint fluid')
199 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
200 call neko_log%message(log_buf)
201 write(log_buf, '(A, A)') 'Name : ', trim(this%name)
202 call neko_log%message(log_buf)
203
204 ! Assign velocity fields
205 call neko_registry%add_field(this%dm_Xh, 'u_adj')
206 call neko_registry%add_field(this%dm_Xh, 'v_adj')
207 call neko_registry%add_field(this%dm_Xh, 'w_adj')
208 this%u_adj => neko_registry%get_field('u_adj')
209 this%v_adj => neko_registry%get_field('v_adj')
210 this%w_adj => neko_registry%get_field('w_adj')
211
212 !
213 ! Material properties
214 !
215 call this%set_material_properties(params, user)
216
217 ! Projection spaces
218 json_key = json_key_fallback(params, &
219 'case.adjoint_fluid.velocity_solver.projection_space_size', &
220 'case.fluid.velocity_solver.projection_space_size')
221 call json_get_or_default(params, json_key, this%vel_projection_dim, 0)
222 json_key = json_key_fallback(params, &
223 'case.adjoint_fluid.pressure_solver.projection_space_size', &
224 'case.fluid.pressure_solver.projection_space_size')
225 call json_get_or_default(params, json_key, this%pr_projection_dim, 0)
226
227 json_key = json_key_fallback(params, &
228 'case.adjoint_fluid.velocity_solver.projection_hold_steps', &
229 'case.fluid.velocity_solver.projection_hold_steps')
230 call json_get_or_default(params, json_key, &
231 this%vel_projection_activ_step, 5)
232 json_key = json_key_fallback(params, &
233 'case.adjoint_fluid.pressure_solver.projection_hold_steps', &
234 'case.fluid.pressure_solver.projection_hold_steps')
235 call json_get_or_default(params, json_key, &
236 this%pr_projection_activ_step, 5)
237
238 json_key = json_key_fallback(params, 'case.adjoint_fluid.freeze', &
239 'case.fluid.freeze')
240 call json_get_or_default(params, json_key, this%freeze, .false.)
241
242 ! TODO
243 ! This needs to be discussed... In pricipal, I think if the forward is
244 ! forced to a
245 ! certain flow rate, then the adjoint should be forced to zero flow rate,
246 ! we had a derivation in
247 ! https://www.sciencedirect.com/science/article/pii/S0045782522006764
248 ! for now I'm commenting this out
249 if (params%valid_path("case.fluid.flow_rate_force")) then
250 call neko_error('Flow rate forcing not yet implemented')
251 this%forced_flow_rate = .true.
252 end if
253
254
255 if (lx .lt. 10) then
256 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
257 else if (lx .ge. 10) then
258 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
259 else
260 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
261 end if
262 call neko_log%message(log_buf)
263 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
264 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
265
266 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
267 call neko_log%message(log_buf)
268 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
269 call neko_log%message(log_buf)
270
271 call json_get(params, 'case.numerics.dealias', logical_val)
272 write(log_buf, '(A, L1)') 'Dealias : ', logical_val
273 call neko_log%message(log_buf)
274
275 call json_get_or_default(params, 'case.output_boundary', logical_val, &
276 .false.)
277 write(log_buf, '(A, L1)') 'Save bdry : ', logical_val
278 call neko_log%message(log_buf)
279
280 call json_get_or_default(params, "case.fluid.full_stress_formulation", &
281 logical_val, .false.)
282 write(log_buf, '(A, L1)') 'Full stress: ', logical_val
283 call neko_log%message(log_buf)
284
285 !
286 ! Setup right-hand side fields.
287 !
288 allocate(this%f_adj_x)
289 allocate(this%f_adj_y)
290 allocate(this%f_adj_z)
291 call this%f_adj_x%init(this%dm_Xh, fld_name = "adjoint_rhs_x")
292 call this%f_adj_y%init(this%dm_Xh, fld_name = "adjoint_rhs_y")
293 call this%f_adj_z%init(this%dm_Xh, fld_name = "adjoint_rhs_z")
294
295 ! Todo: HARRY
296 ! --------------------------------------------------------------------------
297 ! ok here is a chance that we can maybe steal the krylov solvers from the
298 ! forward??
299 !
300 ! something along the lines of
301 !
302 ! if (.not.params%valid_path('case.adjoint_fluid.velocity_solver')) then
303 ! this%ksp_vel => case%fluid%ksp_vel
304 ! this%pc_vel => case%fluid%ksp_vel
305 ! else
306 ! initialize everything
307 ! end if
308 !
309 ! but I don't know how we can steal the krylov solvers out of the forward,
310 ! so for now we'll just initialize two of them...
311 ! Initialize velocity solver
312 if (kspv_init) then
313 call neko_log%section("Adjoint Velocity solver")
314
315 json_key = json_key_fallback(params, &
316 'case.adjoint_fluid.velocity_solver.max_iterations', &
317 'case.fluid.velocity_solver.max_iterations')
318 call json_get_or_default(params, json_key, integer_val, ksp_max_iter)
319
320 json_key = json_key_fallback(params, &
321 'case.adjoint_fluid.velocity_solver.type', &
322 'case.fluid.velocity_solver.type')
323 call json_get(params, json_key, string_val1)
324
325 json_key = json_key_fallback(params, &
326 'case.adjoint_fluid.velocity_solver.preconditioner.type', &
327 'case.fluid.velocity_solver.preconditioner.type')
328 call json_get(params, json_key, string_val2)
329
330 json_key = json_key_fallback(params, &
331 'case.adjoint_fluid.velocity_solver.preconditioner', &
332 'case.fluid.velocity_solver.preconditioner')
333 call json_get(params, json_key, json_subdict)
334
335 json_key = json_key_fallback(params, &
336 'case.adjoint_fluid.velocity_solver.absolute_tolerance', &
337 'case.fluid.velocity_solver.absolute_tolerance')
338 call json_get(params, json_key, real_val)
339
340 json_key = json_key_fallback(params, &
341 'case.adjoint_fluid.velocity_solver.monitor', &
342 'case.fluid.velocity_solver.monitor')
343 call json_get_or_default(params, json_key, logical_val, .false.)
344
345 call neko_log%message('Type : (' // trim(string_val1) // &
346 ', ' // trim(string_val2) // ')')
347
348 write(log_buf, '(A,ES13.6)') 'Abs tol :', real_val
349 call neko_log%message(log_buf)
350 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
351 string_val1, integer_val, real_val, logical_val)
352 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
353 this%c_Xh, this%bcs_vel, &
354 string_val2, json_subdict)
355 call neko_log%end_section()
356 end if
357
358 ! Strict convergence for the velocity solver
359 call json_get_or_default(params, 'case.fluid.strict_convergence', &
360 this%strict_convergence, .false.)
361
362 !! Initialize time-lag fields
363 call this%ulag%init(this%u_adj, 2)
364 call this%vlag%init(this%v_adj, 2)
365 call this%wlag%init(this%w_adj, 2)
366
367 call neko_registry%add_field(this%dm_Xh, 'u_adj_e')
368 call neko_registry%add_field(this%dm_Xh, 'v_adj_e')
369 call neko_registry%add_field(this%dm_Xh, 'w_adj_e')
370 this%u_adj_e => neko_registry%get_field('u_adj_e')
371 this%v_adj_e => neko_registry%get_field('v_adj_e')
372 this%w_adj_e => neko_registry%get_field('w_adj_e')
373
374 ! Initialize the source term
375 call this%source_term%init(this%f_adj_x, this%f_adj_y, this%f_adj_z, &
376 this%c_Xh, user, this%name)
377 call this%source_term%add(params, 'case.adjoint_fluid.source_term')
378
379 call neko_log%end_section()
380
381 end subroutine adjoint_fluid_scheme_init_base
382
384 subroutine adjoint_fluid_scheme_free(this)
385 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
386 class(bc_t), pointer :: bc
387 integer :: i
388
389 bc => null()
390
391 if (allocated(this%ksp_vel)) then
392 call this%ksp_vel%free()
393 deallocate(this%ksp_vel)
394 end if
395
396 if (allocated(this%ksp_prs)) then
397 call this%ksp_prs%free()
398 deallocate(this%ksp_prs)
399 end if
400
401 if (allocated(this%pc_vel)) then
402 call this%pc_vel%free()
403 deallocate(this%pc_vel)
404 end if
405
406 if (allocated(this%pc_prs)) then
407 call this%pc_prs%free()
408 deallocate(this%pc_prs)
409 end if
410
411 do i = 1, this%bcs_vel%size()
412 bc => this%bcs_vel%get(i)
413 if (associated(bc)) then
414 call bc%free()
415 deallocate(bc)
416 end if
417 end do
418 call this%bcs_vel%free()
419
420 do i = 1, this%bcs_prs%size()
421 bc => this%bcs_prs%get(i)
422 if (associated(bc)) then
423 call bc%free()
424 deallocate(bc)
425 end if
426 end do
427 call this%bcs_prs%free()
428
429 call this%source_term%free()
430
431 call this%GLL_to_GL%free()
432
433 call this%gs_Xh%free()
434
435 call this%gs_Xh_GL%free()
436
437 call this%c_Xh%free()
438
439 call this%c_Xh_GL%free()
440
441 call this%scratch_GL%free()
442
443 nullify(this%u_adj)
444 nullify(this%v_adj)
445 nullify(this%w_adj)
446 nullify(this%p_adj)
447
448 nullify(this%u_adj_e)
449 nullify(this%v_adj_e)
450 nullify(this%w_adj_e)
451
452 call this%ulag%free()
453 call this%vlag%free()
454 call this%wlag%free()
455
456
457 if (associated(this%f_adj_x)) then
458 call this%f_adj_x%free()
459 deallocate(this%f_adj_x)
460 end if
461
462 if (associated(this%f_adj_y)) then
463 call this%f_adj_y%free()
464 deallocate(this%f_adj_y)
465 end if
466
467 if (associated(this%f_adj_z)) then
468 call this%f_adj_z%free()
469 deallocate(this%f_adj_z)
470 end if
471
472 nullify(this%f_adj_x)
473 nullify(this%f_adj_y)
474 nullify(this%f_adj_z)
475
476 call this%rho%free()
477 call this%mu%free()
478 call this%dm_Xh%free()
479 call this%dm_Xh_GL%free()
480 call this%Xh%free()
481 call this%Xh_GL%free()
482
483 nullify(this%msh)
484 nullify(bc)
485
486 end subroutine adjoint_fluid_scheme_free
487
490 subroutine adjoint_fluid_scheme_validate(this)
491 class(adjoint_fluid_scheme_incompressible_t), target, intent(inout) :: this
492 ! Variables for retrieving json parameters
493
494 if ((.not. associated(this%u_adj)) .or. &
495 (.not. associated(this%v_adj)) .or. &
496 (.not. associated(this%w_adj)) .or. &
497 (.not. associated(this%p_adj))) then
498 call neko_error('Fields are not registered')
499 end if
500
501 if ((.not. allocated(this%u_adj%x)) .or. &
502 (.not. allocated(this%v_adj%x)) .or. &
503 (.not. allocated(this%w_adj%x)) .or. &
504 (.not. allocated(this%p_adj%x))) then
505 call neko_error('Fields are not allocated')
506 end if
507
508 if (this%u_adj%Xh .ne. this%v_adj%Xh .or. &
509 this%u_adj%Xh .ne. this%w_adj%Xh) then
510 call neko_error('Different function spaces for velocity components')
511 end if
512
513 if (this%u_adj%msh%nelv .ne. this%p_adj%msh%nelv) then
514 call neko_error('Velocity and pressure defined on different meshes')
515 end if
516
517 if (.not. allocated(this%ksp_vel)) then
518 call neko_error('No Krylov solver for velocity defined')
519 end if
520
521 if (.not. allocated(this%ksp_prs)) then
522 call neko_error('No Krylov solver for pressure defined')
523 end if
524
525 end subroutine adjoint_fluid_scheme_validate
526
531 subroutine adjoint_fluid_scheme_bc_apply_vel(this, time, strong)
532 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
533 type(time_state_t), intent(in) :: time
534 logical, intent(in) :: strong
535
536 integer :: i
537 class(bc_t), pointer :: b => null()
538
539 call this%bcs_vel%apply_vector(&
540 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
541 time, strong)
542 call this%gs_Xh%op(this%u_adj, gs_op_min, glb_cmd_event)
543 call this%gs_Xh%op(this%v_adj, gs_op_min, glb_cmd_event)
544 call this%gs_Xh%op(this%w_adj, gs_op_min, glb_cmd_event)
545 call device_event_sync(glb_cmd_event)
546
547 call this%bcs_vel%apply_vector(&
548 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
549 time, strong)
550 call this%gs_Xh%op(this%u_adj, gs_op_max, glb_cmd_event)
551 call this%gs_Xh%op(this%v_adj, gs_op_max, glb_cmd_event)
552 call this%gs_Xh%op(this%w_adj, gs_op_max, glb_cmd_event)
553 call device_event_sync(glb_cmd_event)
554
555 do i = 1, this%bcs_vel%size()
556 b => this%bcs_vel%get(i)
557 b%updated = .false.
558 end do
559 nullify(b)
560
561
562 end subroutine adjoint_fluid_scheme_bc_apply_vel
563
566 subroutine adjoint_fluid_scheme_bc_apply_prs(this, time)
567 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
568 type(time_state_t), intent(in) :: time
569
570 integer :: i
571 class(bc_t), pointer :: b => null()
572
573 call this%bcs_prs%apply(this%p_adj, time)
574 call this%gs_Xh%op(this%p_adj, gs_op_min, glb_cmd_event)
575 call device_event_sync(glb_cmd_event)
576
577 call this%bcs_prs%apply(this%p_adj, time)
578 call this%gs_Xh%op(this%p_adj, gs_op_max, glb_cmd_event)
579 call device_event_sync(glb_cmd_event)
580
581 do i = 1, this%bcs_prs%size()
582 b => this%bcs_prs%get(i)
583 b%updated = .false.
584 end do
585 nullify(b)
586
587 end subroutine adjoint_fluid_scheme_bc_apply_prs
588
591 subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, &
592 max_iter, abstol, monitor)
593 class(ksp_t), allocatable, target, intent(inout) :: ksp
594 integer, intent(in), value :: n
595 character(len=*), intent(in) :: solver
596 integer, intent(in) :: max_iter
597 real(kind=rp), intent(in) :: abstol
598 logical, intent(in) :: monitor
599
600 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
601 monitor = monitor)
602
603 end subroutine adjoint_fluid_scheme_solver_factory
604
606 subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, &
607 bclst, pctype, json)
608 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
609 class(pc_t), allocatable, target, intent(inout) :: pc
610 class(ksp_t), target, intent(inout) :: ksp
611 type(coef_t), target, intent(in) :: coef
612 type(bc_list_t), target, intent(inout) :: bclst
613 character(len=*) :: pctype
614 type(json_file), intent(inout) :: json
615
616 call precon_factory(pc, pctype, coef, bclst, json)
617 call ksp%set_pc(pc)
618
619 end subroutine adjoint_fluid_scheme_precon_factory
620
622 ! TODO
623 ! HARRY
624 ! ok this needs to be discussed.
625 ! To me, the CFL is based on the convecting velocity, so I would argue
626 ! that the CFL of the adjoint is based on
627 ! u, v, w
628 ! not
629 ! u_adj, v_adj, w_adj
630 !
631 ! Then again, this function is really only used for varaible timestep,
632 ! which we can't use if we're checkpointing...
633 !
634 ! hmmmmm.... requires more thought. Because people optimal ICs or Arnouldi
635 ! may use variable timesteps... or us in a steady case..
636 !
637 ! for now.... let's ignore it
638 function adjoint_compute_cfl(this, dt) result(c)
639 class(adjoint_fluid_scheme_incompressible_t), intent(in) :: this
640 real(kind=dp), intent(in) :: dt
641 real(kind=dp) :: c
642
643 c = cfl(dt, this%u_adj%x, this%v_adj%x, this%w_adj%x, &
644 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
645
646 end function adjoint_compute_cfl
647
652 subroutine adjoint_fluid_scheme_update_material_properties(this, time)
653 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
654 type(time_state_t), intent(in) :: time
655 type(field_t), pointer :: nut
656
657 call this%user_material_properties(this%name, &
658 this%material_properties, time)
659
660 if (len(trim(this%nut_field_name)) > 0) then
661 nut => neko_registry%get_field(this%nut_field_name)
662 call field_addcol3(this%mu, nut, this%rho)
663 end if
664
665 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
666 ! host array data to pass constant density and viscosity
667 ! to some routines, we need to make sure that the host
668 ! values are also filled
669 if (neko_bcknd_device .eq. 1) then
670 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
671 device_to_host, sync=.false.)
672 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
673 device_to_host, sync=.false.)
674 end if
675 end subroutine adjoint_fluid_scheme_update_material_properties
676
681 subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
682 class(adjoint_fluid_scheme_incompressible_t), intent(inout) :: this
683 type(json_file), intent(inout) :: params
684 type(user_t), target, intent(in) :: user
685 character(len=LOG_SIZE) :: log_buf
686 ! A local pointer that is needed to make Intel happy
687 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
688 real(kind=rp) :: const_mu, const_rho
689 type(time_state_t) :: time
690
691
692 dummy_mp_ptr => dummy_user_material_properties
693
694 call this%mu%init(this%dm_Xh, "mu")
695 call this%rho%init(this%dm_Xh, "rho")
696 call this%material_properties%init(2)
697 call this%material_properties%assign_to_field(1, this%rho)
698 call this%material_properties%assign_to_field(2, this%mu)
699
700 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
701
702 write(log_buf, '(A)') "Material properties must be set in the user&
703 & file!"
704 call neko_log%message(log_buf)
705 this%user_material_properties => user%material_properties
706
707 call user%material_properties(this%name, &
708 this%material_properties, time)
709
710 else
711 this%user_material_properties => dummy_user_material_properties
712 ! Incorrect user input
713 if (params%valid_path('case.fluid.Re') .and. &
714 (params%valid_path('case.fluid.mu') .or. &
715 params%valid_path('case.fluid.rho'))) then
716 call neko_error("To set the material properties for the fluid, " // &
717 "either provide Re OR mu and rho in the case file.")
718
719 else if (params%valid_path('case.fluid.Re')) then
720 ! Non-dimensional case
721 write(log_buf, '(A)') 'Non-dimensional fluid material properties &
722 & input.'
723 call neko_log%message(log_buf, lvl = neko_log_verbose)
724 write(log_buf, '(A)') 'Density will be set to 1, dynamic viscosity to&
725 & 1/Re.'
726 call neko_log%message(log_buf, lvl = neko_log_verbose)
727
728 ! Read Re into mu for further manipulation.
729 call json_get(params, 'case.fluid.Re', const_mu)
730 write(log_buf, '(A)') 'Read non-dimensional material properties'
731 call neko_log%message(log_buf)
732 write(log_buf, '(A,ES13.6)') 'Re :', const_mu
733 call neko_log%message(log_buf)
734
735 ! Set rho to 1 since the setup is non-dimensional.
736 const_rho = 1.0_rp
737 ! Invert the Re to get viscosity.
738 const_mu = 1.0_rp/const_mu
739 else
740 ! Dimensional case
741 call json_get(params, 'case.fluid.mu', const_mu)
742 call json_get(params, 'case.fluid.rho', const_rho)
743 end if
744 end if
745
746 ! We need to fill the fields based on the parsed const values
747 ! if the user routine is not used.
748 if (associated(user%material_properties, dummy_mp_ptr)) then
749 ! Fill mu and rho field with the physical value
750 call field_cfill(this%mu, const_mu)
751 call field_cfill(this%rho, const_rho)
752
753
754 write(log_buf, '(A,ES13.6)') 'rho :', const_rho
755 call neko_log%message(log_buf)
756 write(log_buf, '(A,ES13.6)') 'mu :', const_mu
757 call neko_log%message(log_buf)
758 end if
759
760 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
761 ! host array data to pass constant density and viscosity
762 ! to some routines, we need to make sure that the host
763 ! values are also filled
764 if (neko_bcknd_device .eq. 1) then
765 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
766 device_to_host, sync=.false.)
767 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
768 device_to_host, sync=.false.)
769 end if
770 end subroutine adjoint_fluid_scheme_set_material_properties
771
subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, user, kspv_init)
Initialise an adjoint scheme.
Implements the adjoint_source_term_t type.
Wrapper contaning and executing the adjoint source terms.