Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
continuation_scheduler.f90
Go to the documentation of this file.
1
34
37 use num_types, only: rp
38 use json_module, only: json_file
39 use json_utils, only: json_get_or_default, json_get_or_lookup, json_get
40 use utils, only: neko_error
41 implicit none
42 private
43
45
46 !------------------------------------------------------------------
47 ! Continuation parameter
48 !------------------------------------------------------------------
49 type continuation_parameter_t
50 character(len=:), allocatable :: name ! Parameter name
51 real(rp), pointer :: target => null() ! Parameter to update
52 real(rp), allocatable :: values(:) ! Values to step through
53 integer :: iterations_per_value = 0 ! How many iterations per value
54 contains
55 procedure :: update => continuation_parameter_update
56 procedure :: free => continuation_parameter_free
57 end type continuation_parameter_t
58
59 !------------------------------------------------------------------
60 ! Continuation scheduler
61 !------------------------------------------------------------------
63 type(continuation_parameter_t), allocatable :: params(:)
64 integer :: default_iterations = 1
65 contains
66 procedure :: init => init_scheduler
67 procedure :: free => free_scheduler
68 procedure :: json_get_or_register
69 procedure :: register_parameter
70 procedure :: update
71 procedure :: get_param_name
72 procedure :: get_n_params
74
75 !------------------------------------------------------------------
76 ! Global continuation object
77 !------------------------------------------------------------------
78 type(continuation_scheduler_t), public, target :: nekotop_continuation
79
80contains
81
83 subroutine init_scheduler(this, json)
84 class(continuation_scheduler_t), intent(inout) :: this
85 type(json_file), intent(inout) :: json
86 integer :: n_default
87
88 call json_get_or_default(json, &
89 'optimization.solver.continuation_iterations', n_default, 1)
90
91 this%default_iterations = n_default
92
93 ! Initialize empty parameter array
94 if (allocated(this%params)) deallocate(this%params)
95 end subroutine init_scheduler
96
98 subroutine free_scheduler(this)
99 class(continuation_scheduler_t), intent(inout) :: this
100 integer :: i
101
102 if (.not. allocated(this%params)) return
103
104 do i = 1, size(this%params)
105 call this%params(i)%free()
106 end do
107
108 deallocate(this%params)
109 end subroutine free_scheduler
110
123 subroutine json_get_or_register(this, json, name, target, value, &
124 default_value)
125 class(continuation_scheduler_t), intent(inout) :: this
126 type(json_file), intent(inout) :: json
127 character(len=*), intent(in) :: name
128 real(kind=rp), target, intent(inout) :: target
129 real(kind=rp), intent(out) :: value
130 real(kind=rp), intent(in), optional :: default_value
131 real(kind=rp), allocatable :: values(:)
132 real(kind=rp) :: scalar_parameter
133 logical :: found
134 integer :: var_type, iter
135
136 ! Inspect JSON for the parameter
137 call json%info(name, found=found, var_type=var_type)
138 if (.not. found) then
139 if (present(default_value)) then
140 value = default_value
141 else
142 call neko_error(trim(name)//" not found and no default provided")
143 end if
144 else if (var_type == 6) then ! scalar
145 if (present(default_value)) then
146 call json_get_or_default(json, name, scalar_parameter, default_value)
147 else
148 call json_get(json, name, scalar_parameter)
149 end if
150 value = scalar_parameter
151 else if (var_type == 3) then ! array
152 call json_get_or_lookup(json, name, values)
153 value = values(1)
154 ! Read optional iterations per parameter step
155 call json_get_or_default(json, trim(name)//'_iterations', iter, &
156 this%default_iterations)
157 ! Register the parameter for continuation
158 call this%register_parameter(name, target, values, iter)
159 else
160 call neko_error(trim(name)//" can only be real variable or real array!")
161 end if
162
163 end subroutine json_get_or_register
164
166 subroutine register_parameter(this, name, target, values, iterations)
167 class(continuation_scheduler_t), intent(inout) :: this
168 character(len=*), intent(in) :: name
169 real(rp), target, intent(inout) :: target
170 real(rp), intent(in) :: values(:)
171 integer, optional, intent(in) :: iterations
172
173 integer :: n, old_size
174 type(continuation_parameter_t), allocatable :: tmp(:)
175 integer :: iter_val
176
177 ! Determine iterations per value
178 if (present(iterations)) then
179 iter_val = iterations
180 else
181 iter_val = this%default_iterations
182 end if
183
184 ! Append new parameter
185 if (.not. allocated(this%params)) then
186 allocate(this%params(1))
187 n = 1
188 else
189 old_size = size(this%params)
190 allocate(tmp(old_size))
191 tmp = this%params
192 deallocate(this%params)
193 allocate(this%params(old_size + 1))
194 this%params(1:old_size) = tmp
195 deallocate(tmp)
196 n = old_size + 1
197 end if
198
199 this%params(n)%name = name
200 this%params(n)%target => target
201 allocate(this%params(n)%values(size(values)))
202 this%params(n)%values = values
203 this%params(n)%iterations_per_value = iter_val
204 end subroutine register_parameter
205
207 subroutine update(this, iter)
208 class(continuation_scheduler_t), intent(inout) :: this
209 integer, intent(in) :: iter
210 integer :: i
211
212 if (.not. allocated(this%params)) return
213
214 do i = 1, size(this%params)
215 call this%params(i)%update(iter)
216 end do
217 end subroutine update
218
220 character(len=32) function get_param_name(this, i)
221 class(continuation_scheduler_t), intent(in) :: this
222 integer, intent(in) :: i
223
224 get_param_name = ''
225 if (.not. allocated(this%params)) return
226 if (i < 1 .or. i > size(this%params)) return
227 get_param_name = this%params(i)%name
228 end function get_param_name
229
231 function get_n_params(this) result(n)
232 class(continuation_scheduler_t), intent(in) :: this
233 integer :: n
234 if (allocated(this%params)) then
235 n = size(this%params)
236 else
237 n = 0
238 end if
239 end function get_n_params
240
242 subroutine continuation_parameter_update(this, iter)
243 class(continuation_parameter_t), intent(inout) :: this
244 integer, intent(in) :: iter
245 integer :: idx
246
247 if (.not. allocated(this%values)) return
248 if (this%iterations_per_value <= 0) return
249
250 idx = (iter - 1) / this%iterations_per_value + 1
251 idx = min(idx, size(this%values))
252
253 this%target = this%values(idx)
254 end subroutine continuation_parameter_update
255
257 subroutine continuation_parameter_free(this)
258 class(continuation_parameter_t), intent(inout) :: this
259 if (allocated(this%name)) deallocate(this%name)
260 if (allocated(this%values)) deallocate(this%values)
261 nullify(this%target)
262 end subroutine continuation_parameter_free
263
264end module continuation_scheduler
Continuation scheduler for the optimization loop.