Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
adjoint_fluid_scheme.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use gather_scatter, only: gs_t
36 use mean_sqr_flow, only: mean_sqr_flow_t
37 use neko_config, only: neko_bcknd_device
38 use checkpoint, only: chkp_t
39 use mean_flow, only: mean_flow_t
40 use num_types, only: rp, i8
41 use comm, only: neko_comm
43 use field, only: field_t
44 use space, only: space_t, gll
45 use dofmap, only: dofmap_t
46 use zero_dirichlet, only: zero_dirichlet_t
47 use krylov, only: ksp_t, krylov_solver_factory, krylov_solver_destroy, &
48 ksp_max_iter
49 use coefs, only: coef_t
50 use usr_inflow, only: usr_inflow_t, usr_inflow_eval
51 use dirichlet, only: dirichlet_t
52 use field_dirichlet, only: field_dirichlet_t
53 use field_dirichlet_vector, only: field_dirichlet_vector_t
54 use jacobi, only: jacobi_t
55 use sx_jacobi, only: sx_jacobi_t
56 use device_jacobi, only: device_jacobi_t
57 use hsmg, only: hsmg_t
58 use phmg, only: phmg_t
59 use precon, only: pc_t, precon_factory, precon_destroy
60 use fluid_stats, only: fluid_stats_t
61 use bc, only: bc_t
62 use bc_list, only: bc_list_t
63 use mesh, only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
64 use math, only: cfill, add2s2, glsum
65 use device_math, only: device_cfill, device_add2s2
66 use time_scheme_controller, only: time_scheme_controller_t
67 use operators, only: cfl
68 use logger, only: neko_log, log_size, neko_log_verbose
69 use field_registry, only: neko_field_registry
70 use json_utils, only: json_get, json_get_or_default, json_extract_object, &
71 json_extract_item
72 use json_module, only: json_file, json_core, json_value
73 use scratch_registry, only: scratch_registry_t
74 use user_intf, only: user_t, dummy_user_material_properties, &
75 user_material_properties
76 use utils, only: neko_error, neko_warning
77 use field_series, only: field_series_t
78 use time_step_controller, only: time_step_controller_t
79 use field_math, only: field_cfill, field_add2s2
80 use wall_model_bc, only: wall_model_bc_t
81 use shear_stress, only: shear_stress_t
82 use gradient_jump_penalty, only: gradient_jump_penalty_t
83
84 use mpi_f08, only: mpi_integer, mpi_sum, mpi_allreduce
86 implicit none
87 private
88
90 type, abstract :: adjoint_fluid_scheme_t
92 type(field_t), pointer :: u_adj => null()
94 type(field_t), pointer :: v_adj => null()
96 type(field_t), pointer :: w_adj => null()
98 type(field_t), pointer :: p_adj => null()
100 type(field_series_t) :: ulag, vlag, wlag
102 type(space_t) :: xh
104 type(dofmap_t) :: dm_xh
106 type(gs_t) :: gs_xh
108 type(coef_t) :: c_xh
110 type(adjoint_source_term_t) :: source_term
112 type(field_t), pointer :: f_adj_x => null()
114 type(field_t), pointer :: f_adj_y => null()
116 type(field_t), pointer :: f_adj_z => null()
117
118 ! Krylov solvers and settings
120 class(ksp_t), allocatable :: ksp_vel
122 class(ksp_t), allocatable :: ksp_prs
124 class(pc_t), allocatable :: pc_vel
126 class(pc_t), allocatable :: pc_prs
128 integer :: vel_projection_dim
130 integer :: pr_projection_dim
132 integer :: vel_projection_activ_step
134 integer :: pr_projection_activ_step
136 logical :: strict_convergence
138 logical :: if_gradient_jump_penalty
139 type(gradient_jump_penalty_t) :: gradient_jump_penalty_u_adj
140 type(gradient_jump_penalty_t) :: gradient_jump_penalty_v_adj
141 type(gradient_jump_penalty_t) :: gradient_jump_penalty_w_adj
142
143 ! List of boundary conditions for pressure
144 type(bc_list_t) :: bcs_prs
145 ! List of boundary conditions for velocity
146 type(bc_list_t) :: bcs_vel
148 type(mesh_t), pointer :: msh => null()
150 type(chkp_t) :: chkp
152 type(mean_flow_t) :: mean
154 type(fluid_stats_t) :: stats
156 type(mean_sqr_flow_t) :: mean_sqr
158 logical :: forced_flow_rate = .false.
160 logical :: freeze = .false.
162 real(kind=rp) :: mu
164 type(field_t) :: mu_field
166 character(len=:), allocatable :: nut_field_name
168 logical :: variable_material_properties = .false.
170 real(kind=rp) :: rho
172 type(field_t) :: rho_field
174 integer(kind=i8) :: glb_n_points
176 integer(kind=i8) :: glb_unique_points
178 type(scratch_registry_t) :: scratch
179 contains
181 procedure, pass(this) :: init_base => adjoint_fluid_scheme_init_base
183 procedure, pass(this) :: scheme_free => adjoint_fluid_scheme_free
185 procedure, pass(this) :: validate => adjoint_fluid_scheme_validate
187 procedure, pass(this) :: bc_apply_vel => adjoint_fluid_scheme_bc_apply_vel
189 procedure, pass(this) :: bc_apply_prs => adjoint_fluid_scheme_bc_apply_prs
191 procedure, pass(this) :: compute_cfl => adjoint_compute_cfl
193 procedure, pass(this) :: set_material_properties => &
196 procedure(adjoint_fluid_scheme_init_intrf), pass(this), deferred :: init
198 procedure(adjoint_fluid_scheme_free_intrf), pass(this), deferred :: free
200 procedure(adjoint_fluid_scheme_step_intrf), pass(this), deferred :: step
203 pass(this), deferred :: restart
205 procedure(adjoint_fluid_scheme_setup_bcs_intrf), pass(this), deferred :: &
206 setup_bcs
208 procedure, pass(this) :: update_material_properties => &
211 procedure, nopass :: solver_factory => adjoint_fluid_scheme_solver_factory
213 procedure, pass(this) :: precon_factory_ => &
216
217
219 abstract interface
220 subroutine adjoint_fluid_scheme_init_intrf(this, msh, lx, params, user, &
221 time_scheme)
223 import json_file
224 import mesh_t
225 import user_t
226 import time_scheme_controller_t
227 class(adjoint_fluid_scheme_t), target, intent(inout) :: this
228 type(mesh_t), target, intent(inout) :: msh
229 integer, intent(in) :: lx
230 type(json_file), target, intent(inout) :: params
231 type(user_t), target, intent(in) :: user
232 type(time_scheme_controller_t), target, intent(in) :: time_scheme
234 end interface
235
237 abstract interface
240 class(adjoint_fluid_scheme_t), intent(inout) :: this
242 end interface
243
245 abstract interface
246 subroutine adjoint_fluid_scheme_step_intrf(this, t, tstep, dt, ext_bdf, &
247 dt_controller)
249 import time_scheme_controller_t
250 import time_step_controller_t
251 import rp
252 class(adjoint_fluid_scheme_t), target, intent(inout) :: this
253 real(kind=rp), intent(in) :: t
254 integer, intent(in) :: tstep
255 real(kind=rp), intent(in) :: dt
256 type(time_scheme_controller_t), intent(in) :: ext_bdf
257 type(time_step_controller_t), intent(in) :: dt_controller
259 end interface
260
262 abstract interface
263 subroutine adjoint_fluid_scheme_restart_intrf(this, dtlag, tlag)
265 import rp
266 class(adjoint_fluid_scheme_t), target, intent(inout) :: this
267 real(kind=rp) :: dtlag(10), tlag(10)
268
270 end interface
271
273 abstract interface
274 subroutine adjoint_fluid_scheme_setup_bcs_intrf(this, user, params)
275 import adjoint_fluid_scheme_t, user_t, json_file
276 class(adjoint_fluid_scheme_t), intent(inout) :: this
277 type(user_t), target, intent(in) :: user
278 type(json_file), intent(inout) :: params
280 end interface
281
282 interface
283
284 module subroutine adjoint_fluid_scheme_factory(object, type_name)
285 class(adjoint_fluid_scheme_t), intent(inout), allocatable :: object
286 character(len=*) :: type_name
287 end subroutine adjoint_fluid_scheme_factory
288 end interface
289
290 public :: adjoint_fluid_scheme_t, adjoint_fluid_scheme_factory
291
292contains
293
295 subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, &
296 user, kspv_init)
297 class(adjoint_fluid_scheme_t), target, intent(inout) :: this
298 type(mesh_t), target, intent(inout) :: msh
299 integer, intent(in) :: lx
300 character(len=*), intent(in) :: scheme
301 type(json_file), target, intent(inout) :: params
302 type(user_t), target, intent(in) :: user
303 logical, intent(in) :: kspv_init
304 character(len=LOG_SIZE) :: log_buf
305 real(kind=rp) :: real_val
306 logical :: logical_val
307 integer :: integer_val
308 character(len=:), allocatable :: string_val1, string_val2
309 real(kind=rp) :: gjp_param_a, gjp_param_b
310 character(len=:), allocatable :: json_key
311
312 !
313 ! SEM simulation fundamentals
314 !
315
316 this%msh => msh
317
318 if (msh%gdim .eq. 2) then
319 call this%Xh%init(gll, lx, lx)
320 else
321 call this%Xh%init(gll, lx, lx, lx)
322 end if
323
324 call this%dm_Xh%init(msh, this%Xh)
325
326 call this%gs_Xh%init(this%dm_Xh)
327
328 call this%c_Xh%init(this%gs_Xh)
329
330 ! Local scratch registry
331 this%scratch = scratch_registry_t(this%dm_Xh, 10, 2)
332
333 !
334 ! First section of fluid log
335 !
336
337 call neko_log%section('Adjoint fluid')
338 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
339 call neko_log%message(log_buf)
340
341 !
342 ! Material properties
343 !
344 call this%set_material_properties(params, user)
345
346 !
347 ! Turbulence modelling and variable material properties
348 !
349 if (params%valid_path('case.fluid.nut_field')) then
350 call neko_error('Variable material properties not yet implemented')
351 call json_get(params, 'case.fluid.nut_field', this%nut_field_name)
352 this%variable_material_properties = .true.
353 else
354 this%nut_field_name = ""
355 end if
356
357 ! Fill mu and rho field with the physical value
358
359 call this%mu_field%init(this%dm_Xh, "mu")
360 call this%rho_field%init(this%dm_Xh, "mu")
361 call field_cfill(this%mu_field, this%mu, this%mu_field%size())
362 call field_cfill(this%rho_field, this%rho, this%mu_field%size())
363
364 ! Since mu, rho is a field, and the none-stress simulation fetches
365 ! data from the host arrays, we need to mirror the constant
366 ! material properties on the host
367 if (neko_bcknd_device .eq. 1) then
368 call cfill(this%mu_field%x, this%mu, this%mu_field%size())
369 call cfill(this%rho_field%x, this%rho, this%rho_field%size())
370 end if
371
372
373 ! Projection spaces
374 json_key = json_key_fallback(params, &
375 'case.adjoint_fluid.velocity_solver.projection_space_size', &
376 'case.fluid.velocity_solver.projection_space_size')
377 call json_get_or_default(params, json_key, this%vel_projection_dim, 20)
378 json_key = json_key_fallback(params, &
379 'case.adjoint_fluid.pressure_solver.projection_space_size', &
380 'case.fluid.pressure_solver.projection_space_size')
381 call json_get_or_default(params, json_key, this%pr_projection_dim, 20)
382
383 json_key = json_key_fallback(params, &
384 'case.adjoint_fluid.velocity_solver.projection_hold_steps', &
385 'case.fluid.velocity_solver.projection_hold_steps')
386 call json_get_or_default(params, json_key, &
387 this%vel_projection_activ_step, 5)
388 json_key = json_key_fallback(params, &
389 'case.adjoint_fluid.pressure_solver.projection_hold_steps', &
390 'case.fluid.pressure_solver.projection_hold_steps')
391 call json_get_or_default(params, json_key, &
392 this%pr_projection_activ_step, 5)
393
394 json_key = json_key_fallback(params, 'case.adjoint_fluid.freeze', &
395 'case.fluid.freeze')
396 call json_get_or_default(params, json_key, this%freeze, .false.)
397
398 ! TODO
399 ! This needs to be discussed... In pricipal, I think if the forward is
400 ! forced to a
401 ! certain flow rate, then the adjoint should be forced to zero flow rate,
402 ! we had a derivation in
403 ! https://www.sciencedirect.com/science/article/pii/S0045782522006764
404 ! for now I'm commenting this out
405 if (params%valid_path("case.fluid.flow_rate_force")) then
406 call neko_error('Flow rate forcing not yet implemented')
407 this%forced_flow_rate = .true.
408 end if
409
410
411 if (lx .lt. 10) then
412 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
413 else if (lx .ge. 10) then
414 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
415 else
416 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
417 end if
418 call neko_log%message(log_buf)
419 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
420 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
421
422 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
423 call neko_log%message(log_buf)
424 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
425 call neko_log%message(log_buf)
426
427 write(log_buf, '(A,ES13.6)') 'rho :', this%rho
428 call neko_log%message(log_buf)
429 write(log_buf, '(A,ES13.6)') 'mu :', this%mu
430 call neko_log%message(log_buf)
431
432 call json_get(params, 'case.numerics.dealias', logical_val)
433 write(log_buf, '(A, L1)') 'Dealias : ', logical_val
434 call neko_log%message(log_buf)
435
436 write(log_buf, '(A, L1)') 'LES : ', this%variable_material_properties
437 call neko_log%message(log_buf)
438
439 call json_get_or_default(params, 'case.output_boundary', logical_val, &
440 .false.)
441 write(log_buf, '(A, L1)') 'Save bdry : ', logical_val
442 call neko_log%message(log_buf)
443
444 !
445 ! Setup right-hand side fields.
446 !
447 allocate(this%f_adj_x)
448 allocate(this%f_adj_y)
449 allocate(this%f_adj_z)
450 call this%f_adj_x%init(this%dm_Xh, fld_name = "adjoint_rhs_x")
451 call this%f_adj_y%init(this%dm_Xh, fld_name = "adjoint_rhs_y")
452 call this%f_adj_z%init(this%dm_Xh, fld_name = "adjoint_rhs_z")
453
454 ! Initialize the source term
455 ! TODO
456 ! HARRY
457 ! Ok, this one I dislike the most... I think the CORRECT solution here is to
458 ! modify
459 ! the fluid_source_term.f90 so that case.fluid is not hardcoded
460 ! whoever coded it originally is probably much smarter than me and has their
461 ! reasons
462 !
463 ! I would envision somehow merging fluid_source_term and scalar_source_term
464 ! (maybe they're different because because it's a vector forcing vs a scalar
465 ! forcing,
466 ! but still...
467 !
468 ! this is my attempt...
469 ! params replaced by adjoint_json
470 !call this%source_term%init(params, this%f_adj_x, this%f_adj_y, &
471 ! this%f_adj_z, this%c_Xh,&
472 ! user)
473
474 call this%source_term%init(this%f_adj_x, this%f_adj_y, this%f_adj_z, &
475 this%c_Xh, user)
476 call this%source_term%add(params, 'case.adjoint_fluid.source_term')
477
478 ! Todo: HARRY
479 ! --------------------------------------------------------------------------
480 ! ok here is a chance that we can maybe steal the krylov solvers from the
481 ! forward??
482 !
483 ! something along the lines of
484 !
485 ! if (.not.params%valid_path('case.adjoint_fluid.velocity_solver')) then
486 ! this%ksp_vel => case%fluid%ksp_vel
487 ! this%pc_vel => case%fluid%ksp_vel
488 ! else
489 ! initialize everything
490 ! end if
491 !
492 ! but I don't know how we can steal the krylov solvers out of the forward,
493 ! so for now we'll just initialize two of them...
494 ! Initialize velocity solver
495 if (kspv_init) then
496 call neko_log%section("Adjoint Velocity solver")
497
498 json_key = json_key_fallback(params, &
499 'case.adjoint_fluid.velocity_solver.max_iterations', &
500 'case.fluid.velocity_solver.max_iterations')
501 call json_get_or_default(params, json_key, integer_val, ksp_max_iter)
502
503 json_key = json_key_fallback(params, &
504 'case.adjoint_fluid.velocity_solver.type', &
505 'case.fluid.velocity_solver.type')
506 call json_get(params, json_key, string_val1)
507
508 json_key = json_key_fallback(params, &
509 'case.adjoint_fluid.velocity_solver.preconditioner', &
510 'case.fluid.velocity_solver.preconditioner')
511 call json_get(params, json_key, string_val2)
512
513 json_key = json_key_fallback(params, &
514 'case.adjoint_fluid.velocity_solver.absolute_tolerance', &
515 'case.fluid.velocity_solver.absolute_tolerance')
516 call json_get(params, json_key, real_val)
517
518 json_key = json_key_fallback(params, &
519 'case.adjoint_fluid.velocity_solver.monitor', &
520 'case.fluid.velocity_solver.monitor')
521 call json_get_or_default(params, json_key, logical_val, .false.)
522
523 call neko_log%message('Type : ('// trim(string_val1) // &
524 ', ' // trim(string_val2) // ')')
525
526 write(log_buf, '(A,ES13.6)') 'Abs tol :', real_val
527 call neko_log%message(log_buf)
528 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
529 string_val1, integer_val, real_val, logical_val)
530 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
531 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_vel, string_val2)
532 call neko_log%end_section()
533 end if
534
535 ! Strict convergence for the velocity solver
536 call json_get_or_default(params, 'case.fluid.strict_convergence', &
537 this%strict_convergence, .false.)
538
539 ! Assign velocity fields
540 call neko_field_registry%add_field(this%dm_Xh, 'u_adj')
541 call neko_field_registry%add_field(this%dm_Xh, 'v_adj')
542 call neko_field_registry%add_field(this%dm_Xh, 'w_adj')
543 this%u_adj => neko_field_registry%get_field('u_adj')
544 this%v_adj => neko_field_registry%get_field('v_adj')
545 this%w_adj => neko_field_registry%get_field('w_adj')
546
547 !! Initialize time-lag fields
548 call this%ulag%init(this%u_adj, 2)
549 call this%vlag%init(this%v_adj, 2)
550 call this%wlag%init(this%w_adj, 2)
551
552 ! Initiate gradient jump penalty
553 call json_get_or_default(params, &
554 'case.fluid.gradient_jump_penalty.enabled',&
555 this%if_gradient_jump_penalty, .false.)
556
557 if (this%if_gradient_jump_penalty .eqv. .true.) then
558 call neko_error('Gradient jump penalty not implemented for adjoint')
559
560 if ((this%dm_Xh%xh%lx - 1) .eq. 1) then
561 call json_get_or_default(params, &
562 'case.fluid.gradient_jump_penalty.tau',&
563 gjp_param_a, 0.02_rp)
564 gjp_param_b = 0.0_rp
565 else
566 call json_get_or_default(params, &
567 'case.fluid.gradient_jump_penalty.scaling_factor',&
568 gjp_param_a, 0.8_rp)
569 call json_get_or_default(params, &
570 'case.fluid.gradient_jump_penalty.scaling_exponent',&
571 gjp_param_b, 4.0_rp)
572 end if
573 call this%gradient_jump_penalty_u_adj%init(params, this%dm_Xh, &
574 this%c_Xh, gjp_param_a, gjp_param_b)
575 call this%gradient_jump_penalty_v_adj%init(params, this%dm_Xh, &
576 this%c_Xh, gjp_param_a, gjp_param_b)
577 call this%gradient_jump_penalty_w_adj%init(params, this%dm_Xh, &
578 this%c_Xh, gjp_param_a, gjp_param_b)
579 end if
580
581 call neko_log%end_section()
582
583 end subroutine adjoint_fluid_scheme_init_base
584
585 ! ========================================================================== !
586 ! Todo: This section need to be moved
587
588 ! !> Initialize all components of the current scheme
589 ! subroutine adjoint_fluid_scheme_init_all(this, msh, lx, params, kspv_init, &
590 ! kspp_init, scheme, user)
591 ! implicit none
592 ! class(adjoint_fluid_scheme_t), target, intent(inout) :: this
593 ! type(mesh_t), target, intent(inout) :: msh
594 ! integer, intent(inout) :: lx
595 ! type(json_file), target, intent(inout) :: params
596 ! type(user_t), target, intent(in) :: user
597 ! logical :: kspv_init
598 ! logical :: kspp_init
599 ! character(len=*), intent(in) :: scheme
600 ! real(kind=rp) :: abs_tol
601 ! integer :: integer_val, ierr
602 ! character(len=:), allocatable :: solver_type, precon_type, json_key
603 ! character(len=LOG_SIZE) :: log_buf
604
605 ! call adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, user, &
606 ! kspv_init)
607
608 ! call neko_field_registry%add_field(this%dm_Xh, 'p_adj')
609 ! this%p_adj => neko_field_registry%get_field('p_adj')
610
611 ! ! HARRY
612 ! ! Holy shit pressure BC's confuse me on a good day...
613 ! ! but they're especially confusing for the adjoint.
614 ! ! for now... I'm keeping them the same as the primal
615 ! ! but I wouldn't be surprised if this is incorrect for the adjoint
616 ! !
617 ! ! Setup pressure boundary conditions
618 ! !
619 ! call this%bcs_prs%init()
620 ! call this%bc_prs%init_base(this%c_Xh)
621 ! call this%bc_prs%mark_zones_from_list(msh%labeled_zones,&
622 ! 'o', this%bc_labels)
623 ! call this%bc_prs%mark_zones_from_list(msh%labeled_zones,&
624 ! 'on', this%bc_labels)
625
626 ! ! Field dirichlet pressure bc
627 ! call this%user_field_bc_prs%init_base(this%c_Xh)
628 ! call this%user_field_bc_prs%mark_zones_from_list(msh%labeled_zones,&
629 ! 'd_pres', this%bc_labels)
630 ! call this%user_field_bc_prs%finalize()
631 ! call MPI_Allreduce(this%user_field_bc_prs%msk(0), integer_val, 1, &
632 ! MPI_INTEGER, MPI_SUM, NEKO_COMM, ierr)
633
634 ! if (integer_val .gt. 0) call this%user_field_bc_prs%init_field('d_pres')
635 ! call this%bcs_prs%append(this%user_field_bc_prs)
636 ! call this%user_field_bc_vel%bc_list%append(this%user_field_bc_prs)
637
638 ! if (msh%outlet%size .gt. 0) then
639 ! call this%bc_prs%mark_zone(msh%outlet)
640 ! end if
641 ! if (msh%outlet_normal%size .gt. 0) then
642 ! call this%bc_prs%mark_zone(msh%outlet_normal)
643 ! end if
644
645 ! call this%bc_prs%finalize()
646 ! call this%bc_prs%set_g(0.0_rp)
647 ! call this%bcs_prs%append(this%bc_prs)
648 ! call this%bc_dong%init_base(this%c_Xh)
649 ! call this%bc_dong%mark_zones_from_list(msh%labeled_zones,&
650 ! 'o+dong', this%bc_labels)
651 ! call this%bc_dong%mark_zones_from_list(msh%labeled_zones,&
652 ! 'on+dong', this%bc_labels)
653 ! call this%bc_dong%finalize()
654
655
656 ! call this%bc_dong%init(this%c_Xh, params)
657
658 ! call this%bcs_prs%append(this%bc_dong)
659
660 ! ! Pressure solver
661 ! ! hopefully we can do the same trick here as we will eventually do for the
662 ! ! velocity solver
663 ! if (kspp_init) then
664 ! call neko_log%section("Pressure solver")
665
666 ! json_key = json_key_fallback(params, &
667 ! 'case.adjoint_fluid.pressure_solver.max_iterations', &
668 ! 'case.fluid.pressure_solver.max_iterations')
669 ! call json_get_or_default(params, json_key, integer_val, 800)
670
671 ! json_key = json_key_fallback(params, &
672 ! 'case.adjoint_fluid.pressure_solver.type', &
673 ! 'case.fluid.pressure_solver.type')
674 ! call json_get(params, json_key, solver_type)
675
676 ! json_key = json_key_fallback(params, &
677 ! 'case.adjoint_fluid.pressure_solver.preconditioner', &
678 ! 'case.fluid.pressure_solver.preconditioner')
679 ! call json_get(params, json_key, precon_type)
680
681 ! json_key = json_key_fallback(params, &
682 ! 'case.adjoint_fluid.pressure_solver.absolute_tolerance', &
683 ! 'case.fluid.pressure_solver.absolute_tolerance')
684 ! call json_get(params, json_key, abs_tol)
685
686 ! call neko_log%message('Type : ('// trim(solver_type) // &
687 ! ', ' // trim(precon_type) // ')')
688 ! write(log_buf, '(A,ES13.6)') 'Abs tol :', abs_tol
689 ! call neko_log%message(log_buf)
690
691 ! call adjoint_fluid_scheme_solver_factory(this%ksp_prs, &
692 ! this%dm_Xh%size(), &
693 ! solver_type, integer_val, abs_tol)
694 ! call adjoint_fluid_scheme_precon_factory(this%pc_prs, this%ksp_prs, &
695 ! this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_prs, precon_type)
696
697 ! call neko_log%end_section()
698
699 ! end if
700
701
702 ! call neko_log%end_section()
703
704 ! end subroutine adjoint_fluid_scheme_init_all
705
706 ! End of section to be moved
707 ! ========================================================================== !
708
710 subroutine adjoint_fluid_scheme_free(this)
711 class(adjoint_fluid_scheme_t), intent(inout) :: this
712
713 !
714 ! Free everything related to field_dirichlet BCs
715 !
716
717 call this%Xh%free()
718
719 if (allocated(this%ksp_vel)) then
720 call krylov_solver_destroy(this%ksp_vel)
721 deallocate(this%ksp_vel)
722 end if
723
724 if (allocated(this%ksp_prs)) then
725 call krylov_solver_destroy(this%ksp_prs)
726 deallocate(this%ksp_prs)
727 end if
728
729 if (allocated(this%pc_vel)) then
730 call precon_destroy(this%pc_vel)
731 deallocate(this%pc_vel)
732 end if
733
734 if (allocated(this%pc_prs)) then
735 call precon_destroy(this%pc_prs)
736 deallocate(this%pc_prs)
737 end if
738
739 call this%source_term%free()
740
741 call this%gs_Xh%free()
742
743 call this%c_Xh%free()
744
745 call this%scratch%free()
746
747 nullify(this%u_adj)
748 nullify(this%v_adj)
749 nullify(this%w_adj)
750 nullify(this%p_adj)
751
752 call this%ulag%free()
753 call this%vlag%free()
754 call this%wlag%free()
755
756
757 if (associated(this%f_adj_x)) then
758 call this%f_adj_x%free()
759 end if
760
761 if (associated(this%f_adj_y)) then
762 call this%f_adj_y%free()
763 end if
764
765 if (associated(this%f_adj_z)) then
766 call this%f_adj_z%free()
767 end if
768
769 nullify(this%f_adj_x)
770 nullify(this%f_adj_y)
771 nullify(this%f_adj_z)
772
773 call this%mu_field%free()
774
775 ! Free gradient jump penalty
776 if (this%if_gradient_jump_penalty .eqv. .true.) then
777 call this%gradient_jump_penalty_u_adj%free()
778 call this%gradient_jump_penalty_v_adj%free()
779 call this%gradient_jump_penalty_w_adj%free()
780 end if
781
782 end subroutine adjoint_fluid_scheme_free
783
786 subroutine adjoint_fluid_scheme_validate(this)
787 class(adjoint_fluid_scheme_t), target, intent(inout) :: this
788 ! Variables for retrieving json parameters
789
790 if ((.not. associated(this%u_adj)) .or. &
791 (.not. associated(this%v_adj)) .or. &
792 (.not. associated(this%w_adj)) .or. &
793 (.not. associated(this%p_adj))) then
794 call neko_error('Fields are not registered')
795 end if
796
797 if ((.not. allocated(this%u_adj%x)) .or. &
798 (.not. allocated(this%v_adj%x)) .or. &
799 (.not. allocated(this%w_adj%x)) .or. &
800 (.not. allocated(this%p_adj%x))) then
801 call neko_error('Fields are not allocated')
802 end if
803
804 if (.not. allocated(this%ksp_vel)) then
805 call neko_error('No Krylov solver for velocity defined')
806 end if
807
808 if (.not. allocated(this%ksp_prs)) then
809 call neko_error('No Krylov solver for pressure defined')
810 end if
811
812 !
813 ! Setup checkpoint structure (if everything is fine)
814 !
815 call this%chkp%init(this%u_adj, this%v_adj, this%w_adj, this%p_adj)
816
817 end subroutine adjoint_fluid_scheme_validate
818
823 subroutine adjoint_fluid_scheme_bc_apply_vel(this, t, tstep, strong)
824 class(adjoint_fluid_scheme_t), intent(inout) :: this
825 real(kind=rp), intent(in) :: t
826 integer, intent(in) :: tstep
827 logical, intent(in) :: strong
828
829 call this%bcs_vel%apply_vector(&
830 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
831 t, tstep, strong)
832
833 end subroutine adjoint_fluid_scheme_bc_apply_vel
834
837 subroutine adjoint_fluid_scheme_bc_apply_prs(this, t, tstep)
838 class(adjoint_fluid_scheme_t), intent(inout) :: this
839 real(kind=rp), intent(in) :: t
840 integer, intent(in) :: tstep
841
842 call this%bcs_prs%apply(this%p_adj, t, tstep)
843
844 end subroutine adjoint_fluid_scheme_bc_apply_prs
845
848 subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, &
849 max_iter, abstol, monitor)
850 class(ksp_t), allocatable, target, intent(inout) :: ksp
851 integer, intent(in), value :: n
852 character(len=*), intent(in) :: solver
853 integer, intent(in) :: max_iter
854 real(kind=rp), intent(in) :: abstol
855 logical, intent(in) :: monitor
856
857 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
858 monitor = monitor)
859
860 end subroutine adjoint_fluid_scheme_solver_factory
861
863 subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, dof, gs, &
864 bclst, pctype)
865 class(adjoint_fluid_scheme_t), intent(inout) :: this
866 class(pc_t), allocatable, target, intent(inout) :: pc
867 class(ksp_t), target, intent(inout) :: ksp
868 type(coef_t), target, intent(in) :: coef
869 type(dofmap_t), target, intent(in) :: dof
870 type(gs_t), target, intent(inout) :: gs
871 type(bc_list_t), target, intent(inout) :: bclst
872 character(len=*) :: pctype
873
874 call precon_factory(pc, pctype)
875
876 select type (pcp => pc)
877 type is (jacobi_t)
878 call pcp%init(coef, dof, gs)
879 type is (sx_jacobi_t)
880 call pcp%init(coef, dof, gs)
881 type is (device_jacobi_t)
882 call pcp%init(coef, dof, gs)
883 type is (hsmg_t)
884 if (len_trim(pctype) .gt. 4) then
885 if (index(pctype, '+') .eq. 5) then
886 call pcp%init(dof%msh, dof%Xh, coef, dof, gs, bclst, &
887 trim(pctype(6:)))
888 else
889 call neko_error('Unknown coarse grid solver')
890 end if
891 else
892 call pcp%init(dof%msh, dof%Xh, coef, dof, gs, bclst)
893 end if
894 type is (phmg_t)
895 call pcp%init(dof%msh, dof%Xh, coef, dof, gs, bclst)
896 end select
897
898 call ksp%set_pc(pc)
899
900 end subroutine adjoint_fluid_scheme_precon_factory
901
903 ! TODO
904 ! HARRY
905 ! ok this needs to be discussed.
906 ! To me, the CFL is based on the convecting velocity, so I would argue
907 ! that the CFL of the adjoint is based on
908 ! u, v, w
909 ! not
910 ! u_adj, v_adj, w_adj
911 !
912 ! Then again, this function is really only used for varaible timestep,
913 ! which we can't use if we're checkpointing...
914 !
915 ! hmmmmm.... requires more thought. Because people optimal ICs or Arnouldi
916 ! may use variable timesteps... or us in a steady case..
917 !
918 ! for now.... let's ignore it
919 function adjoint_compute_cfl(this, dt) result(c)
920 class(adjoint_fluid_scheme_t), intent(in) :: this
921 real(kind=rp), intent(in) :: dt
922 real(kind=rp) :: c
923
924 c = cfl(dt, this%u_adj%x, this%v_adj%x, this%w_adj%x, &
925 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
926
927 end function adjoint_compute_cfl
928
929 ! ========================================================================== !
930 ! Todo: This section need to be moved
931
932 ! !> Set boundary types for the diagnostic output.
933 ! !! @param params The JSON case file.
934 ! subroutine adjoint_fluid_scheme_set_bc_type_output(this, params)
935 ! class(adjoint_fluid_scheme_t), intent(inout) :: this
936 ! type(json_file), intent(inout) :: params
937 ! type(dirichlet_t) :: bdry_mask
938 ! logical :: found
939
940 ! !
941 ! ! Check if we need to output boundaries
942 ! !
943 ! call json_get_or_default(params, 'case.output_boundary', found, .false.)
944
945 ! if (found) then
946 ! call this%bdry%init(this%dm_Xh, 'bdry')
947 ! this%bdry = 0.0_rp
948
949 ! call bdry_mask%init_base(this%c_Xh)
950 ! call bdry_mask%mark_zone(this%msh%wall)
951 ! call bdry_mask%mark_zones_from_list(this%msh%labeled_zones,&
952 ! 'w', this%bc_labels)
953 ! call bdry_mask%finalize()
954 ! call bdry_mask%set_g(1.0_rp)
955 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
956 ! call bdry_mask%free()
957
958 ! call bdry_mask%init_base(this%c_Xh)
959 ! call bdry_mask%mark_zone(this%msh%inlet)
960 ! call bdry_mask%mark_zones_from_list(this%msh%labeled_zones,&
961 ! 'v', this%bc_labels)
962 ! call bdry_mask%finalize()
963 ! call bdry_mask%set_g(2.0_rp)
964 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
965 ! call bdry_mask%free()
966
967 ! call bdry_mask%init_base(this%c_Xh)
968 ! call bdry_mask%mark_zone(this%msh%outlet)
969 ! call bdry_mask%mark_zones_from_list(this%msh%labeled_zones,&
970 ! 'o', this%bc_labels)
971 ! call bdry_mask%finalize()
972 ! call bdry_mask%set_g(3.0_rp)
973 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
974 ! call bdry_mask%free()
975
976 ! call bdry_mask%init_base(this%c_Xh)
977 ! call bdry_mask%mark_zone(this%msh%sympln)
978 ! call bdry_mask%mark_zones_from_list(this%msh%labeled_zones,&
979 ! 'sym', this%bc_labels)
980 ! call bdry_mask%finalize()
981 ! call bdry_mask%set_g(4.0_rp)
982 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
983 ! call bdry_mask%free()
984
985 ! call bdry_mask%init_base(this%c_Xh)
986 ! call bdry_mask%mark_zone(this%msh%outlet_normal)
987 ! call bdry_mask%mark_zones_from_list(this%msh%labeled_zones,&
988 ! 'on', this%bc_labels)
989 ! call bdry_mask%finalize()
990 ! call bdry_mask%set_g(5.0_rp)
991 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
992 ! call bdry_mask%free()
993
994 ! call bdry_mask%init_base(this%c_Xh)
995 ! call bdry_mask%mark_zone(this%msh%periodic)
996 ! call bdry_mask%finalize()
997 ! call bdry_mask%set_g(6.0_rp)
998 ! call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
999 ! call bdry_mask%free()
1000 ! end if
1001
1002 ! end subroutine adjoint_fluid_scheme_set_bc_type_output
1003
1004 ! End of section to be moved
1005 ! ========================================================================== !
1006
1007
1009 subroutine adjoint_fluid_scheme_update_material_properties(this)
1010 class(adjoint_fluid_scheme_t), intent(inout) :: this
1011 type(field_t), pointer :: nut
1012 integer :: n
1013
1014 this%mu_field = this%mu
1015 if (this%variable_material_properties) then
1016 nut => neko_field_registry%get_field(this%nut_field_name)
1017 n = nut%size()
1018 call field_add2s2(this%mu_field, nut, this%rho, n)
1019 end if
1020
1021 end subroutine adjoint_fluid_scheme_update_material_properties
1022
1026 subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
1027 class(adjoint_fluid_scheme_t), intent(inout) :: this
1028 type(json_file), intent(inout) :: params
1029 type(user_t), target, intent(in) :: user
1030 character(len=LOG_SIZE) :: log_buf
1031 ! A local pointer that is needed to make Intel happy
1032 procedure(user_material_properties), pointer :: dummy_mp_ptr
1033 real(kind=rp) :: dummy_lambda, dummy_cp
1034
1035 dummy_mp_ptr => dummy_user_material_properties
1036
1037 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
1038
1039 write(log_buf, '(A)') "Material properties must be set in the user&
1040 & file!"
1041 call neko_log%message(log_buf)
1042 call user%material_properties(0.0_rp, 0, this%rho, this%mu, &
1043 dummy_cp, dummy_lambda, params)
1044 else
1045
1046 ! Incorrect user input
1047 if (params%valid_path('case.fluid.Re') .and. &
1048 (params%valid_path('case.fluid.mu') .or. &
1049 params%valid_path('case.fluid.rho'))) then
1050 call neko_error("To set the material properties for the fluid,&
1051 & either provide Re OR mu and rho in the case file.")
1052
1053 ! Non-dimensional case
1054 else if (params%valid_path('case.fluid.Re')) then
1055
1056 write(log_buf, '(A)') 'Non-dimensional fluid material properties &
1057 & input.'
1058 call neko_log%message(log_buf, lvl = neko_log_verbose)
1059 write(log_buf, '(A)') 'Density will be set to 1, dynamic viscosity to&
1060 & 1/Re.'
1061 call neko_log%message(log_buf, lvl = neko_log_verbose)
1062
1063 ! Read Re into mu for further manipulation.
1064 call json_get(params, 'case.fluid.Re', this%mu)
1065 write(log_buf, '(A)') 'Read non-dimensional material properties'
1066 call neko_log%message(log_buf)
1067 write(log_buf, '(A,ES13.6)') 'Re :', this%mu
1068 call neko_log%message(log_buf)
1069
1070 ! Set rho to 1 since the setup is non-dimensional.
1071 this%rho = 1.0_rp
1072 ! Invert the Re to get viscosity.
1073 this%mu = 1.0_rp/this%mu
1074 ! Dimensional case
1075 else
1076 call json_get(params, 'case.fluid.mu', this%mu)
1077 call json_get(params, 'case.fluid.rho', this%rho)
1078 end if
1079
1080 end if
1081 end subroutine adjoint_fluid_scheme_set_material_properties
1082
1083end module adjoint_fluid_scheme
Abstract interface to dealocate an adjoint formulation.
Abstract interface to initialize an adjoint formulation.
Abstract interface to restart an adjoint scheme.
Abstract interface to setup boundary conditions.
subroutine adjoint_fluid_scheme_validate(this)
Validate that all fields, solvers etc necessary for performing time-stepping are defined.
real(kind=rp) function adjoint_compute_cfl(this, dt)
Compute CFL.
subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, dof, gs, bclst, pctype)
Initialize a Krylov preconditioner.
subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, max_iter, abstol, monitor)
Initialize a linear solver.
subroutine adjoint_fluid_scheme_bc_apply_vel(this, t, tstep, strong)
Apply all boundary conditions defined for velocity Here we perform additional gs operations to take c...
subroutine adjoint_fluid_scheme_update_material_properties(this)
Update the values of mu_field if necessary.
subroutine adjoint_fluid_scheme_bc_apply_prs(this, t, tstep)
Apply all boundary conditions defined for pressure.
subroutine adjoint_fluid_scheme_free(this)
Deallocate a fluid formulation.
subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, user, kspv_init)
Initialise an adjoint scheme.
subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
Sets rho and mu.
Implements the adjoint_source_term_t type.
character(len=:) function, allocatable, public json_key_fallback(json, lookup, fallback)
Create a json_string based on fallback logic. If the lookup key is present in the json object,...
User defined user region.
Definition user.f90:2
Wrapper contaning and executing the adjoint source terms.