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
31
32 implicit none
33
34 ! ========================================================================= !
35 ! Module interface
36 ! ========================================================================= !
37 private
40
41contains
42
43 ! ========================================================================= !
44 ! Public routines
45 ! ========================================================================= !
46
55 subroutine reset(neko_case)
56 type(case_t), intent(inout) :: neko_case
57 real(kind=rp) :: t
58 integer :: i
59 character(len=:), allocatable :: string_val
60 logical :: has_scalar, freezeflow
61 type(field_t), pointer :: u, v, w, p, s
62 type(json_file) :: json_subdict
63
64 ! ------------------------------------------------------------------------ !
65 ! Setup shorthand notation
66 ! ------------------------------------------------------------------------ !
67
68 u => neko_case%fluid%u
69 v => neko_case%fluid%v
70 w => neko_case%fluid%w
71 p => neko_case%fluid%p
72 if (allocated(neko_case%scalars)) then
73 s => neko_case%scalars%scalar_fields(1)%s
74 else
75 nullify(s)
76 end if
77
78 ! ------------------------------------------------------------------------ !
79 ! Reset the timing parameters
80 ! ------------------------------------------------------------------------ !
81
82 call neko_case%time%reset()
83 t = neko_case%time%start_time
84 do i = 1, size(neko_case%time%tlag)
85 neko_case%time%tlag(i) = t - i*neko_case%time%dtlag(i)
86 end do
87
88 ! Reset the time step counter
89 call neko_case%output_controller%set_counter(neko_case%time)
90
91 ! Restart the fields
92 call neko_case%fluid%restart(neko_case%chkp)
93 if (allocated(neko_case%scalars)) then
94 call neko_case%scalars%restart(neko_case%chkp)
95 end if
96
97 ! Reset the external BDF coefficients
98 do i = 1, size(neko_case%time%dtlag)
99 call neko_case%fluid%ext_bdf%set_coeffs(neko_case%time%dtlag)
100 end do
101
102 ! Restart the simulation components
103 call neko_simcomps%restart(neko_case%time)
104
105 ! ------------------------------------------------------------------------ !
106 ! Reset the fluid field to the initial condition
107 ! ------------------------------------------------------------------------ !
108
109 call json_get(neko_case%params, &
110 'case.fluid.initial_condition.type', string_val)
111 call json_get(neko_case%params, 'case.fluid.initial_condition', &
112 json_subdict)
113
114 if (trim(string_val) .ne. 'user') then
115 call set_flow_ic(u, v, w, p, &
116 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
117 string_val, json_subdict)
118 else
119 call set_flow_ic(u, v, w, p, &
120 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, &
121 neko_case%user%initial_conditions, neko_case%fluid%name)
122 end if
123
124 ! zero out all lags etc
125 ! (not sure what to do with the abx's)
126 call field_rzero(neko_case%fluid%f_x)
127 call field_rzero(neko_case%fluid%f_y)
128 call field_rzero(neko_case%fluid%f_z)
129 call neko_case%fluid%ulag%set(neko_case%fluid%f_x)
130 call neko_case%fluid%vlag%set(neko_case%fluid%f_x)
131 call neko_case%fluid%wlag%set(neko_case%fluid%f_x)
132 ! ------------------------------------------------------------------------ !
133 ! Reset the scalar field to the initial condition
134 ! ------------------------------------------------------------------------ !
135
136 ! check for a single scalar
137 call json_get_or_default(neko_case%params, &
138 'case.scalar.enabled', has_scalar, .false.)
139
140 if (has_scalar) then
141 ! check for multiple scalars
142 if (size(neko_case%scalars%scalar_fields) .gt. 1) then
143 call neko_error('Multiple scalars not supported')
144 end if
145 ! zero out lag terms and RHS
146 call neko_case%scalars%scalar_fields(1)%slag%set(neko_case%fluid%f_x)
147 call field_rzero(neko_case%scalars%scalar_fields(1)%f_Xh)
148 ! reset the forward scalar
149 call json_get(neko_case%params, &
150 'case.scalar.initial_condition.type', string_val)
151 call json_get(neko_case%params, &
152 'case.scalar.initial_condition', json_subdict)
153 if (trim(string_val) .ne. 'user') then
154 if (trim(neko_case%scalars%scalar_fields(1)%name) .eq. &
155 'temperature') then
156 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%s, &
157 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
158 json_subdict, 0)
159 else
160 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%s, &
161 neko_case%fluid%c_Xh, neko_case%fluid%gs_Xh, string_val, &
162 json_subdict, 1)
163 end if
164 else
165 call set_scalar_ic(neko_case%scalars%scalar_fields(1)%name, &
166 neko_case%scalars%scalar_fields(1)%s, &
167 neko_case%scalars%scalar_fields(1)%c_Xh, &
168 neko_case%scalars%scalar_fields(1)%gs_Xh, &
169 neko_case%user%initial_conditions)
170 end if
171 end if
172
173 ! ------------------------------------------------------------------------ !
174 ! Reset the "freeze" parameter of the flow
175 ! ------------------------------------------------------------------------ !
176
177 call json_get_or_default(neko_case%params, &
178 'case.fluid.freeze_flow', freezeflow, .false.)
179
180 neko_case%fluid%freeze = freezeflow
181
182 end subroutine reset
183
193 subroutine reset_adjoint(adjoint_case, neko_case)
194 type(adjoint_case_t), intent(inout) :: adjoint_case
195 type(case_t), intent(inout) :: neko_case
196 real(kind=rp) :: t
197 integer :: i
198 character(len=:), allocatable :: string_val
199 logical :: has_scalar, freezeflow
200 type(field_t), pointer :: u_adj, v_adj, w_adj, p_adj, s_adj
201 type(json_file) :: json_subdict
202
203 ! ------------------------------------------------------------------------ !
204 ! Setup shorthand notation
205 ! ------------------------------------------------------------------------ !
206
207 u_adj => adjoint_case%fluid_adj%u_adj
208 v_adj => adjoint_case%fluid_adj%v_adj
209 w_adj => adjoint_case%fluid_adj%w_adj
210 p_adj => adjoint_case%fluid_adj%p_adj
211 if (allocated(adjoint_case%adjoint_scalars)) then
212 s_adj => adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj
213 else
214 nullify(s_adj)
215 end if
216
217 ! ------------------------------------------------------------------------ !
218 ! Reset the timing parameters
219 ! ------------------------------------------------------------------------ !
220
221 call adjoint_case%time%reset()
222 t = adjoint_case%time%start_time
223 do i = 1, size(adjoint_case%time%tlag)
224 adjoint_case%time%tlag(i) = t - i*adjoint_case%time%dtlag(i)
225 end do
226
227 ! Reset the time step counter
228 call adjoint_case%output_controller%set_counter(adjoint_case%time)
229
230 ! Reset the external BDF coefficients
231 do i = 1, size(adjoint_case%time%dtlag)
232 call adjoint_case%fluid_adj%ext_bdf%set_coeffs(adjoint_case%time%dtlag)
233 end do
234
235 ! ------------------------------------------------------------------------ !
236 ! Reset the adjoint fluid to the initial (final) condition
237 ! ------------------------------------------------------------------------ !
238
239 ! don't fallback to the fluid here
240 call json_get(neko_case%params, &
241 'case.adjoint_fluid.initial_condition.type', string_val)
242 call json_get(neko_case%params, 'case.adjoint_fluid.initial_condition', &
243 json_subdict)
244
245 if (trim(string_val) .ne. 'user') then
246 call set_flow_ic(u_adj, v_adj, w_adj, p_adj, &
247 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
248 string_val, json_subdict)
249 else
250 call neko_error("adjoint user initial conditions not supported")
251 end if
252
253 ! zero out all lags etc
254 ! (not sure what to do with the abx's_adj)
255 call field_rzero(adjoint_case%fluid_adj%f_adj_x)
256 call field_rzero(adjoint_case%fluid_adj%f_adj_y)
257 call field_rzero(adjoint_case%fluid_adj%f_adj_z)
258 call adjoint_case%fluid_adj%ulag%set(adjoint_case%fluid_adj%f_adj_x)
259 call adjoint_case%fluid_adj%vlag%set(adjoint_case%fluid_adj%f_adj_x)
260 call adjoint_case%fluid_adj%wlag%set(adjoint_case%fluid_adj%f_adj_x)
261 ! ------------------------------------------------------------------------ !
262 ! Reset the scalar field to the initial condition
263 ! ------------------------------------------------------------------------ !
264
265 ! check for a single scalar
266 call json_get_or_default(neko_case%params, 'case.scalar.enabled', &
267 has_scalar, .false.)
268
269 if (has_scalar) then
270 ! check for multiple adjoint_scalars
271 if (size(adjoint_case%adjoint_scalars%adjoint_scalar_fields) .gt. 1) then
272 call neko_error('Multiple adjoint scalars not supported')
273 end if
274 ! zero out lag terms and RHS
275 call adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj_lag% &
276 set(adjoint_case%fluid_adj%f_adj_x)
277 call field_rzero( &
278 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%f_Xh)
279 ! reset the forward scalar
280 call json_get(neko_case%params, &
281 'case.adjoint_scalar.initial_condition.type', string_val)
282 call json_get(neko_case%params, &
283 'case.adjoint_scalar.initial_condition', json_subdict)
284 if (trim(string_val) .ne. 'user') then
285 if (trim(neko_case%scalars%scalar_fields(1)%name) .eq. &
286 'temperature') then
287 call set_scalar_ic( &
288 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
289 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
290 string_val, json_subdict, 0)
291 else
292 call set_scalar_ic( &
293 adjoint_case%adjoint_scalars%adjoint_scalar_fields(1)%s_adj, &
294 adjoint_case%fluid_adj%c_Xh, adjoint_case%fluid_adj%gs_Xh, &
295 string_val, json_subdict, 1)
296 end if
297 else
298 call neko_error("adjoint scalar user IC not supported")
299 end if
300 end if
301
302 ! ------------------------------------------------------------------------ !
303 ! Reset the "freeze" parameter of the flow
304 ! ------------------------------------------------------------------------ !
305
306 call json_get_or_default(neko_case%params, &
307 'case.adjoint_fluid.freeze_flow', freezeflow, .false.)
308
309 adjoint_case%fluid_adj%freeze = freezeflow
310
311 end subroutine reset_adjoint
312
320 subroutine vector_to_field(field, vector)
321 type(field_t), intent(inout) :: field
322 type(vector_t), intent(in) :: vector
323
324 ! first check they're the same size
325 if (field%size() .ne. vector%size()) then
326 call neko_error("vector and field are not the same size")
327 end if
328
329 if (neko_bcknd_device .eq. 1) then
330 call device_copy(field%x_d, vector%x_d, field%size())
331 else
332 call copy(field%x, vector%x, field%size())
333 end if
334
335 end subroutine vector_to_field
336
344 subroutine field_to_vector(vector, field)
345 type(vector_t), intent(inout) :: vector
346 type(field_t), intent(in) :: field
347
348 ! first check they're the same size
349 if (field%size() .ne. vector%size()) then
350 call neko_error("vector and field are not the same size")
351 end if
352
353 if (neko_bcknd_device .eq. 1) then
354 call device_copy(vector%x_d, field%x_d, field%size())
355 else
356 call copy(vector%x, field%x, field%size())
357 end if
358
359 end subroutine field_to_vector
360
369 subroutine get_scalar_indicies(i_primal, i_adjoint, scalars, &
370 adjoint_scalars, primal_name)
371 integer, intent(out) :: i_primal
372 integer, intent(out) :: i_adjoint
373 type(scalars_t), intent(inout) :: scalars
374 type(adjoint_scalars_t), intent(inout) :: adjoint_scalars
375 character(len=*), intent(in) :: primal_name
376 integer :: i, n_primal_scalars, n_adjoint_scalars
377
378 i_primal = -1
379 i_adjoint = -1
380 n_adjoint_scalars = size(adjoint_scalars%adjoint_scalar_fields)
381 n_primal_scalars = size(scalars%scalar_fields)
382
383 if ((n_adjoint_scalars .eq. 1) .and. (n_primal_scalars .eq. 1)) then
384 i_primal = 1
385 i_adjoint = 1
386 return
387 end if
388
389 do i = 1, n_adjoint_scalars
390 if (adjoint_scalars%adjoint_scalar_fields(i)%primal_name &
391 .eq. primal_name) then
392 i_adjoint = i
393 exit
394 end if
395 end do
396
397 do i = 1, n_primal_scalars
398 if (scalars%scalar_fields(i)%name .eq. primal_name) then
399 i_primal = i
400 exit
401 end if
402 end do
403
404 if (i_primal .le. 0 .or. i_adjoint .le. 0) then
405 call neko_error('could not find matching primal and adjoint' // &
406 ' scalar fields')
407 end if
408
409 end subroutine get_scalar_indicies
410
411end module neko_ext
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:345
subroutine, public reset(neko_case)
Reset the case data structure.
Definition neko_ext.f90:56
subroutine, public reset_adjoint(adjoint_case, neko_case)
Reset the adjoint case data structure.
Definition neko_ext.f90:194
subroutine, public vector_to_field(field, vector)
Vector to field.
Definition neko_ext.f90:321
subroutine, public get_scalar_indicies(i_primal, i_adjoint, scalars, adjoint_scalars, primal_name)
get scalar indices
Definition neko_ext.f90:371
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.