13 #include "../general/annotation.hpp" 14 #include "../general/forall.hpp" 15 #include "../general/globals.hpp" 16 #include "../fem/bilinearform.hpp" 53 #endif // MFEM_USE_MPI 60 if (dot_prod_type == 0)
74 int print_level_ = print_lvl;
77 if (dot_prod_type != 0)
80 MPI_Comm_rank(comm, &rank);
99 if (dot_prod_type != 0)
102 MPI_Comm_rank(comm, &rank);
105 derived_print_level = -1;
119 if (comm != MPI_COMM_NULL)
121 MPI_Comm_rank(comm, &rank);
125 switch (print_level_)
142 MFEM_WARNING(
"Unknown print level " << print_level_ <<
143 ". Defaulting to level 0.");
159 else if (print_options_.
summary)
191 const Vector& x,
bool final)
const 202 ess_tdof_list(nullptr),
211 Solver(
a.FESpace()->GetTrueVSize()),
214 ess_tdof_list(&ess_tdofs),
219 a.AssembleDiagonal(diag);
233 ess_tdof_list(&ess_tdofs),
266 MFEM_ASSERT(
height ==
width,
"not a square matrix!");
268 ess_tdof_list =
nullptr;
280 const double delta = damping;
281 auto D = diag.
Read();
282 auto DI = dinv.
Write();
283 const bool use_abs_diag_ = use_abs_diag;
288 MFEM_ABORT_KERNEL(
"Zero diagonal entry in OperatorJacobiSmoother");
290 if (!use_abs_diag_) { DI[i] =
delta / D[i]; }
291 else { DI[i] =
delta / std::abs(D[i]); }
293 if (ess_tdof_list && ess_tdof_list->
Size() > 0)
295 auto I = ess_tdof_list->
Read();
307 MFEM_ASSERT(x.
Size() ==
Width(),
"invalid input vector");
308 MFEM_ASSERT(y.
Size() ==
Height(),
"invalid output vector");
312 MFEM_VERIFY(oper,
"iterative_mode == true requires the forward operator");
313 oper->
Mult(y, residual);
322 auto DI = dinv.
Read();
323 auto R = residual.
Read();
327 Y[i] += DI[i] * R[i];
334 int order_,
double max_eig_estimate_)
338 max_eig_estimate(max_eig_estimate_),
343 ess_tdof_list(ess_tdofs),
345 oper(&oper_) {
Setup(); }
351 int order_, MPI_Comm comm,
int power_iterations,
double power_tolerance)
356 int order_,
int power_iterations,
double power_tolerance)
364 ess_tdof_list(ess_tdofs),
378 power_iterations, power_tolerance);
386 int order_,
double max_eig_estimate_)
393 int order_, MPI_Comm comm,
int power_iterations,
double power_tolerance)
395 power_iterations, power_tolerance) { }
400 int order_,
int power_iterations,
double power_tolerance)
409 auto D = diag.
Read();
410 auto X = dinv.
Write();
411 mfem::forall(N, [=] MFEM_HOST_DEVICE (
int i) { X[i] = 1.0 / D[i]; });
412 auto I = ess_tdof_list.
Read();
421 double upper_bound = 1.2 * max_eig_estimate;
422 double lower_bound = 0.3 * max_eig_estimate;
423 double theta = 0.5 * (upper_bound + lower_bound);
424 double delta = 0.5 * (upper_bound - lower_bound);
430 coeffs[0] = 1.0 / theta;
435 double tmp_0 = 1.0/(pow(
delta, 2) - 2*pow(theta, 2));
436 coeffs[0] = -4*theta*tmp_0;
442 double tmp_0 = 3*pow(
delta, 2);
443 double tmp_1 = pow(theta, 2);
444 double tmp_2 = 1.0/(-4*pow(theta, 3) + theta*tmp_0);
445 coeffs[0] = tmp_2*(tmp_0 - 12*tmp_1);
446 coeffs[1] = 12/(tmp_0 - 4*tmp_1);
447 coeffs[2] = -4*tmp_2;
452 double tmp_0 = pow(
delta, 2);
453 double tmp_1 = pow(theta, 2);
454 double tmp_2 = 8*tmp_0;
455 double tmp_3 = 1.0/(pow(
delta, 4) + 8*pow(theta, 4) - tmp_1*tmp_2);
456 coeffs[0] = tmp_3*(32*pow(theta, 3) - 16*theta*tmp_0);
457 coeffs[1] = tmp_3*(-48*tmp_1 + tmp_2);
458 coeffs[2] = 32*theta*tmp_3;
459 coeffs[3] = -8*tmp_3;
464 double tmp_0 = 5*pow(
delta, 4);
465 double tmp_1 = pow(theta, 4);
466 double tmp_2 = pow(theta, 2);
467 double tmp_3 = pow(
delta, 2);
468 double tmp_4 = 60*tmp_3;
469 double tmp_5 = 20*tmp_3;
470 double tmp_6 = 1.0/(16*pow(theta, 5) - pow(theta, 3)*tmp_5 + theta*tmp_0);
471 double tmp_7 = 160*tmp_2;
472 double tmp_8 = 1.0/(tmp_0 + 16*tmp_1 - tmp_2*tmp_5);
473 coeffs[0] = tmp_6*(tmp_0 + 80*tmp_1 - tmp_2*tmp_4);
474 coeffs[1] = tmp_8*(tmp_4 - tmp_7);
475 coeffs[2] = tmp_6*(-tmp_5 + tmp_7);
476 coeffs[3] = -80*tmp_8;
477 coeffs[4] = 16*tmp_6;
481 MFEM_ABORT(
"Chebyshev smoother not implemented for order = " << order);
489 MFEM_ABORT(
"Chebyshev smoother not implemented for iterative mode");
494 MFEM_ABORT(
"Chebyshev smoother requires operator");
503 for (
int k = 0; k < order; ++k)
508 oper->
Mult(residual, helperVector);
509 residual = helperVector;
514 auto Dinv = dinv.
Read();
516 mfem::forall(n, [=] MFEM_HOST_DEVICE (
int i) { R[i] *= Dinv[i]; });
520 auto C = coeffs.
Read();
521 mfem::forall(n, [=] MFEM_HOST_DEVICE (
int i) { Y[i] += C[k] * R[i]; });
570 double r0, nom, nom0, nomold = 1, cf;
586 nom0 = nom = sqrt(
Dot(
z,
z));
590 nom0 = nom = sqrt(
Dot(
r,
r));
596 mfem::out <<
" Iteration : " << setw(3) << right << 0 <<
" ||Br|| = " 629 nom = sqrt(
Dot(
z,
z));
633 nom = sqrt(
Dot(
r,
r));
654 mfem::out <<
" Iteration : " << setw(3) << right << (i-1)
655 <<
" ||Br|| = " << setw(11) << left << nom
656 <<
"\tConv. rate: " << cf <<
'\n';
664 const auto rf = pow (nom/nom0, 1.0/
final_iter);
666 <<
"Conv. rate: " << cf <<
'\n' 667 <<
"Average reduction factor: "<< rf <<
'\n';
671 mfem::out <<
"SLI: No convergence!" <<
'\n';
678 int print_iter,
int max_num_iter,
679 double RTOLERANCE,
double ATOLERANCE)
693 int print_iter,
int max_num_iter,
694 double RTOLERANCE,
double ATOLERANCE)
721 double r0, den, nom, nom0, betanom,
alpha,
beta;
744 nom0 = nom =
Dot(
d,
r);
746 MFEM_ASSERT(
IsFinite(nom),
"nom = " << nom);
749 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = " 758 mfem::out <<
"PCG: The preconditioner is not positive definite. (Br, r) = " 778 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
783 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = " 813 MFEM_ASSERT(
IsFinite(betanom),
"betanom = " << betanom);
818 mfem::out <<
"PCG: The preconditioner is not positive definite. (Br, r) = " 828 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = " 829 << betanom << std::endl;
857 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
862 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = " 885 const auto arf = pow (betanom/nom0, 0.5/
final_iter);
886 mfem::out <<
"Average reduction factor = " << arf <<
'\n';
890 mfem::out <<
"PCG: No convergence!" <<
'\n';
899 int print_iter,
int max_num_iter,
900 double RTOLERANCE,
double ATOLERANCE)
914 int print_iter,
int max_num_iter,
915 double RTOLERANCE,
double ATOLERANCE)
931 double &cs,
double &sn)
938 else if (fabs(dy) > fabs(dx))
940 double temp = dx / dy;
941 sn = 1.0 / sqrt( 1.0 + temp*temp );
946 double temp = dy / dx;
947 cs = 1.0 / sqrt( 1.0 + temp*temp );
954 double temp = cs * dx + sn * dy;
955 dy = -sn * dx + cs * dy;
965 for (
int i = k; i >= 0; i--)
968 for (
int j = i - 1; j >= 0; j--)
970 y(j) -= h(j,i) * y(i);
974 for (
int j = 0; j <= k; j++)
1043 <<
" Iteration : " << setw(3) << 0
1044 <<
" ||B r|| = " <<
beta 1054 if (v[0] == NULL) { v[0] =
new Vector(n); }
1055 v[0]->Set(1.0/
beta, r);
1058 for (i = 0; i <
m && j <=
max_iter; i++, j++)
1070 for (k = 0; k <= i; k++)
1072 H(k,i) =
Dot(w, *v[k]);
1073 w.
Add(-H(k,i), *v[k]);
1077 MFEM_ASSERT(
IsFinite(H(i+1,i)),
"Norm(w) = " << H(i+1,i));
1078 if (v[i+1] == NULL) { v[i+1] =
new Vector(n); }
1079 v[i+1]->Set(1.0/H(i+1,i), w);
1081 for (k = 0; k < i; k++)
1090 const double resid = fabs(
s(i+1));
1091 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1104 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
1105 <<
" Iteration : " << setw(3) << j
1106 <<
" ||B r|| = " << resid <<
'\n';
1147 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
1157 mfem::out <<
"GMRES: No convergence!\n";
1162 for (i = 0; i < v.
Size(); i++)
1202 <<
" Iteration : " << setw(3) << 0
1203 <<
" || r || = " <<
beta 1211 for (i= 0; i<=
m; i++)
1220 if (v[0] == NULL) { v[0] =
new Vector(
b.Size()); }
1225 for (i = 0; i <
m && j <=
max_iter; i++, j++)
1228 if (z[i] == NULL) { z[i] =
new Vector(
b.Size()); }
1241 for (k = 0; k <= i; k++)
1243 H(k,i) =
Dot( r, *v[k]);
1244 r.Add(-H(k,i), (*v[k]));
1248 if (v[i+1] == NULL) { v[i+1] =
new Vector(
b.Size()); }
1250 v[i+1] ->
Add (1.0/H(i+1,i), r);
1252 for (k = 0; k < i; k++)
1261 const double resid = fabs(
s(i+1));
1262 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1266 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
1267 <<
" Iteration : " << setw(3) << j
1268 <<
" || r || = " << resid << endl;
1284 for (i= 0; i<=
m; i++)
1286 if (v[i]) {
delete v[i]; }
1287 if (z[i]) {
delete z[i]; }
1315 for (i = 0; i <=
m; i++)
1317 if (v[i]) {
delete v[i]; }
1318 if (z[i]) {
delete z[i]; }
1325 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
1326 <<
" Iteration : " << setw(3) << j-1
1331 mfem::out <<
"FGMRES: Number of iterations: " << j-1 <<
'\n';
1335 mfem::out <<
"FGMRES: No convergence!\n";
1341 int &max_iter,
int m,
double &tol,
double atol,
int printit)
1360 int print_iter,
int max_num_iter,
int m,
double rtol,
double atol)
1362 GMRES(A, x,
b, B, max_num_iter, m, rtol, atol, print_iter);
1384 double resid, tol_goal;
1400 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1403 mfem::out <<
" Iteration : " << setw(3) << 0
1411 if (resid <= tol_goal)
1426 mfem::out <<
" Iteration : " << setw(3) << i
1427 <<
" ||r|| = " << resid <<
'\n';
1441 mfem::out <<
"BiCGStab: No convergence!\n";
1467 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1468 if (resid < tol_goal)
1473 mfem::out <<
" Iteration : " << setw(3) << i
1474 <<
" ||s|| = " << resid <<
'\n';
1487 mfem::out <<
" Iteration : " << setw(3) << i
1488 <<
" ||s|| = " << resid;
1507 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1510 mfem::out <<
" ||r|| = " << resid <<
'\n';
1513 if (resid < tol_goal)
1520 mfem::out <<
" Iteration : " << setw(3) << i
1521 <<
" ||r|| = " << resid <<
'\n';
1536 mfem::out <<
" Iteration : " << setw(3) << i
1537 <<
" ||r|| = " << resid <<
'\n';
1545 mfem::out <<
"BiCGStab: No convergence!\n";
1558 <<
" ||r|| = " << resid <<
'\n';
1566 mfem::out <<
"BiCGStab: No convergence!\n";
1571 int &max_iter,
double &tol,
double atol,
int printit)
1580 bicgstab.
Mult(
b, x);
1587 int print_iter,
int max_num_iter,
double rtol,
double atol)
1589 BiCGSTAB(A, x,
b, B, max_num_iter, rtol, atol, print_iter);
1625 double beta, eta, gamma0, gamma1, sigma0, sigma1;
1626 double alpha,
delta, rho1, rho2, rho3, norm_goal;
1647 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1648 gamma0 = gamma1 = 1.;
1649 sigma0 = sigma1 = 0.;
1653 if (eta <= norm_goal)
1661 mfem::out <<
"MINRES: iteration " << setw(3) << 0 <<
": ||r||_B = " 1684 rho2 = sigma1*
alpha + gamma0*gamma1*
beta;
1699 w0.
Set(1./rho1, *z);
1703 add(1./rho1, *z, -rho2/rho1,
w1,
w0);
1707 add(-rho3/rho1,
w0, -rho2/rho1,
w1,
w0);
1708 w0.
Add(1./rho1, *z);
1712 gamma1 =
delta/rho1;
1714 x.
Add(gamma1*eta,
w0);
1720 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1722 if (fabs(eta) <= norm_goal)
1729 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = " 1730 << fabs(eta) <<
'\n';
1732 Monitor(it, fabs(eta), *z, x);
1750 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = " 1751 << fabs(eta) <<
'\n';
1776 mfem::out <<
"MINRES: No convergence!\n";
1781 int max_it,
double rtol,
double atol)
1795 int print_it,
int max_it,
double rtol,
double atol)
1813 MFEM_ASSERT(
height ==
width,
"square Operator is required.");
1821 MFEM_ASSERT(
oper != NULL,
"the Operator is not set (use SetOperator).");
1822 MFEM_ASSERT(
prec != NULL,
"the Solver is not set (use SetSolver).");
1825 double norm0, norm, norm_goal;
1826 const bool have_b = (
b.Size() ==
Height());
1844 mfem::out <<
"Newton iteration " << setw(2) << 0
1845 <<
" : ||r|| = " << norm <<
"...\n";
1852 for (it = 0;
true; it++)
1854 MFEM_ASSERT(
IsFinite(norm),
"norm = " << norm);
1857 mfem::out <<
"Newton iteration " << setw(2) << it
1858 <<
" : ||r|| = " << norm;
1861 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
1867 if (norm <= norm_goal)
1900 add(x, -c_scale,
c, x);
1923 mfem::out <<
"Newton: No convergence!\n";
1929 const double rtol_max,
1930 const double alpha_,
1931 const double gamma_)
1936 this->
alpha = alpha_;
1937 this->
gamma = gamma_;
1942 const double fnorm)
const 1950 double sg_threshold = 0.1;
1970 MFEM_ABORT(
"Unknown adaptive linear solver rtol version");
1975 if (sg_eta > sg_threshold) { eta = std::max(eta, sg_eta); }
1979 iterative_solver->SetRelTol(eta);
1983 mfem::out <<
"Eisenstat-Walker rtol = " << eta <<
"\n";
1990 const double fnorm)
const 2009 MFEM_VERIFY(
oper != NULL,
"the Operator is not set (use SetOperator).");
2020 int last_saved_id = -1;
2023 double norm0, norm, norm_goal;
2024 const bool have_b = (
b.Size() ==
Height());
2035 if (have_b) {
r -=
b; }
2042 mfem::out <<
"LBFGS iteration " << setw(2) << 0
2043 <<
" : ||r|| = " << norm <<
"...\n";
2046 for (it = 0;
true; it++)
2048 MFEM_ASSERT(
IsFinite(norm),
"norm = " << norm);
2052 <<
" : ||r|| = " << norm;
2055 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
2060 if (norm <= norm_goal)
2079 add(x, -c_scale,
c, x);
2091 sk =
c; sk *= -c_scale;
2095 last_saved_id = (last_saved_id ==
m-1) ? 0 : last_saved_id+1;
2100 for (
int i = last_saved_id; i > -1; i--)
2108 for (
int i =
m-1; i > last_saved_id; i--)
2119 for (
int i = last_saved_id+1; i <
m ; i++)
2125 for (
int i = 0; i < last_saved_id+1 ; i++)
2145 mfem::out <<
"LBFGS: No convergence!\n";
2151 int m_max,
int m_min,
int m_step,
double cf,
2152 double &tol,
double &atol,
int printit)
2159 Vector s(m+1), cs(m+1), sn(m+1);
2166 double normb = w.Norml2();
2178 resid =
beta / normb;
2180 if (resid * resid <= tol)
2182 tol = resid * resid;
2190 <<
" Iteration : " << setw(3) << 0
2191 <<
" (r, r) = " <<
beta*
beta <<
'\n';
2194 tol *= (normb*normb);
2195 tol = (atol > tol) ? atol : tol;
2199 for (i= 0; i<=m; i++)
2206 while (j <= max_iter)
2214 for (i = 0; i < m && j <= max_iter; i++)
2219 for (k = 0; k <= i; k++)
2221 H(k,i) = w * (*v[k]);
2222 w.
Add(-H(k,i), (*v[k]));
2225 H(i+1,i) = w.Norml2();
2227 v[i+1] ->
Add (1.0/H(i+1,i), w);
2229 for (k = 0; k < i; k++)
2238 resid = fabs(
s(i+1));
2242 <<
" Iteration : " << setw(3) << i+1
2243 <<
" (r, r) = " << resid*resid <<
'\n';
2246 if ( resid*resid < tol)
2249 tol = resid * resid;
2251 for (i= 0; i<=m; i++)
2270 if ( resid*resid < tol)
2272 tol = resid * resid;
2274 for (i= 0; i<=m; i++)
2283 if (m - m_step >= m_min)
2296 tol = resid * resid;
2297 for (i= 0; i<=m; i++)
2307 : C(C_), D(D_), c_e(NULL), d_lo(NULL), d_hi(NULL), x_lo(NULL), x_hi(NULL),
2316 MFEM_ASSERT(
C,
"The C operator is unspecified -- can't set constraints.");
2317 MFEM_ASSERT(c.
Size() ==
C->
Height(),
"Wrong size of the constraint.");
2325 MFEM_ASSERT(
D,
"The D operator is unspecified -- can't set constraints.");
2327 "Wrong size of the constraint.");
2335 "Wrong size of the constraint.");
2352 MFEM_WARNING(
"Objective functional is ignored as SLBQP always minimizes" 2353 "the l2 norm of (x - x_target).");
2355 MFEM_ASSERT(
prob.GetC(),
"Linear constraint is not set.");
2356 MFEM_ASSERT(
prob.GetC()->Height() == 1,
"Solver expects scalar constraint.");
2377 mfem::out <<
"SLBQP iteration " << it <<
": residual = " << r
2378 <<
", lambda = " << l <<
'\n';
2401 const double smin = 0.1;
2408 mfem::out <<
"SLBQP bracketing phase" <<
'\n';
2426 llow = l; rlow = r; l = l + dl;
2429 r =
solve(l,xt,x,nclip);
2432 while ((r < 0) && (nclip <
max_iter))
2436 if (
s < smin) {
s = smin; }
2441 r =
solve(l,xt,x,nclip);
2449 lupp = l; rupp = r; l = l - dl;
2452 r =
solve(l,xt,x,nclip);
2455 while ((r > 0) && (nclip <
max_iter))
2459 if (
s < smin) {
s = smin; }
2464 r =
solve(l,xt,x,nclip);
2477 mfem::out <<
"SLBQP secant phase" <<
'\n';
2480 s = 1.0 - rlow/rupp; dl = dl/
s; l = lupp - dl;
2483 r =
solve(l,xt,x,nclip);
2486 while ( (fabs(r) > tol) && (nclip <
max_iter) )
2492 lupp = l; rupp = r;
s = 1.0 - rlow/rupp;
2493 dl = (lupp - llow)/
s; l = lupp - dl;
2498 if (
s < smin) {
s = smin; }
2500 lnew = 0.75*llow + 0.25*l;
2501 if (lnew < l-dl) { lnew = l-dl; }
2502 lupp = l; rupp = r; l = lnew;
2503 s = (lupp - llow)/(lupp - l);
2511 llow = l; rlow = r;
s = 1.0 - rlow/rupp;
2512 dl = (lupp - llow)/
s; l = lupp - dl;
2517 if (
s < smin) {
s = smin; }
2519 lnew = 0.75*lupp + 0.25*l;
2520 if (lnew < l+dl) { lnew = l+dl; }
2521 llow = l; rlow = r; l = lnew;
2522 s = (lupp - llow)/(lupp - l);
2527 r =
solve(l,xt,x,nclip);
2543 <<
" lambda = " << l <<
'\n' 2548 mfem::out <<
"SLBQP: No convergence!" <<
'\n';
2552 struct WeightMinHeap
2554 const std::vector<double> &w;
2555 std::vector<size_t> c;
2556 std::vector<int> loc;
2558 WeightMinHeap(
const std::vector<double> &w_) : w(w_)
2560 c.reserve(w.size());
2561 loc.resize(w.size());
2562 for (
size_t i=0; i<w.size(); ++i) { push(i); }
2565 size_t percolate_up(
size_t pos,
double val)
2567 for (; pos > 0 && w[c[(pos-1)/2]] > val; pos = (pos-1)/2)
2569 c[pos] = c[(pos-1)/2];
2570 loc[c[(pos-1)/2]] = pos;
2575 size_t percolate_down(
size_t pos,
double val)
2577 while (2*pos+1 < c.size())
2579 size_t left = 2*pos+1;
2580 size_t right = left+1;
2582 if (right < c.size() && w[c[right]] < w[c[left]]) { tgt = right; }
2583 else { tgt = left; }
2584 if (w[c[tgt]] < val)
2602 size_t pos = c.size()-1;
2603 pos = percolate_up(pos, val);
2611 size_t j = c.back();
2615 if (c.empty()) {
return i; }
2618 pos = percolate_down(pos, val);
2624 void update(
size_t i)
2626 size_t pos = loc[i];
2628 pos = percolate_up(pos, val);
2629 pos = percolate_down(pos, val);
2634 bool picked(
size_t i)
2649 for (
int i=0; i<n; ++i)
2651 for (
int j=I[i]; j<I[i+1]; ++j)
2653 V[j] = abs(V[j]/D[i]);
2657 std::vector<double> w(n, 0.0);
2658 for (
int k=0; k<n; ++k)
2661 for (
int ii=I[k]; ii<I[k+1]; ++ii)
2666 for (
int kk=I[i]; kk<I[i+1]; ++kk)
2674 for (
int jj=I[k]; jj<I[k+1]; ++jj)
2677 if (j == k) {
continue; }
2678 double C_kj = V[jj];
2679 bool ij_exists =
false;
2680 for (
int jj2=I[i]; jj2<I[i+1]; ++jj2)
2688 if (!ij_exists) { w[k] += pow(C_ik*C_kj,2); }
2694 WeightMinHeap w_heap(w);
2698 for (
int ii=0; ii<n; ++ii)
2700 int pi = w_heap.pop();
2703 for (
int kk=I[pi]; kk<I[pi+1]; ++kk)
2706 if (w_heap.picked(k)) {
continue; }
2710 for (
int ii2=I[k]; ii2<I[k+1]; ++ii2)
2713 if (w_heap.picked(i)) {
continue; }
2716 for (
int kk2=I[i]; kk2<I[i+1]; ++kk2)
2724 for (
int jj=I[k]; jj<I[k+1]; ++jj)
2727 if (j == k || w_heap.picked(j)) {
continue; }
2728 double C_kj = V[jj];
2729 bool ij_exists =
false;
2730 for (
int jj2=I[i]; jj2<I[i+1]; ++jj2)
2738 if (!ij_exists) { w[k] += pow(C_ik*C_kj,2); }
2751 block_size(block_size_),
2753 reordering(reordering_)
2760 :
BlockILU(block_size_, reordering_, k_fill_)
2782 MFEM_ABORT(
"BlockILU must be created with a SparseMatrix or HypreParMatrix");
2787 MFEM_ASSERT(A->
Finalized(),
"Matrix must be finalized.");
2788 CreateBlockPattern(*A);
2792 void BlockILU::CreateBlockPattern(
const SparseMatrix &A)
2794 MFEM_VERIFY(k_fill == 0,
"Only block ILU(0) is currently supported.");
2795 if (A.
Height() % block_size != 0)
2797 MFEM_ABORT(
"BlockILU: block size must evenly divide the matrix size");
2801 const int *I = A.
GetI();
2802 const int *J = A.
GetJ();
2803 const double *V = A.
GetData();
2805 int nblockrows = nrows / block_size;
2807 std::vector<std::set<int>> unique_block_cols(nblockrows);
2809 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2811 for (
int bi = 0; bi < block_size; ++bi)
2813 int i = iblock * block_size + bi;
2814 for (
int k = I[i]; k < I[i + 1]; ++k)
2816 unique_block_cols[iblock].insert(J[k] / block_size);
2819 nnz += unique_block_cols[iblock].size();
2824 SparseMatrix C(nblockrows, nblockrows);
2825 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2827 for (
int jblock : unique_block_cols[iblock])
2829 for (
int bi = 0; bi < block_size; ++bi)
2831 int i = iblock * block_size + bi;
2832 for (
int k = I[i]; k < I[i + 1]; ++k)
2835 if (j >= jblock * block_size && j < (jblock + 1) * block_size)
2837 C.Add(iblock, jblock, V[k]*V[k]);
2844 double *CV = C.GetData();
2845 for (
int i=0; i<C.NumNonZeroElems(); ++i)
2847 CV[i] = sqrt(CV[i]);
2856 MFEM_ABORT(
"BlockILU: unknown reordering")
2863 for (
int i=0; i<nblockrows; ++i)
2871 for (
int i=0; i<nblockrows; ++i)
2877 std::vector<std::vector<int>> unique_block_cols_perminv(nblockrows);
2878 for (
int i=0; i<nblockrows; ++i)
2880 std::vector<int> &cols = unique_block_cols_perminv[i];
2881 for (
int j : unique_block_cols[P[i]])
2883 cols.push_back(Pinv[j]);
2885 std::sort(cols.begin(), cols.end());
2892 AB.
SetSize(block_size, block_size, nnz);
2893 DB.
SetSize(block_size, block_size, nblockrows);
2896 ipiv.
SetSize(block_size*nblockrows);
2899 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2901 int iblock_perm = P[iblock];
2902 for (
int jblock : unique_block_cols_perminv[iblock])
2904 int jblock_perm = P[jblock];
2905 if (iblock == jblock)
2907 ID[iblock] = counter;
2909 JB[counter] = jblock;
2910 for (
int bi = 0; bi < block_size; ++bi)
2912 int i = iblock_perm*block_size + bi;
2913 for (
int k = I[i]; k < I[i + 1]; ++k)
2916 if (j >= jblock_perm*block_size && j < (jblock_perm + 1)*block_size)
2918 int bj = j - jblock_perm*block_size;
2920 AB(bi, bj, counter) = val;
2922 if (iblock == jblock)
2924 DB(bi, bj, iblock) = val;
2931 IB[iblock + 1] = counter;
2935 void BlockILU::Factorize()
2937 int nblockrows =
Height()/block_size;
2940 for (
int i=0; i<nblockrows; ++i)
2942 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2943 factorization.Factor(block_size);
2949 DenseMatrix A_ik, A_ij, A_kj;
2951 for (
int i=1; i<nblockrows; ++i)
2954 for (
int kk=IB[i]; kk<IB[i+1]; ++kk)
2958 if (k == i) {
break; }
2961 MFEM_ABORT(
"Matrix must be sorted with nonzero diagonal");
2963 LUFactors A_kk_inv(DB.
GetData(k), &ipiv[k*block_size]);
2964 A_ik.UseExternalData(&AB(0,0,kk), block_size, block_size);
2966 A_kk_inv.RightSolve(block_size, block_size, A_ik.GetData());
2968 for (
int jj=kk+1; jj<IB[i+1]; ++jj)
2971 if (j <= k) {
continue; }
2972 A_ij.UseExternalData(&AB(0,0,jj), block_size, block_size);
2973 for (
int ll=IB[k]; ll<IB[k+1]; ++ll)
2978 A_kj.UseExternalData(&AB(0,0,ll), block_size, block_size);
2985 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2986 factorization.Factor(block_size);
2998 MFEM_ASSERT(
height > 0,
"BlockILU(0) preconditioner is not constructed");
2999 int nblockrows =
Height()/block_size;
3008 for (
int i=0; i<nblockrows; ++i)
3011 for (
int ib=0; ib<block_size; ++ib)
3013 yi[ib] =
b[ib + P[i]*block_size];
3015 for (
int k=IB[i]; k<ID[i]; ++k)
3025 for (
int i=nblockrows-1; i >= 0; --i)
3028 for (
int ib=0; ib<block_size; ++ib)
3030 xi[ib] = y[ib + i*block_size];
3032 for (
int k=ID[i]+1; k<IB[i+1]; ++k)
3040 LUFactors A_ii_inv(&DB(0,0,i), &ipiv[i*block_size]);
3048 int it,
double norm,
const Vector &r,
bool final)
3052 double bc_norm_squared = 0.0;
3058 bc_norm_squared += r_entry*r_entry;
3063 if (comm != MPI_COMM_NULL)
3065 double glob_bc_norm_squared = 0.0;
3066 MPI_Reduce(&bc_norm_squared, &glob_bc_norm_squared, 1, MPI_DOUBLE,
3068 bc_norm_squared = glob_bc_norm_squared;
3070 MPI_Comm_rank(comm, &rank);
3071 print = (rank == 0);
3074 if ((it == 0 ||
final || bc_norm_squared > 0.0) && print)
3076 mfem::out <<
" ResidualBCMonitor : b.c. residual norm = " 3077 << sqrt(bc_norm_squared) << endl;
3082 #ifdef MFEM_USE_SUITESPARSE 3107 umfpack_di_free_numeric(&
Numeric);
3111 umfpack_dl_free_numeric(&
Numeric);
3116 MFEM_VERIFY(
mat,
"not a SparseMatrix");
3125 MFEM_VERIFY(
width ==
height,
"not a square matrix");
3138 umfpack_di_report_status(
Control, status);
3140 " umfpack_di_symbolic() failed!");
3148 umfpack_di_report_status(
Control, status);
3150 " umfpack_di_numeric() failed!");
3152 umfpack_di_free_symbolic(&
Symbolic);
3156 SuiteSparse_long status;
3160 AI =
new SuiteSparse_long[
width + 1];
3161 AJ =
new SuiteSparse_long[Ap[
width]];
3162 for (
int i = 0; i <=
width; i++)
3164 AI[i] = (SuiteSparse_long)(Ap[i]);
3166 for (
int i = 0; i < Ap[
width]; i++)
3168 AJ[i] = (SuiteSparse_long)(Ai[i]);
3176 umfpack_dl_report_status(
Control, status);
3178 " umfpack_dl_symbolic() failed!");
3186 umfpack_dl_report_status(
Control, status);
3188 " umfpack_dl_numeric() failed!");
3190 umfpack_dl_free_symbolic(&
Symbolic);
3197 mfem_error(
"UMFPackSolver::Mult : matrix is not set!" 3198 " Call SetOperator first!");
3210 umfpack_di_report_status(
Control, status);
3211 mfem_error(
"UMFPackSolver::Mult : umfpack_di_solve() failed!");
3216 SuiteSparse_long status =
3223 umfpack_dl_report_status(
Control, status);
3224 mfem_error(
"UMFPackSolver::Mult : umfpack_dl_solve() failed!");
3232 mfem_error(
"UMFPackSolver::MultTranspose : matrix is not set!" 3233 " Call SetOperator first!");
3245 umfpack_di_report_status(
Control, status);
3247 " umfpack_di_solve() failed!");
3252 SuiteSparse_long status =
3259 umfpack_dl_report_status(
Control, status);
3261 " umfpack_dl_solve() failed!");
3274 umfpack_di_free_numeric(&
Numeric);
3278 umfpack_dl_free_numeric(&
Numeric);
3293 "Had Numeric pointer in KLU, but not Symbolic");
3301 MFEM_VERIFY(
mat != NULL,
"not a SparseMatrix");
3309 MFEM_VERIFY(
width ==
height,
"not a square matrix");
3321 MFEM_VERIFY(
mat != NULL,
3322 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
3335 MFEM_VERIFY(
mat != NULL,
3336 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
3355 #endif // MFEM_USE_SUITESPARSE 3363 for (
int i = 0; i < block_dof.
NumRows(); ++i)
3368 block_solvers[i].SetOperator(sub_A);
3377 for (
int i = 0; i < block_dof.
NumRows(); ++i)
3382 block_solvers[i].Mult(sub_rhs, sub_sol);
3396 add(-1.0, z, 1.0, x, z);
3413 add(-1.0, z, 1.0, x, z);
3422 :
Solver(0, false), global_size(-1)
3430 :
Solver(0, false), mycomm(mycomm_), global_size(-1), parallel(true) { }
3438 MFEM_VERIFY(
height ==
width,
"Solver must be a square Operator!");
3444 MFEM_VERIFY(solver,
"Solver hasn't been set, call SetSolver() first.");
3448 MFEM_VERIFY(
height ==
width,
"Solver must be a square Operator!");
3454 MFEM_VERIFY(solver,
"Solver hasn't been set, call SetSolver() first.");
3456 "solver was modified externally! call SetSolver() again!");
3457 MFEM_VERIFY(
height ==
b.Size(),
"incompatible input Vector size!");
3458 MFEM_VERIFY(
height == x.
Size(),
"incompatible output Vector size!");
3461 Orthogonalize(
b, b_ortho);
3467 solver->
Mult(b_ortho, x);
3470 Orthogonalize(x, x);
3473 void OrthoSolver::Orthogonalize(
const Vector &v,
Vector &v_ortho)
const 3475 if (global_size == -1)
3481 MPI_Allreduce(MPI_IN_PLACE, &global_size, 1, HYPRE_MPI_BIG_INT,
3489 double global_sum = v.
Sum();
3494 MPI_Allreduce(MPI_IN_PLACE, &global_sum, 1, MPI_DOUBLE, MPI_SUM, mycomm);
3498 double ratio = global_sum /
static_cast<double>(global_size);
3502 for (
int i = 0; i < v_ortho.
Size(); ++i)
3504 v_ortho(i) = v(i) - ratio;
3511 bool op_is_symmetric,
3513 :
Solver(op.NumRows()), aux_map_(aux_map, own_aux_map)
3515 aux_system_.
Reset(
RAP(&op, aux_map));
3518 aux_smoother_.
As<
HypreSmoother>()->SetOperatorSymmetry(op_is_symmetric);
3521 void AuxSpaceSmoother::Mult(
const Vector &x,
Vector &y,
bool transpose)
const 3526 Vector aux_sol(aux_rhs.Size());
3533 aux_smoother_->
Mult(aux_rhs, aux_sol);
3537 aux_map_->
Mult(aux_sol, y);
3539 #endif // MFEM_USE_MPI 3541 #ifdef MFEM_USE_LAPACK 3544 dormqr_(
char *,
char *,
int *,
int *,
int *,
double *,
int*,
double *,
3545 double *,
int *,
double *,
int*,
int*);
3548 dgeqrf_(
int *,
int *,
double *,
int *,
double *,
double *,
int *,
int *);
3551 dgemv_(
char *,
int *,
int *,
double *,
double *,
int *,
double *,
int *,
3552 double *,
double *,
int *);
3555 dtrsm_(
char *side,
char *uplo,
char *transa,
char *diag,
int *m,
int *n,
3556 double *
alpha,
double *
a,
int *lda,
double *
b,
int *ldb);
3559 :
Solver(0), mat(nullptr), const_tol_(1.0e-14), min_nnz_(0),
3560 max_nnz_(0), verbosity_(0), res_change_termination_tol_(1.0e-4),
3561 zero_tol_(1.0e-14), rhs_delta_(1.0e-11), n_outer_(100000),
3562 n_inner_(100000), nStallCheck_(100), normalize_(true),
3569 MFEM_VERIFY(mat,
"NNLSSolver operator must be of type DenseMatrix");
3581 qr_residual_mode_ = qr_residual_mode;
3584 NNLS_qrres_on_ =
true;
3593 MFEM_VERIFY(rhs_lb.
Size() == m && rhs_ub.
Size() == m,
"");
3599 Vector rhs_halfgap = rhs_ub;
3600 rhs_halfgap -= rhs_lb;
3603 Vector rhs_avg_glob = rhs_avg;
3604 Vector rhs_halfgap_glob = rhs_halfgap;
3605 Vector halfgap_target(m);
3606 halfgap_target = 1.0e3 * const_tol_;
3610 for (
int i=0; i<m; ++i)
3612 const double s = halfgap_target(i) / rhs_halfgap_glob(i);
3613 row_scaling_[i] =
s;
3615 rhs_lb(i) = (rhs_avg(i) *
s) - halfgap_target(i);
3616 rhs_ub(i) = (rhs_avg(i) *
s) + halfgap_target(i);
3622 MFEM_VERIFY(mat,
"NNLSSolver operator must be of type DenseMatrix");
3624 mat->
Mult(w, rhs_ub);
3625 rhs_ub *= row_scaling_;
3630 for (
int i=0; i<rhs_ub.Size(); ++i)
3632 rhs_lb(i) -= rhs_delta_;
3633 rhs_ub(i) += rhs_delta_;
3637 Solve(rhs_lb, rhs_ub, sol);
3642 for (
int i=0; i<sol.
Size(); ++i)
3650 mfem::out <<
"Number of nonzeros in NNLSSolver solution: " << nnz
3651 <<
", out of " << sol.
Size() << endl;
3655 mat->
Mult(sol, res);
3656 res *= row_scaling_;
3658 const double normGsol = res.
Norml2();
3659 const double normRHS = rhs_Gw.
Norml2();
3662 const double relNorm = res.
Norml2() / std::max(normGsol, normRHS);
3663 mfem::out <<
"Relative residual norm for NNLSSolver solution of Gs = Gw: " 3674 MFEM_VERIFY(rhs_lb.
Size() == m && rhs_lb.
Size() == m && soln.
Size() == n,
"");
3675 MFEM_VERIFY(n >= m,
"NNLSSolver system cannot be over-determined.");
3687 Vector rhs_halfgap(rhs_ub);
3688 rhs_halfgap -= rhs_lb;
3691 Vector rhs_avg_glob(rhs_avg);
3692 Vector rhs_halfgap_glob(rhs_halfgap);
3701 std::vector<unsigned int> nz_ind(m);
3708 int min_nnz_cap = std::min(static_cast<int>(min_nnz_), std::min(m,n));
3710 std::vector<double> l2_res_hist;
3711 std::vector<unsigned int> stalled_indices;
3712 int stalledFlag = 0;
3713 int num_stalled = 0;
3714 int nz_ind_zero = 0;
3717 Vector soln_nz_glob_up(m);
3720 Vector mat_0_data(m * n);
3721 Vector mat_qr_data(m * n);
3722 Vector submat_data(m * n);
3730 std::vector<double> work;
3731 int n_outer_iter = 0;
3732 int n_total_inner_iter = 0;
3739 res_glob = rhs_avg_glob;
3740 Vector qt_rhs_glob = rhs_avg_glob;
3741 Vector qqt_rhs_glob = qt_rhs_glob;
3742 Vector sub_qt = rhs_avg_glob;
3745 double mu_tol = 0.0;
3748 Vector rhs_scaled(rhs_halfgap_glob);
3750 rhs_scaled *= row_scaling_;
3753 mu_tol = 1.0e-15 * tmp.
Max();
3759 for (
int oiter = 0; oiter < n_outer_; ++oiter)
3763 rmax = fabs(res_glob(0)) - rhs_halfgap_glob(0);
3764 for (
int i=1; i<m; ++i)
3766 rmax = std::max(rmax, fabs(res_glob(i)) - rhs_halfgap_glob(i));
3769 l2_res_hist.push_back(res_glob.
Norml2());
3773 mfem::out <<
"NNLS " << oiter <<
" " << n_total_inner_iter <<
" " << m
3774 <<
" " << n <<
" " << n_glob <<
" " << rmax <<
" " 3775 << l2_res_hist[oiter] << endl;
3777 if (rmax <= const_tol_ && n_glob >= min_nnz_cap)
3781 mfem::out <<
"NNLS target tolerance met" << endl;
3787 if (n_glob >= max_nnz_)
3791 mfem::out <<
"NNLS target nnz met" << endl;
3801 mfem::out <<
"NNLS system is square... exiting" << endl;
3808 if (oiter > nStallCheck_)
3812 for (
int i=0; i<nStallCheck_/2; ++i)
3814 mean0 += l2_res_hist[oiter - i];
3815 mean1 += l2_res_hist[oiter - (nStallCheck_) - i];
3818 double mean_res_change = (mean1 / mean0) - 1.0;
3819 if (std::abs(mean_res_change) < res_change_termination_tol_)
3823 mfem::out <<
"NNLSSolver stall detected... exiting" << endl;
3831 res_glob *= row_scaling_;
3834 for (
int i = 0; i < n_nz_ind; ++i)
3836 mu(nz_ind[i]) = 0.0;
3838 for (
unsigned int i = 0; i < stalled_indices.size(); ++i)
3840 mu(stalled_indices[i]) = 0.0;
3847 num_stalled = stalled_indices.size();
3848 if (num_stalled > 0)
3852 mfem::out <<
"NNLS Lagrange multiplier is below the minimum " 3853 <<
"threshold: mumax = " << mumax <<
", mutol = " 3854 << mu_tol <<
"\n" <<
" Resetting stalled indices " 3855 <<
"vector of size " << num_stalled <<
"\n";
3857 stalled_indices.resize(0);
3861 for (
int i = 0; i < n_nz_ind; ++i)
3863 mu(nz_ind[i]) = 0.0;
3872 double tmax =
mu(0);
3873 for (
int i=1; i<n; ++i)
3884 nz_ind[n_nz_ind] = imax;
3889 mfem::out <<
"Found next index: " << imax <<
" " << mumax << endl;
3892 for (
int i=0; i<m; ++i)
3894 mat_0_data(i + (n_glob*m)) = (*mat)(i,imax) * row_scaling_[i];
3895 mat_qr_data(i + (n_glob*m)) = mat_0_data(i + (n_glob*m));
3898 i_qr_start = n_glob;
3903 mfem::out <<
"Updated matrix with new index" << endl;
3906 for (
int iiter = 0; iiter < n_inner_; ++iiter)
3908 ++n_total_inner_iter;
3911 const bool incremental_update =
true;
3912 n_update = n_glob - i_qr_start;
3913 m_update = m - i_qr_start;
3914 if (incremental_update)
3922 mat_qr_data.
GetData() + (i_qr_start * m), &m,
3923 work.data(), &lwork, &info);
3924 MFEM_VERIFY(info == 0,
"");
3925 lwork =
static_cast<int>(work[0]);
3929 mat_qr_data.
GetData() + (i_qr_start * m), &m,
3930 work.data(), &lwork, &info);
3931 MFEM_VERIFY(info == 0,
"");
3938 for (
int i=0; i<m_update; ++i)
3939 for (
int j=0; j<n_update; ++j)
3941 submat_data[i + (j * m_update)] =
3942 mat_qr_data[i + i_qr_start + ((j + i_qr_start) * m)];
3946 for (
int j=0; j<n_update; ++j)
3948 sub_tau[j] = tau[i_qr_start + j];
3953 work.data(), &lwork, &info);
3954 MFEM_VERIFY(info == 0,
"");
3955 lwork =
static_cast<int>(work[0]);
3956 if (lwork == 0) { lwork = 1; }
3960 work.data(), &lwork, &info);
3961 MFEM_VERIFY(info == 0,
"");
3964 for (
int i=0; i<m_update; ++i)
3965 for (
int j=0; j<n_update; ++j)
3967 mat_qr_data[i + i_qr_start + ((j + i_qr_start)* m)] =
3968 submat_data[i + (j * m_update)];
3971 for (
int j=0; j<n_update; ++j)
3973 tau[i_qr_start + j] = sub_tau[j];
3979 for (
int i=0; i<m; ++i)
3980 for (
int j=0; j<n_glob; ++j)
3982 mat_qr_data(i + (j*m)) = mat_0_data(i + (j*m));
3991 work.data(), &lwork, &info);
3992 MFEM_VERIFY(info == 0,
"");
3993 lwork =
static_cast<int>(work[0]);
3997 work.data(), &lwork, &info);
3998 MFEM_VERIFY(info == 0,
"");
4003 mfem::out <<
"Updated QR " << iiter << endl;
4007 if (incremental_update && iiter == 0)
4017 for (
int i=0; i<m_update; ++i)
4019 submat_data[i] = mat_qr_data[i + i_qr_start + (i_qr_start * m)];
4020 sub_qt[i] = qt_rhs_glob[i + i_qr_start];
4023 sub_tau[0] = tau[i_qr_start];
4028 work.data(), &lwork, &info);
4029 MFEM_VERIFY(info == 0,
"");
4030 lwork =
static_cast<int>(work[0]);
4035 work.data(), &lwork, &info);
4036 MFEM_VERIFY(info == 0,
"");
4038 for (
int i=0; i<m_update; ++i)
4040 qt_rhs_glob[i + i_qr_start] = sub_qt[i];
4046 qt_rhs_glob = rhs_avg_glob;
4052 work.data(), &lwork, &info);
4053 MFEM_VERIFY(info == 0,
"");
4054 lwork =
static_cast<int>(work[0]);
4059 work.data(), &lwork, &info);
4060 MFEM_VERIFY(info == 0,
"");
4065 mfem::out <<
"Updated rhs " << iiter << endl;
4072 dtrsm_(&lside, &upper, ¬rans, &nounit,
4073 &n_glob, &ione, &fone,
4079 mfem::out <<
"Solved triangular system " << iiter << endl;
4084 double smin = n_glob > 0 ? vec1(0) : 0.0;
4085 for (
int i=0; i<n_glob; ++i)
4087 soln_nz_glob_up(i) = vec1(i);
4088 smin = std::min(smin, soln_nz_glob_up(i));
4091 if (smin > zero_tol_)
4094 for (
int i=0; i<n_glob; ++i)
4096 soln_nz_glob(i) = soln_nz_glob_up(i);
4107 mfem::out <<
"Start pruning " << iiter << endl;
4108 for (
int i = 0; i < n_glob; ++i)
4110 if (soln_nz_glob_up(i) <= zero_tol_)
4112 mfem::out << i <<
" " << n_glob <<
" " << soln_nz_glob_up(i) << endl;
4117 if (soln_nz_glob_up(n_glob - 1) <= zero_tol_)
4124 mfem::out <<
"Detected stall due to adding and removing same " 4125 <<
"column. Switching to QR residual calculation " 4126 <<
"method." << endl;
4130 mfem::out <<
"Detected stall due to adding and removing same" 4131 <<
" column. Exiting now." << endl;
4138 NNLS_qrres_on_ =
true;
4142 double alpha = 1.0e300;
4144 for (
int i = 0; i < n_glob; ++i)
4146 if (soln_nz_glob_up(i) <= zero_tol_)
4148 alpha = std::min(
alpha, soln_nz_glob(i)/(soln_nz_glob(i) - soln_nz_glob_up(i)));
4153 for (
int i = 0; i < n_glob; ++i)
4155 soln_nz_glob(i) +=
alpha*(soln_nz_glob_up(i) - soln_nz_glob(i));
4156 if (i == 0 || soln_nz_glob(i) < smin)
4158 smin = soln_nz_glob(i);
4162 while (smin > zero_tol_)
4170 smin = soln_nz_glob(0);
4171 for (
int i = 1; i < n_glob; ++i)
4173 if (soln_nz_glob(i) < smin)
4175 smin = soln_nz_glob(i);
4180 alpha = soln_nz_glob(index_min)/(soln_nz_glob(index_min)
4181 - soln_nz_glob_up(index_min));
4184 for (
int i = 0; i < n_glob; ++i)
4186 soln_nz_glob(i) +=
alpha*(soln_nz_glob_up(i) - soln_nz_glob(i));
4191 i_qr_start = n_glob+1;
4197 smin = n_glob > 0 ? soln_nz_glob(0) : 0.0;
4198 for (
int i=1; i<n_glob; ++i)
4200 smin = std::min(smin, soln_nz_glob(i));
4203 if (smin < zero_tol_)
4212 if (zero_ibool == 0)
4221 for (
int i = 0; i < n_glob; ++i)
4223 if (soln_nz_glob(i) < zero_tol_)
4229 MFEM_VERIFY(ind_zero != -1,
"");
4232 for (
int i = 0; i < ind_zero; ++i)
4239 for (
int i=0; i<m; ++i)
4240 for (
int j=ind_zero; j<n_glob-1; ++j)
4242 mat_qr_data(i + (j*m)) = mat_0_data(i + ((j+1)*m));
4247 for (
int i=0; i<m; ++i)
4248 for (
int j=ind_zero; j<n_glob-1; ++j)
4250 mat_0_data(i + (j*m)) = mat_qr_data(i + (j*m));
4255 for (
int i = nz_ind_zero; i < n_nz_ind-1; ++i)
4257 nz_ind[i] = nz_ind[i+1];
4262 for (
int i = ind_zero; i < n_glob-1; ++i)
4264 soln_nz_glob(i) = soln_nz_glob(i+1);
4267 i_qr_start = std::min(i_qr_start, ind_zero);
4273 mfem::out <<
"Finished pruning " << iiter << endl;
4278 if (stalledFlag == 1)
4282 num_stalled = stalled_indices.size();
4283 stalled_indices.resize(num_stalled + 1);
4284 stalled_indices[num_stalled] = imax;
4287 mfem::out <<
"Adding index " << imax <<
" to stalled index list " 4288 <<
"of size " << num_stalled << endl;
4293 if (!NNLS_qrres_on_)
4295 res_glob = rhs_avg_glob;
4296 double fmone = -1.0;
4297 dgemv_(¬rans, &m, &n_glob, &fmone,
4299 soln_nz_glob.
GetData(), &ione, &fone,
4309 for (
int i=0; i<n_glob; ++i)
4311 qqt_rhs_glob(i) = qt_rhs_glob(i);
4314 dormqr_(&lside, ¬rans, &m, &ione, &n_glob, mat_qr_data.
GetData(), &m,
4316 work.data(), &lwork, &info);
4318 MFEM_VERIFY(info == 0,
"");
4319 lwork =
static_cast<int>(work[0]);
4321 dormqr_(&lside, ¬rans, &m, &ione, &n_glob, mat_qr_data.
GetData(), &m,
4323 work.data(), &lwork, &info);
4324 MFEM_VERIFY(info == 0,
"");
4325 res_glob = rhs_avg_glob;
4326 res_glob -= qqt_rhs_glob;
4331 mfem::out <<
"Computed residual" << endl;
4338 MFEM_VERIFY(n_glob == n_nz_ind,
"");
4340 for (
int i = 0; i < n_glob; ++i)
4342 soln(nz_ind[i]) = soln_nz_glob(i);
4347 mfem::out <<
"NNLS solver: m = " << m <<
", n = " << n
4348 <<
", outer_iter = " << n_outer_iter <<
", inner_iter = " 4349 << n_total_inner_iter;
4357 mfem::out << endl <<
"Warning, NNLS convergence stalled: " 4358 << (exit_flag == 2) << endl;
4359 mfem::out <<
"resErr = " << rmax <<
" vs tol = " << const_tol_
4360 <<
"; mumax = " << mumax <<
" vs tol = " << mu_tol << endl;
4364 #endif // MFEM_USE_LAPACK const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
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 ...
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
const double * HostReadData() const
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
void dgemv_(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *)
Conjugate gradient method.
void trans(const Vector &u, Vector &x)
double Info[UMFPACK_INFO]
Chebyshev accelerated smoothing with given vector, no matrix necessary.
void dgeqrf_(int *, int *, double *, int *, double *, double *, int *, int *)
Array< Vector * > ykArray
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
void GetDiag(Vector &d) const
Returns the Diagonal of A.
void SetSize(int s)
Resize the vector to size s.
void Mult(const Vector &w, Vector &sol) const override
Operator application: y=A(x).
virtual const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
void MinimumDiscardedFillOrdering(SparseMatrix &C, Array< int > &p)
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
int RowSize(const int i) const
Returns the number of elements in row i.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
bool summary
A summary of the solver process will be reported after the last iteration to mfem::out.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
virtual void ProcessNewState(const Vector &x) const
This method can be overloaded in derived classes to perform computations that need knowledge of the n...
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
bool first_and_last
Information about the first and last iteration will be printed to mfem::out.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
OperatorJacobiSmoother(const double damping=1.0)
Default constructor: the diagonal will be computed by subsequent calls to SetOperator() using the Ope...
int * GetJ()
Return the array J.
void dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual void Solve(int m, int n, double *X) const
int Size() const
Returns the size of the vector.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
Data type dense matrix using column-major storage.
virtual double * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
virtual MemoryClass GetMemoryClass() const
Return the MemoryClass preferred by the Operator.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
int * GetI()
Return the array I.
bool errors
If a fatal problem has been detected the failure will be reported to mfem::err.
void SetQRResidualMode(const QRresidualMode qr_residual_mode)
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void SetOperator(const Operator &op)
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Reordering
The reordering method used by the BlockILU factorization.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
void Mult(const Vector &b, Vector &x) const
Solve the system LUx = b, where L and U are the block ILU factors.
int print_level
(DEPRECATED) Legacy print level definition, which is left for compatibility with custom iterative sol...
void SortColumnIndices()
Sort the column indices corresponding to each row.
void add(const Vector &v1, const Vector &v2, Vector &v)
void Monitor(int it, double norm, const Vector &r, const Vector &x, bool final=false) const
double GetFinalNorm() const
Returns the final residual norm after termination of the solver during the last call to Mult()...
virtual void SetOperator(const Operator &op)
Set the Operator that is the OrthoSolver is to invert (approximately).
double * GetData()
Return the element data, i.e. the array A.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
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)
bool IsFinite(const double &val)
virtual void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
double Norm(const Vector &x) const
const class IterativeSolver * iter_solver
The last IterativeSolver to which this monitor was attached.
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
General product operator: x -> (A*B)(x) = A(B(x)).
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
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 Solve(const Vector &rhs_lb, const Vector &rhs_ub, Vector &soln) const
Solve the NNLS problem. Specifically, we find a vector soln, such that rhs_lb < mat*soln < rhs_ub is ...
int GetNumConstraints() const
double solve(double l, const Vector &xt, Vector &x, int &nclip) const
Solve QP at fixed lambda.
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)
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
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 MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
void Update(Vector &x, int k, DenseMatrix &h, Vector &s, Array< Vector *> &v)
const int * HostReadJ() const
void SetMaxIter(int max_it)
OperatorChebyshevSmoother(const Operator &oper_, const Vector &d, const Array< int > &ess_tdof_list, int order, double max_eig_estimate)
void SetLinearConstraint(const Vector &w_, double a_)
double Sum() const
Return the sum of the vector entries.
DirectSubBlockSolver(const SparseMatrix &A, const SparseMatrix &block_dof)
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
void print_iteration(int it, double r, double l) const
void AddMult_a(double a, const Vector &x, Vector &y) const
y += a * A.x
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)
PrintLevel & Iterations()
void Setup(const Vector &diag)
Parallel smoothers in hypre.
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 SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
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.
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
Array< Vector * > skArray
PrintLevel & FirstAndLast()
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
void Mult(const double *x, double *y) const
Matrix vector multiplication.
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
bool Finalized() const
Returns whether or not CSR format has been finalized.
BlockILU(int block_size_, Reordering reordering_=Reordering::MINIMUM_DISCARDED_FILL, int k_fill_=0)
double * GetData() const
Return a pointer to the beginning of the Vector data.
Stationary linear iteration: x <- x + B (b - A x)
void SetInequalityConstraint(const Vector &dl, const Vector &dh)
void SetEqualityConstraint(const Vector &c)
void dormqr_(char *, char *, int *, int *, int *, double *, int *, double *, double *, int *, double *, int *, int *)
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
virtual void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
void Swap(Array< T > &, Array< T > &)
void SetAbsTol(double atol)
PrintLevel print_options
Output behavior for the iterative solver.
double p(const Vector &x, double t)
void SetRelTol(double rtol)
double Control[UMFPACK_CONTROL]
Abstract base class for iterative solver.
void forall(int N, lambda &&body)
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 ...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void subtract(const Vector &x, const Vector &y, Vector &z)
MemoryType
Memory types supported by MFEM.
void SetAdaptiveLinRtol(const int type=2, const double rtol0=0.5, const double rtol_max=0.9, const double alpha=0.5 *(1.0+sqrt(5.0)), const double gamma=1.0)
Enable adaptive linear solver relative tolerance algorithm.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
bool GetConverged() const
Returns true if the last call to Mult() converged successfully.
int max_iter
Limit for the number of iterations the solver is allowed to do.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void AdaptiveLinRtolPostSolve(const Vector &x, const Vector &b, const int it, const double fnorm) const
Method for the adaptive linear solver rtol invoked after the linear solve.
static int GuessLegacyPrintLevel(PrintLevel)
Use some heuristics to guess a legacy print level corresponding to the given PrintLevel.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
double Max() const
Returns the maximal element of the vector.
const int * HostReadI() const
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 NormalizeConstraints(Vector &rhs_lb, Vector &rhs_ub) const
double InnerProduct(HypreParVector *x, HypreParVector *y)
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
double rel_tol
Relative tolerance.
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)
virtual void Mult(const Vector &xt, Vector &x) const
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
AuxSpaceSmoother(const HypreParMatrix &op, HypreParMatrix *aux_map, bool op_is_symmetric=true, bool own_aux_map=false)
void SetOperator(const Operator &op)
Recompute the diagonal using the method AssembleDiagonal of the given new Operator, op.
void GeneratePlaneRotation(double &dx, double &dy, double &cs, double &sn)
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
virtual void AssembleDiagonal(Vector &diag) const
Computes the diagonal entries into diag. Typically, this operation only makes sense for linear Operat...
PrintLevel FromLegacyPrintLevel(int)
Convert a legacy print level integer to a PrintLevel object.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
double Norml2() const
Returns the l2 norm of the vector.
double Dot(const Vector &x, const Vector &y) const
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
int Size() const
Return the logical size of the array.
MPI_Comm GetComm() const
Return the associated MPI communicator, or MPI_COMM_NULL if no communicator is set.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void SetSolver(Solver &s)
Set the solver used by the OrthoSolver.
void Mult(const Vector &b, Vector &x) const
Perform the action of the OrthoSolver: P * solver * P where P is the projection to the subspace of ve...
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)
bool warnings
If a non-fatal problem has been detected some context-specific information will be reported to mfem::...
bool iterations
Detailed information about each iteration will be reported to mfem::out.
void SetOperator(const Operator &op) override
The operator must be a DenseMatrix.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
const OptimizationProblem * problem
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
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...
virtual double ComputeScalingFactor(const Vector &x, const Vector &b) const
This method can be overloaded in derived classes to implement line search algorithms.
Wrapper for hypre's ParCSR matrix class.
void SetBounds(const Vector &lo_, const Vector &hi_)
void AddMult_a(double alpha, const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += alpha * B * C.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
void AdaptiveLinRtolPreSolve(const Vector &x, const int it, const double fnorm) const
Method for the adaptive linear solver rtol invoked before the linear solve.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
IterativeSolverMonitor * monitor
virtual void MonitorResidual(int it, double norm, const Vector &r, bool final)
Monitor the residual vector r.
virtual double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
int width
Dimension of the input / number of columns in the matrix.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Settings for the output behavior of the IterativeSolver.
const Operator * C
Not owned, some can remain unused (NULL).
double abs_tol
Absolute tolerance.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
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.