Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
neko_ext.f90
Go to the documentation of this file.
1
39
43 use case, only: case_t
44 use adjoint_case, only: adjoint_case_t
45 use json_utils, only: json_get, json_get_or_default
46 use num_types, only: rp
47 use simcomp_executor, only: neko_simcomps
48 use flow_ic, only: set_flow_ic
49 use scalar_ic, only: set_scalar_ic
50 use field, only: field_t
51 use chkp_output, only: chkp_output_t
52 use output_controller, only: output_controller_t
53 ! for vector/field math
54 use math, only: copy
55 use device_math, only: device_copy
56 use neko_config, only : neko_bcknd_device
57 use vector, only: vector_t
58 use field, only: field_t
59 use utils, only: neko_error
60 use json_module, only : json_file
61 use scalars, only: scalars_t
63 use field_math, only: field_rzero, field_copy
64 use fluid_pnpn, only: fluid_pnpn_t
66
67 implicit none
68
69 ! ========================================================================= !
70 ! Module interface
71 ! ========================================================================= !
72 private
75
76contains
77
78 ! ========================================================================= !
79 ! Public routines
80 ! ========================================================================= !
81
90 subroutine reset(neko_case)
91 type(case_t), intent(inout) :: neko_case
92 real(kind=rp) :: t
93 integer :: i
94 character(len=:), allocatable :: string_val
95 logical :: has_scalar, freezeflow
96 type(field_t), pointer :: u, v, w, p, s
97 type(json_file) :: json_subdict
98
99 ! ------------------------------------------------------------------------ !
100 ! Setup shorthand notation
101 ! ------------------------------------------------------------------------ !
102
103 u => neko_case%fluid%u
104 v => neko_case%fluid%v
105 w => neko_case%fluid%w
106 p => neko_case%fluid%p
107 if (allocated(neko_case%scalars)) then
108 s => neko_case%scalars%scalar_fields(1)%scalar%s
109 else
110 nullify(s)
111 end if
112
113 ! ------------------------------------------------------------------------ !
114 ! Reset the timing parameters
115 ! ------------------------------------------------------------------------ !
116
117 call neko_case%time%reset()
118 t = neko_case%time%start_time
119 do i = 1, size(neko_case%time%tlag)
120 neko_case%time%tlag(i) = t - i*neko_case%time%dtlag(i)
121 end do
122
123 ! Reset the time step counter
124 call neko_case%output_controller%set_counter(neko_case%time)
125
126 ! Restart the fields
127 call neko_case%fluid%restart(neko_case%chkp)
128 if (allocated(neko_case%scalars)) then
129 call neko_case%scalars%restart(neko_case%chkp)
130 end if
131
132 ! Reset the external BDF coefficients
133 do i = 1, size(neko_case%time%dtlag)
134 call neko_case%fluid%ext_bdf%set_coeffs(neko_case%time%dtlag)
135 end do
136
137 ! Restart the simulation components
138 call neko_simcomps%restart(neko_case%time)
139
140 ! ------------------------------------------------------------------------ !
141 ! Reset the fluid field to the initial condition
142 ! ------------------------------------------------------------------------ !
143
144 call json_get(neko_case%params, &
145 'case.fluid.initial_condition.type', string_val)
146 call json_get(neko_case%params, 'case.fluid.initial_condition', &
147 json_subdict)
148
149 if (trim(string_val) .ne. 'user') then
150 call set_flow_ic(u, v, w, p, &
151 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
152 string_val, json_subdict)
153 else
154 call set_flow_ic(u, v, w, p, &
155 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
156 neko_case%user%initial_conditions, neko_case%fluid%name)
157 end if
158
159 ! set lags to IC
160 call neko_case%fluid%ulag%set(u)
161 call neko_case%fluid%vlag%set(v)
162 call neko_case%fluid%wlag%set(w)
163 ! zero out RHS etc
164 select type (f => neko_case%fluid)
165 type is (fluid_pnpn_t)
166 call field_rzero(f%abx1)
167 call field_rzero(f%aby1)
168 call field_rzero(f%abz1)
169 call field_rzero(f%abx2)
170 call field_rzero(f%aby2)
171 call field_rzero(f%abz2)
172 call field_copy(f%u_e, u)
173 call field_copy(f%v_e, v)
174 call field_copy(f%w_e, w)
175 end select
176 call field_rzero(neko_case%fluid%f_x)
177 call field_rzero(neko_case%fluid%f_y)
178 call field_rzero(neko_case%fluid%f_z)
179 ! ------------------------------------------------------------------------ !
180 ! Reset the scalar field to the initial condition
181 ! ------------------------------------------------------------------------ !
182
183 ! check for a single scalar
184 call json_get_or_default(neko_case%params, &
185 'case.scalar.enabled', has_scalar, .false.)
186
187 if (has_scalar) then
188 ! check for multiple scalars
189 if (size(neko_case%scalars%scalar_fields) .gt. 1) then
190 call neko_error('Multiple scalars not supported')
191 end if
192 ! zero out RHS
193 call field_rzero(neko_case%scalars%scalar_fields(1)%scalar%f_Xh)
194 ! reset the forward scalar
195 call json_get(neko_case%params, &
196 'case.scalar.initial_condition.type', string_val)
197 call json_get(neko_case%params, &
198 'case.scalar.initial_condition', json_subdict)
199 if (trim(string_val) .ne. 'user') then
200 if (trim(neko_case%scalars%scalar_fields(1)%scalar%name) .eq. &
201 'temperature') then
202 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%scalar%s, &
203 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
204 json_subdict, 0)
205 else
206 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%scalar%s, &
207 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
208 json_subdict, 1)
209 end if
210 else
211 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%scalar%name, &
212 neko_case%scalars%scalar_fields(1)%scalar%s, &
213 neko_case%scalars%scalar_fields(1)%scalar%c_Xh, &
214 neko_case%scalars%scalar_fields(1)%scalar%gs_Xh, &
215 neko_case%user%initial_conditions)
216 end if
217 ! set lags to IC
218 call neko_case%scalars%scalar_fields(1)%scalar%slag%set(&
219 neko_case%scalars%scalar_fields(1)%scalar%s)
220 end if
221
222 ! ------------------------------------------------------------------------ !
223 ! Reset the "freeze" parameter of the flow
224 ! ------------------------------------------------------------------------ !
225
226 call json_get_or_default(neko_case%params, &
227 'case.fluid.freeze_flow', freezeflow, .false.)
228
229 neko_case%fluid%freeze = freezeflow
230
231 end subroutine reset
232
242 subroutine reset_adjoint(adjoint_case, neko_case)
243 type(adjoint_case_t), intent(inout) :: adjoint_case
244 type(case_t), intent(inout) :: neko_case
245 real(kind=rp) :: t
246 integer :: i
247 character(len=:), allocatable :: string_val
248 logical :: has_scalar, freezeflow
249 type(field_t), pointer :: u_adj, v_adj, w_adj, p_adj, s_adj
250 type(json_file) :: json_subdict
251
252 ! ------------------------------------------------------------------------ !
253 ! Setup shorthand notation
254 ! ------------------------------------------------------------------------ !
255
256 u_adj => adjoint_case%fluid_adj%u_adj
257 v_adj => adjoint_case%fluid_adj%v_adj
258 w_adj => adjoint_case%fluid_adj%w_adj
259 p_adj => adjoint_case%fluid_adj%p_adj
260 if (allocated(adjoint_case%adjoint_scalars)) then
261 s_adj => adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj
262 else
263 nullify(s_adj)
264 end if
265
266 ! ------------------------------------------------------------------------ !
267 ! Reset the timing parameters
268 ! ------------------------------------------------------------------------ !
269
270 call adjoint_case%time%reset()
271 t = adjoint_case%time%start_time
272 do i = 1, size(adjoint_case%time%tlag)
273 adjoint_case%time%tlag(i) = t - i*adjoint_case%time%dtlag(i)
274 end do
275
276 ! Reset the time step counter
277 call adjoint_case%output_controller%set_counter(adjoint_case%time)
278 if (adjoint_case%norm_output_enabled) then
279 call adjoint_case%norm_output_ctrl%set_counter(adjoint_case%time)
280 end if
281
282 ! Reset the external BDF coefficients
283 do i = 1, size(adjoint_case%time%dtlag)
284 call adjoint_case%fluid_adj%ext_bdf%set_coeffs(adjoint_case%time%dtlag)
285 end do
286
287 ! ------------------------------------------------------------------------ !
288 ! Reset the adjoint fluid to the initial (final) condition
289 ! ------------------------------------------------------------------------ !
290
291 ! don't fallback to the fluid here
292 call json_get(neko_case%params, &
293 'case.adjoint_fluid.initial_condition.type', string_val)
294 call json_get(neko_case%params, 'case.adjoint_fluid.initial_condition', &
295 json_subdict)
296
297 if (trim(string_val) .ne. 'user') then
298 call set_flow_ic(u_adj, v_adj, w_adj, p_adj, &
299 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
300 string_val, json_subdict)
301 else
302 call neko_error("adjoint user initial conditions not supported")
303 end if
304
305 ! set lags to IC
306 call adjoint_case%fluid_adj%ulag%set(u_adj)
307 call adjoint_case%fluid_adj%vlag%set(v_adj)
308 call adjoint_case%fluid_adj%wlag%set(w_adj)
309 ! zero out RHS etc
310 select type (f => adjoint_case%fluid_adj)
311 type is (adjoint_fluid_pnpn_t)
312 call field_rzero(f%abx1)
313 call field_rzero(f%aby1)
314 call field_rzero(f%abz1)
315 call field_rzero(f%abx2)
316 call field_rzero(f%aby2)
317 call field_rzero(f%abz2)
318 end select
319 ! zero out all lags etc
320 ! (not sure what to do with the abx's_adj)
321 call field_rzero(adjoint_case%fluid_adj%f_adj_x)
322 call field_rzero(adjoint_case%fluid_adj%f_adj_y)
323 call field_rzero(adjoint_case%fluid_adj%f_adj_z)
324 ! ------------------------------------------------------------------------ !
325 ! Reset the scalar field to the initial condition
326 ! ------------------------------------------------------------------------ !
327
328 ! check for a single scalar
329 call json_get_or_default(neko_case%params, 'case.scalar.enabled', &
330 has_scalar, .false.)
331
332 if (has_scalar) then
333 ! check for multiple adjoint_scalars
334 if (size(adjoint_case%adjoint_scalars%adjoint_scalar_fields) .gt. 1) then
335 call neko_error('Multiple adjoint scalars not supported')
336 end if
337 ! zero out lag terms
338 call field_rzero( &
339 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%f_Xh)
340 ! reset the forward scalar
341 call json_get(neko_case%params, &
342 'case.adjoint_scalar.initial_condition.type', string_val)
343 call json_get(neko_case%params, &
344 'case.adjoint_scalar.initial_condition', json_subdict)
345 if (trim(string_val) .ne. 'user') then
346 if (trim(neko_case%scalars%scalar_fields(1)%scalar%name) .eq. &
347 'temperature') then
348 call set_scalar_ic( &
349 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
350 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
351 string_val, json_subdict, 0)
352 else
353 call set_scalar_ic( &
354 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
355 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
356 string_val, json_subdict, 1)
357 end if
358 else
359 call neko_error("adjoint scalar user IC not supported")
360 end if
361 ! set lags to IC
362 call adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj_lag% &
363 set(adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj)
364 end if
365
366 ! ------------------------------------------------------------------------ !
367 ! Reset the "freeze" parameter of the flow
368 ! ------------------------------------------------------------------------ !
369
370 call json_get_or_default(neko_case%params, &
371 'case.adjoint_fluid.freeze_flow', freezeflow, .false.)
372
373 adjoint_case%fluid_adj%freeze = freezeflow
374
375 end subroutine reset_adjoint
376
384 subroutine vector_to_field(field, vector)
385 type(field_t), intent(inout) :: field
386 type(vector_t), intent(in) :: vector
387
388 ! first check they're the same size
389 if (field%size() .ne. vector%size()) then
390 call neko_error("vector and field are not the same size")
391 end if
392
393 if (neko_bcknd_device .eq. 1) then
394 call device_copy(field%x_d, vector%x_d, field%size())
395 else
396 call copy(field%x, vector%x, field%size())
397 end if
398
399 end subroutine vector_to_field
400
408 subroutine field_to_vector(vector, field)
409 type(vector_t), intent(inout) :: vector
410 type(field_t), intent(in) :: field
411
412 ! first check they're the same size
413 if (field%size() .ne. vector%size()) then
414 call neko_error("vector and field are not the same size")
415 end if
416
417 if (neko_bcknd_device .eq. 1) then
418 call device_copy(vector%x_d, field%x_d, field%size())
419 else
420 call copy(vector%x, field%x, field%size())
421 end if
422
423 end subroutine field_to_vector
424
433 subroutine get_scalar_indicies(i_primal, i_adjoint, scalars, &
434 adjoint_scalars, primal_name)
435 integer, intent(out) :: i_primal
436 integer, intent(out) :: i_adjoint
437 type(scalars_t), intent(inout) :: scalars
438 type(adjoint_scalars_t), intent(inout) :: adjoint_scalars
439 character(len=*), intent(in) :: primal_name
440 integer :: i, n_primal_scalars, n_adjoint_scalars
441
442 i_primal = -1
443 i_adjoint = -1
444 n_adjoint_scalars = size(adjoint_scalars%adjoint_scalar_fields)
445 n_primal_scalars = size(scalars%scalar_fields)
446
447 if ((n_adjoint_scalars .eq. 1) .and. (n_primal_scalars .eq. 1)) then
448 i_primal = 1
449 i_adjoint = 1
450 return
451 end if
452
453 do i = 1, n_adjoint_scalars
454 if (adjoint_scalars%adjoint_scalar_fields(i)%primal_name &
455 .eq. primal_name) then
456 i_adjoint = i
457 exit
458 end if
459 end do
460
461 do i = 1, n_primal_scalars
462 if (scalars%scalar_fields(i)%scalar%name .eq. primal_name) then
463 i_primal = i
464 exit
465 end if
466 end do
467
468 if (i_primal .le. 0 .or. i_adjoint .le. 0) then
469 call neko_error('could not find matching primal and adjoint' // &
470 ' scalar fields')
471 end if
472
473 end subroutine get_scalar_indicies
474
475end module neko_ext
Adjoint Pn/Pn formulation.
Contains the adjoint_scalars_t type that manages multiple scalar fields.
Contains extensions to the neko library required to run the topology optimization code.
Definition neko_ext.f90:42
subroutine, public field_to_vector(vector, field)
Field to vector.
Definition neko_ext.f90:409
subroutine, public reset(neko_case)
Reset the case data structure.
Definition neko_ext.f90:91
subroutine, public reset_adjoint(adjoint_case, neko_case)
Reset the adjoint case data structure.
Definition neko_ext.f90:243
subroutine, public vector_to_field(field, vector)
Vector to field.
Definition neko_ext.f90:385
subroutine, public get_scalar_indicies(i_primal, i_adjoint, scalars, adjoint_scalars, primal_name)
get scalar indices
Definition neko_ext.f90:435
Adjoint case type. Todo: This should Ideally be a subclass of case_t, however, that is not yet suppor...
Type to manage multiple adjoint scalar transport equations.