MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
mma.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_MMA
13#define MFEM_MMA
14
15#include "../config/config.hpp"
16
17#include <memory>
18
19#ifdef MFEM_USE_MPI
20#include <mpi.h>
21#endif
22
23namespace mfem
24{
25// forward declaration
26class Vector;
27
28/** \brief MMA (Method of Moving Asymptotes) solves a nonlinear optimization
29 * problem involving an objective function, inequality constraints,
30 * and variable bounds.
31 *
32 * \details
33 * This class finds ${\bf x} \in R^n$ that solves the following nonlinear
34 * program:
35 * $$
36 * \begin{array}{ll}
37 * \min_{{\bf x} \in R^n} & F({\bf x})\\
38 * \textrm{subject to} & C({\bf x})_i \leq 0,\quad
39 * \textrm{for all}\quad i = 1,\ldots m\\
40 * & {\bf x}_{\textrm{lo}} \leq {\bf x} \leq
41 * {\bf x}_{\textrm{hi}}.
42 * \end{array}
43 * $$
44 * Here $F : R^n \to R$ is the objective function, and
45 * $C : R^n \to R^m$ is a set of $m$ inequality constraints. The
46 * variable bounds are sometimes called box constraints. By
47 * convention, the routine seeks ${\bf x}$ that minimizes the
48 * objective function, $F$. Maximization problems should be
49 * reformulated as a minimization of $-F$.
50 *
51 * The objective functions are replaced by convex functions
52 * chosen based on gradient information, and solved using a dual method.
53 * The unique optimal solution of this subproblem is returned as the next
54 * iteration point. Optimality is determined by the KKT conditions.
55 *
56 * The "Update" function in MMA advances the optimization and must be
57 * called in every optimization iteration. Current and previous iteration
58 * points construct the "moving asymptotes". The design variables,
59 * objective function, constraints are passed to an approximating
60 * subproblem. The design variables are updated and returned. Its
61 * implementation closely follows the original formulation of <a
62 * href="https://people.kth.se/~krille/mmagcmma.pdf">'Svanberg, K. (2007).
63 * MMA and GCMMA-two methods for nonlinear optimization. vol, 1, 1-15.'</a>
64 *
65 * When used in parallel, all Vectors are assumed to be true dof vectors,
66 * and the operators are expected to be defined for tdof vectors.
67 * */
68
69class MMA
70{
71public:
72 /**
73 * \brief Serial constructor
74 * \param nVar total number of design parameters
75 * \param nCon number of inequality constraints (i.e., $C$)
76 * \param xval initial values for design parameters (a pointer
77 * to \p nVar doubles). Caller retains ownership of
78 * this pointer/data.
79 * \param iterationNumber the starting iteration number
80 */
81 MMA(int nVar, int nCon, real_t *xval, int iterationNumber = 0);
82
83 /**
84 * \brief Serial constructor
85 * \param nVar total number of design parameters
86 * \param nCon number of inequality constraints (i.e., $C$)
87 * \param xval initial values for design parameters (size should
88 * be \p nVar). Caller retains ownership of
89 * this Vector.
90 * \param iterationNumber the starting iteration number
91 */
92 MMA(const int nVar, int nCon, Vector & xval, int iterationNumber = 0);
93
94#ifdef MFEM_USE_MPI
95 /**
96 * \brief Parallel constructor
97 * \param comm_ the MPI communicator participating in the NLP solve
98 * \param nVar number of design parameters on this MPI rank
99 * \param nCon total number of inequality constraints (i.e., $C$).
100 * Every MPI rank provides the same value here.
101 * \param xval initial values for design parameters on this MPI rank
102 * (a pointer to \p nVar doubles). Caller retains ownership
103 * of this pointer/data.
104 * \param iterationNumber the starting iteration number. All MPI ranks
105 * should pass in the same value here.
106 *
107 * \details
108 * Each MPI rank has a subset of the total design variable vector, and
109 * calls for that MPI rank always address its subset of the design
110 * variable vector and gradients with respect to its subset of the design
111 * variable vector.
112 *
113 * If you wanted to determine the global number of design variables, it
114 * would be determined as follows:
115 * \code{.cpp}
116 * int globalDesignVars;
117 * MPI_Allreduce(&nVar, &globalDesignVars, 1, MPI_INT, MPI_SUM, comm_);
118 * \endcode
119 */
120 MMA(MPI_Comm comm_, int nVar, int nCon, real_t *xval,
121 int iterationNumber = 0);
122 /**
123 * \brief Parallel constructor
124 * \param comm_ the MPI communicator participating in the NLP solve
125 * \param nVar number of design parameters on this MPI rank
126 * \param nCon total number of inequality constraints (i.e., $C$).
127 * Every MPI rank provides the same value here.
128 * \param xval initial values for design parameters (size should
129 * be \p nVar). Caller retains ownership of
130 * this Vector.
131 * \param iterationNumber the starting iteration number. All MPI ranks
132 * should pass in the same value here.
133 *
134 * \details
135 * Each MPI rank has a subset of the total design variable vector, and
136 * calls for that MPI rank always address its subset of the design
137 * variable vector and gradients with respect to its subset of the design
138 * variable vector.
139 *
140 * If you wanted to determine the global number of design variables, it
141 * would be determined as follows:
142 * \code{.cpp}
143 * int globalDesignVars;
144 * MPI_Allreduce(&nVar, &globalDesignVars, 1, MPI_INT, MPI_SUM, comm_);
145 * \endcode
146 */
147 MMA(MPI_Comm comm_, const int nVar, const int nCon, const Vector & xval,
148 int iterationNumber = 0);
149#endif
150
151 /// Destructor
152 ~MMA();
153
154 /**
155 * \brief Update the optimization parameters for a constrained
156 * nonlinear program
157 * \param dfdx vector of size nVar holding the gradients of the
158 * objective function with respect to
159 * the design variables,
160 * $\frac{\partial F}{\partial {\bf x}_i}$
161 * for each variable on this rank.
162 * \param gx vector of size nCon holding the values of the
163 * inequality constraints. Every MPI rank should
164 * pass in the same values here.
165 * \param dgdx vector of size $\textrm{nCon}\cdot\textrm{nVar}$
166 * holding the gradients of the constraints in
167 * row-major order. For example, {dg0dx0, dg0dx1, ...,}
168 * {dg1dx0, dg1dx1, ..., }, ...
169 * \param xmin vector of size nVar holding the lower bounds on
170 * the design values. \p xmin and \p xmax are
171 * the box constraints.
172 * \param xmax vector of size nVar holding the upper bounds on
173 * the design values. \p xmin and \p xmax are
174 * the box constraints.
175 * \param xval vector of size nVar. On entry, this holds the
176 * value of the design variables where the objective,
177 * constraints, and their gradients were evaluated.
178 * On exit, this holds the result of the MMA iteration,
179 * the next design variable value to use.
180 *
181 * \details
182 * The caller retains ownership of all Vectors passed into this method.
183 */
184 void Update(const Vector& dfdx,
185 const Vector& gx, const Vector& dgdx,
186 const Vector& xmin, const Vector& xmax,
187 Vector& xval);
188
189 /**
190 * \brief Update the optimization parameters for an unconstrained
191 * nonlinear program
192 * \param dfdx vector of size nVar holding the gradients of the
193 * objective function with respect to
194 * the design variables,
195 * $\frac{\partial F}{\partial {\bf x}_i}$
196 * for each variable on this rank.
197 * \param xmin vector of size nVar holding the lower bounds on
198 * the design values. \p xmin and \p xmax are
199 * the box constraints.
200 * \param xmax vector of size nVar holding the upper bounds on
201 * the design values. \p xmin and \p xmax are
202 * the box constraints.
203 * \param xval vector of size nVar. On entry, this holds the
204 * value of the design variables where the objective,
205 * constraints, and their gradients were evaluated.
206 * On exit, this holds the result of the MMA iteration,
207 * the next design variable value to use.
208 *
209 * \details
210 * The caller retains ownership of all Vectors passed into this method.
211 * This should be used when the number of inequality constraints is zero.
212 */
213 void Update( const Vector& dfdx,
214 const Vector& xmin, const Vector& xmax,
215 Vector& xval);
216
217 /**
218 * \brief Change the iteration number
219 * \param iterationNumber the new iteration number
220 */
221 void SetIteration( int iterationNumber ) { iter = iterationNumber; };
222
223 /// Return the current iteration number
224 int GetIteration() const { return iter; };
225
226 /**
227 * \brief change the print level
228 * \param print_lvl the new print level
229 */
230 void SetPrintLevel(int print_lvl) { print_level = print_lvl; }
231
232protected:
233 // Local vectors
234 ::std::unique_ptr<real_t[]> a, b, c, d;
237 int nCon, nVar;
238
239 // counter for Update() calls
240 int iter = 0;
241
242 // print level: 1 = none, 2 = warnings
243 int print_level = 1;
244
245 // Global: Asymptotes, bounds, objective approx., constraint approx.
246 ::std::unique_ptr<real_t[]> low, upp;
247 ::std::unique_ptr<real_t[]> x, y, xsi, eta, lam, mu, s;
248
249private:
250 // MMA-specific
251 real_t asyinit, asyincr, asydecr;
252 real_t xmamieps, lowmin, lowmax, uppmin, uppmax, zz;
253 ::std::unique_ptr<real_t[]> factor;
254
255 /// values from the previous two iterations
256 ::std::unique_ptr<real_t[]> xo1, xo2;
257
258 /// KKT norm
259 real_t kktnorm;
260
261 /// initialization state
262 bool isInitialized = false;
263
264#ifdef MFEM_USE_MPI
265 MPI_Comm comm;
266#endif
267
268 /// Allocate the memory for MMA
269 void AllocData(int nVar, int nCon);
270
271 /// Initialize data
272 void InitData(real_t *xval);
273
274 /// Update the optimization parameters
275 /// dfdx[nVar] - gradients of the objective
276 /// gx[nCon] - values of the constraints
277 /// dgdx[nCon*nVar] - gradients of the constraints
278 /// xxmin[nVar] - lower bounds
279 /// xxmax[nVar] - upper bounds
280 /// xval[nVar] - (input: current optimization parameters)
281 /// xval[nVar] - (output: updated optimization parameters)
282 void Update(const real_t* dfdx, const real_t* gx,
283 const real_t* dgdx,
284 const real_t* xxmin,const real_t* xxmax,
285 real_t* xval);
286
287 /// Subproblem base class
288 class MMASubBase
289 {
290 public:
291 /// Constructor
292 MMASubBase(MMA& mma) :mma_ref(mma) {}
293
294 /// Destructor
295 virtual ~MMASubBase() {}
296
297 /// Update the optimization parameters
298 virtual
299 void Update(const real_t* dfdx,
300 const real_t* gx,
301 const real_t* dgdx,
302 const real_t* xmin,
303 const real_t* xmax,
304 const real_t* xval)=0;
305
306 protected:
307 MMA& mma_ref;
308 };
309
310 ::std::unique_ptr<MMASubBase> mSubProblem;
311
312 friend class MMASubSvanberg;
313
314 class MMASubSvanberg:public MMASubBase
315 {
316 public:
317 /// Constructor
318 MMASubSvanberg(MMA& mma, int nVar, int nCon):MMASubBase(mma)
319 {
320 AllocSubData(nVar,nCon);
321
322 nVar_global = nVar;
323#ifdef MFEM_USE_MPI
324 MPI_Allreduce(&nVar, &nVar_global, 1, MPI_INT, MPI_SUM, mma.comm);
325#endif
326 }
327
328 /// Destructor
329 virtual
330 ~MMASubSvanberg() = default;
331
332 /// Update the optimization parameters
333 virtual
334 void Update(const real_t* dfdx,
335 const real_t* gx,
336 const real_t* dgdx,
337 const real_t* xmin,
338 const real_t* xmax,
339 const real_t* xval);
340
341 private:
342 int ittt, itto, itera, nVar_global;
343
344 real_t epsi, delz, dz, dzet, stmxx, stmalfa, stmbeta,
345 sum, stminv, steg, zold, zetold,
346 residunorm, residumax, resinew, raa0, albefa, move, xmamieps;
347
348 ::std::unique_ptr<real_t[]> sum1, ux1, xl1, plam, qlam, gvec, residu, GG, delx,
349 dely,
350 dellam,
351 dellamyi, diagx, diagy, diaglamyi, bb, bb1, Alam, AA, AA1,
352 dlam, dx, dy, dxsi, deta, dmu, Axx, axz, ds, xx, dxx,
353 stepxx, stepalfa, stepbeta, xold, yold,
354 lamold, xsiold, etaold, muold, sold, p0, q0, P, Q, alfa,
355 beta, xmami, b;
356
357 // parallel helper variables
358 real_t global_max = 0.0;
359 real_t global_norm = 0.0;
360 real_t stmxx_global = 0.0;
361 real_t stmalfa_global = 0.0;
362 real_t stmbeta_global = 0.0;
363
364 ::std::unique_ptr<real_t[]> b_local, gvec_local, Alam_local, sum_local,
365 sum_global;
366
367 /// Allocate the memory for the subproblem
368 void AllocSubData(int nVar, int nCon);
369
370 };
371};
372
373} // mfem namespace
374
375#endif // MFEM_MMA
MMA (Method of Moving Asymptotes) solves a nonlinear optimization problem involving an objective func...
Definition mma.hpp:70
::std::unique_ptr< real_t[]> mu
Definition mma.hpp:247
::std::unique_ptr< real_t[]> b
Definition mma.hpp:234
::std::unique_ptr< real_t[]> eta
Definition mma.hpp:247
int print_level
Definition mma.hpp:243
::std::unique_ptr< real_t[]> d
Definition mma.hpp:234
real_t a0
Definition mma.hpp:235
~MMA()
Destructor.
Definition mma.cpp:1028
real_t machineEpsilon
Definition mma.hpp:235
real_t zet
Definition mma.hpp:236
friend class MMASubSvanberg
Definition mma.hpp:312
::std::unique_ptr< real_t[]> c
Definition mma.hpp:234
void Update(const Vector &dfdx, const Vector &gx, const Vector &dgdx, const Vector &xmin, const Vector &xmax, Vector &xval)
Update the optimization parameters for a constrained nonlinear program.
Definition mma.cpp:1072
MMA(int nVar, int nCon, real_t *xval, int iterationNumber=0)
Serial constructor.
Definition mma.cpp:975
void SetIteration(int iterationNumber)
Change the iteration number.
Definition mma.hpp:221
::std::unique_ptr< real_t[]> upp
Definition mma.hpp:246
::std::unique_ptr< real_t[]> a
Definition mma.hpp:234
::std::unique_ptr< real_t[]> x
Definition mma.hpp:247
::std::unique_ptr< real_t[]> xsi
Definition mma.hpp:247
int GetIteration() const
Return the current iteration number.
Definition mma.hpp:224
::std::unique_ptr< real_t[]> lam
Definition mma.hpp:247
::std::unique_ptr< real_t[]> low
Definition mma.hpp:246
real_t z
Definition mma.hpp:236
::std::unique_ptr< real_t[]> y
Definition mma.hpp:247
int nCon
Definition mma.hpp:237
void SetPrintLevel(int print_lvl)
change the print level
Definition mma.hpp:230
::std::unique_ptr< real_t[]> s
Definition mma.hpp:247
int nVar
Definition mma.hpp:237
int iter
Definition mma.hpp:240
real_t epsimin
Definition mma.hpp:235
Vector data type.
Definition vector.hpp:82
real_t b
Definition lissajous.cpp:42
mfem::real_t real_t
float real_t
Definition config.hpp:46
void Update(Vector &x, int k, DenseMatrix &h, Vector &s, Array< Vector * > &v)
Definition solvers.cpp:1113