Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
set_optimization_ic.f90
Go to the documentation of this file.
1
34!
37 use gather_scatter, only : gs_t, gs_op_add
38 use neko_config, only : neko_bcknd_device
39 use num_types, only : rp
40 use device_math, only : device_col2
41 use device, only : device_memcpy, host_to_device
42 use field, only : field_t
43 use utils, only : neko_error, filename_chsuffix, filename_suffix, &
44 neko_warning, neko_fname_len, extract_fld_file_index
45 use coefs, only : coef_t
46 use math, only : col2, cfill, cfill_mask
47 use json_module, only : json_file
48 use json_utils, only: json_get, json_get_or_default
49 use point_zone, only: point_zone_t
50 use point_zone_registry, only: neko_point_zone_registry
51 use registry, only: neko_registry
52 use logger, only: neko_log, log_size
53 use fld_file_data, only: fld_file_data_t
54 use fld_file, only: fld_file_t
55 use checkpoint, only: chkp_t
56 use file, only: file_t
57 use global_interpolation, only: global_interpolation_t
58 use interpolation, only: interpolator_t
59 use space, only: space_t, gll
60 implicit none
61 private
62
64 module procedure set_optimization_ic_int
65 end interface set_optimization_ic
66
67 public :: set_optimization_ic
68
69contains
70
85 subroutine set_optimization_ic_int(fld, coef, gs, params)
86 type(field_t), intent(inout) :: fld
87 type(coef_t), intent(in) :: coef
88 type(gs_t), intent(inout) :: gs
89 type(json_file), intent(inout) :: params
90
91 ! Variables for retrieving JSON parameters
92 character(len=:), allocatable :: type
93 real(kind=rp) :: ic_value
94 character(len=:), allocatable :: read_str
95 character(len=:), allocatable :: fname, mesh_fname
96 real(kind=rp) :: zone_value, tol
97 logical :: interpolate
98
99 call json_get(params, "type", type)
100
101 select case (trim(type))
102 case ('uniform')
103 call json_get(params, 'value', ic_value)
104 call set_optimization_ic_uniform(fld, ic_value)
105
106 case ('point_zone')
107 call json_get(params, 'base_value', ic_value)
108 call json_get(params, 'zone_name', read_str)
109 call json_get(params, 'zone_value', zone_value)
110
111 call set_optimization_ic_point_zone(fld, ic_value, read_str, zone_value)
112
113 case ('field')
114 call json_get(params, 'file_name', fname)
115 call json_get_or_default(params, 'interpolate', interpolate, .false.)
116 call json_get_or_default(params, 'tolerance', tol, 0.000001_rp)
117 call json_get_or_default(params, 'mesh_file_name', mesh_fname, "none")
118
119 call set_optimization_ic_fld(fld, fname, interpolate, tol, mesh_fname)
120
121 case default
122 call neko_error('Invalid initial condition')
123
124 end select
125
126 call set_optimization_ic_common(fld, coef, gs)
127
128 end subroutine set_optimization_ic_int
129
136 subroutine set_optimization_ic_common(fld, coef, gs)
137 type(field_t), intent(inout) :: fld
138 type(coef_t), intent(in) :: coef
139 type(gs_t), intent(inout) :: gs
140 integer :: n
141
142 n = fld%dof%size()
143 if (neko_bcknd_device .eq. 1) then
144 call device_memcpy(fld%x, fld%x_d, n, &
145 host_to_device, sync = .false.)
146 end if
147
148 ! Ensure continuity across elements for initial conditions
149 call gs%op(fld%x, n, gs_op_add)
150
151 if (neko_bcknd_device .eq. 1) then
152 call device_col2(fld%x_d, coef%mult_d, n)
153 else
154 call col2(fld%x, coef%mult, n)
155 end if
156
157 end subroutine set_optimization_ic_common
158
163 subroutine set_optimization_ic_uniform(fld, ic_value)
164 type(field_t), intent(inout) :: fld
165 real(kind=rp), intent(in) :: ic_value
166 integer :: n
167 character(len=LOG_SIZE) :: log_buf
168
169 call neko_log%message("Type : uniform")
170 write (log_buf, '(A,ES12.6)') "Value: ", ic_value
171 call neko_log%message(log_buf)
172
173 fld = ic_value
174 n = fld%dof%size()
175 if (neko_bcknd_device .eq. 1) then
176 call cfill(fld%x, ic_value, n)
177 end if
178
179 end subroutine set_optimization_ic_uniform
180
188 subroutine set_optimization_ic_point_zone(fld, base_value, zone_name, &
189 zone_value)
190 type(field_t), intent(inout) :: fld
191 real(kind=rp), intent(in) :: base_value
192 character(len=*), intent(in) :: zone_name
193 real(kind=rp), intent(in) :: zone_value
194
195 ! Internal variables
196 character(len=LOG_SIZE) :: log_buf
197 class(point_zone_t), pointer :: zone
198 integer :: size
199
200 call neko_log%message("Type : point_zone")
201 write (log_buf, '(A,ES12.6)') "Base value: ", base_value
202 call neko_log%message(log_buf)
203 call neko_log%message("Zone name : " // trim(zone_name))
204 write (log_buf, '(A,ES12.6)') "Zone value: ", zone_value
205 call neko_log%message(log_buf)
206
207 size = fld%dof%size()
208 zone => neko_point_zone_registry%get_point_zone(trim(zone_name))
209
210 call set_optimization_ic_uniform(fld, base_value)
211 call cfill_mask(fld%x, zone_value, size, zone%mask%get(), zone%size)
212
213 end subroutine set_optimization_ic_point_zone
214
229 subroutine set_optimization_ic_fld(fld, file_name, &
230 interpolate, tolerance, mesh_file_name)
231 type(field_t), intent(inout) :: fld
232 character(len=*), intent(in) :: file_name
233 logical, intent(in) :: interpolate
234 real(kind=rp), intent(in) :: tolerance
235 character(len=*), intent(inout) :: mesh_file_name
236
237 character(len=LOG_SIZE) :: log_buf
238 integer :: sample_idx, sample_mesh_idx
239 type(fld_file_data_t) :: fld_data
240 type(file_t) :: f
241 logical :: mesh_mismatch
242
243 ! ---- For the mesh to mesh interpolation
244 type(global_interpolation_t) :: global_interp
245 ! -----
246
247 ! ---- For space to space interpolation
248 type(space_t) :: prev_Xh
249 type(interpolator_t) :: space_interp
250 ! ----
251
252 call neko_log%message("Type : field")
253 call neko_log%message("File name : " // trim(file_name))
254 write (log_buf, '(A,L1)') "Interpolation: ", interpolate
255 call neko_log%message(log_buf)
256
257 ! Extract sample index from the file name
258 sample_idx = extract_fld_file_index(file_name, -1)
259
260 if (sample_idx .eq. -1) then
261 call neko_error("Invalid file name for the initial condition. The " // &
262 "file format must be e.g. 'mean0.f00001'")
263 end if
264
265 ! Change from "field0.f000*" to "field0.fld" for the fld reader
266 call filename_chsuffix(file_name, trim(file_name), 'fld')
267
268 call fld_data%init()
269 call f%init(trim(file_name))
270
271 if (interpolate) then
272
273 ! If no mesh file is specified, use the default file name
274 if (mesh_file_name .eq. "none") then
275 mesh_file_name = trim(file_name)
276 sample_mesh_idx = sample_idx
277 else
278
279 ! Extract sample index from the mesh file name
280 sample_mesh_idx = extract_fld_file_index(mesh_file_name, -1)
281
282 if (sample_mesh_idx .eq. -1) then
283 call neko_error("Invalid file name for the initial condition." // &
284 " The file format must be e.g. 'mean0.f00001'")
285 end if
286
287 write (log_buf, '(A,ES12.6)') "Tolerance : ", tolerance
288 call neko_log%message(log_buf)
289 write (log_buf, '(A,A)') "Mesh file : ", &
290 trim(mesh_file_name)
291 call neko_log%message(log_buf)
292
293 end if ! if mesh_file_name .eq. none
294
295 ! Read the mesh coordinates if they are not in our fld file
296 if (sample_mesh_idx .ne. sample_idx) then
297 call f%set_counter(sample_mesh_idx)
298 call f%read(fld_data)
299 end if
300
301 end if
302
303 ! Read the field file containing (u,v,w,p)
304 call f%set_counter(sample_idx)
305 call f%read(fld_data)
306
307 !
308 ! Check that the data in the fld file matches the current case.
309 ! Note that this is a safeguard and there are corner cases where
310 ! two different meshes have the same dimension and same # of elements
311 ! but this should be enough to cover obvious cases.
312 !
313 mesh_mismatch = (fld_data%glb_nelv .ne. fld%msh%glb_nelv .or. &
314 fld_data%gdim .ne. fld%msh%gdim)
315
316 if (mesh_mismatch .and. .not. interpolate) then
317 call neko_error("The fld file must match the current mesh! " // &
318 "Use 'interpolate': 'true' to enable interpolation.")
319 else if (.not. mesh_mismatch .and. interpolate) then
320 call neko_log%warning("You have activated interpolation but you " // &
321 "might still be using the same mesh.")
322 end if
323
324
325 ! Mesh interpolation if specified
326 if (interpolate) then
327 ! Issue a warning if the mesh is in single precision
328 select type (ft => f%file_type)
329 type is (fld_file_t)
330 if (.not. ft%dp_precision) then
331 call neko_warning("The coordinates read from the field file " // &
332 "are in single precision.")
333 call neko_log%message("It is recommended to use a mesh in " // &
334 "double precision for better interpolation results.")
335 call neko_log%message("If the interpolation does not work, " // &
336 "you can try to increase the tolerance.")
337 end if
338 class default
339 end select
340
341 ! Generates an interpolator object and performs the point search
342 call fld_data%generate_interpolator(global_interp, fld%dof, fld%msh, &
343 tolerance)
344
345 ! Evaluate design
346 ! NOTE. Is is currently the convention in the design0.f* files that
347 ! the unfiltered design should be stored in the u component.
348 call global_interp%evaluate(fld%x, fld_data%u%x, on_host=.false.)
349 call global_interp%free()
350
351 else ! No interpolation, just potentially from different spaces
352
353 ! Build a space_t object from the data in the fld file
354 call prev_xh%init(gll, fld_data%lx, fld_data%ly, fld_data%lz)
355 call space_interp%init(fld%Xh, prev_xh)
356
357 ! Do the space-to-space interpolation
358 call space_interp%map_host(fld%x, fld_data%t%x, fld_data%nelv, fld%Xh)
359
360 call space_interp%free()
361
362 end if
363
364 call fld_data%free()
365
366 end subroutine set_optimization_ic_fld
367
368end module optimization_ic
Optimization initial condition.