Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
simulation_adjoint.f90
Go to the documentation of this file.
1
34!
37 use mpi_f08, only: mpi_wtime
38 use neko_config, only: neko_bcknd_device
39 use num_types, only: rp, dp
40 use time_scheme_controller, only: time_scheme_controller_t
41 use file, only: file_t
42 use logger, only: log_size, neko_log
43 use profiler, only: profiler_start_region, profiler_end_region
44 use json_utils, only: json_get_or_default
45 use time_state, only : time_state_t
46 use time_step_controller, only: time_step_controller_t
47 use adjoint_case, only: adjoint_case_t
48 use scratch_registry, only: neko_scratch_registry
49 use device_math, only: device_glsc3
50 use math, only: glsc3
51 use vector, only: vector_t
52 implicit none
53 private
54
57
58contains
59
60
62 subroutine simulation_adjoint_init(C, dt_controller)
63 type(adjoint_case_t), intent(inout) :: c
64 type(time_step_controller_t), intent(inout) :: dt_controller
65 character(len=LOG_SIZE) :: log_buf
66
67 ! Write the initial logging message
68 call neko_log%section('Adjoint Starting simulation')
69 write(log_buf, '(A, E15.7,A,E15.7,A)') &
70 'T : [', c%time%t, ',', c%time%end_time, ']'
71 call neko_log%message(log_buf)
72 if (.not. dt_controller%is_variable_dt) then
73 write(log_buf, '(A, E15.7)') 'dt : ', c%time%dt
74 else
75 write(log_buf, '(A, E15.7)') 'CFL : ', dt_controller%cfl_trg
76 end if
77 call neko_log%message(log_buf)
78
79 ! Call stats, samplers and user-init before time loop
80 call neko_log%section('Postprocessing')
81 call c%output_controller%execute(c%time)
82 call simulation_adjoint_norm_output(c, c%time)
83
84 call c%case%user%initialize(c%time)
85 call neko_log%end_section()
86 call neko_log%newline()
87
88 end subroutine simulation_adjoint_init
89
92 type(adjoint_case_t), intent(inout) :: c
93 logical :: output_at_end
94
95 ! Run a final output if specified in the json
96 call json_get_or_default(c%case%params, 'case.output_at_end', &
97 output_at_end, .true.)
98 call c%output_controller%execute(c%time, output_at_end)
99
100 if (.not. (output_at_end) .and. c%time%t .lt. c%time%end_time) then
101 call simulation_adjoint_joblimit_chkp(c, c%time%t)
102 end if
103
104 ! Finalize the user modules
105 call c%case%user%finalize(c%time)
106
107 call neko_log%end_section('Normal end.')
108
109 end subroutine simulation_adjoint_finalize
110
112 subroutine simulation_adjoint_step(C, dt_controller, cfl, &
113 tstep_loop_start_time, final_time)
114 type(adjoint_case_t), intent(inout) :: c
115 real(kind=rp), intent(inout) :: cfl
116 type(time_step_controller_t), intent(inout) :: dt_controller
117 real(kind=dp), intent(in) :: tstep_loop_start_time
118 real(kind=rp), optional, intent(in) :: final_time
119 real(kind=rp) :: t_bkp
120 real(kind=dp) :: start_time, end_time, tstep_start_time
121 character(len=LOG_SIZE) :: log_buf
122
123 ! Setup the time step, and start time
124 call profiler_start_region('Time-Step Adjoint')
125 c%time%tstep = c%time%tstep + 1
126 start_time = mpi_wtime()
127 tstep_start_time = start_time
128
129 ! Compute the next time step
130 ! NOTE. we should be wary here since CFL is based on the convective velocity
131 ! not the adjoint velocity
132 cfl = c%fluid_adj%compute_cfl(c%time%dt)
133 call dt_controller%set_dt(c%time, cfl)
134 if (dt_controller%is_variable_dt) cfl = c%fluid_adj%compute_cfl(c%time%dt)
135
136 ! Calculate the cfl after the possibly varied dt
137 ! cfl = C%fluid_adj%compute_cfl(C%time%dt)
138
139 ! Advance time step from t to t+dt and print the status
140 call simulation_settime(c%time, c%fluid_adj%ext_bdf)
141 ! for cosmetic reasons we want the simulation to run backwards
142 if (present(final_time)) then
143 t_bkp = c%time%t
144 c%time%t = final_time - t_bkp
145 end if
146 call c%time%status()
147
148 call neko_log%begin()
149
150 write(log_buf, '(A,E15.7,1x,A,E15.7)') 'CFL:', cfl, 'dt:', c%time%dt
151 call neko_log%message(log_buf)
152
153 ! Scalar step
154 ! (Note that for the adjoint we should the adjoint_scalars first)
155 if (allocated(c%adjoint_scalars)) then
156 start_time = mpi_wtime()
157 call neko_log%section('Adjoint scalar')
158 call c%adjoint_scalars%step(c%time, &
159 c%case%fluid%ext_bdf, dt_controller)
160 end_time = mpi_wtime()
161 write(log_buf, '(A,E15.7)') &
162 'Scalar step time: ', end_time-start_time
163 call neko_log%end_section(log_buf)
164 end if
165
166 ! Fluid step
167 call neko_log%section('Adjoint fluid')
168 call c%fluid_adj%step(c%time, dt_controller)
169 end_time = mpi_wtime()
170 write(log_buf, '(A,E15.7)') &
171 'Fluid step time (s): ', end_time-start_time
172 call neko_log%end_section(log_buf)
173
174 ! Postprocessing
175 call neko_log%section('Postprocessing')
176
177 ! Correct the time so the output fields are the same as the primal
178 if (present(final_time)) then
179 c%time%t = t_bkp
180 end if
181
182 ! Run any IO needed.
183 call c%output_controller%execute(c%time)
184 call simulation_adjoint_norm_output(c, c%time)
185
186 call neko_log%end_section()
187
188 ! End the step and print summary
189 end_time = mpi_wtime()
190 call neko_log%section('Step summary')
191 write(log_buf, '(A,I8,A,E15.7)') &
192 'Total time for step ', c%time%tstep, ' (s): ', &
193 end_time - tstep_start_time
194 call neko_log%message(log_buf)
195 write(log_buf, '(A,E15.7)') &
196 'Total elapsed time (s): ', end_time-tstep_loop_start_time
197 call neko_log%message(log_buf)
198
199 call neko_log%end_section()
200 call neko_log%end()
201 call profiler_end_region
202
203
204 end subroutine simulation_adjoint_step
205
206 subroutine simulation_settime(time, ext_bdf)
207 type(time_state_t), intent(inout) :: time
208 type(time_scheme_controller_t), intent(inout), allocatable :: ext_bdf
209 integer :: i
210
211 if (allocated(ext_bdf)) then
212 do i = 10, 2, -1
213 time%tlag(i) = time%tlag(i-1)
214 time%dtlag(i) = time%dtlag(i-1)
215 end do
216
217 time%dtlag(1) = time%dt
218 time%tlag(1) = time%t
219 if (ext_bdf%ndiff .eq. 0) then
220 time%dtlag(2) = time%dt
221 time%tlag(2) = time%t
222 end if
223
224 call ext_bdf%set_coeffs(time%dtlag)
225 end if
226
227 time%t = time%t + time%dt
228
229 end subroutine simulation_settime
230
233 type(adjoint_case_t), intent(inout) :: c
234 integer :: i
235 type(file_t) :: chkpf, previous_meshf
236 character(len=LOG_SIZE) :: log_buf
237 character(len=:), allocatable :: restart_file
238 character(len=:), allocatable :: restart_mesh_file
239 real(kind=rp) :: tol
240 logical :: found
241
242 call c%case%params%get('case.restart_file', restart_file, found)
243 call c%case%params%get('case.restart_mesh_file', restart_mesh_file, found)
244
245 if (found) then
246 call previous_meshf%init(trim(restart_mesh_file))
247 call previous_meshf%read(c%fluid_adj%chkp%previous_mesh)
248 end if
249
250 call c%case%params%get('case.mesh2mesh_tolerance', tol, found)
251
252 if (found) c%case%fluid%chkp%mesh2mesh_tol = tol
253
254 call chkpf%init(trim(restart_file))
255 call chkpf%read(c%fluid_adj%chkp)
256 c%time%dtlag = c%fluid_adj%chkp%dtlag
257 c%time%tlag = c%fluid_adj%chkp%tlag
258
259 ! Free the previous mesh, dont need it anymore
260 do i = 1, size(c%time%dtlag)
261 call c%case%fluid%ext_bdf%set_coeffs(c%time%dtlag)
262 end do
263
264 call c%fluid_adj%restart(c%case%chkp)
265 call c%case%fluid%chkp%previous_mesh%free()
266 if (allocated(c%adjoint_scalars)) then
267 call c%adjoint_scalars%restart(c%case%chkp)
268 end if
269
270 c%time%t = real(c%case%fluid%chkp%restart_time(), kind=rp)
271 call neko_log%section('Restarting from checkpoint')
272 write(log_buf, '(A,A)') 'File : ', trim(restart_file)
273 call neko_log%message(log_buf)
274 write(log_buf, '(A,E15.7)') 'Time : ', c%time%t
275 call neko_log%message(log_buf)
276 call neko_log%end_section()
277
278 call c%output_controller%set_counter(c%time)
279 if (c%norm_output_enabled) then
280 call c%norm_output_ctrl%set_counter(c%time)
281 end if
282 end subroutine simulation_adjoint_restart
283
284 subroutine simulation_adjoint_norm_output(C, time_output)
285 type(adjoint_case_t), intent(inout) :: c
286 type(time_state_t), intent(in) :: time_output
287 type(vector_t), pointer :: data_line
288 real(kind=rp) :: norm_l2
289 integer :: n, idx
290
291 if (.not. c%norm_output_enabled) return
292 if (.not. c%norm_output_ctrl%check(time_output)) return
293
294 n = c%fluid_adj%c_Xh%dof%size()
295 if (neko_bcknd_device .eq. 1) then
296 norm_l2 = device_glsc3(c%fluid_adj%u_adj%x_d, &
297 c%fluid_adj%u_adj%x_d, c%fluid_adj%c_Xh%B_d, n) + &
298 device_glsc3(c%fluid_adj%v_adj%x_d, &
299 c%fluid_adj%v_adj%x_d, c%fluid_adj%c_Xh%B_d, n) + &
300 device_glsc3(c%fluid_adj%w_adj%x_d, &
301 c%fluid_adj%w_adj%x_d, c%fluid_adj%c_Xh%B_d, n)
302 else
303 norm_l2 = glsc3(c%fluid_adj%u_adj%x, c%fluid_adj%u_adj%x, &
304 c%fluid_adj%c_Xh%B, n) + &
305 glsc3(c%fluid_adj%v_adj%x, c%fluid_adj%v_adj%x, &
306 c%fluid_adj%c_Xh%B, n) + &
307 glsc3(c%fluid_adj%w_adj%x, c%fluid_adj%w_adj%x, &
308 c%fluid_adj%c_Xh%B, n)
309 end if
310
311 norm_l2 = sqrt(norm_l2) / c%fluid_adj%c_Xh%volume
312
313 call neko_scratch_registry%request(data_line, idx, 1, .false.)
314 data_line%x = [norm_l2]
315 call c%norm_output_file%write(data_line, time_output%t)
316 call neko_scratch_registry%relinquish(idx)
317 call c%norm_output_ctrl%register_execution()
318 end subroutine simulation_adjoint_norm_output
319
321 subroutine simulation_adjoint_joblimit_chkp(C, t)
322 type(adjoint_case_t), intent(inout) :: c
323 real(kind=rp), intent(inout) :: t
324 type(file_t) :: chkpf
325 character(len=:), allocatable :: chkp_format
326 character(len=LOG_SIZE) :: log_buf
327 character(len=10) :: format_str
328 logical :: found
329
330 call c%case%params%get('case.checkpoint_format', chkp_format, found)
331 call c%case%fluid%chkp%sync_host()
332 format_str = '.chkp'
333 if (found) then
334 if (chkp_format .eq. 'hdf5') then
335 format_str = '.h5'
336 end if
337 end if
338 call chkpf%init(c%case%output_directory // 'joblimit' // trim(format_str))
339 call chkpf%write(c%case%fluid%chkp, t)
340 write(log_buf, '(A)') '! saving checkpoint >>>'
341 call neko_log%message(log_buf)
342
343 end subroutine simulation_adjoint_joblimit_chkp
344
345end module simulation_adjoint
Adjoint simulation driver.
subroutine, public simulation_adjoint_init(c, dt_controller)
Initialise a simulation_adjoint of a case.
subroutine, public simulation_adjoint_step(c, dt_controller, cfl, tstep_loop_start_time, final_time)
Compute a single time-step of an adjoint case.
subroutine, public simulation_adjoint_restart(c)
Restart a case C from a given checkpoint.
subroutine, public simulation_adjoint_finalize(c)
Finalize a simulation of a case.
Adjoint case type. Todo: This should Ideally be a subclass of case_t, however, that is not yet suppor...