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);
113 Solver(a.FESpace()->GetTrueVSize()),
117 ess_tdof_list(ess_tdofs),
134 ess_tdof_list(ess_tdofs),
143 const double delta = damping;
144 auto D = diag.
Read();
145 auto DI = dinv.
Write();
146 MFEM_FORALL(i, N, DI[i] = delta / D[i]; );
147 auto I = ess_tdof_list.
Read();
148 MFEM_FORALL(i, ess_tdof_list.
Size(), DI[I[i]] =
delta; );
153 MFEM_ASSERT(x.
Size() == N,
"invalid input vector");
154 MFEM_ASSERT(y.
Size() == N,
"invalid output vector");
158 oper->
Mult(y, residual);
167 auto DI = dinv.
Read();
168 auto R = residual.
Read();
170 MFEM_FORALL(i, N, Y[i] += DI[i] * R[i]; );
219 double r0, nom, nom0, nomold = 1, cf;
235 nom0 = nom =
Dot(
z,
r);
239 nom0 = nom =
Dot(
r,
r);
243 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = "
282 cf = sqrt(nom/nomold);
284 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = "
285 << nom <<
"\tConv. rate: " << cf <<
'\n';
291 mfem::out <<
"Number of SLI iterations: " << i <<
'\n'
292 <<
"Conv. rate: " << cf <<
'\n';
294 mfem::out <<
"(B r_0, r_0) = " << nom0 <<
'\n'
295 <<
"(B r_N, r_N) = " << nom <<
'\n'
296 <<
"Number of SLI iterations: " << i <<
'\n';
310 mfem::err <<
"SLI: No convergence!" <<
'\n';
311 mfem::out <<
"(B r_0, r_0) = " << nom0 <<
'\n'
312 <<
"(B r_N, r_N) = " << nom <<
'\n'
313 <<
"Number of SLI iterations: " <<
final_iter <<
'\n';
317 mfem::out <<
"Average reduction factor = "
324 int print_iter,
int max_num_iter,
325 double RTOLERANCE,
double ATOLERANCE)
337 int print_iter,
int max_num_iter,
338 double RTOLERANCE,
double ATOLERANCE)
361 double r0, den, nom, nom0, betanom,
alpha, beta;
383 nom0 = nom =
Dot(
d,
r);
384 MFEM_ASSERT(
IsFinite(nom),
"nom = " << nom);
388 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = "
403 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
408 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = "
438 MFEM_ASSERT(
IsFinite(betanom),
"betanom = " << betanom);
442 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = "
450 mfem::out <<
"Number of PCG iterations: " << i <<
'\n';
454 mfem::out <<
" Iteration : " << setw(3) << i <<
" (B r, r) = "
478 MFEM_ASSERT(
IsFinite(den),
"den = " << den);
483 mfem::out <<
"PCG: The operator is not positive definite. (Ad, d) = "
500 mfem::out <<
" Iteration : " << setw(3) << 0 <<
" (B r, r) = "
506 mfem::out <<
"PCG: No convergence!" <<
'\n';
510 mfem::out <<
"Average reduction factor = "
511 << pow (betanom/nom0, 0.5/
final_iter) <<
'\n';
517 int print_iter,
int max_num_iter,
518 double RTOLERANCE,
double ATOLERANCE)
530 int print_iter,
int max_num_iter,
531 double RTOLERANCE,
double ATOLERANCE)
545 double &cs,
double &sn)
552 else if (fabs(dy) > fabs(dx))
554 double temp = dx / dy;
555 sn = 1.0 / sqrt( 1.0 + temp*temp );
560 double temp = dy / dx;
561 cs = 1.0 / sqrt( 1.0 + temp*temp );
568 double temp = cs * dx + sn * dy;
569 dy = -sn * dx + cs * dy;
579 for (
int i = k; i >= 0; i--)
582 for (
int j = i - 1; j >= 0; j--)
584 y(j) -= h(j,i) * y(i);
588 for (
int j = 0; j <= k; j++)
641 double beta =
Norm(r);
642 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
657 <<
" Iteration : " << setw(3) << 0
658 <<
" ||B r|| = " << beta << (
print_level == 3 ?
" ...\n" :
"\n");
665 if (v[0] == NULL) { v[0] =
new Vector(n); }
666 v[0]->Set(1.0/beta, r);
667 s = 0.0; s(0) = beta;
669 for (i = 0; i <
m && j <=
max_iter; i++, j++)
681 for (k = 0; k <= i; k++)
683 H(k,i) =
Dot(w, *v[k]);
684 w.
Add(-H(k,i), *v[k]);
688 MFEM_ASSERT(
IsFinite(H(i+1,i)),
"Norm(w) = " << H(i+1,i));
689 if (v[i+1] == NULL) { v[i+1] =
new Vector(n); }
690 v[i+1]->Set(1.0/H(i+1,i), w);
692 for (k = 0; k < i; k++)
701 resid = fabs(s(i+1));
702 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
715 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
716 <<
" Iteration : " << setw(3) << j
717 <<
" ||B r|| = " << resid <<
'\n';
739 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
768 for (i = 0; i < v.
Size(); i++)
793 double beta =
Norm(r);
794 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
809 <<
" Iteration : " << setw(3) << 0
810 <<
" || r || = " << beta << endl;
815 for (i= 0; i<=
m; i++)
824 if (v[0] == NULL) { v[0] =
new Vector(b.
Size()); }
826 v[0] ->
Add (1.0/beta, r);
827 s = 0.0; s(0) = beta;
829 for (i = 0; i <
m && j <=
max_iter; i++, j++)
832 if (z[i] == NULL) { z[i] =
new Vector(b.
Size()); }
845 for (k = 0; k <= i; k++)
847 H(k,i) =
Dot( r, *v[k]);
848 r.Add(-H(k,i), (*v[k]));
852 if (v[i+1] == NULL) { v[i+1] =
new Vector(b.
Size()); }
854 v[i+1] ->
Add (1.0/H(i+1,i), r);
856 for (k = 0; k < i; k++)
865 double resid = fabs(s(i+1));
866 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
869 mfem::out <<
" Pass : " << setw(2) << (j-1)/
m+1
870 <<
" Iteration : " << setw(3) << j
871 <<
" || r || = " << resid << endl;
886 for (i= 0; i<=
m; i++)
888 if (v[i]) {
delete v[i]; }
889 if (z[i]) {
delete z[i]; }
905 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
917 for (i= 0; i<=
m; i++)
919 if (v[i]) {
delete v[i]; }
920 if (z[i]) {
delete z[i]; }
926 for (i = 0; i <=
m; i++)
928 if (v[i]) {
delete v[i]; }
929 if (z[i]) {
delete z[i]; }
935 mfem::out <<
"FGMRES: No convergence!" << endl;
943 int &max_iter,
int m,
double &tol,
double atol,
int printit)
960 int print_iter,
int max_num_iter,
int m,
double rtol,
double atol)
962 GMRES(A, x, b, B, max_num_iter, m, rtol, atol, print_iter);
984 double resid, tol_goal;
985 double rho_1, rho_2=1.0,
alpha=1.0, beta, omega=1.0;
1000 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1002 mfem::out <<
" Iteration : " << setw(3) << 0
1003 <<
" ||r|| = " << resid <<
'\n';
1007 if (resid <= tol_goal)
1021 mfem::out <<
" Iteration : " << setw(3) << i
1022 <<
" ||r|| = " << resid <<
'\n';
1034 beta = (rho_1/rho_2) * (
alpha/omega);
1050 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1051 if (resid < tol_goal)
1055 mfem::out <<
" Iteration : " << setw(3) << i
1056 <<
" ||s|| = " << resid <<
'\n';
1063 mfem::out <<
" Iteration : " << setw(3) << i
1064 <<
" ||s|| = " << resid;
1081 MFEM_ASSERT(
IsFinite(resid),
"resid = " << resid);
1084 mfem::out <<
" ||r|| = " << resid <<
'\n';
1086 if (resid < tol_goal)
1108 int &max_iter,
double &tol,
double atol,
int printit)
1117 bicgstab.
Mult(b, x);
1124 int print_iter,
int max_num_iter,
double rtol,
double atol)
1126 BiCGSTAB(A, x, b, B, max_num_iter, rtol, atol, print_iter);
1152 double beta, eta, gamma0, gamma1, sigma0, sigma1;
1153 double alpha,
delta, rho1, rho2, rho3, norm_goal;
1173 eta = beta = sqrt(
Dot(*z,
v1));
1174 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1175 gamma0 = gamma1 = 1.;
1176 sigma0 = sigma1 = 0.;
1180 if (eta <= norm_goal)
1188 mfem::out <<
"MINRES: iteration " << setw(3) << 0 <<
": ||r||_B = "
1201 MFEM_ASSERT(
IsFinite(alpha),
"alpha = " << alpha);
1208 delta = gamma1*alpha - gamma0*sigma1*beta;
1210 rho2 = sigma1*alpha + gamma0*gamma1*beta;
1220 MFEM_ASSERT(
IsFinite(beta),
"beta = " << beta);
1221 rho1 = hypot(delta, beta);
1225 w0.
Set(1./rho1, *z);
1229 add(1./rho1, *z, -rho2/rho1,
w1,
w0);
1233 add(-rho3/rho1,
w0, -rho2/rho1,
w1,
w0);
1234 w0.
Add(1./rho1, *z);
1238 gamma1 = delta/rho1;
1240 x.
Add(gamma1*eta,
w0);
1246 MFEM_ASSERT(
IsFinite(eta),
"eta = " << eta);
1248 if (fabs(eta) <= norm_goal)
1255 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = "
1256 << fabs(eta) <<
'\n';
1291 eta = sqrt(
Dot(*z,
v1));
1292 mfem::out <<
"MINRES: iteration " << setw(3) << it <<
": ||r||_B = "
1293 << eta <<
" (re-computed)" <<
'\n';
1298 mfem::out <<
"MINRES: No convergence!\n";
1303 int max_it,
double rtol,
double atol)
1315 int print_it,
int max_it,
double rtol,
double atol)
1333 MFEM_ASSERT(
height ==
width,
"square Operator is required.");
1341 MFEM_ASSERT(
oper != NULL,
"the Operator is not set (use SetOperator).");
1342 MFEM_ASSERT(
prec != NULL,
"the Solver is not set (use SetSolver).");
1345 double norm0, norm, norm_goal;
1359 norm0 = norm =
Norm(
r);
1365 for (it = 0;
true; it++)
1367 MFEM_ASSERT(
IsFinite(norm),
"norm = " << norm);
1370 mfem::out <<
"Newton iteration " << setw(2) << it
1371 <<
" : ||r|| = " << norm;
1374 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
1379 if (norm <= norm_goal)
1401 add(x, -c_scale,
c, x);
1420 int m_max,
int m_min,
int m_step,
double cf,
1421 double &tol,
double &atol,
int printit)
1428 Vector s(m+1), cs(m+1), sn(m+1);
1435 double normb = w.Norml2();
1445 double beta = r.
Norml2();
1447 resid = beta / normb;
1449 if (resid * resid <= tol)
1451 tol = resid * resid;
1458 <<
" Iteration : " << setw(3) << 0
1459 <<
" (r, r) = " << beta*beta <<
'\n';
1461 tol *= (normb*normb);
1462 tol = (atol > tol) ? atol : tol;
1466 for (i= 0; i<=m; i++)
1473 while (j <= max_iter)
1476 v[0] ->
Add (1.0/beta, r);
1477 s = 0.0; s(0) = beta;
1481 for (i = 0; i < m && j <= max_iter; i++)
1486 for (k = 0; k <= i; k++)
1488 H(k,i) = w * (*v[k]);
1489 w.
Add(-H(k,i), (*v[k]));
1492 H(i+1,i) = w.Norml2();
1494 v[i+1] ->
Add (1.0/H(i+1,i), w);
1496 for (k = 0; k < i; k++)
1505 resid = fabs(s(i+1));
1508 <<
" Iteration : " << setw(3) << i+1
1509 <<
" (r, r) = " << resid*resid <<
'\n';
1511 if ( resid*resid < tol)
1514 tol = resid * resid;
1516 for (i= 0; i<=m; i++)
1535 if ( resid*resid < tol)
1537 tol = resid * resid;
1539 for (i= 0; i<=m; i++)
1548 if (m - m_step >= m_min)
1561 tol = resid * resid;
1562 for (i= 0; i<=m; i++)
1572 : C(C_), D(D_), c_e(NULL), d_lo(NULL), d_hi(NULL), x_lo(NULL), x_hi(NULL),
1581 MFEM_ASSERT(
C,
"The C operator is unspecified -- can't set constraints.");
1582 MFEM_ASSERT(c.
Size() ==
C->
Height(),
"Wrong size of the constraint.");
1590 MFEM_ASSERT(
D,
"The D operator is unspecified -- can't set constraints.");
1592 "Wrong size of the constraint.");
1600 "Wrong size of the constraint.");
1617 MFEM_WARNING(
"Objective functional is ignored as SLBQP always minimizes"
1618 "the l2 norm of (x - x_target).");
1620 MFEM_ASSERT(prob.
GetC(),
"Linear constraint is not set.");
1621 MFEM_ASSERT(prob.
GetC()->
Height() == 1,
"Solver expects scalar constraint.");
1641 mfem::out <<
"SLBQP iteration " << it <<
": residual = " << r
1642 <<
", lambda = " << l <<
'\n';
1664 const double smin = 0.1;
1671 mfem::out <<
"SLBQP bracketing phase" <<
'\n';
1675 r =
solve(l,xt,x,nclip);
1689 llow = l; rlow = r; l = l + dl;
1692 r =
solve(l,xt,x,nclip);
1695 while ((r < 0) && (nclip <
max_iter))
1699 if (s < smin) { s = smin; }
1704 r =
solve(l,xt,x,nclip);
1712 lupp = l; rupp = r; l = l - dl;
1715 r =
solve(l,xt,x,nclip);
1718 while ((r > 0) && (nclip <
max_iter))
1722 if (s < smin) { s = smin; }
1727 r =
solve(l,xt,x,nclip);
1740 mfem::out <<
"SLBQP secant phase" <<
'\n';
1743 s = 1.0 - rlow/rupp; dl = dl/s; l = lupp - dl;
1746 r =
solve(l,xt,x,nclip);
1749 while ( (fabs(r) > tol) && (nclip <
max_iter) )
1755 lupp = l; rupp = r; s = 1.0 - rlow/rupp;
1756 dl = (lupp - llow)/s; l = lupp - dl;
1761 if (s < smin) { s = smin; }
1763 lnew = 0.75*llow + 0.25*l;
1764 if (lnew < l-dl) { lnew = l-dl; }
1765 lupp = l; rupp = r; l = lnew;
1766 s = (lupp - llow)/(lupp - l);
1774 llow = l; rlow = r; s = 1.0 - rlow/rupp;
1775 dl = (lupp - llow)/s; l = lupp - dl;
1780 if (s < smin) { s = smin; }
1782 lnew = 0.75*lupp + 0.25*l;
1783 if (lnew < l+dl) { lnew = l+dl; }
1784 llow = l; rlow = r; l = lnew;
1785 s = (lupp - llow)/(lupp - l);
1790 r =
solve(l,xt,x,nclip);
1799 mfem::err <<
"SLBQP not converged!" <<
'\n';
1809 mfem::out <<
"SLBQP iterations = " << nclip <<
'\n';
1810 mfem::out <<
"SLBQP lambda = " << l <<
'\n';
1811 mfem::out <<
"SLBQP residual = " << r <<
'\n';
1815 struct WeightMinHeap
1817 const std::vector<double> &w;
1818 std::vector<size_t> c;
1819 std::vector<int> loc;
1821 WeightMinHeap(
const std::vector<double> &w_) : w(w_)
1823 c.reserve(w.size());
1824 loc.resize(w.size());
1825 for (
size_t i=0; i<w.size(); ++i) { push(i); }
1828 size_t percolate_up(
size_t pos,
double val)
1830 for (; pos > 0 && w[c[(pos-1)/2]] > val; pos = (pos-1)/2)
1832 c[pos] = c[(pos-1)/2];
1833 loc[c[(pos-1)/2]] = pos;
1838 size_t percolate_down(
size_t pos,
double val)
1840 while (2*pos+1 < c.size())
1842 size_t left = 2*pos+1;
1843 size_t right = left+1;
1845 if (right < c.size() && w[c[right]] < w[c[left]]) { tgt = right; }
1846 else { tgt = left; }
1847 if (w[c[tgt]] < val)
1865 size_t pos = c.size()-1;
1866 pos = percolate_up(pos, val);
1874 size_t j = c.back();
1878 if (c.empty()) {
return i; }
1881 pos = percolate_down(pos, val);
1887 void update(
size_t i)
1889 size_t pos = loc[i];
1891 pos = percolate_up(pos, val);
1892 pos = percolate_down(pos, val);
1897 bool picked(
size_t i)
1912 for (
int i=0; i<n; ++i)
1914 for (
int j=I[i]; j<I[i+1]; ++j)
1916 V[j] = abs(V[j]/D[i]);
1920 std::vector<double> w(n, 0.0);
1922 for (
int k=0; k<n; ++k)
1924 for (
int ii=I[k]; ii<I[k+1]; ++ii)
1926 double C_ki = V[ii];
1927 for (
int jj=I[k]; jj<I[k+1]; ++jj)
1929 if (jj == ii) {
continue; }
1930 double C_jk = V[jj];
1931 w[k] += pow(C_jk*C_ki, 2);
1937 WeightMinHeap w_heap(w);
1941 for (
int i=0; i<n; ++i)
1943 int pi = w_heap.pop();
1946 for (
int kk=I[pi]; kk<I[pi+1]; ++kk)
1949 if (w_heap.picked(k)) {
continue; }
1952 for (
int ii=I[k]; ii<I[k+1]; ++ii)
1954 if (w_heap.picked(J[ii])) {
continue; }
1955 double C_ki = V[ii];
1956 for (
int jj=I[k]; jj<I[k+1]; ++jj)
1958 if (jj == ii || w_heap.picked(J[jj])) {
continue; }
1959 double C_jk = V[jj];
1960 w[k] += pow(C_jk*C_ki, 2);
1973 block_size(block_size_),
1975 reordering(reordering_)
1982 :
BlockILU(block_size_, reordering_, k_fill_)
2004 MFEM_ABORT(
"BlockILU must be created with a SparseMatrix or HypreParMatrix");
2009 MFEM_ASSERT(A->
Finalized(),
"Matrix must be finalized.");
2010 CreateBlockPattern(*A);
2014 void BlockILU::CreateBlockPattern(
const SparseMatrix &A)
2016 MFEM_VERIFY(k_fill == 0,
"Only block ILU(0) is currently supported.");
2017 if (A.
Height() % block_size != 0)
2019 MFEM_ABORT(
"BlockILU: block size must evenly divide the matrix size");
2023 const int *I = A.
GetI();
2024 const int *J = A.
GetJ();
2025 const double *V = A.
GetData();
2027 int nblockrows = nrows / block_size;
2029 std::vector<std::set<int>> unique_block_cols(nblockrows);
2031 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2033 for (
int bi = 0; bi < block_size; ++bi)
2035 int i = iblock * block_size + bi;
2036 for (
int k = I[i]; k < I[i + 1]; ++k)
2038 unique_block_cols[iblock].insert(J[k] / block_size);
2041 nnz += unique_block_cols[iblock].size();
2046 SparseMatrix C(nblockrows, nblockrows);
2047 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2049 for (
int jblock : unique_block_cols[iblock])
2051 for (
int bi = 0; bi < block_size; ++bi)
2053 int i = iblock * block_size + bi;
2054 for (
int k = I[i]; k < I[i + 1]; ++k)
2057 if (j >= jblock * block_size && j < (jblock + 1) * block_size)
2059 C.Add(iblock, jblock, V[k]*V[k]);
2066 double *CV = C.GetData();
2067 for (
int i=0; i<C.NumNonZeroElems(); ++i)
2069 CV[i] = sqrt(CV[i]);
2078 MFEM_ABORT(
"BlockILU: unknown reordering")
2085 for (
int i=0; i<nblockrows; ++i)
2093 for (
int i=0; i<nblockrows; ++i)
2099 std::vector<std::vector<int>> unique_block_cols_perminv(nblockrows);
2100 for (
int i=0; i<nblockrows; ++i)
2102 std::vector<int> &cols = unique_block_cols_perminv[i];
2103 for (
int j : unique_block_cols[P[i]])
2105 cols.push_back(Pinv[j]);
2107 std::sort(cols.begin(), cols.end());
2114 AB.
SetSize(block_size, block_size, nnz);
2115 DB.
SetSize(block_size, block_size, nblockrows);
2118 ipiv.
SetSize(block_size*nblockrows);
2121 for (
int iblock = 0; iblock < nblockrows; ++iblock)
2123 int iblock_perm = P[iblock];
2124 for (
int jblock : unique_block_cols_perminv[iblock])
2126 int jblock_perm = P[jblock];
2127 if (iblock == jblock)
2129 ID[iblock] = counter;
2131 JB[counter] = jblock;
2132 for (
int bi = 0; bi < block_size; ++bi)
2134 int i = iblock_perm*block_size + bi;
2135 for (
int k = I[i]; k < I[i + 1]; ++k)
2138 if (j >= jblock_perm*block_size && j < (jblock_perm + 1)*block_size)
2140 int bj = j - jblock_perm*block_size;
2142 AB(bi, bj, counter) = val;
2144 if (iblock == jblock)
2146 DB(bi, bj, iblock) = val;
2153 IB[iblock + 1] = counter;
2157 void BlockILU::Factorize()
2159 int nblockrows =
Height()/block_size;
2162 for (
int i=0; i<nblockrows; ++i)
2164 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2165 factorization.Factor(block_size);
2171 DenseMatrix A_ik, A_ij, A_kj;
2173 for (
int i=1; i<nblockrows; ++i)
2176 for (
int kk=IB[i]; kk<IB[i+1]; ++kk)
2180 if (k == i) {
break; }
2183 MFEM_ABORT(
"Matrix must be sorted with nonzero diagonal");
2185 LUFactors A_kk_inv(DB.
GetData(k), &ipiv[k*block_size]);
2186 A_ik.UseExternalData(&AB(0,0,kk), block_size, block_size);
2188 A_kk_inv.RightSolve(block_size, block_size, A_ik.GetData());
2190 for (
int jj=kk+1; jj<IB[i+1]; ++jj)
2193 if (j <= k) {
continue; }
2194 A_ij.UseExternalData(&AB(0,0,jj), block_size, block_size);
2195 for (
int ll=IB[k]; ll<IB[k+1]; ++ll)
2200 A_kj.UseExternalData(&AB(0,0,ll), block_size, block_size);
2207 LUFactors factorization(DB.
GetData(i), &ipiv[i*block_size]);
2208 factorization.Factor(block_size);
2220 MFEM_ASSERT(
height > 0,
"BlockILU(0) preconditioner is not constructed");
2221 int nblockrows =
Height()/block_size;
2230 for (
int i=0; i<nblockrows; ++i)
2233 for (
int ib=0; ib<block_size; ++ib)
2235 yi[ib] = b[ib + P[i]*block_size];
2237 for (
int k=IB[i]; k<ID[i]; ++k)
2247 for (
int i=nblockrows-1; i >= 0; --i)
2250 for (
int ib=0; ib<block_size; ++ib)
2252 xi[ib] = y[ib + i*block_size];
2254 for (
int k=ID[i]+1; k<IB[i+1]; ++k)
2262 LUFactors A_ii_inv(&DB(0,0,i), &ipiv[i*block_size]);
2264 A_ii_inv.
Solve(block_size, 1, xi);
2268 #ifdef MFEM_USE_SUITESPARSE
2295 umfpack_di_free_numeric(&
Numeric);
2299 umfpack_dl_free_numeric(&
Numeric);
2304 MFEM_VERIFY(
mat,
"not a SparseMatrix");
2313 MFEM_VERIFY(
width ==
height,
"not a square matrix");
2321 int status = umfpack_di_symbolic(
width,
width, Ap, Ai, Ax, &Symbolic,
2326 umfpack_di_report_status(
Control, status);
2328 " umfpack_di_symbolic() failed!");
2331 status = umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &
Numeric,
2336 umfpack_di_report_status(
Control, status);
2338 " umfpack_di_numeric() failed!");
2340 umfpack_di_free_symbolic(&Symbolic);
2344 SuiteSparse_long status;
2348 AI =
new SuiteSparse_long[
width + 1];
2349 AJ =
new SuiteSparse_long[Ap[
width]];
2350 for (
int i = 0; i <=
width; i++)
2352 AI[i] = (SuiteSparse_long)(Ap[i]);
2354 for (
int i = 0; i < Ap[
width]; i++)
2356 AJ[i] = (SuiteSparse_long)(Ai[i]);
2359 status = umfpack_dl_symbolic(
width,
width,
AI,
AJ, Ax, &Symbolic,
2364 umfpack_dl_report_status(
Control, status);
2366 " umfpack_dl_symbolic() failed!");
2369 status = umfpack_dl_numeric(
AI,
AJ, Ax, Symbolic, &
Numeric,
2374 umfpack_dl_report_status(
Control, status);
2376 " umfpack_dl_numeric() failed!");
2378 umfpack_dl_free_symbolic(&Symbolic);
2385 mfem_error(
"UMFPackSolver::Mult : matrix is not set!"
2386 " Call SetOperator first!");
2393 umfpack_di_report_info(Control,
Info);
2396 umfpack_di_report_status(Control, status);
2397 mfem_error(
"UMFPackSolver::Mult : umfpack_di_solve() failed!");
2402 SuiteSparse_long status =
2405 umfpack_dl_report_info(Control,
Info);
2408 umfpack_dl_report_status(Control, status);
2409 mfem_error(
"UMFPackSolver::Mult : umfpack_dl_solve() failed!");
2417 mfem_error(
"UMFPackSolver::MultTranspose : matrix is not set!"
2418 " Call SetOperator first!");
2425 umfpack_di_report_info(Control,
Info);
2428 umfpack_di_report_status(Control, status);
2430 " umfpack_di_solve() failed!");
2435 SuiteSparse_long status =
2438 umfpack_dl_report_info(Control,
Info);
2441 umfpack_dl_report_status(Control, status);
2443 " umfpack_dl_solve() failed!");
2456 umfpack_di_free_numeric(&
Numeric);
2460 umfpack_dl_free_numeric(&
Numeric);
2475 "Had Numeric pointer in KLU, but not Symbolic");
2483 MFEM_VERIFY(
mat != NULL,
"not a SparseMatrix");
2491 MFEM_VERIFY(
width ==
height,
"not a square matrix");
2503 MFEM_VERIFY(
mat != NULL,
2504 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
2517 MFEM_VERIFY(
mat != NULL,
2518 "KLUSolver::Mult : matrix is not set! Call SetOperator first!");
2537 #endif // MFEM_USE_SUITESPARSE
void ApplyPlaneRotation(double &dx, double &dy, double &cs, double &sn)
int Size() const
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
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void SetSize(int s)
Resize the vector to size s.
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 ...
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.
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).
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(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
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.
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
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)
void SetRelTol(double rtol)
double Control[UMFPACK_CONTROL]
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 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 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
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...
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.
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.