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
6
9module neko_ext
10 use case, only: case_t
11 use adjoint_case, only: adjoint_case_t
12 use json_utils, only: json_get, json_get_or_default
13 use num_types, only: rp
14 use simcomp_executor, only: neko_simcomps
15 use flow_ic, only: set_flow_ic
16 use scalar_ic, only: set_scalar_ic
17 use field, only: field_t
18 use chkp_output, only: chkp_output_t
19 use output_controller, only: output_controller_t
20 ! for vector/field math
21 use math, only: copy
22 use device_math, only: device_copy
23 use neko_config, only : neko_bcknd_device
24 use vector, only: vector_t
25 use field, only: field_t
26 use utils, only: neko_error
27 use json_module, only : json_file
28 use scalars, only: scalars_t
30 use field_math, only: field_rzero, field_copy
31 use fluid_pnpn, only: fluid_pnpn_t
33
34 implicit none
35
36 ! ========================================================================= !
37 ! Module interface
38 ! ========================================================================= !
39 private
42
43contains
44
45 ! ========================================================================= !
46 ! Public routines
47 ! ========================================================================= !
48
57 subroutine reset(neko_case)
58 type(case_t), intent(inout) :: neko_case
59 real(kind=rp) :: t
60 integer :: i
61 character(len=:), allocatable :: string_val
62 logical :: has_scalar, freezeflow
63 type(field_t), pointer :: u, v, w, p, s
64 type(json_file) :: json_subdict
65
66 ! ------------------------------------------------------------------------ !
67 ! Setup shorthand notation
68 ! ------------------------------------------------------------------------ !
69
70 u => neko_case%fluid%u
71 v => neko_case%fluid%v
72 w => neko_case%fluid%w
73 p => neko_case%fluid%p
74 if (allocated(neko_case%scalars)) then
75 s => neko_case%scalars%scalar_fields(1)%s
76 else
77 nullify(s)
78 end if
79
80 ! ------------------------------------------------------------------------ !
81 ! Reset the timing parameters
82 ! ------------------------------------------------------------------------ !
83
84 call neko_case%time%reset()
85 t = neko_case%time%start_time
86 do i = 1, size(neko_case%time%tlag)
87 neko_case%time%tlag(i) = t - i*neko_case%time%dtlag(i)
88 end do
89
90 ! Reset the time step counter
91 call neko_case%output_controller%set_counter(neko_case%time)
92
93 ! Restart the fields
94 call neko_case%fluid%restart(neko_case%chkp)
95 if (allocated(neko_case%scalars)) then
96 call neko_case%scalars%restart(neko_case%chkp)
97 end if
98
99 ! Reset the external BDF coefficients
100 do i = 1, size(neko_case%time%dtlag)
101 call neko_case%fluid%ext_bdf%set_coeffs(neko_case%time%dtlag)
102 end do
103
104 ! Restart the simulation components
105 call neko_simcomps%restart(neko_case%time)
106
107 ! ------------------------------------------------------------------------ !
108 ! Reset the fluid field to the initial condition
109 ! ------------------------------------------------------------------------ !
110
111 call json_get(neko_case%params, &
112 'case.fluid.initial_condition.type', string_val)
113 call json_get(neko_case%params, 'case.fluid.initial_condition', &
114 json_subdict)
115
116 if (trim(string_val) .ne. 'user') then
117 call set_flow_ic(u, v, w, p, &
118 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
119 string_val, json_subdict)
120 else
121 call set_flow_ic(u, v, w, p, &
122 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
123 neko_case%user%initial_conditions, neko_case%fluid%name)
124 end if
125
126 ! set lags to IC
127 call neko_case%fluid%ulag%set(u)
128 call neko_case%fluid%vlag%set(v)
129 call neko_case%fluid%wlag%set(w)
130 ! zero out RHS etc
131 select type (f => neko_case%fluid)
132 type is (fluid_pnpn_t)
133 call field_rzero(f%abx1)
134 call field_rzero(f%aby1)
135 call field_rzero(f%abz1)
136 call field_rzero(f%abx2)
137 call field_rzero(f%aby2)
138 call field_rzero(f%abz2)
139 call field_copy(f%u_e, u)
140 call field_copy(f%v_e, v)
141 call field_copy(f%w_e, w)
142 end select
143 call field_rzero(neko_case%fluid%f_x)
144 call field_rzero(neko_case%fluid%f_y)
145 call field_rzero(neko_case%fluid%f_z)
146 ! ------------------------------------------------------------------------ !
147 ! Reset the scalar field to the initial condition
148 ! ------------------------------------------------------------------------ !
149
150 ! check for a single scalar
151 call json_get_or_default(neko_case%params, &
152 'case.scalar.enabled', has_scalar, .false.)
153
154 if (has_scalar) then
155 ! check for multiple scalars
156 if (size(neko_case%scalars%scalar_fields) .gt. 1) then
157 call neko_error('Multiple scalars not supported')
158 end if
159 ! zero out RHS
160 call field_rzero(neko_case%scalars%scalar_fields(1)%f_Xh)
161 ! reset the forward scalar
162 call json_get(neko_case%params, &
163 'case.scalar.initial_condition.type', string_val)
164 call json_get(neko_case%params, &
165 'case.scalar.initial_condition', json_subdict)
166 if (trim(string_val) .ne. 'user') then
167 if (trim(neko_case%scalars%scalar_fields(1)%name) .eq. &
168 'temperature') then
169 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%s, &
170 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
171 json_subdict, 0)
172 else
173 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%s, &
174 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
175 json_subdict, 1)
176 end if
177 else
178 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%name, &
179 neko_case%scalars%scalar_fields(1)%s, &
180 neko_case%scalars%scalar_fields(1)%c_Xh, &
181 neko_case%scalars%scalar_fields(1)%gs_Xh, &
182 neko_case%user%initial_conditions)
183 end if
184 ! set lags to IC
185 call neko_case%scalars%scalar_fields(1)%slag%set(&
186 neko_case%scalars%scalar_fields(1)%s)
187 end if
188
189 ! ------------------------------------------------------------------------ !
190 ! Reset the "freeze" parameter of the flow
191 ! ------------------------------------------------------------------------ !
192
193 call json_get_or_default(neko_case%params, &
194 'case.fluid.freeze_flow', freezeflow, .false.)
195
196 neko_case%fluid%freeze = freezeflow
197
198 end subroutine reset
199
209 subroutine reset_adjoint(adjoint_case, neko_case)
210 type(adjoint_case_t), intent(inout) :: adjoint_case
211 type(case_t), intent(inout) :: neko_case
212 real(kind=rp) :: t
213 integer :: i
214 character(len=:), allocatable :: string_val
215 logical :: has_scalar, freezeflow
216 type(field_t), pointer :: u_adj, v_adj, w_adj, p_adj, s_adj
217 type(json_file) :: json_subdict
218
219 ! ------------------------------------------------------------------------ !
220 ! Setup shorthand notation
221 ! ------------------------------------------------------------------------ !
222
223 u_adj => adjoint_case%fluid_adj%u_adj
224 v_adj => adjoint_case%fluid_adj%v_adj
225 w_adj => adjoint_case%fluid_adj%w_adj
226 p_adj => adjoint_case%fluid_adj%p_adj
227 if (allocated(adjoint_case%adjoint_scalars)) then
228 s_adj => adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj
229 else
230 nullify(s_adj)
231 end if
232
233 ! ------------------------------------------------------------------------ !
234 ! Reset the timing parameters
235 ! ------------------------------------------------------------------------ !
236
237 call adjoint_case%time%reset()
238 t = adjoint_case%time%start_time
239 do i = 1, size(adjoint_case%time%tlag)
240 adjoint_case%time%tlag(i) = t - i*adjoint_case%time%dtlag(i)
241 end do
242
243 ! Reset the time step counter
244 call adjoint_case%output_controller%set_counter(adjoint_case%time)
245
246 ! Reset the external BDF coefficients
247 do i = 1, size(adjoint_case%time%dtlag)
248 call adjoint_case%fluid_adj%ext_bdf%set_coeffs(adjoint_case%time%dtlag)
249 end do
250
251 ! ------------------------------------------------------------------------ !
252 ! Reset the adjoint fluid to the initial (final) condition
253 ! ------------------------------------------------------------------------ !
254
255 ! don't fallback to the fluid here
256 call json_get(neko_case%params, &
257 'case.adjoint_fluid.initial_condition.type', string_val)
258 call json_get(neko_case%params, 'case.adjoint_fluid.initial_condition', &
259 json_subdict)
260
261 if (trim(string_val) .ne. 'user') then
262 call set_flow_ic(u_adj, v_adj, w_adj, p_adj, &
263 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
264 string_val, json_subdict)
265 else
266 call neko_error("adjoint user initial conditions not supported")
267 end if
268
269 ! set lags to IC
270 call adjoint_case%fluid_adj%ulag%set(u_adj)
271 call adjoint_case%fluid_adj%vlag%set(v_adj)
272 call adjoint_case%fluid_adj%wlag%set(w_adj)
273 ! zero out RHS etc
274 select type (f => adjoint_case%fluid_adj)
275 type is (adjoint_fluid_pnpn_t)
276 call field_rzero(f%abx1)
277 call field_rzero(f%aby1)
278 call field_rzero(f%abz1)
279 call field_rzero(f%abx2)
280 call field_rzero(f%aby2)
281 call field_rzero(f%abz2)
282 end select
283 ! zero out all lags etc
284 ! (not sure what to do with the abx's_adj)
285 call field_rzero(adjoint_case%fluid_adj%f_adj_x)
286 call field_rzero(adjoint_case%fluid_adj%f_adj_y)
287 call field_rzero(adjoint_case%fluid_adj%f_adj_z)
288 ! ------------------------------------------------------------------------ !
289 ! Reset the scalar field to the initial condition
290 ! ------------------------------------------------------------------------ !
291
292 ! check for a single scalar
293 call json_get_or_default(neko_case%params, 'case.scalar.enabled', &
294 has_scalar, .false.)
295
296 if (has_scalar) then
297 ! check for multiple adjoint_scalars
298 if (size(adjoint_case%adjoint_scalars%adjoint_scalar_fields) .gt. 1) then
299 call neko_error('Multiple adjoint scalars not supported')
300 end if
301 ! zero out lag terms
302 call field_rzero( &
303 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%f_Xh)
304 ! reset the forward scalar
305 call json_get(neko_case%params, &
306 'case.adjoint_scalar.initial_condition.type', string_val)
307 call json_get(neko_case%params, &
308 'case.adjoint_scalar.initial_condition', json_subdict)
309 if (trim(string_val) .ne. 'user') then
310 if (trim(neko_case%scalars%scalar_fields(1)%name) .eq. &
311 'temperature') then
312 call set_scalar_ic( &
313 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
314 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
315 string_val, json_subdict, 0)
316 else
317 call set_scalar_ic( &
318 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
319 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
320 string_val, json_subdict, 1)
321 end if
322 else
323 call neko_error("adjoint scalar user IC not supported")
324 end if
325 ! set lags to IC
326 call adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj_lag% &
327 set(adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj)
328 end if
329
330 ! ------------------------------------------------------------------------ !
331 ! Reset the "freeze" parameter of the flow
332 ! ------------------------------------------------------------------------ !
333
334 call json_get_or_default(neko_case%params, &
335 'case.adjoint_fluid.freeze_flow', freezeflow, .false.)
336
337 adjoint_case%fluid_adj%freeze = freezeflow
338
339 end subroutine reset_adjoint
340
348 subroutine vector_to_field(field, vector)
349 type(field_t), intent(inout) :: field
350 type(vector_t), intent(in) :: vector
351
352 ! first check they're the same size
353 if (field%size() .ne. vector%size()) then
354 call neko_error("vector and field are not the same size")
355 end if
356
357 if (neko_bcknd_device .eq. 1) then
358 call device_copy(field%x_d, vector%x_d, field%size())
359 else
360 call copy(field%x, vector%x, field%size())
361 end if
362
363 end subroutine vector_to_field
364
372 subroutine field_to_vector(vector, field)
373 type(vector_t), intent(inout) :: vector
374 type(field_t), intent(in) :: field
375
376 ! first check they're the same size
377 if (field%size() .ne. vector%size()) then
378 call neko_error("vector and field are not the same size")
379 end if
380
381 if (neko_bcknd_device .eq. 1) then
382 call device_copy(vector%x_d, field%x_d, field%size())
383 else
384 call copy(vector%x, field%x, field%size())
385 end if
386
387 end subroutine field_to_vector
388
397 subroutine get_scalar_indicies(i_primal, i_adjoint, scalars, &
398 adjoint_scalars, primal_name)
399 integer, intent(out) :: i_primal
400 integer, intent(out) :: i_adjoint
401 type(scalars_t), intent(inout) :: scalars
402 type(adjoint_scalars_t), intent(inout) :: adjoint_scalars
403 character(len=*), intent(in) :: primal_name
404 integer :: i, n_primal_scalars, n_adjoint_scalars
405
406 i_primal = -1
407 i_adjoint = -1
408 n_adjoint_scalars = size(adjoint_scalars%adjoint_scalar_fields)
409 n_primal_scalars = size(scalars%scalar_fields)
410
411 if ((n_adjoint_scalars .eq. 1) .and. (n_primal_scalars .eq. 1)) then
412 i_primal = 1
413 i_adjoint = 1
414 return
415 end if
416
417 do i = 1, n_adjoint_scalars
418 if (adjoint_scalars%adjoint_scalar_fields(i)%primal_name &
419 .eq. primal_name) then
420 i_adjoint = i
421 exit
422 end if
423 end do
424
425 do i = 1, n_primal_scalars
426 if (scalars%scalar_fields(i)%name .eq. primal_name) then
427 i_primal = i
428 exit
429 end if
430 end do
431
432 if (i_primal .le. 0 .or. i_adjoint .le. 0) then
433 call neko_error('could not find matching primal and adjoint' // &
434 ' scalar fields')
435 end if
436
437 end subroutine get_scalar_indicies
438
439end 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:9
subroutine, public field_to_vector(vector, field)
Field to vector.
Definition neko_ext.f90:373
subroutine, public reset(neko_case)
Reset the case data structure.
Definition neko_ext.f90:58
subroutine, public reset_adjoint(adjoint_case, neko_case)
Reset the adjoint case data structure.
Definition neko_ext.f90:210
subroutine, public vector_to_field(field, vector)
Vector to field.
Definition neko_ext.f90:349
subroutine, public get_scalar_indicies(i_primal, i_adjoint, scalars, adjoint_scalars, primal_name)
get scalar indices
Definition neko_ext.f90:399
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.