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
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
117 subroutine json_get_or_register(this, json, name, target, default_value)
118 class(continuation_scheduler_t), intent(inout) :: this
119 type(json_file), intent(inout) :: json
120 character(len=*), intent(in) :: name
121 real(kind=rp), target, intent(inout) :: target
122 real(kind=rp), intent(inout) :: default_value
123 real(kind=rp), allocatable :: values(:)
124 real(kind=rp) :: scalar_parameter
125 logical :: found
126 integer :: var_type, iter
127
128 ! Inspect JSON for the parameter
129 call json%info(name, found=found, var_type=var_type)
130 if (.not. found) then
131 else if (var_type == 6) then ! scalar
132 call json_get_or_default(json, name, scalar_parameter, default_value)
133 default_value = scalar_parameter
134 else if (var_type == 3) then ! array
135 call json_get_or_lookup(json, name, values)
136 default_value = values(1)
137 ! Read optional iterations per parameter step
138 call json_get_or_default(json, trim(name)//'_iterations', iter, &
139 this%default_iterations)
140 ! Register the parameter for continuation
141 call this%register_parameter(name, target, values, iter)
142 else
143 call neko_error(trim(name)//" can only be real variable or real array!")
144 end if
145
146 end subroutine json_get_or_register
147
149 subroutine register_parameter(this, name, target, values, iterations)
150 class(continuation_scheduler_t), intent(inout) :: this
151 character(len=*), intent(in) :: name
152 real(rp), target, intent(inout) :: target
153 real(rp), intent(in) :: values(:)
154 integer, optional, intent(in) :: iterations
155
156 integer :: n, old_size
157 type(continuation_parameter_t), allocatable :: tmp(:)
158 integer :: iter_val
159
160 ! Determine iterations per value
161 if (present(iterations)) then
162 iter_val = iterations
163 else
164 iter_val = this%default_iterations
165 end if
166
167 ! Append new parameter
168 if (.not. allocated(this%params)) then
169 allocate(this%params(1))
170 n = 1
171 else
172 old_size = size(this%params)
173 allocate(tmp(old_size))
174 tmp = this%params
175 deallocate(this%params)
176 allocate(this%params(old_size + 1))
177 this%params(1:old_size) = tmp
178 deallocate(tmp)
179 n = old_size + 1
180 end if
181
182 this%params(n)%name = name
183 this%params(n)%target => target
184 allocate(this%params(n)%values(size(values)))
185 this%params(n)%values = values
186 this%params(n)%iterations_per_value = iter_val
187 end subroutine register_parameter
188
190 subroutine update(this, iter)
191 class(continuation_scheduler_t), intent(inout) :: this
192 integer, intent(in) :: iter
193 integer :: i
194
195 if (.not. allocated(this%params)) return
196
197 do i = 1, size(this%params)
198 call this%params(i)%update(iter)
199 end do
200 end subroutine update
201
203 character(len=32) function get_param_name(this, i)
204 class(continuation_scheduler_t), intent(in) :: this
205 integer, intent(in) :: i
206
207 get_param_name = ''
208 if (.not. allocated(this%params)) return
209 if (i < 1 .or. i > size(this%params)) return
210 get_param_name = this%params(i)%name
211 end function get_param_name
212
214 function get_n_params(this) result(n)
215 class(continuation_scheduler_t), intent(in) :: this
216 integer :: n
217 if (allocated(this%params)) then
218 n = size(this%params)
219 else
220 n = 0
221 end if
222 end function get_n_params
223
225 subroutine continuation_parameter_update(this, iter)
226 class(continuation_parameter_t), intent(inout) :: this
227 integer, intent(in) :: iter
228 integer :: idx
229
230 if (.not. allocated(this%values)) return
231 if (this%iterations_per_value <= 0) return
232
233 idx = (iter - 1) / this%iterations_per_value + 1
234 idx = min(idx, size(this%values))
235
236 this%target = this%values(idx)
237 end subroutine continuation_parameter_update
238
240 subroutine continuation_parameter_free(this)
241 class(continuation_parameter_t), intent(inout) :: this
242 if (allocated(this%name)) deallocate(this%name)
243 if (allocated(this%values)) deallocate(this%values)
244 nullify(this%target)
245 end subroutine continuation_parameter_free
246
247end module continuation_scheduler
Continuation scheduler for the optimization loop.