Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
mma_optimizer.f90
Go to the documentation of this file.
2 use optimizer, only: optimizer_t
3 use problem, only : problem_t
4 use mma, only: mma_t
5 use problem, only: problem_t
6 use num_types, only: rp
7 use utils, only: neko_error
8 use json_module, only: json_file
9 use json_utils, only: json_get_or_default
10 use simulation, only: simulation_t
11 use design, only: design_t
12 use field, only: field_t
13 use field_registry, only: neko_field_registry
14
15 use vector, only: vector_t
16 use matrix, only: matrix_t
17
18 !only to print nglobal when running in parallel
19 use comm, only: neko_comm, pe_rank
20 use mpi_f08, only: mpi_integer, mpi_sum, mpi_allreduce
21
22 use neko_config, only: neko_bcknd_device
23 ! Inclusions from external dependencies and standard libraries
24 use, intrinsic :: iso_fortran_env, only: stderr => error_unit
25
26 use math, only: copy, cmult
27 use device_math, only: device_copy
28 use field_math, only: field_rzero
29 use neko_ext, only: reset
31 use device, only: device_memcpy, host_to_device, device_to_host
33
34 use device_math, only: device_copy
35 implicit none
36 private
37 public :: mma_optimizer_t
38
39 ! Concrete type for MMA optimizer
40 type, extends(optimizer_t) :: mma_optimizer_t
41
42 type(mma_t) :: mma
43
50 real(kind=rp) :: scale
51 logical :: auto_scale
52
53 contains
54
55 ! Override the deferred methods
56 generic :: init => init_from_json, init_from_components
57 procedure, pass(this) :: init_from_json => mma_optimizer_init_from_json
58 procedure, pass(this) :: init_from_components => &
60
61 procedure :: run => mma_optimizer_run
62 procedure :: free => mma_optimizer_free
63
64 end type mma_optimizer_t
65
66contains
67
69 subroutine mma_optimizer_init_from_json(this, parameters, problem, design, &
70 simulation, max_iterations, tolerance)
71 class(mma_optimizer_t), intent(inout) :: this
72 type(json_file), intent(inout) :: parameters
73 class(problem_t), intent(in) :: problem
74 class(design_t), intent(in) :: design
75 type(simulation_t), intent(in) :: simulation
76 integer, intent(in) :: max_iterations
77 real(kind=rp), intent(in) :: tolerance
78
79 character(len=1024) :: optimization_header
80 character(len=1024) :: problem_header
81
82 type(vector_t) :: x
83 type(json_file) :: solver_parameters
84
85 ! Initialize the logger
86 call this%logger%init('optimization_data.csv')
87
88 ! Write the header
89 problem_header = problem%get_log_header()
90 optimization_header = 'iter, ' // trim(problem_header) // &
91 ', KKTmax, KKTnorm2, scaling factor'
92 call this%logger%set_header(trim(optimization_header))
93
94 x = design%get_design()
95
96 if (pe_rank .eq. 0) then
97 print *, "Initializing mma_optimizer with steady_state_problem_t."
98 end if
99
100 call json_get_subdict(parameters, "optimization.solver", solver_parameters)
101 call this%mma%init(x%x, design%size(), problem%get_n_constraints(), &
102 solver_parameters, this%scale, this%auto_scale)
103
104 call this%init_from_components(problem, design, simulation, &
105 max_iterations, tolerance)
106
107 call x%free()
108 end subroutine mma_optimizer_init_from_json
109
111 subroutine mma_optimizer_init_from_components(this, problem, design, &
112 simulation, max_iterations, tolerance)
113 class(mma_optimizer_t), intent(inout) :: this
114 class(problem_t), intent(in) :: problem
115 class(design_t), intent(in) :: design
116 type(simulation_t), intent(in) :: simulation
117 integer, intent(in) :: max_iterations
118 real(kind=rp), intent(in) :: tolerance
119
120 call this%init_base(max_iterations, tolerance)
121
123
125 subroutine mma_optimizer_run(this, problem, design, simulation)
126 class(mma_optimizer_t), intent(inout) :: this
127 class(problem_t), intent(inout) :: problem
128 class(design_t), intent(inout) :: design
129 type(simulation_t), intent(inout) :: simulation
130
131 type(vector_t) :: x
132
133 integer :: iter, ierr, nglobal, n
134 real(kind=rp) :: scaling_factor
135
136 real(kind=rp) :: objective_value
137 type(vector_t) :: all_objectives
138 type(vector_t) :: constraint_value
139 type(vector_t) :: objective_sensitivities
140 type(matrix_t) :: constraint_sensitivities
141
142 type(vector_t) :: log_data
143
144
145 n = design%size()
146 call mpi_allreduce(n, nglobal, 1, mpi_integer, mpi_sum, neko_comm, ierr)
147
149 scaling_factor = 1.0_rp
150 if (pe_rank .eq. 0) then
151 print *, "max_iterations for the optimization loop = ", &
152 this%max_iterations
153 end if
154
155 call simulation%run_forward()
156 call problem%compute(design)
157
158 call simulation%run_backward()
159 call problem%compute_sensitivity(design)
160
161 call problem%get_objective_value(objective_value)
162 call problem%get_constraint_values(constraint_value)
163 call problem%get_objective_sensitivities(objective_sensitivities)
164 call problem%get_constraint_sensitivities(constraint_sensitivities)
165 call problem%get_all_objective_values(all_objectives)
166
167 ! Stamp the initial condition
168 call mma_logger_assemble_data(log_data, 0, objective_value, &
169 all_objectives, constraint_value, 0.0_rp, 0.0_rp, scaling_factor, &
170 problem%get_n_objectives(), problem%get_n_constraints())
171 call this%logger%write(log_data)
172
173 call simulation%write(0)
174 call design%write(0)
175
176 do iter = 1, this%max_iterations
177 if (this%mma%get_residumax() .lt. this%tolerance) exit
178
179 ! Scaling
180 if (this%auto_scale .eqv. .true.) then
181 scaling_factor = abs(this%scale/constraint_value%x(1))
182 else
183 scaling_factor = abs(this%scale)
184 end if
185
186 x = design%get_design()
187
188 ! Use scaled sensitivities to update the design variable
189 call this%mma%update(iter, x%x, objective_sensitivities, &
190 scaling_factor * constraint_value, &
191 scaling_factor * constraint_sensitivities)
192
193 call design%update_design(x)
194
195 call simulation%run_forward()
196 call problem%compute(design)
197
198 call simulation%run_backward()
199 call problem%compute_sensitivity(design)
200
201 call problem%get_objective_value(objective_value)
202 call problem%get_constraint_values(constraint_value)
203 call problem%get_objective_sensitivities(objective_sensitivities)
204 call problem%get_constraint_sensitivities(constraint_sensitivities)
205 call problem%get_all_objective_values(all_objectives)
206
207 call this%mma%KKT(x%x, objective_sensitivities, &
208 constraint_value, constraint_sensitivities)
209
210 ! Stamp the i^th iteration
211 call mma_logger_assemble_data(log_data, iter, objective_value, &
212 all_objectives, constraint_value, this%mma%get_residumax(), &
213 this%mma%get_residunorm(), scaling_factor, &
214 problem%get_n_objectives(), problem%get_n_constraints())
215 call this%logger%write(log_data)
216
217 call simulation%write(iter)
218 call design%write(iter)
219 call simulation%reset()
220 end do
221
222 ! Final state after optimization
223 if (pe_rank .eq. 0) then
224 print *, "MMA Optimization completed after", iter-1, "iterations."
225 end if
226
227 call constraint_value%free()
228 call objective_sensitivities%free()
229 call constraint_sensitivities%free()
230
231 end subroutine mma_optimizer_run
232
233 ! Free resources associated with the MMA optimizer
234 subroutine mma_optimizer_free(this)
235 class(mma_optimizer_t), intent(inout) :: this
236
237 ! Free MMA-specific data
238 call this%mma%free()
239 end subroutine mma_optimizer_free
240
241 ! package up the log data
242 subroutine mma_logger_assemble_data(log_data, iter, objective_value, &
243 all_objectives, constraint_value, residumax, residunorm, &
244 scaling_factor, n, m)
245 type(vector_t), intent(out) :: log_data
246 integer, intent(in) :: iter
247 real(kind=rp), intent(in) ::objective_value
248 type(vector_t), intent(in) :: all_objectives
249 type(vector_t), intent(in) :: constraint_value
250 real(kind=rp), intent(in) :: residumax, residunorm, scaling_factor
251 integer, intent(in) :: n, m
252 integer :: i_tmp1, i_tmp2
253
254 ! initialize the logger data
255 ! iter | tot F | F_1 | .. |F_n | C_1 | ... | C_n | KKT | KKT2 | scale |
256 call log_data%init(5 + n + m)
257
258 ! iteration
259 log_data%x(1) = real(iter, kind=rp)
260
261 ! total objective
262 log_data%x(2) = objective_value
263
264 ! individual objectives
265 i_tmp1 = 3
266 i_tmp2 = i_tmp1 + n - 1
267 log_data%x(i_tmp1 : i_tmp2) = all_objectives%x
268
269 ! constraints
270 i_tmp1 = i_tmp2 + 1
271 i_tmp2 = i_tmp1 + m - 1
272 log_data%x(i_tmp1 : i_tmp2) = constraint_value%x
273
274 ! convergence stuff
275 log_data%x(i_tmp2 + 1) = residumax
276 log_data%x(i_tmp2 + 2) = residunorm
277 log_data%x(i_tmp2 + 3) = scaling_factor
278
279 end subroutine mma_logger_assemble_data
280end module mma_optimizer
281
Implements the design_t.
Definition design.f90:34
subroutine, public json_get_subdict(json, key, output)
Extract a sub-object from a json object.
Some common Masking operations we may need.
Definition mask_ops.f90:34
subroutine mma_optimizer_init_from_json(this, parameters, problem, design, simulation, max_iterations, tolerance)
Initialize the MMA optimizer from JSON file.
subroutine mma_optimizer_free(this)
subroutine mma_optimizer_run(this, problem, design, simulation)
Define the optimization loop for MMA.
subroutine mma_logger_assemble_data(log_data, iter, objective_value, all_objectives, constraint_value, residumax, residunorm, scaling_factor, n, m)
subroutine mma_optimizer_init_from_components(this, problem, design, simulation, max_iterations, tolerance)
Initialize the MMA optimizer from JSON file.
Definition mma.f90:34
Contains extensions to the neko library required to run the topology optimization code.
Definition neko_ext.f90:9
subroutine, public reset(neko_case)
Reset the case data structure.
Definition neko_ext.f90:42
Module for handling the optimization problem.
Definition problem.f90:35
Implements the steady_problem_t type.
An abstract design type.
Definition design.f90:48
Abstract optimizer class.
Definition optimizer.f90:18
The abstract problem type.
Definition problem.f90:61