24#if __cplusplus >= 201402L
25inline ::std::unique_ptr<::mfem::real_t[]> allocArray(
int size) { return ::std::make_unique<::mfem::real_t[]>(size); }
27inline ::std::unique_ptr<::mfem::real_t[]> allocArray(
int size) { return ::std::unique_ptr<::mfem::real_t[]>(new ::mfem::real_t[size]); }
32extern "C" void dgesv_(
int* nLAP,
int* nrhs,
double* AA,
int* lda,
34 double* bb,
int* ldb,
int* info);
36extern "C" void sgesv_(
int* nLAP,
int* nrhs,
float* AA,
int* lda,
38 float* bb,
int* ldb,
int* info);
50 ::std::unique_ptr<::std::unique_ptr<real_t[]>[]> A(
51 new ::std::unique_ptr<
real_t[]>[nLAP]);
52 for (
int i = 0; i < nLAP; ++i)
54 A[i] = allocArray(nLAP);
56 ::std::unique_ptr<real_t[]> B = allocArray(nLAP);
57 for (
int i = 0; i < nLAP; ++i)
59 for (
int j = 0; j < nLAP; ++j)
61 A[i][j] = AA1[j * nLAP + i];
67 ::std::unique_ptr<::std::unique_ptr<real_t[]>[]> L(
68 new ::std::unique_ptr<
real_t[]>[nLAP]),
69 U(new ::std::unique_ptr<
real_t[]>[nLAP]);
70 for (
int i = 0; i < nLAP; ++i)
72 L[i] = allocArray(nLAP);
73 U[i] = allocArray(nLAP);
74 for (
int j = 0; j < nLAP; ++j)
81 for (
int i = 0; i < nLAP; ++i)
83 for (
int k = i; k < nLAP; ++k)
86 for (
int j = 0; j < i; ++j)
88 sum += (L[i][j] * U[j][k]);
90 U[i][k] = A[i][k] - sum;
92 for (
int k = i; k < nLAP; ++k)
101 for (
int j = 0; j < i; ++j)
103 sum += (L[k][j] * U[j][i]);
105 L[k][i] = (A[k][i] - sum) / U[i][i];
111 for (
int i = 0; i < nLAP; ++i)
115 MFEM_ABORT(
"Error: matrix in MMA LU Solve is singular.");
120 ::std::unique_ptr<real_t[]> Y=allocArray(nLAP);
121 for (
int i = 0; i < nLAP; ++i)
124 for (
int j = 0; j < i; ++j)
126 sum += L[i][j] * Y[j];
128 Y[i] = (B[i] - sum) / L[i][i];
132 ::std::unique_ptr<real_t[]> X=allocArray(nLAP);
133 for (
int i = nLAP - 1; i >= 0; --i)
136 for (
int j = i + 1; j < nLAP; ++j)
138 sum += U[i][j] * X[j];
140 X[i] = (Y[i] - sum) / U[i][i];
145 for (
int i = 0; i < (nCon + 1); i++)
151void MMA::MMASubSvanberg::AllocSubData(
int nvar,
int ncon)
154 ittt = itto = itera = 0;
159 ux1 = allocArray(nvar);
160 xl1 = allocArray(nvar);
161 plam = allocArray(nvar);
162 qlam = allocArray(nvar);
163 gvec = allocArray(ncon);
164 residu = allocArray(3 * nvar + 4 * ncon + 2);
165 GG = allocArray(nvar * ncon);
166 delx = allocArray(nvar);
167 dely = allocArray(ncon);
168 dellam = allocArray(ncon);
169 dellamyi = allocArray(ncon);
170 diagx = allocArray(nvar);
171 diagy = allocArray(ncon);
172 diaglamyi = allocArray(ncon);
173 bb = allocArray(nvar + 1);
174 bb1 = allocArray(ncon + 1);
175 Alam = allocArray(ncon * ncon);
176 AA = allocArray((nvar + 1) * (nvar + 1));
177 AA1 = allocArray((ncon + 1) * (ncon + 1));
178 dlam = allocArray(ncon);
179 dx = allocArray(nvar);
180 dy = allocArray(ncon);
181 dxsi = allocArray(nvar);
182 deta = allocArray(nvar);
183 dmu = allocArray(ncon);
184 Axx = allocArray(nvar * ncon);
185 axz = allocArray(nvar);
186 ds = allocArray(ncon);
187 xx = allocArray(4 * ncon + 2 * nvar + 2);
188 dxx = allocArray(4 * ncon + 2 * nvar + 2);
189 stepxx = allocArray(4 * ncon + 2 * nvar + 2);
191 sum1 = allocArray(nvar);
192 stepalfa = allocArray(nvar);
193 stepbeta = allocArray(nvar);
194 xold = allocArray(nvar);
195 yold = allocArray(ncon);
196 lamold = allocArray(ncon);
197 xsiold = allocArray(nvar);
198 etaold = allocArray(nvar);
199 muold = allocArray(ncon);
200 sold = allocArray(ncon);
201 q0 = allocArray(nvar);
202 p0 = allocArray(nvar);
203 P = allocArray(ncon * nvar);
204 Q = allocArray(ncon * nvar);
205 alfa = allocArray(nvar);
206 beta = allocArray(nvar);
207 xmami = allocArray(nvar);
208 b = allocArray(ncon);
210 b_local = allocArray(ncon);
211 gvec_local = allocArray(ncon);
212 Alam_local = allocArray(ncon * ncon);
213 sum_local = allocArray(ncon);
214 sum_global = allocArray(ncon);
217 for (
int i=0; i<(3 * nvar + 4 * ncon + 2); i++)
223void MMA::MMASubSvanberg::Update(
const real_t* dfdx,
230 MMA& mma = this->mma_ref;
234 MPI_Comm_rank(mma.comm, &rank);
249 for (
int i = 0; i < ncon; i++)
255 for (
int i = 0; i < nvar; i++)
261 alfa[i] = std::max(std::max(mma.low[i] + albefa * (xval[i] - mma.low[i]),
262 xval[i] - move * (xmax[i] - xmin[i])), xmin[i]);
263 beta[i] = std::min(std::min(mma.upp[i] - albefa * (mma.upp[i] - xval[i]),
264 xval[i] + move * (xmax[i] - xmin[i])), xmax[i]);
265 xmami[i] = std::max(xmax[i] - xmin[i], xmamieps);
268 ux1[i] = mma.upp[i] - xval[i];
269 if (std::fabs(ux1[i]) <= mma.machineEpsilon)
271 ux1[i] = mma.machineEpsilon;
273 xl1[i] = xval[i] - mma.low[i];
274 if (std::fabs(xl1[i]) <= mma.machineEpsilon)
276 xl1[i] = mma.machineEpsilon;
278 p0[i] = ( std::max(dfdx[i], zero) + 0.001 * (std::max(dfdx[i],
279 zero) + std::max(-dfdx[i], zero)) + raa0 / xmami[i]) * ux1[i] * ux1[i];
280 q0[i] = ( std::max(-dfdx[i], zero) + 0.001 * (std::max(dfdx[i],
281 zero) + std::max(-dfdx[i], zero)) + raa0 / xmami[i]) * xl1[i] * xl1[i];
288 for (
int i = 0; i < ncon; i++)
290 for (
int j = 0; j < nvar; j++)
294 P[i * nvar + j] = (std::max(dgdx[i * nvar + j],
295 zero) + 0.001 * (std::max(dgdx[i * nvar + j],
296 zero) + std::max(-1*dgdx[i * nvar + j],
297 zero)) + raa0 / xmami[j]) * ux1[j] * ux1[j];
298 Q[i * nvar + j] = (std::max(-1*dgdx[i * nvar + j],
299 zero) + 0.001 * (std::max(dgdx[i * nvar + j],
300 zero) + std::max(-1*dgdx[i * nvar + j],
301 zero)) + raa0 / xmami[j]) * xl1[j] * xl1[j];
303 b_local[i] = b_local[i] + P[i * nvar + j] / ux1[j] + Q[i * nvar + j] / xl1[j];
307 std::copy(b_local.get(), b_local.get() + ncon,
b.get());
310 MPI_Allreduce(b_local.get(),
b.get(), ncon, MPITypeMap<real_t>::mpi_type,
315 for (
int i = 0; i < ncon; i++)
321 for (
int i = 0; i < nvar; i++)
323 mma.x[i] = 0.5 * (alfa[i] +
beta[i]);
324 mma.xsi[i] = 1.0/(mma.x[i] - alfa[i]);
325 mma.xsi[i] = std::max(mma.xsi[i],
static_cast<real_t>(1.0));
326 mma.eta[i] = 1.0/(
beta[i] - mma.x[i]);
327 mma.eta[i] = std::max(mma.eta[i],
static_cast<real_t>(1.0));
332 for (
int i = 0; i < ncon; i++)
336 mma.mu[i] = std::max(1.0, 0.5 * mma.c[i]);
340 while (epsi > mma.epsimin)
342 residu[nvar + ncon] = mma.a0 - mma.zet;
343 for (
int i = 0; i < nvar; i++)
345 ux1[i] = mma.upp[i] - mma.x[i];
346 if (std::fabs(ux1[i]) < mma.machineEpsilon)
348 ux1[i] = mma.machineEpsilon;
351 xl1[i] = mma.x[i] - mma.low[i];
352 if (std::fabs(xl1[i]) < mma.machineEpsilon)
354 xl1[i] = mma.machineEpsilon;
360 for (
int j = 0; j < ncon; j++)
362 plam[i] += P[j * nvar + i] * mma.lam[j];
363 qlam[i] += Q[j * nvar + i] * mma.lam[j];
364 residu[nvar + ncon] -= mma.a[j] * mma.lam[j];
366 residu[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]) -
367 mma.xsi[i] + mma.eta[i];
369 residu[nvar + ncon + 1 + ncon + i] = mma.xsi[i] * (mma.x[i] - alfa[i]) -
371 if (std::fabs(mma.x[i]-alfa[i]) < mma.machineEpsilon)
373 residu[nvar + ncon + 1 + ncon + i] = mma.xsi[i] * mma.machineEpsilon - epsi;
375 residu[nvar + ncon + 1 + ncon + nvar + i] = mma.eta[i] *
376 (
beta[i] - mma.x[i]) - epsi;
377 if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
379 residu[nvar + ncon + 1 + ncon + nvar + i] = mma.eta[i] * mma.machineEpsilon -
383 for (
int i = 0; i < ncon; i++)
387 for (
int j = 0; j < nvar; j++)
389 gvec_local[i] = gvec_local[i] + P[i * nvar + j] / ux1[j] + Q[i * nvar + j] /
394 std::copy(gvec_local.get(), gvec_local.get() + ncon, gvec.get());
397 MPI_Allreduce(gvec_local.get(), gvec.get(), ncon, MPITypeMap<real_t>::mpi_type,
404 for (
int i = 0; i < ncon; i++)
406 residu[nvar + i] = mma.c[i] + mma.d[i] * mma.y[i] - mma.mu[i] -
408 residu[nvar + ncon + 1 + i] = gvec[i] - mma.a[i] * mma.z - mma.y[i] +
410 residu[nvar + ncon + 1 + ncon + 2 * nvar + i] = mma.mu[i] * mma.y[i] -
412 residu[nvar + ncon + 1 + 2 * nvar + 2 * ncon + 1 + i] = mma.lam[i] * mma.s[i]
415 residu[nvar + ncon + 1 + 2 * nvar + 2 * ncon] = mma.zet * mma.z - epsi;
421 for (
int i = 0; i < (3 * nvar + 4 * ncon + 2); i++)
423 residunorm += residu[i] * residu[i];
424 residumax = std::max(residumax, std::abs(residu[i]));
427 global_norm = residunorm;
428 global_max = residumax;
431 MPI_Allreduce(&residunorm, &global_norm, 1
432 , MPITypeMap<real_t>::mpi_type, MPI_SUM, mma.comm);
433 MPI_Allreduce(&residumax, &global_max, 1
434 , MPITypeMap<real_t>::mpi_type, MPI_MAX, mma.comm);
437 residunorm = std::sqrt(global_norm);
438 residumax = global_max;
442 while (residumax > 0.9 * epsi && ittt < 200)
445 for (
int i = 0; i < nvar; i++)
447 ux1[i] = mma.upp[i] - mma.x[i];
448 if (std::fabs(ux1[i]) < mma.machineEpsilon)
450 ux1[i] = mma.machineEpsilon;
453 xl1[i] = mma.x[i] - mma.low[i];
454 if (std::fabs(xl1[i]) <= mma.machineEpsilon)
456 xl1[i] = mma.machineEpsilon;
461 for (
int j = 0; j < ncon; j++)
463 plam[i] += P[j * nvar + i] * mma.lam[j];
464 qlam[i] += Q[j * nvar + i] * mma.lam[j];
467 if (std::fabs(mma.x[i] - alfa[i]) < mma.machineEpsilon)
469 if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
471 delx[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]);
472 diagx[i] = 2 * (plam[i] / (ux1[i] * ux1[i] * ux1[i]) + qlam[i] /
473 (xl1[i] * xl1[i] * xl1[i])) + mma.xsi[i] / mma.machineEpsilon + mma.eta[i] /
478 delx[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]) - epsi /
479 mma.machineEpsilon + epsi / (
beta[i] - mma.x[i]);
480 diagx[i] = 2 * (plam[i] / (ux1[i] * ux1[i] * ux1[i]) + qlam[i] /
481 (xl1[i] * xl1[i] * xl1[i])) + mma.xsi[i] / (mma.x[i] - alfa[i]) +
482 mma.eta[i] / (
beta[i] - mma.x[i]);
485 else if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
487 delx[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]) - epsi /
488 (mma.x[i] - alfa[i]) + epsi / mma.machineEpsilon;
489 diagx[i] = 2 * (plam[i] / (ux1[i] * ux1[i] * ux1[i]) + qlam[i] /
490 (xl1[i] * xl1[i] * xl1[i])) + mma.xsi[i] / (mma.x[i] - alfa[i]) +
491 mma.eta[i] / mma.machineEpsilon;
495 delx[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]) - epsi /
496 (mma.x[i] - alfa[i]) + epsi / (
beta[i] - mma.x[i]);
497 diagx[i] = 2 * (plam[i] / (ux1[i] * ux1[i] * ux1[i]) + qlam[i] /
498 (xl1[i] * xl1[i] * xl1[i])) + mma.xsi[i] / (mma.x[i] - alfa[i]) +
499 mma.eta[i] / (
beta[i] - mma.x[i]);
503 for (
int i = 0; i < ncon; i++)
507 for (
int j = 0; j < nvar; j++)
509 gvec_local[i] = gvec_local[i] + P[i * nvar + j] / ux1[j] + Q[i * nvar + j] /
511 GG[i * nvar + j] = P[i * nvar + j] / (ux1[j] * ux1[j]) - Q[i * nvar + j] /
516 std::copy(gvec_local.get(), gvec_local.get() + ncon, gvec.get());
518 MPI_Allreduce(gvec_local.get(), gvec.get(), ncon,
519 MPITypeMap<real_t>::mpi_type, MPI_SUM, mma.comm);
522 delz = mma.a0 - epsi / mma.z;
523 for (
int i = 0; i < ncon; i++)
525 dely[i] = mma.c[i] + mma.d[i] * mma.y[i] - mma.lam[i] - epsi / mma.y[i];
526 delz -= mma.a[i] * mma.lam[i];
527 dellam[i] = gvec[i] - mma.a[i] * mma.z - mma.y[i] -
b[i] + epsi /
529 diagy[i] = mma.d[i] + mma.mu[i] / mma.y[i];
530 diaglamyi[i] = mma.s[i] / mma.lam[i] + 1.0 / diagy[i];
533 if (ncon < nVar_global)
537 for (
int j = 0; j < ncon; j++)
540 for (
int i = 0; i < nvar; i++)
542 sum_local[j] = sum_local[j] + GG[j * nvar + i] * (delx[i] / diagx[i]);
546 std::copy(sum_local.get(), sum_local.get() + ncon, sum_global.get());
549 MPI_Allreduce(sum_local.get(), sum_global.get(), ncon,
550 MPITypeMap<real_t>::mpi_type, MPI_SUM, mma.comm);
553 for (
int j = 0; j < ncon; j++)
555 bb1[j] = - sum_global[j] + dellam[j] + dely[j] / diagy[j];
560 for (
int i = 0; i < ncon; i++)
563 for (
int k = 0; k < nvar; k++)
565 Axx[i * nvar + k] = GG[k * ncon + i] / diagx[k];
569 for (
int i = 0; i < ncon; i++)
571 for (
int j = 0; j < ncon; j++)
573 Alam_local[i * ncon + j] = 0.0;
574 for (
int k = 0; k < nvar; k++)
576 Alam_local[i * ncon + j] += Axx[i * nvar + k] * GG[j * nvar + k];
581 std::copy(Alam_local.get(), Alam_local.get() + ncon * ncon, Alam.get());
583 MPI_Reduce(Alam_local.get(), Alam.get(), ncon * ncon,
584 MPITypeMap<real_t>::mpi_type, MPI_SUM, 0, mma.comm);
589 for (
int i = 0; i < ncon; i++)
591 for (
int j = 0; j < ncon; j++)
595 Alam[i * ncon + j] += diaglamyi[i];
601 for (
int i = 0; i < ncon; i++)
603 for (
int j = 0; j < ncon; j++)
605 AA1[i * (ncon + 1) + j] = Alam[i * ncon + j];
607 AA1[i * (ncon + 1) + ncon] = mma.a[i];
609 for (
int i = 0; i < ncon; i++)
611 AA1[ncon * (ncon + 1) + i] = mma.a[i];
613 AA1[(ncon + 1) * (ncon + 1) - 1] = -mma.zet / mma.z;
615#ifdef MFEM_USE_LAPACK
622 int* ipiv =
new int[nLAP];
623#if defined(MFEM_USE_DOUBLE)
624 dgesv_(&nLAP, &nrhs, AA1.get(), &lda, ipiv, bb1.get(), &ldb, &info);
625#elif defined(MFEM_USE_SINGLE)
626 sgesv_(&nLAP, &nrhs, AA1.get(), &lda, ipiv, bb1.get(), &ldb, &info);
628#error "Only single and double precision are supported!"
636 MFEM_ABORT(
"MMA: matrix is singular.");
640 MFEM_ABORT(
"MMA: Argument " << info <<
641 " in linear system solve has illegal value.");
644 solveLU(ncon, AA1.get(), bb1.get());
648 MPI_Bcast(bb1.get(), ncon + 1,
649 MPITypeMap<real_t>::mpi_type, 0, mma.comm);
652 for (
int i = 0; i < ncon; i++)
659 for (
int i = 0; i < nvar; i++)
662 for (
int j = 0; j < ncon; j++)
664 sum = sum + GG[j * nvar + i] * dlam[j];
666 dx[i] = -sum / diagx[i] - delx[i] / diagx[i];
671 MFEM_ABORT(
"MMA: Optimization problem case which has more constraints than design variables is not implemented!");
674 for (
int i = 0; i < ncon; i++)
676 dy[i] = -dely[i] / diagy[i] + dlam[i] / diagy[i];
677 dmu[i] = -mma.mu[i] + epsi / mma.y[i] - (mma.mu[i] * dy[i]) / mma.y[i];
678 ds[i] = -mma.s[i] + epsi / mma.lam[i] - (mma.s[i] * dlam[i]) / mma.lam[i];
682 xx[ncon + 1 + i] = mma.lam[i];
683 xx[2 * ncon + 1 + 2 * nvar + i] = mma.mu[i];
684 xx[3 * ncon + 2 * nvar + 2 + i] = mma.s[i];
687 dxx[ncon + 1 + i] = dlam[i];
688 dxx[2 * ncon + 1 + 2 * nvar + i] = dmu[i];
689 dxx[3 * ncon + 2 * nvar + 2 + i] = ds[i];
692 xx[3 * ncon + 2 * nvar + 1] = mma.zet;
694 for (
int i = 0; i < nvar; i++)
697 if (std::fabs(mma.x[i] - alfa[i]) < mma.machineEpsilon)
699 if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
701 dxsi[i] = -mma.xsi[i] + epsi / mma.machineEpsilon - (mma.xsi[i] * dx[i]) /
703 deta[i] = -mma.eta[i] + epsi / mma.machineEpsilon + (mma.eta[i] * dx[i]) /
708 dxsi[i] = -mma.xsi[i] + epsi / mma.machineEpsilon - (mma.xsi[i] * dx[i]) /
710 deta[i] = -mma.eta[i] + epsi / (
beta[i] - mma.x[i]) +
711 (mma.eta[i] * dx[i]) / (
beta[i] - mma.x[i]);
714 else if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
716 dxsi[i] = -mma.xsi[i] + epsi / (mma.x[i] - alfa[i]) -
717 (mma.xsi[i] * dx[i]) / (mma.x[i] - alfa[i]);
718 deta[i] = -mma.eta[i] + epsi / mma.machineEpsilon + (mma.eta[i] * dx[i]) /
723 dxsi[i] = -mma.xsi[i] + epsi / (mma.x[i] - alfa[i]) -
724 (mma.xsi[i] * dx[i]) / (mma.x[i] - alfa[i]);
725 deta[i] = -mma.eta[i] + epsi / (
beta[i] - mma.x[i]) +
726 (mma.eta[i] * dx[i]) / (
beta[i] - mma.x[i]);
728 xx[ncon + 1 + ncon + i] = mma.xsi[i];
729 xx[ncon + 1 + ncon + nvar + i] = mma.eta[i];
730 dxx[ncon + 1 + ncon + i] = dxsi[i];
731 dxx[ncon + 1 + ncon + nvar + i] = deta[i];
733 dzet = -mma.zet + epsi / mma.z - mma.zet * dz / mma.z;
734 dxx[3 * ncon + 2 * nvar + 1] = dzet;
737 for (
int i = 0; i < (4 * ncon + 2 * nvar + 2); i++)
739 stepxx[i] = -1.01*dxx[i] / xx[i];
740 stmxx = std::max(stepxx[i], stmxx);
742 stmxx_global = stmxx;
744 MPI_Allreduce(&stmxx, &stmxx_global, 1,
745 MPITypeMap<real_t>::mpi_type, MPI_MAX, mma.comm);
750 for (
int i = 0; i < nvar; i++)
753 if (std::fabs(mma.x[i] - alfa[i]) < mma.machineEpsilon)
755 stepalfa[i] = -1.01*dx[i] / mma.machineEpsilon;
759 stepalfa[i] = -1.01*dx[i] / (mma.x[i] - alfa[i]);
761 if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
763 stepbeta[i] = 1.01*dx[i] / mma.machineEpsilon;
767 stepbeta[i] = 1.01*dx[i] / (
beta[i] - mma.x[i]);
769 stmalfa = std::max(stepalfa[i], stmalfa);
770 stmbeta = std::max(stepbeta[i], stmbeta);
772 stmalfa_global = stmalfa;
773 stmbeta_global = stmbeta;
775 MPI_Allreduce(&stmalfa, &stmalfa_global, 1,
776 MPITypeMap<real_t>::mpi_type, MPI_MAX, mma.comm);
777 MPI_Allreduce(&stmbeta, &stmbeta_global, 1,
778 MPITypeMap<real_t>::mpi_type, MPI_MAX, mma.comm);
780 stminv = std::max(std::max(std::max(stmalfa_global, stmbeta_global),
781 stmxx_global),
static_cast<real_t>(1.0));
784 for (
int i = 0; i < nvar; i++)
787 xsiold[i] = mma.xsi[i];
788 etaold[i] = mma.eta[i];
790 for (
int i = 0; i < ncon; i++)
793 lamold[i] = mma.lam[i];
794 muold[i] = mma.mu[i];
801 resinew = 2.0 * residunorm;
802 while (resinew > residunorm && itto < 50)
806 for (
int i = 0; i < ncon; ++i)
808 mma.y[i] = yold[i] + steg * dy[i];
809 if (std::fabs(mma.y[i])< mma.machineEpsilon)
811 mma.y[i] = mma.machineEpsilon;
814 mma.lam[i] = lamold[i] + steg * dlam[i];
815 if (std::fabs(mma.lam[i])< mma.machineEpsilon )
817 mma.lam[i] = mma.machineEpsilon;
819 mma.mu[i] = muold[i] + steg * dmu[i];
820 mma.s[i] = sold[i] + steg * ds[i];
823 residu[nvar + ncon] = mma.a0 - mma.zet;
824 for (
int i = 0; i < nvar; ++i)
826 mma.x[i] = xold[i] + steg * dx[i];
827 mma.xsi[i] = xsiold[i] + steg * dxsi[i];
828 mma.eta[i] = etaold[i] + steg * deta[i];
830 ux1[i] = mma.upp[i] - mma.x[i];
831 if (std::fabs(ux1[i]) < mma.machineEpsilon)
833 ux1[i] = mma.machineEpsilon;
835 xl1[i] = mma.x[i] - mma.low[i];
836 if (std::fabs(xl1[i]) < mma.machineEpsilon )
838 xl1[i] = mma.machineEpsilon;
843 for (
int j = 0; j < ncon; j++)
845 plam[i] += P[j * nvar + i] * mma.lam[j];
846 qlam[i] += Q[j * nvar + i] * mma.lam[j];
847 residu[nvar + ncon] -= mma.a[j] * mma.lam[j];
852 residu[i] = plam[i] / (ux1[i] * ux1[i]) - qlam[i] / (xl1[i] * xl1[i]) -
853 mma.xsi[i] + mma.eta[i];
855 residu[nvar + ncon + 1 + ncon + i] = mma.xsi[i] * (mma.x[i] - alfa[i]) -
857 if (std::fabs(mma.x[i] - alfa[i]) < mma.machineEpsilon)
859 residu[nvar + ncon + 1 + ncon + i] = mma.xsi[i] * mma.machineEpsilon - epsi;
861 residu[nvar + ncon + 1 + ncon + nvar + i] = mma.eta[i] *
862 (
beta[i] - mma.x[i]) - epsi;
863 if (std::fabs(
beta[i] - mma.x[i]) < mma.machineEpsilon)
865 residu[nvar + ncon + 1 + ncon + nvar + i] = mma.eta[i] * mma.machineEpsilon -
869 mma.z = zold + steg * dz;
870 if (std::fabs(mma.z) < mma.machineEpsilon)
872 mma.z = mma.machineEpsilon;
874 mma.zet = zetold + steg * dzet;
877 for (
int i = 0; i < ncon; i++)
880 for (
int j = 0; j < nvar; j++)
882 gvec_local[i] = gvec_local[i] + P[i * nvar + j] / ux1[j] + Q[i * nvar + j] /
886 std::copy(gvec_local.get(), gvec_local.get() + ncon, gvec.get());
889 MPI_Allreduce(gvec_local.get(), gvec.get(), ncon,
890 MPITypeMap<real_t>::mpi_type, MPI_SUM, mma.comm);
894 for (
int i = 0; i < ncon; i++)
896 residu[nvar + i] = mma.c[i] + mma.d[i] * mma.y[i]
897 - mma.mu[i] - mma.lam[i];
898 residu[nvar + ncon + 1 + i] = gvec[i] - mma.a[i] * mma.z
899 - mma.y[i] + mma.s[i] -
b[i];
901 residu[nvar + ncon + 1 + ncon + 2 * nvar + i] = mma.mu[i]
904 residu[nvar + ncon + 1 + 2 * nvar + 2 * ncon + 1 + i] =
905 mma.lam[i] * mma.s[i] - epsi;
907 residu[nvar + ncon + 1 + 2 * nvar + 2 * ncon] =
908 mma.zet * mma.z - epsi;
913 for (
int i = 0; i < (3 * nvar + 4 * ncon + 2); i++)
915 resinew = resinew + residu[i] * residu[i];
918 global_norm = resinew;
920 MPI_Allreduce(&resinew, &global_norm, 1,
921 MPITypeMap<real_t>::mpi_type, MPI_SUM, mma.comm);
925 resinew = std::sqrt(global_norm);
930 residunorm = resinew;
932 for (
int i = 0; i < (3 * nvar + 4 * ncon + 2); i++)
934 residumax = std::max(residumax, std::abs(residu[i]));
936 global_max = residumax;
938 MPI_Allreduce(&residumax, &global_max, 1,
939 MPITypeMap<real_t>::mpi_type, MPI_MAX, mma.comm);
941 residumax = global_max;
945 if (ittt > 198 && mma.print_level>=2)
947 out <<
"Warning: Max number of iterations reached in MMA subsolve.\n";
955void MMA::InitData(
real_t *xval)
957 for (
int i = 0; i <
nVar; i++)
965 for (
int i = 0; i <
nCon; i++)
984#if __cplusplus >= 201402L
985 mSubProblem = ::std::make_unique<MMA::MMASubSvanberg>(*
this,
nVar,
nCon);
987 mSubProblem.reset(
new MMA::MMASubSvanberg(*
this,
nVar,
nCon));
992 xval.GetData(),
iter)
999 MPI_Comm_rank(comm_, &rank);
1010 colour = MPI_UNDEFINED;
1014 MPI_Comm_split(comm_, colour, rank, &comm);
1019 mSubProblem.reset(
new MMA::MMASubSvanberg(*
this,
nVar,
nCon));
1022MMA::MMA(MPI_Comm comm_,
const int & nVar,
const int & nCon,
1023 const Vector & xval,
int iter) :
MMA(comm_, nVar, nCon, xval.GetData(), iter)
1032void MMA::AllocData(
int nVariables,
int nConstr)
1038 x= allocArray(
nVar);
1039 xo1 = allocArray(
nVar);
1040 xo2 = allocArray(
nVar);
1042 y = allocArray(
nCon);
1043 c = allocArray(
nCon);
1044 d = allocArray(
nCon);
1045 a = allocArray(
nCon);
1053 s = allocArray(
nCon);
1067 factor = allocArray(
nVar);
1068 lowmin = lowmax = uppmin = uppmax = zz = 0.0;
1087 MFEM_ASSERT(0 ==
nCon,
1088 "MMA nCon != 0. Provide constraint values and gradients");
1104 for (
int i = 0; i <
nVar; i++)
1106 low[i] = xval[i] - asyinit * (xmax[i] - xmin[i]);
1107 upp[i] = xval[i] + asyinit * (xmax[i] - xmin[i]);
1112 for (
int i = 0; i <
nVar; i++)
1115 zz = (xval[i] - xo1[i]) * (xo1[i] - xo2[i]);
1118 factor[i] = asyincr;
1122 factor[i] = asydecr;
1131 low[i] = xval[i] - factor[i] * (xo1[i] -
low[i]);
1132 upp[i] = xval[i] + factor[i] * (
upp[i] - xo1[i]);
1134 lowmin = xval[i] - 10.0 * (xmax[i] - xmin[i]);
1135 lowmax = xval[i] - 0.01 * (xmax[i] - xmin[i]);
1136 uppmin = xval[i] + 0.01 * (xmax[i] - xmin[i]);
1137 uppmax = xval[i] + 10.0 * (xmax[i] - xmin[i]);
1139 low[i] = std::max(
low[i], lowmin);
1140 low[i] = std::min(
low[i], lowmax);
1141 upp[i] = std::max(
upp[i], uppmin);
1142 upp[i] = std::min(
upp[i], uppmax);
1146 mSubProblem->Update(dfdx,gx,dgdx,xmin,xmax,xval);
1148 for (
int i = 0; i <
nVar; i++)
MMA (Method of Moving Asymptotes) solves an optimization problem of the form:
::std::unique_ptr< real_t[]> mu
::std::unique_ptr< real_t[]> b
::std::unique_ptr< real_t[]> eta
::std::unique_ptr< real_t[]> d
::std::unique_ptr< real_t[]> c
void Update(const Vector &dfdx, const Vector &gx, const Vector &dgdx, const Vector &xmin, const Vector &xmax, Vector &xval)
MMA(int nVar, int nCon, real_t *xval, int iterationNumber=0)
Serial MMA.
::std::unique_ptr< real_t[]> upp
::std::unique_ptr< real_t[]> a
::std::unique_ptr< real_t[]> x
::std::unique_ptr< real_t[]> xsi
::std::unique_ptr< real_t[]> lam
::std::unique_ptr< real_t[]> low
::std::unique_ptr< real_t[]> y
::std::unique_ptr< real_t[]> s
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
void sgesv_(int *nLAP, int *nrhs, float *AA, int *lda, int *ipiv, float *bb, int *ldb, int *info)
void dgesv_(int *nLAP, int *nrhs, double *AA, int *lda, int *ipiv, double *bb, int *ldb, int *info)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void solveLU(int nCon, real_t *AA1, real_t *bb1)