39 use num_types,
only: rp
43 use json_module,
only: json_file
44 use json_utils,
only: json_get_or_default
45 use field,
only: field_t
46 use field_math,
only: field_copy, field_cadd, field_col2, field_cmult
47 use neko_config,
only: neko_bcknd_device
48 use math,
only: glsc2, copy
49 use device_math,
only: device_glsc2, device_copy
51 use coefs,
only: coef_t
52 use scratch_registry,
only: neko_scratch_registry
53 use utils,
only: neko_error
58 use field_math,
only: field_addcol3, field_col3
69 type(field_t),
pointer :: phi
71 real(kind=rp) :: phi_ref
73 class(coef_t),
pointer :: coef
75 real(kind=rp) :: domain_volume
77 character(len=:),
allocatable :: scalar_name
83 type(field_t),
pointer :: u, v, w, u_adj, v_adj, w_adj
88 procedure,
public, pass(this) :: init_json_sim => &
91 procedure,
public, pass(this) :: init_from_attributes => &
92 scalar_mixing_init_attributes
94 procedure,
public, pass(this) :: free => scalar_mixing_free
96 procedure,
public, pass(this) :: update_value => &
97 scalar_mixing_update_value
99 procedure,
public, pass(this) :: update_sensitivity => &
100 scalar_mixing_update_sensitivity
113 type(json_file),
intent(inout) :: json
114 class(
design_t),
intent(in) :: design
116 real(kind=rp) :: weight
117 real(kind=rp) :: phi_ref
118 character(len=:),
allocatable :: name
119 character(len=:),
allocatable :: mask_name
120 character(len=:),
allocatable :: scalar_name
122 call json_get_or_default(json,
"weight", weight, 1.0_rp)
123 call json_get_or_default(json,
"mask_name", mask_name,
"")
124 call json_get_or_default(json,
"target_concentration", phi_ref, 0.5_rp)
125 call json_get_or_default(json,
"name", name,
"Scalar Mixing")
126 call json_get_or_default(json,
"scalar_name", scalar_name,
"s")
129 call this%init_from_attributes(
design, simulation, weight, name, &
130 mask_name, phi_ref, scalar_name)
142 subroutine scalar_mixing_init_attributes(this, design, simulation, weight, &
143 name, mask_name, phi_ref, scalar_name)
145 class(
design_t),
intent(in) :: design
147 real(kind=rp),
intent(in) :: weight
148 real(kind=rp),
intent(in) :: phi_ref
149 character(len=*),
intent(in) :: mask_name
150 character(len=*),
intent(in) :: name
151 character(len=*),
intent(in) :: scalar_name
154 integer :: i_scalar, i_adjoint_scalar
157 if (.not.
allocated(simulation%adjoint_case%adjoint_scalars))
then
158 call neko_error(
"adjoint passive scalar not initialized")
162 call this%init_base(name,
design%size(), weight, mask_name)
165 this%coef => simulation%fluid%c_Xh
168 if (this%has_mask)
then
171 this%domain_volume = this%coef%volume
174 this%scalar_name = trim(scalar_name)
178 simulation%adjoint_scalars, this%scalar_name)
182 associate(f_phi_adj => &
183 simulation%adjoint_scalars%adjoint_scalar_fields(i_adjoint_scalar)%f_Xh)
186 this%phi_ref = phi_ref
189 this%phi => simulation%scalars%scalar_fields(i_scalar)%s
192 call adjoint_forcing%init_from_components(f_phi_adj, this%phi, &
193 this%get_weight(), this%phi_ref, this%mask, this%has_mask, this%coef)
198 call simulation%adjoint_scalars%adjoint_scalar_fields(i_adjoint_scalar) &
199 %source_term%add_source_term(adjoint_forcing)
203 this%u => simulation%fluid%u
204 this%v => simulation%fluid%v
205 this%w => simulation%fluid%w
206 this%u_adj => simulation%adjoint_fluid%u_adj
207 this%v_adj => simulation%adjoint_fluid%v_adj
208 this%w_adj => simulation%adjoint_fluid%w_adj
209 end subroutine scalar_mixing_init_attributes
212 subroutine scalar_mixing_free(this)
214 call this%free_base()
224 end subroutine scalar_mixing_free
229 subroutine scalar_mixing_update_value(this, design)
231 class(design_t),
intent(in) :: design
232 type(field_t),
pointer :: work
233 integer :: temp_indices(1), n
241 call neko_scratch_registry%request_field(work, temp_indices(1), .false.)
245 call field_copy(work, this%phi)
247 call field_cadd(work, -this%phi_ref)
249 call field_col2(work, work)
251 if (this%has_mask)
then
252 call mask_exterior_const(work, this%mask, 0.0_rp)
255 if (neko_bcknd_device .eq. 1)
then
256 this%value = device_glsc2(work%x_d, this%coef%B_d, n)
258 this%value = glsc2(work%x, this%coef%B, n)
262 this%value = 0.5_rp * this%value / this%domain_volume
265 call neko_scratch_registry%relinquish_field(temp_indices)
266 end subroutine scalar_mixing_update_value
272 subroutine scalar_mixing_update_sensitivity(this, design)
274 class(design_t),
intent(in) :: design
276 end subroutine scalar_mixing_update_sensitivity
Implements the adjoint_mixing_scalar_source_term type.
Some common Masking operations we may need.
real(kind=rp) function, public compute_masked_volume(mask, coef)
Compute the volume of the domain contained within the mask.
Contains extensions to the neko library required to run the topology optimization code.
subroutine, public get_scalar_indicies(i_primal, i_adjoint, scalars, adjoint_scalars, primal_name)
get scalar indices
Implements the objective_t type.
An objective function corresponding to the mixing of a passive scalar .
subroutine scalar_mixing_init_json_sim(this, json, design, simulation)
The common constructor using a JSON object.
Implements the steady_problem_t type.
The abstract objective type.
An objective function corresponding to the mixing of a passive scalar .