Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
base_functional.f90
Go to the documentation of this file.
1
34
37 use design, only: design_t
38 use json_module, only: json_file
39 use json_utils, only: json_get
40 use num_types, only: rp, dp, xp
41 use point_zone, only: point_zone_t
42 use simulation_m, only: simulation_t
43 use time_state, only: time_state_t
44 use vector, only: vector_t
45 use utils, only: neko_error
46 use scratch_registry, only: neko_scratch_registry
47 use vector_math, only: vector_copy, vector_add3s2, vector_rzero
48 implicit none
49 private
50
61 type, abstract, public :: base_functional_t
62
64 character(len=25) :: name = ""
65
67 real(kind=rp) :: value = 0.0_dp
69 type(vector_t) :: sensitivity
71 logical :: has_mask = .false.
73 class(point_zone_t), pointer :: mask => null()
74
75 ! ----------------------------------------------------------------------- !
76 ! Variables related to time averaging of the functional value and
77 ! sensitivity
78
80 real(kind=dp) :: start_time = 0.0_dp
82 real(kind=dp) :: end_time = huge(0.0_dp)
85 real(kind=xp) :: value_weight = 0.0_xp
88 real(kind=xp) :: sensitivity_weight = 0.0_xp
89
90 contains
91
92 ! ----------------------------------------------------------------------- !
93 ! Derived class interfaces
94
96 generic :: init => init_json, init_json_sim
97
99 procedure, pass(this) :: init_json => functional_init_json
101 procedure, pass(this) :: init_json_sim => functional_init_json_sim
103 procedure(functional_free), pass(this), deferred :: free
104
106 procedure(functional_update_value), pass(this), deferred :: update_value
108 procedure(functional_update_sensitivity), pass(this), deferred :: &
109 update_sensitivity
110
112 procedure, pass(this) :: get_value => functional_get_value
114 procedure, pass(this) :: get_sensitivity => functional_get_sensitivity
116 procedure, pass(this) :: get_log_size => functional_get_log_size
118 procedure, pass(this) :: get_log_headers => functional_get_log_headers
120 procedure, pass(this) :: get_log_values => functional_get_log_values
122 procedure, pass(this) :: reset_value => functional_reset_value
124 procedure, pass(this) :: reset_sensitivity => functional_reset_sensitivity
126 procedure, pass(this) :: accumulate_value => functional_accumulate_value
128 procedure, pass(this) :: accumulate_sensitivity => &
129 functional_accumulate_sensitivity
130
132 procedure, private, pass(this) :: in_window => functional_in_window
133 end type base_functional_t
134
135 ! -------------------------------------------------------------------------- !
136 ! Interface specifications for the derived types, these are the constructors
137 ! for the different types of objective functions.
138
139 abstract interface
140
142 subroutine functional_free(this)
143 import base_functional_t
144 class(base_functional_t), intent(inout) :: this
145 end subroutine functional_free
146
148 subroutine functional_update_value(this, design)
150 class(base_functional_t), intent(inout) :: this
151 class(design_t), intent(in) :: design
152 end subroutine functional_update_value
153
155 subroutine functional_update_sensitivity(this, design)
157 class(base_functional_t), intent(inout) :: this
158 class(design_t), intent(in) :: design
159 end subroutine functional_update_sensitivity
160
161 end interface
162
163contains
164
166 subroutine functional_init_json(this, json, design)
167 class(base_functional_t), intent(inout) :: this
168 type(json_file), intent(inout) :: json
169 class(design_t), intent(in) :: design
170 character(len=:), allocatable :: type
171
172 call json_get(json, 'type', type)
173 call neko_error("Functional type: '" // type // &
174 "' does not support initialization without simulation")
175 end subroutine functional_init_json
176
178 subroutine functional_init_json_sim(this, json, design, simulation)
179 class(base_functional_t), intent(inout) :: this
180 type(json_file), intent(inout) :: json
181 class(design_t), intent(in) :: design
182 type(simulation_t), target, intent(inout) :: simulation
183 character(len=:), allocatable :: type
184
185 call json_get(json, 'type', type)
186 call neko_error("Functional type: '" // type // &
187 "' does not support initialization with simulation")
188 end subroutine functional_init_json_sim
189
191 function functional_get_value(this) result(v)
192 class(base_functional_t), intent(in) :: this
193 real(kind=rp) :: v
194
195 v = this%value
196 end function functional_get_value
197
199 subroutine functional_get_sensitivity(this, sensitivity)
200 class(base_functional_t), intent(in) :: this
201 type(vector_t), intent(inout) :: sensitivity
202
203 sensitivity = this%sensitivity
204 end subroutine functional_get_sensitivity
205
209 function functional_get_log_size(this) result(n)
210 class(base_functional_t), intent(in) :: this
211 integer :: n
212
213 n = 1
214 end function functional_get_log_size
215
219 subroutine functional_get_log_headers(this, headers)
220 class(base_functional_t), intent(in) :: this
221 character(len=*), intent(out) :: headers(:)
222
223 if (size(headers) .eq. 0) return
224 headers(1) = trim(this%name)
225 end subroutine functional_get_log_headers
226
230 subroutine functional_get_log_values(this, values)
231 class(base_functional_t), intent(in) :: this
232 real(kind=rp), intent(out) :: values(:)
233
234 if (size(values) .eq. 0) return
235 values(1) = this%value
236 end subroutine functional_get_log_values
237
239 subroutine functional_reset_value(this)
240 class(base_functional_t), intent(inout) :: this
241
242 this%value = 0.0_dp
243 this%value_weight = 0.0_dp
244 end subroutine functional_reset_value
245
247 subroutine functional_reset_sensitivity(this)
248 class(base_functional_t), intent(inout) :: this
249
250 call vector_rzero(this%sensitivity)
251 this%sensitivity_weight = 0.0_dp
252 end subroutine functional_reset_sensitivity
253
267 subroutine functional_accumulate_value(this, design, time)
268 class(base_functional_t), intent(inout) :: this
269 class(design_t), intent(in) :: design
270 type(time_state_t), intent(in) :: time
271 real(kind=xp) :: value_new, value_old, weight_new, weight_old, dt
272
273 if (.not. this%in_window(time)) return
274
275 ! Store the old value and compute the new value.
276 value_old = real(this%value, kind=xp)
277 call this%update_value(design)
278 value_new = real(this%value, kind=xp)
279
280 ! Compute the weights for the old and new values.
281 dt = real(time%dt, kind=xp)
282 weight_new = dt / (this%value_weight + dt)
283 weight_old = this%value_weight / (this%value_weight + dt)
284
285 ! Rectangle rule; could potentially use higher order trapezoidal/Simpson
286 ! etc, but this should suffice.
287 this%value = real(value_old * weight_old + value_new * weight_new, kind=rp)
288 this%value_weight = this%value_weight + dt
289 end subroutine functional_accumulate_value
290
298 subroutine functional_accumulate_sensitivity(this, design, time)
299 class(base_functional_t), intent(inout) :: this
300 class(design_t), intent(in) :: design
301 type(time_state_t), intent(in) :: time
302 real(kind=xp) :: weight_new, weight_old, dt
303 type(vector_t), pointer :: sensitivity_new, sensitivity_old
304 integer :: n, idx(2)
305
306 if (.not. this%in_window(time)) return
307
308 n = this%sensitivity%size()
309 call neko_scratch_registry%request(sensitivity_new, idx(1), n, .false.)
310 call neko_scratch_registry%request(sensitivity_old, idx(2), n, .false.)
311
312 ! Store old sensitivity and compute new sensitivity.
313 call vector_copy(sensitivity_old, this%sensitivity)
314 call this%update_sensitivity(design)
315 call vector_copy(sensitivity_new, this%sensitivity)
316
317 ! Compute the weights for the old and new sensitivities.
318 dt = real(time%dt, kind=xp)
319 weight_new = dt / (this%sensitivity_weight + dt)
320 weight_old = this%sensitivity_weight / (this%sensitivity_weight + dt)
321
322 ! Rectangle rule; could potentially use higher order trapezoidal/Simpson
323 ! etc, but this should suffice.
324 call vector_add3s2(this%sensitivity, &
325 sensitivity_new, sensitivity_old, weight_new, weight_old)
326 this%sensitivity_weight = this%sensitivity_weight + dt
327
328 nullify(sensitivity_new)
329 nullify(sensitivity_old)
330 call neko_scratch_registry%relinquish(idx)
331 end subroutine functional_accumulate_sensitivity
332
333 ! -------------------------------------------------------------------------- !
334 ! Private helper methods
335
345 pure function functional_in_window(this, time) result(inside)
346 class(base_functional_t), intent(in) :: this
347 type(time_state_t), intent(in) :: time
348 logical :: inside
349 real(kind=rp) :: tol
350
351 tol = 1.0e-6_rp * time%dt
352 inside = time%t .ge. this%start_time - tol .and. &
353 time%t .le. this%end_time + tol
354 end function functional_in_window
355end module base_functional
Defines the abstract the base_functional_t type.
Implements the design_t.
Definition design.f90:36
Implements the steady_problem_t type.
An abstract design type.
Definition design.f90:53