13 #include "../general/forall.hpp"
14 #include "../general/globals.hpp"
15 #include "../fem/bilinearform.hpp"
59 if (dot_prod_type == 0)
75 if (dot_prod_type == 0)
82 MPI_Comm_rank(comm, &rank);
109 const Vector& x,
bool final)
const
122 Solver(a.FESpace()->GetTrueVSize()),
126 ess_tdof_list(ess_tdofs),
143 ess_tdof_list(ess_tdofs),
152 const double delta = damping;
153 auto D = diag.
Read();
154 auto DI = dinv.
Write();
155 MFEM_FORALL(i, N, DI[i] = delta / D[i]; );
156 auto I = ess_tdof_list.
Read();
157 MFEM_FORALL(i, ess_tdof_list.
Size(), DI[I[i]] =
delta; );
162 MFEM_ASSERT(x.
Size() == N,
"invalid input vector");
163 MFEM_ASSERT(y.
Size() == N,
"invalid output vector");
167 oper->
Mult(y, residual);
176 auto DI = dinv.
Read();
177 auto R = residual.
Read();
179 MFEM_FORALL(i, N, Y[i] += DI[i] * R[i]; );
185 int order_,
double max_eig_estimate_)
189 max_eig_estimate(max_eig_estimate_),
194 ess_tdof_list(ess_tdofs),
196 oper(oper_) {
Setup(); }
202 int order_, MPI_Comm comm,
int power_iterations,
double power_tolerance)
207 int order_,
int power_iterations,
double power_tolerance)
215 ess_tdof_list(ess_tdofs),
229 power_iterations, power_tolerance);
238 auto D = diag.
Read();
239 auto X = dinv.
Write();
240 MFEM_FORALL(i, N, X[i] = 1.0 / D[i]; );
241 auto I = ess_tdof_list.
Read();
242 MFEM_FORALL(i, ess_tdof_list.
Size(), X[I[i]] = 1.0; );
247 double upper_bound = 1.2 * max_eig_estimate;
248 double lower_bound = 0.3 * max_eig_estimate;
249 double theta = 0.5 * (upper_bound + lower_bound);
250 double delta = 0.5 * (upper_bound - lower_bound);
256 coeffs[0] = 1.0 / theta;
261 double tmp_0 = 1.0/(pow(delta, 2) - 2*pow(theta, 2));
262 coeffs[0] = -4*theta*tmp_0;
268 double tmp_0 = 3*pow(delta, 2);
269 double tmp_1 = pow(theta, 2);
270 double tmp_2 = 1.0/(-4*pow(theta, 3) + theta*tmp_0);
271 coeffs[0] = tmp_2*(tmp_0 - 12*tmp_1);
272 coeffs[1] = 12/(tmp_0 - 4*tmp_1);
273 coeffs[2] = -4*tmp_2;
278 double tmp_0 = pow(delta, 2);
279 double tmp_1 = pow(theta, 2);
280 double tmp_2 = 8*tmp_0;
281 double tmp_3 = 1.0/(pow(delta, 4) + 8*pow(theta, 4) - tmp_1*tmp_2);
282 coeffs[0] = tmp_3*(32*pow(theta, 3) - 16*theta*tmp_0);
283 coeffs[1] = tmp_3*(-48*tmp_1 + tmp_2);
284 coeffs[2] = 32*theta*tmp_3;
285 coeffs[3] = -8*tmp_3;
290 double tmp_0 = 5*pow(delta, 4);
291 double tmp_1 = pow(theta, 4);
292 double tmp_2 = pow(theta, 2);
293 double tmp_3 = pow(delta, 2);
294 double tmp_4 = 60*tmp_3;
295 double tmp_5 = 20*tmp_3;
296 double tmp_6 = 1.0/(16*pow(theta, 5) - pow(theta, 3)*tmp_5 + theta*tmp_0);
297 double tmp_7 = 160*tmp_2;
298 double tmp_8 = 1.0/(tmp_0 + 16*tmp_1 - tmp_2*tmp_5);
299 coeffs[0] = tmp_6*(tmp_0 + 80*tmp_1 - tmp_2*tmp_4);
300 coeffs[1] = tmp_8*(tmp_4 - tmp_7);
301 coeffs[2] = tmp_6*(-tmp_5 + tmp_7);
302 coeffs[3] = -80*tmp_8;
303 coeffs[4] = 16*tmp_6;
307 MFEM_ABORT(
"Chebyshev smoother not implemented for order = " << order);
315 MFEM_ABORT(
"Chebyshev smoother not implemented for iterative mode");
320 MFEM_ABORT(
"Chebyshev smoother requires operator");
329 for (
int k = 0; k < order; ++k)
334 oper->
Mult(residual, helperVector);
335 residual = helperVector;
340 auto Dinv = dinv.
Read();
342 MFEM_FORALL(i, n, R[i] *= Dinv[i]; );
346 auto C = coeffs.
Read();
347 MFEM_FORALL(i, n, Y[i] += C[k] * R[i]; );
396 double r0, nom, nom0, nomold = 1, cf;
412 nom0 = nom = sqrt(
Dot(
z,
z));
416 nom0 = nom = sqrt(
Dot(
r,
r));
420 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" ||Br|| = "
452 nom = sqrt(
Dot(
z,
z));
456 nom = sqrt(
Dot(
r,
r));
461 mfem::out <<
" Iteration : " << setw(3) << i <<
" ||Br|| = "
462 << nom <<
"\tConv. rate: " << cf <<
'\n';
468 mfem::out <<
"Number of SLI iterations: " << i <<
'\n'
469 <<
"Conv. rate: " << cf <<
'\n';
471 mfem::out <<
"||Br_0|| = " << nom0 <<
'\n'
472 <<
"||Br_N|| = " << nom <<
'\n'
473 <<
"Number of SLI iterations: " << i <<
'\n';
487 mfem::err <<
"SLI: No convergence!" <<
'\n';
488 mfem::out <<
"||Br_0|| = " << nom0 <<
'\n'
489 <<
"||Br_N|| = " << nom <<
'\n'
490 <<
"Number of SLI iterations: " <<
final_iter <<
'\n';
494 mfem::out <<
"Average reduction factor = "
501 int print_iter,
int max_num_iter,
502 double RTOLERANCE,
double ATOLERANCE)
514 int print_iter,
int max_num_iter,
515 double RTOLERANCE,
double ATOLERANCE)
538 double r0, den, nom, nom0, betanom,
alpha, beta;
560 nom0 = nom =
Dot(d,
r);
561 MFEM_ASSERT(
IsFinite(nom),
"nom = " << nom);
564 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = "
573 mfem::out <<
"PCG: The preconditioner is not positive definite. (Br, r) = "
592 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
597 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = "
627 MFEM_ASSERT(
IsFinite(betanom),
"betanom = " << betanom);
632 mfem::out <<
"PCG: The preconditioner is not positive definite. (Br, r) = "
642 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = "
652 mfem::out <<
"Number of PCG iterations: " << i <<
'\n';
656 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = "
680 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
685 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = "
702 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = "
708 mfem::out <<
"PCG: No convergence!" <<
'\n';
712 mfem::out <<
"Average reduction factor = "
713 << pow (betanom/nom0, 0.5/
final_iter) <<
'\n';
721 int print_iter,
int max_num_iter,
722 double RTOLERANCE,
double ATOLERANCE)
734 int print_iter,
int max_num_iter,
735 double RTOLERANCE,
double ATOLERANCE)
749 double &cs,
double &sn)
756 else if (fabs(dy) > fabs(dx))
758 double temp = dx / dy;
759 sn = 1.0 / sqrt( 1.0 + temp*temp );
764 double temp = dy / dx;
765 cs = 1.0 / sqrt( 1.0 + temp*temp );
772 double temp = cs * dx + sn * dy;
773 dy = -sn * dx + cs * dy;
783 for (
int i = k; i >= 0; i--)
786 for (
int j = i - 1; j >= 0; j--)
788 y(j) -= h(j,i) * y(i);
792 for (
int j = 0; j <= k; j++)
845 double beta =
Norm(r);
846 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
861 <<
" Iteration : " << setw(3) << 0
862 <<
" ||B r|| = " << beta << (
print_level == 3 ?
" ...\n" :
"\n");
871 if (v[0] == NULL) { v[0] =
new Vector(n); }
872 v[0]->Set(1.0/beta, r);
873 s = 0.0; s(0) = beta;
875 for (i = 0; i <
m && j <=
max_iter; i++, j++)
887 for (k = 0; k <= i; k++)
889 H(k,i) =
Dot(w, *v[k]);
890 w.
Add(-H(k,i), *v[k]);
894 MFEM_ASSERT(
IsFinite(H(i+1,i)),
"Norm(w) = " << H(i+1,i));
895 if (v[i+1] == NULL) { v[i+1] =
new Vector(n); }
896 v[i+1]->Set(1.0/H(i+1,i), w);
898 for (k = 0; k < i; k++)
907 resid = fabs(s(i+1));
908 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
921 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
922 <<
" Iteration : " << setw(3) << j
923 <<
" ||B r|| = " << resid <<
'\n';
947 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
979 for (i = 0; i < v.
Size(); i++)
1004 double beta =
Norm(r);
1005 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
1020 <<
" Iteration : " << setw(3) << 0
1021 <<
" || r || = " << beta << endl;
1028 for (i= 0; i<=
m; i++)
1037 if (v[0] == NULL) { v[0] =
new Vector(b.
Size()); }
1039 v[0] ->
Add (1.0/beta, r);
1040 s = 0.0; s(0) = beta;
1042 for (i = 0; i <
m && j <=
max_iter; i++, j++)
1045 if (z[i] == NULL) { z[i] =
new Vector(b.
Size()); }
1058 for (k = 0; k <= i; k++)
1060 H(k,i) =
Dot( r, *v[k]);
1061 r.Add(-H(k,i), (*v[k]));
1065 if (v[i+1] == NULL) { v[i+1] =
new Vector(b.
Size()); }
1067 v[i+1] ->
Add (1.0/H(i+1,i), r);
1069 for (k = 0; k < i; k++)
1078 double resid = fabs(s(i+1));
1079 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1082 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
1083 <<
" Iteration : " << setw(3) << j
1084 <<
" || r || = " << resid << endl;
1100 for (i= 0; i<=
m; i++)
1102 if (v[i]) {
delete v[i]; }
1103 if (z[i]) {
delete z[i]; }
1119 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
1131 for (i= 0; i<=
m; i++)
1133 if (v[i]) {
delete v[i]; }
1134 if (z[i]) {
delete z[i]; }
1140 for (i = 0; i <=
m; i++)
1142 if (v[i]) {
delete v[i]; }
1143 if (z[i]) {
delete z[i]; }
1149 mfem::out <<
"FGMRES: No convergence!" << endl;
1157 int &max_iter,
int m,
double &tol,
double atol,
int printit)
1174 int print_iter,
int max_num_iter,
int m,
double rtol,
double atol)
1176 GMRES(A, x, b, B, max_num_iter, m, rtol, atol, print_iter);
1198 double resid, tol_goal;
1199 double rho_1, rho_2=1.0,
alpha=1.0, beta,
omega=1.0;
1214 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1216 mfem::out <<
" Iteration : " << setw(3) << 0
1217 <<
" ||r|| = " << resid <<
'\n';
1223 if (resid <= tol_goal)
1237 mfem::out <<
" Iteration : " << setw(3) << i
1238 <<
" ||r|| = " << resid <<
'\n';
1253 beta = (rho_1/rho_2) * (
alpha/omega);
1269 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1270 if (resid < tol_goal)
1274 mfem::out <<
" Iteration : " << setw(3) << i
1275 <<
" ||s|| = " << resid <<
'\n';
1282 mfem::out <<
" Iteration : " << setw(3) << i
1283 <<
" ||s|| = " << resid;
1301 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1304 mfem::out <<
" ||r|| = " << resid <<
'\n';
1307 if (resid < tol_goal)
1329 int &max_iter,
double &tol,
double atol,
int printit)
1338 bicgstab.
Mult(b, x);
1345 int print_iter,
int max_num_iter,
double rtol,
double atol)
1347 BiCGSTAB(A, x, b, B, max_num_iter, rtol, atol, print_iter);
1373 double beta, eta, gamma0, gamma1, sigma0, sigma1;
1374 double alpha,
delta, rho1, rho2, rho3, norm_goal;
1394 eta = beta = sqrt(
Dot(*z,
v1));
1395 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1396 gamma0 = gamma1 = 1.;
1397 sigma0 = sigma1 = 0.;
1401 if (eta <= norm_goal)
1409 mfem::out <<
"MINRES: iteration " << setw(3) << 0 <<
": ||r||_B = "
1423 MFEM_ASSERT(
IsFinite(alpha),
"alpha = " << alpha);
1430 delta = gamma1*alpha - gamma0*sigma1*beta;
1432 rho2 = sigma1*alpha + gamma0*gamma1*beta;
1442 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
1443 rho1 = hypot(delta, beta);
1447 w0.
Set(1./rho1, *z);
1451 add(1./rho1, *z, -rho2/rho1,
w1,
w0);
1455 add(-rho3/rho1,
w0, -rho2/rho1,
w1,
w0);
1456 w0.
Add(1./rho1, *z);
1460 gamma1 = delta/rho1;
1462 x.
Add(gamma1*eta,
w0);
1468 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1470 if (fabs(eta) <= norm_goal)
1477 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = "
1478 << fabs(eta) <<
'\n';
1480 Monitor(it, fabs(eta), *z, x);
1515 eta = sqrt(
Dot(*z,
v1));
1516 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = "
1517 << eta <<
" (re-computed)" <<
'\n';
1522 mfem::out <<
"MINRES: No convergence!\n";
1527 int max_it,
double rtol,
double atol)
1539 int print_it,
int max_it,
double rtol,
double atol)
1557 MFEM_ASSERT(
height ==
width,
"square Operator is required.");
1565 MFEM_ASSERT(
oper != NULL,
"the Operator is not set (use SetOperator).");
1566 MFEM_ASSERT(
prec != NULL,
"the Solver is not set (use SetSolver).");
1569 double norm0, norm, norm_goal;
1585 norm0 = norm =
Norm(
r);
1591 for (it = 0;
true; it++)
1593 MFEM_ASSERT(
IsFinite(norm),
"norm = " << norm);
1596 mfem::out <<
"Newton iteration " << setw(2) << it
1597 <<
" : ||r|| = " << norm;
1600 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
1606 if (norm <= norm_goal)
1628 add(x, -c_scale,
c, x);
1646 MFEM_VERIFY(
oper != NULL,
"the Operator is not set (use SetOperator).");
1658 int last_saved_id = -1;
1661 double norm0, norm, norm_goal;
1671 if (have_b) {
r -=
b; }
1675 norm0 = norm =
Norm(
r);
1677 for (it = 0;
true; it++)
1679 MFEM_ASSERT(
IsFinite(norm),
"norm = " << norm);
1683 <<
" : ||r|| = " << norm;
1686 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
1691 if (norm <= norm_goal)
1710 add(x, -c_scale,
c, x);
1722 sk =
c; sk *= -c_scale;
1723 const double gamma =
Dot(sk, yk)/
Dot(yk, yk);
1726 last_saved_id = (last_saved_id ==
m-1) ? 0 : last_saved_id+1;
1727 skM.SetCol(last_saved_id, sk);
1728 ykM.
SetCol(last_saved_id, yk);
1731 for (
int i = last_saved_id; i > -1; i--)
1733 skM.GetColumn(i, sk);
1735 rho(i) = 1./
Dot(sk, yk);
1741 for (
int i =
m-1; i > last_saved_id; i--)
1743 skM.GetColumn(i, sk);
1745 rho(i) = 1./
Dot(sk, yk);
1754 for (
int i = last_saved_id+1; i <
m ; i++)
1756 skM.GetColumn(i,sk);
1758 double betai = rho(i)*
Dot(yk,
c);
1762 for (
int i = 0; i < last_saved_id+1 ; i++)
1764 skM.GetColumn(i,sk);
1766 double betai = rho(i)*
Dot(yk,
c);
1779 int m_max,
int m_min,
int m_step,
double cf,
1780 double &tol,
double &atol,
int printit)
1787 Vector s(m+1), cs(m+1), sn(m+1);
1794 double normb = w.Norml2();
1804 double beta = r.
Norml2();
1806 resid = beta / normb;
1808 if (resid * resid <= tol)
1810 tol = resid * resid;
1817 <<
" Iteration : " << setw(3) << 0
1818 <<
" (r, r) = " << beta*beta <<
'\n';
1820 tol *= (normb*normb);
1821 tol = (atol > tol) ? atol : tol;
1825 for (i= 0; i<=m; i++)
1832 while (j <= max_iter)
1835 v[0] ->
Add (1.0/beta, r);
1836 s = 0.0; s(0) = beta;
1840 for (i = 0; i < m && j <= max_iter; i++)
1845 for (k = 0; k <= i; k++)
1847 H(k,i) = w * (*v[k]);
1848 w.
Add(-H(k,i), (*v[k]));
1851 H(i+1,i) = w.Norml2();
1853 v[i+1] ->
Add (1.0/H(i+1,i), w);
1855 for (k = 0; k < i; k++)
1864 resid = fabs(s(i+1));
1867 <<
" Iteration : " << setw(3) << i+1
1868 <<
" (r, r) = " << resid*resid <<
'\n';
1870 if ( resid*resid < tol)
1873 tol = resid * resid;
1875 for (i= 0; i<=m; i++)
1894 if ( resid*resid < tol)
1896 tol = resid * resid;
1898 for (i= 0; i<=m; i++)
1907 if (m - m_step >= m_min)
1920 tol = resid * resid;
1921 for (i= 0; i<=m; i++)
1931 : C(C_), D(D_), c_e(NULL), d_lo(NULL), d_hi(NULL), x_lo(NULL), x_hi(NULL),
1940 MFEM_ASSERT(
C,
"The C operator is unspecified -- can't set constraints.");
1941 MFEM_ASSERT(c.
Size() ==
C->
Height(),
"Wrong size of the constraint.");
1949 MFEM_ASSERT(
D,
"The D operator is unspecified -- can't set constraints.");
1951 "Wrong size of the constraint.");
1959 "Wrong size of the constraint.");
1976 MFEM_WARNING(
"Objective functional is ignored as SLBQP always minimizes"
1977 "the l2 norm of (x - x_target).");
1979 MFEM_ASSERT(prob.
GetC(),
"Linear constraint is not set.");
1980 MFEM_ASSERT(prob.
GetC()->
Height() == 1,
"Solver expects scalar constraint.");
2000 mfem::out <<
"SLBQP iteration " << it <<
": residual = " << r
2001 <<
", lambda = " << l <<
'\n';
2023 const double smin = 0.1;
2030 mfem::out <<
"SLBQP bracketing phase" <<
'\n';
2034 r =
solve(l,xt,x,nclip);
2048 llow = l; rlow = r; l = l + dl;
2051 r =
solve(l,xt,x,nclip);
2054 while ((r < 0) && (nclip <
max_iter))
2058 if (s < smin) { s = smin; }
2063 r =
solve(l,xt,x,nclip);
2071 lupp = l; rupp = r; l = l - dl;
2074 r =
solve(l,xt,x,nclip);
2077 while ((r > 0) && (nclip <
max_iter))
2081 if (s < smin) { s = smin; }
2086 r =
solve(l,xt,x,nclip);
2099 mfem::out <<
"SLBQP secant phase" <<
'\n';
2102 s = 1.0 - rlow/rupp; dl = dl/s; l = lupp - dl;
2105 r =
solve(l,xt,x,nclip);
2108 while ( (fabs(r) > tol) && (nclip <
max_iter) )
2114 lupp = l; rupp = r; s = 1.0 - rlow/rupp;
2115 dl = (lupp - llow)/s; l = lupp - dl;
2120 if (s < smin) { s = smin; }
2122 lnew = 0.75*llow + 0.25*l;
2123 if (lnew < l-dl) { lnew = l-dl; }
2124 lupp = l; rupp = r; l = lnew;
2125 s = (lupp - llow)/(lupp - l);
2133 llow = l; rlow = r; s = 1.0 - rlow/rupp;
2134 dl = (lupp - llow)/s; l = lupp - dl;
2139 if (s < smin) { s = smin; }
2141 lnew = 0.75*lupp + 0.25*l;
2142 if (lnew < l+dl) { lnew = l+dl; }
2143 llow = l; rlow = r; l = lnew;
2144 s = (lupp - llow)/(lupp - l);
2149 r =
solve(l,xt,x,nclip);
2158 mfem::err <<
"SLBQP not converged!" <<
'\n';
2168 mfem::out <<
"SLBQP iterations = " << nclip <<
'\n';
2169 mfem::out <<
"SLBQP lambda = " << l <<
'\n';
2170 mfem::out <<
"SLBQP residual = " << r <<
'\n';
2174 struct WeightMinHeap
2176 const std::vector<double> &w;
2177 std::vector<size_t> c;
2178 std::vector<int> loc;
2180 WeightMinHeap(
const std::vector<double> &w_) : w(w_)
2182 c.reserve(w.size());
2183 loc.resize(w.size());
2184 for (
size_t i=0; i<w.size(); ++i) { push(i); }
2187 size_t percolate_up(
size_t pos,
double val)
2189 for (; pos > 0 && w[c[(pos-1)/2]] > val; pos = (pos-1)/2)
2191 c[pos] = c[(pos-1)/2];
2192 loc[c[(pos-1)/2]] = pos;
2197 size_t percolate_down(
size_t pos,
double val)
2199 while (2*pos+1 < c.size())
2201 size_t left = 2*pos+1;
2202 size_t right = left+1;
2204 if (right < c.size() && w[c[right]] < w[c[left]]) { tgt = right; }
2205 else { tgt = left; }
2206 if (w[c[tgt]] < val)
2224 size_t pos = c.size()-1;
2225 pos = percolate_up(pos, val);
2233 size_t j = c.back();
2237 if (c.empty()) {
return i; }
2240 pos = percolate_down(pos, val);
2246 void update(
size_t i)
2248 size_t pos = loc[i];
2250 pos = percolate_up(pos, val);
2251 pos = percolate_down(pos, val);
2256 bool picked(
size_t i)
2271 for (
int i=0; i<n; ++i)
2273 for (
int j=I[i]; j<I[i+1]; ++j)
2275 V[j] = abs(V[j]/D[i]);
2279 std::vector<double> w(n, 0.0);
2280 for (
int k=0; k<n; ++k)
2283 for (
int ii=I[k]; ii<I[k+1]; ++ii)
2288 for (
int kk=I[i]; kk<I[i+1]; ++kk)
2296 for (
int jj=I[k]; jj<I[k+1]; ++jj)
2299 if (j == k) {
continue; }
2300 double C_kj = V[jj];
2301 bool ij_exists =
false;
2302 for (
int jj2=I[i]; jj2<I[i+1]; ++jj2)
2310 if (!ij_exists) { w[k] += pow(C_ik*C_kj,2); }
2316 WeightMinHeap w_heap(w);
2320 for (
int ii=0; ii<n; ++ii)
2322 int pi = w_heap.pop();
2325 for (
int kk=I[pi]; kk<I[pi+1]; ++kk)
2328 if (w_heap.picked(k)) {
continue; }
2332 for (
int ii2=I[k]; ii2<I[k+1]; ++ii2)
2335 if (w_heap.picked(i)) {
continue; }
2338 for (
int kk2=I[i]; kk2<I[i+1]; ++kk2)
2346 for (
int jj=I[k]; jj<I[k+1]; ++jj)
2349 if (j == k || w_heap.picked(j)) {
continue; }
2350 double C_kj = V[jj];
2351 bool ij_exists =
false;
2352 for (
int jj2=I[i]; jj2<I[i+1]; ++jj2)
2360 if (!ij_exists) { w[k] += pow(C_ik*C_kj,2); }
2373 block_size(block_size_),
2375 reordering(reordering_)
2382 :
BlockILU(block_size_, reordering_, k_fill_)
2404 MFEM_ABORT(
"BlockILU must be created with a SparseMatrix or HypreParMatrix");
2409 MFEM_ASSERT(A->
Finalized(),
"Matrix must be finalized.");
2410 CreateBlockPattern(*A);
2414 void BlockILU::CreateBlockPattern(
const SparseMatrix &A)
2416 MFEM_VERIFY(k_fill == 0,
"Only block ILU(0) is currently supported.");
2417 if (A.
Height() % block_size != 0)
2419 MFEM_ABORT(
"BlockILU: block size must evenly divide the matrix size");
2423 const int *I = A.
GetI();
2424 const int *J = A.
GetJ();
2425 const double *V = A.
GetData();
2427 int nblockrows = nrows / block_size;
2429 std::vector<std::set<int>> unique_block_cols(nblockrows);
2431 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2433 for (
int bi = 0; bi < block_size; ++bi)
2435 int i = iblock * block_size + bi;
2436 for (
int k = I[i]; k < I[i + 1]; ++k)
2438 unique_block_cols[iblock].insert(J[k] / block_size);
2441 nnz += unique_block_cols[iblock].size();
2446 SparseMatrix C(nblockrows, nblockrows);
2447 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2449 for (
int jblock : unique_block_cols[iblock])
2451 for (
int bi = 0; bi < block_size; ++bi)
2453 int i = iblock * block_size + bi;
2454 for (
int k = I[i]; k < I[i + 1]; ++k)
2457 if (j >= jblock * block_size && j < (jblock + 1) * block_size)
2459 C.Add(iblock, jblock, V[k]*V[k]);
2466 double *CV = C.GetData();
2467 for (
int i=0; i<C.NumNonZeroElems(); ++i)
2469 CV[i] = sqrt(CV[i]);
2478 MFEM_ABORT(
"BlockILU: unknown reordering")
2485 for (
int i=0; i<nblockrows; ++i)
2493 for (
int i=0; i<nblockrows; ++i)
2499 std::vector<std::vector<int>> unique_block_cols_perminv(nblockrows);
2500 for (
int i=0; i<nblockrows; ++i)
2502 std::vector<int> &cols = unique_block_cols_perminv[i];
2503 for (
int j : unique_block_cols[P[i]])
2505 cols.push_back(Pinv[j]);
2507 std::sort(cols.begin(), cols.end());
2514 AB.
SetSize(block_size, block_size, nnz);
2515 DB.
SetSize(block_size, block_size, nblockrows);
2518 ipiv.
SetSize(block_size*nblockrows);
2521 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2523 int iblock_perm = P[iblock];
2524 for (
int jblock : unique_block_cols_perminv[iblock])
2526 int jblock_perm = P[jblock];
2527 if (iblock == jblock)
2529 ID[iblock] = counter;
2531 JB[counter] = jblock;
2532 for (
int bi = 0; bi < block_size; ++bi)
2534 int i = iblock_perm*block_size + bi;
2535 for (
int k = I[i]; k < I[i + 1]; ++k)
2538 if (j >= jblock_perm*block_size && j < (jblock_perm + 1)*block_size)
2540 int bj = j - jblock_perm*block_size;
2542 AB(bi, bj, counter) = val;
2544 if (iblock == jblock)
2546 DB(bi, bj, iblock) = val;
2553 IB[iblock + 1] = counter;
2557 void BlockILU::Factorize()
2559 int nblockrows =
Height()/block_size;
2562 for (
int i=0; i<nblockrows; ++i)
2564 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2565 factorization.Factor(block_size);
2571 DenseMatrix A_ik, A_ij, A_kj;
2573 for (
int i=1; i<nblockrows; ++i)
2576 for (
int kk=IB[i]; kk<IB[i+1]; ++kk)
2580 if (k == i) {
break; }
2583 MFEM_ABORT(
"Matrix must be sorted with nonzero diagonal");
2585 LUFactors A_kk_inv(DB.
GetData(k), &ipiv[k*block_size]);
2586 A_ik.UseExternalData(&AB(0,0,kk), block_size, block_size);
2588 A_kk_inv.RightSolve(block_size, block_size, A_ik.GetData());
2590 for (
int jj=kk+1; jj<IB[i+1]; ++jj)
2593 if (j <= k) {
continue; }
2594 A_ij.UseExternalData(&AB(0,0,jj), block_size, block_size);
2595 for (
int ll=IB[k]; ll<IB[k+1]; ++ll)
2600 A_kj.UseExternalData(&AB(0,0,ll), block_size, block_size);
2607 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2608 factorization.Factor(block_size);
2620 MFEM_ASSERT(
height > 0,
"BlockILU(0) preconditioner is not constructed");
2621 int nblockrows =
Height()/block_size;
2630 for (
int i=0; i<nblockrows; ++i)
2633 for (
int ib=0; ib<block_size; ++ib)
2635 yi[ib] = b[ib + P[i]*block_size];
2637 for (
int k=IB[i]; k<ID[i]; ++k)
2647 for (
int i=nblockrows-1; i >= 0; --i)
2650 for (
int ib=0; ib<block_size; ++ib)
2652 xi[ib] = y[ib + i*block_size];
2654 for (
int k=ID[i]+1; k<IB[i+1]; ++k)
2662 LUFactors A_ii_inv(&DB(0,0,i), &ipiv[i*block_size]);
2664 A_ii_inv.
Solve(block_size, 1, xi);
2670 int it,
double norm,
const Vector &r,
bool final)
2674 double bc_norm_squared = 0.0;
2680 bc_norm_squared += r_entry*r_entry;
2685 if (comm != MPI_COMM_NULL)
2687 double glob_bc_norm_squared = 0.0;
2688 MPI_Reduce(&bc_norm_squared, &glob_bc_norm_squared, 1, MPI_DOUBLE,
2690 bc_norm_squared = glob_bc_norm_squared;
2692 MPI_Comm_rank(comm, &rank);
2693 print = (rank == 0);
2696 if ((it == 0 ||
final || bc_norm_squared > 0.0) && print)
2698 mfem::out <<
" ResidualBCMonitor : b.c. residual norm = "
2699 << sqrt(bc_norm_squared) << endl;
2704 #ifdef MFEM_USE_SUITESPARSE
2731 umfpack_di_free_numeric(&
Numeric);
2735 umfpack_dl_free_numeric(&
Numeric);
2740 MFEM_VERIFY(
mat,
"not a SparseMatrix");
2749 MFEM_VERIFY(
width ==
height,
"not a square matrix");
2757 int status = umfpack_di_symbolic(
width,
width, Ap, Ai, Ax, &Symbolic,
2762 umfpack_di_report_status(
Control, status);
2764 " umfpack_di_symbolic() failed!");
2767 status = umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &
Numeric,
2772 umfpack_di_report_status(
Control, status);
2774 " umfpack_di_numeric() failed!");
2776 umfpack_di_free_symbolic(&Symbolic);
2780 SuiteSparse_long status;
2784 AI =
new SuiteSparse_long[
width + 1];
2785 AJ =
new SuiteSparse_long[Ap[
width]];
2786 for (
int i = 0; i <=
width; i++)
2788 AI[i] = (SuiteSparse_long)(Ap[i]);
2790 for (
int i = 0; i < Ap[
width]; i++)
2792 AJ[i] = (SuiteSparse_long)(Ai[i]);
2795 status = umfpack_dl_symbolic(
width,
width,
AI,
AJ, Ax, &Symbolic,
2800 umfpack_dl_report_status(
Control, status);
2802 " umfpack_dl_symbolic() failed!");
2805 status = umfpack_dl_numeric(
AI,
AJ, Ax, Symbolic, &
Numeric,
2810 umfpack_dl_report_status(
Control, status);
2812 " umfpack_dl_numeric() failed!");
2814 umfpack_dl_free_symbolic(&Symbolic);
2821 mfem_error(
"UMFPackSolver::Mult : matrix is not set!"
2822 " Call SetOperator first!");
2829 umfpack_di_report_info(Control,
Info);
2832 umfpack_di_report_status(Control, status);
2833 mfem_error(
"UMFPackSolver::Mult : umfpack_di_solve() failed!");
2838 SuiteSparse_long status =
2841 umfpack_dl_report_info(Control,
Info);
2844 umfpack_dl_report_status(Control, status);
2845 mfem_error(
"UMFPackSolver::Mult : umfpack_dl_solve() failed!");
2853 mfem_error(
"UMFPackSolver::MultTranspose : matrix is not set!"
2854 " Call SetOperator first!");
2861 umfpack_di_report_info(Control,
Info);
2864 umfpack_di_report_status(Control, status);
2866 " umfpack_di_solve() failed!");
2871 SuiteSparse_long status =
2874 umfpack_dl_report_info(Control,
Info);
2877 umfpack_dl_report_status(Control, status);
2879 " umfpack_dl_solve() failed!");
2892 umfpack_di_free_numeric(&
Numeric);
2896 umfpack_dl_free_numeric(&
Numeric);
2911 "Had Numeric pointer in KLU, but not Symbolic");
2919 MFEM_VERIFY(
mat != NULL,
"not a SparseMatrix");
2927 MFEM_VERIFY(
width ==
height,
"not a square matrix");
2939 MFEM_VERIFY(
mat != NULL,
2940 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
2953 MFEM_VERIFY(
mat != NULL,
2954 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
2973 #endif // MFEM_USE_SUITESPARSE
const Array< int > * ess_dofs_list
Not owned.
void ApplyPlaneRotation(double &dx, double &dy, double &cs, double &sn)
PowerMethod helper class to estimate the largest eigenvalue of an operator using the iterative power ...
int Size() const
Return the logical size of the array.
Conjugate gradient method.
virtual void MultTranspose(const Vector &b, Vector &x) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
double Info[UMFPACK_INFO]
void Mult(const Vector &b, Vector &x) const
Solve the system LUx = b, where L and U are the block ILU factors.
int GetNumIterations() const
void SetCol(int c, const double *col)
MPI_Comm GetComm() const
Return the associated MPI communicator, or MPI_COMM_NULL if no communicator is set.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void SetSize(int s)
Resize the vector to size s.
void Monitor(int it, double norm, const Vector &r, const Vector &x, bool final=false) const
virtual void ProcessNewState(const Vector &x) const
This method can be overloaded in derived classes to perform computations that need knowledge of the n...
void MinimumDiscardedFillOrdering(SparseMatrix &C, Array< int > &p)
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
double Norml2() const
Returns the l2 norm of the vector.
int * GetJ()
Return the array J.
void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
class IterativeSolver * iter_solver
The last IterativeSolver to which this monitor was attached.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Data type dense matrix using column-major storage.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
int Size() const
Returns the size of the vector.
int * GetI()
Return the array I.
void SetSize(int i, int j, int k)
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
virtual void MultTranspose(const Vector &b, Vector &x) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
void SetOperator(const Operator &op)
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
const Operator * GetC() const
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Reordering
The reordering method used by the BlockILU factorization.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void SortColumnIndices()
Sort the column indices corresponding to each row.
void add(const Vector &v1, const Vector &v2, Vector &v)
double Norm(const Vector &x) const
double GetFinalNorm() const
double * GetData()
Return the element data, i.e. the array A.
int BiCGSTAB(const Operator &A, Vector &x, const Vector &b, Solver &M, int &max_iter, double &tol, double atol, int printit)
BiCGSTAB method. (tolerances are squared)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
bool IsFinite(const double &val)
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
General product operator: x -> (A*B)(x) = A(B(x)).
void SetLinearConstraint(const Vector &_w, double _a)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
void SetPrintLevel(int print_lvl)
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
double solve(double l, const Vector &xt, Vector &x, int &nclip) const
Solve QP at fixed lambda.
int GetNumConstraints() const
OperatorChebyshevSmoother(Operator *oper_, const Vector &d, const Array< int > &ess_tdof_list, int order, double max_eig_estimate)
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
void MINRES(const Operator &A, const Vector &b, Vector &x, int print_it, int max_it, double rtol, double atol)
MINRES method without preconditioner. (tolerances are squared)
void Add(const double c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
Jacobi smoothing for a given bilinear form (no matrix necessary).
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void SetMaxIter(int max_it)
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
void CG(const Operator &A, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Conjugate gradient method. (tolerances are squared)
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void print_iteration(int it, double r, double l) const
void Setup(const Vector &diag)
void PCG(const Operator &A, Solver &B, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Preconditioned conjugate gradient method. (tolerances are squared)
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
void Solve(int m, int n, double *X) const
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
double Dot(const Vector &x, const Vector &y) const
void GetColumn(int c, Vector &col) const
BlockILU(int block_size_, Reordering reordering_=Reordering::MINIMUM_DISCARDED_FILL, int k_fill_=0)
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
OperatorJacobiSmoother(const BilinearForm &a, const Array< int > &ess_tdof_list, const double damping=1.0)
bool Finalized() const
Returns whether or not CSR format has been finalized.
Stationary linear iteration: x <- x + B (b - A x)
void SetInequalityConstraint(const Vector &dl, const Vector &dh)
void SetEqualityConstraint(const Vector &c)
void Swap(Array< T > &, Array< T > &)
void SetAbsTol(double atol)
double p(const Vector &x, double t)
void SetRelTol(double rtol)
double Control[UMFPACK_CONTROL]
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void subtract(const Vector &x, const Vector &y, Vector &z)
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void Update(Vector &x, int k, DenseMatrix &h, Vector &s, Array< Vector * > &v)
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
Vector & Set(const double a, const Vector &x)
(*this) = a * x
int height
Dimension of the output / number of rows in the matrix.
virtual void SetOptimizationProblem(const OptimizationProblem &prob)
void SetBounds(const Vector &_lo, const Vector &_hi)
double InnerProduct(HypreParVector *x, HypreParVector *y)
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
void GetDiag(Vector &d) const
Returns the Diagonal of A.
virtual double ComputeScalingFactor(const Vector &x, const Vector &b) const
This method can be overloaded in derived classes to implement line search algorithms.
OptimizationProblem(int insize, const Operator *C_, const Operator *D_)
In parallel, insize is the number of the local true dofs.
void SetSolutionBounds(const Vector &xl, const Vector &xh)
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void GeneratePlaneRotation(double &dx, double &dy, double &cs, double &sn)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
virtual void Mult(const Vector &xt, Vector &x) const
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void AddMult_a(double a, const Vector &x, Vector &y) const
y += a * A.x
void MonitorResidual(int it, double norm, const Vector &r, bool final) override
Monitor the residual vector r.
virtual void MonitorSolution(int it, double norm, const Vector &x, bool final)
Monitor the solution vector x.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
int aGMRES(const Operator &A, Vector &x, const Vector &b, const Operator &M, int &max_iter, int m_max, int m_min, int m_step, double cf, double &tol, double &atol, int printit)
const OptimizationProblem * problem
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
double EstimateLargestEigenvalue(Operator &opr, Vector &v0, int numSteps=10, double tolerance=1e-8, int seed=12345)
Returns an estimate of the largest eigenvalue of the operator opr using the iterative power method...
Wrapper for hypre's ParCSR matrix class.
void AddMult_a(double alpha, const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += alpha * B * C.
IterativeSolverMonitor * monitor
virtual void MonitorResidual(int it, double norm, const Vector &r, bool final)
Monitor the residual vector r.
int width
Dimension of the input / number of columns in the matrix.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
const Operator * C
Not owned, some can remain unused (NULL).
void SLI(const Operator &A, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Stationary linear iteration. (tolerances are squared)
int GMRES(const Operator &A, Vector &x, const Vector &b, Solver &M, int &max_iter, int m, double &tol, double atol, int printit)
GMRES method. (tolerances are squared)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
virtual void SetOperator(const Operator &op)
Factorize the given Operator op which must be a SparseMatrix.