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)%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)%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)%name) .eq. &
201 'temperature') then
202 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%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)%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)%name, &
212 neko_case%scalars%scalar_fields(1)%s, &
213 neko_case%scalars%scalar_fields(1)%c_Xh, &
214 neko_case%scalars%scalar_fields(1)%gs_Xh, &
215 neko_case%user%initial_conditions)
216 end if
217 ! set lags to IC
218 call neko_case%scalars%scalar_fields(1)%slag%set(&
219 neko_case%scalars%scalar_fields(1)%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
279 ! Reset the external BDF coefficients
280 do i = 1, size(adjoint_case%time%dtlag)
281 call adjoint_case%fluid_adj%ext_bdf%set_coeffs(adjoint_case%time%dtlag)
282 end do
283
284 ! ------------------------------------------------------------------------ !
285 ! Reset the adjoint fluid to the initial (final) condition
286 ! ------------------------------------------------------------------------ !
287
288 ! don't fallback to the fluid here
289 call json_get(neko_case%params, &
290 'case.adjoint_fluid.initial_condition.type', string_val)
291 call json_get(neko_case%params, 'case.adjoint_fluid.initial_condition', &
292 json_subdict)
293
294 if (trim(string_val) .ne. 'user') then
295 call set_flow_ic(u_adj, v_adj, w_adj, p_adj, &
296 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
297 string_val, json_subdict)
298 else
299 call neko_error("adjoint user initial conditions not supported")
300 end if
301
302 ! set lags to IC
303 call adjoint_case%fluid_adj%ulag%set(u_adj)
304 call adjoint_case%fluid_adj%vlag%set(v_adj)
305 call adjoint_case%fluid_adj%wlag%set(w_adj)
306 ! zero out RHS etc
307 select type (f => adjoint_case%fluid_adj)
308 type is (adjoint_fluid_pnpn_t)
309 call field_rzero(f%abx1)
310 call field_rzero(f%aby1)
311 call field_rzero(f%abz1)
312 call field_rzero(f%abx2)
313 call field_rzero(f%aby2)
314 call field_rzero(f%abz2)
315 end select
316 ! zero out all lags etc
317 ! (not sure what to do with the abx's_adj)
318 call field_rzero(adjoint_case%fluid_adj%f_adj_x)
319 call field_rzero(adjoint_case%fluid_adj%f_adj_y)
320 call field_rzero(adjoint_case%fluid_adj%f_adj_z)
321 ! ------------------------------------------------------------------------ !
322 ! Reset the scalar field to the initial condition
323 ! ------------------------------------------------------------------------ !
324
325 ! check for a single scalar
326 call json_get_or_default(neko_case%params, 'case.scalar.enabled', &
327 has_scalar, .false.)
328
329 if (has_scalar) then
330 ! check for multiple adjoint_scalars
331 if (size(adjoint_case%adjoint_scalars%adjoint_scalar_fields) .gt. 1) then
332 call neko_error('Multiple adjoint scalars not supported')
333 end if
334 ! zero out lag terms
335 call field_rzero( &
336 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%f_Xh)
337 ! reset the forward scalar
338 call json_get(neko_case%params, &
339 'case.adjoint_scalar.initial_condition.type', string_val)
340 call json_get(neko_case%params, &
341 'case.adjoint_scalar.initial_condition', json_subdict)
342 if (trim(string_val) .ne. 'user') then
343 if (trim(neko_case%scalars%scalar_fields(1)%name) .eq. &
344 'temperature') then
345 call set_scalar_ic( &
346 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
347 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
348 string_val, json_subdict, 0)
349 else
350 call set_scalar_ic( &
351 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
352 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
353 string_val, json_subdict, 1)
354 end if
355 else
356 call neko_error("adjoint scalar user IC not supported")
357 end if
358 ! set lags to IC
359 call adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj_lag% &
360 set(adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj)
361 end if
362
363 ! ------------------------------------------------------------------------ !
364 ! Reset the "freeze" parameter of the flow
365 ! ------------------------------------------------------------------------ !
366
367 call json_get_or_default(neko_case%params, &
368 'case.adjoint_fluid.freeze_flow', freezeflow, .false.)
369
370 adjoint_case%fluid_adj%freeze = freezeflow
371
372 end subroutine reset_adjoint
373
381 subroutine vector_to_field(field, vector)
382 type(field_t), intent(inout) :: field
383 type(vector_t), intent(in) :: vector
384
385 ! first check they're the same size
386 if (field%size() .ne. vector%size()) then
387 call neko_error("vector and field are not the same size")
388 end if
389
390 if (neko_bcknd_device .eq. 1) then
391 call device_copy(field%x_d, vector%x_d, field%size())
392 else
393 call copy(field%x, vector%x, field%size())
394 end if
395
396 end subroutine vector_to_field
397
405 subroutine field_to_vector(vector, field)
406 type(vector_t), intent(inout) :: vector
407 type(field_t), intent(in) :: field
408
409 ! first check they're the same size
410 if (field%size() .ne. vector%size()) then
411 call neko_error("vector and field are not the same size")
412 end if
413
414 if (neko_bcknd_device .eq. 1) then
415 call device_copy(vector%x_d, field%x_d, field%size())
416 else
417 call copy(vector%x, field%x, field%size())
418 end if
419
420 end subroutine field_to_vector
421
430 subroutine get_scalar_indicies(i_primal, i_adjoint, scalars, &
431 adjoint_scalars, primal_name)
432 integer, intent(out) :: i_primal
433 integer, intent(out) :: i_adjoint
434 type(scalars_t), intent(inout) :: scalars
435 type(adjoint_scalars_t), intent(inout) :: adjoint_scalars
436 character(len=*), intent(in) :: primal_name
437 integer :: i, n_primal_scalars, n_adjoint_scalars
438
439 i_primal = -1
440 i_adjoint = -1
441 n_adjoint_scalars = size(adjoint_scalars%adjoint_scalar_fields)
442 n_primal_scalars = size(scalars%scalar_fields)
443
444 if ((n_adjoint_scalars .eq. 1) .and. (n_primal_scalars .eq. 1)) then
445 i_primal = 1
446 i_adjoint = 1
447 return
448 end if
449
450 do i = 1, n_adjoint_scalars
451 if (adjoint_scalars%adjoint_scalar_fields(i)%primal_name &
452 .eq. primal_name) then
453 i_adjoint = i
454 exit
455 end if
456 end do
457
458 do i = 1, n_primal_scalars
459 if (scalars%scalar_fields(i)%name .eq. primal_name) then
460 i_primal = i
461 exit
462 end if
463 end do
464
465 if (i_primal .le. 0 .or. i_adjoint .le. 0) then
466 call neko_error('could not find matching primal and adjoint' // &
467 ' scalar fields')
468 end if
469
470 end subroutine get_scalar_indicies
471
472end 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:406
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:382
subroutine, public get_scalar_indicies(i_primal, i_adjoint, scalars, adjoint_scalars, primal_name)
get scalar indices
Definition neko_ext.f90:432
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.