//---------------------------------------------------------------------- // // //Note this needs to be changed for non-zero k-points! doublevar Average_ekt::gen_sample(int nstep, doublevar tstep, int e, Array2 <dcomplex> & movals, Sample_point * sample) { int ndim=3; Array1 <doublevar> r(ndim),rold(ndim); Array2 <dcomplex> movals_old(nmo,1); movals.Resize(nmo,1); sample->getElectronPos(e,rold); calc_mos(sample,e,movals_old); doublevar acc=0; for(int step=0; step < nstep; step++) { for(int d=0; d< ndim; d++) { r(d)=rold(d)+sqrt(tstep)*rng.gasdev(); } sample->setElectronPos(e,r); calc_mos(sample,e,movals); doublevar sum_old=0,sum=0; for(int mo=0; mo < nmo; mo++) { sum_old+=norm(movals_old(mo,0)); sum+=norm(movals(mo,0)); } if(rng.ulec() < sum/sum_old) { movals_old=movals; rold=r; acc++; } } //cout << "acceptance " << acc/nstep << endl; movals=movals_old; sample->setElectronPos(e,rold); doublevar sum=0; for(int mo=0; mo < nmo; mo++) { sum+=norm(movals(mo,0)); } return sum; }
Matrix<double> sparse_bicgstab(SpMatrix* A, Matrix<double> b, Matrix<double> xold, double tol, int maxiter) // Solves general linear system Ax=b using stabilized biconjugate gradient method of van der Vorst { Matrix<double> rold(b.rows(), 1); Matrix<double> r(b.rows(), 1); Matrix<double> rhat(b.rows(), 1); Matrix<double> t(b.rows(), 1); Matrix<double> vold(b.rows(), 1); Matrix<double> v(b.rows(), 1); Matrix<double> pold(b.rows(), 1); Matrix<double> p(b.rows(), 1); Matrix<double> s(b.rows(), 1); Matrix<double> errdiff(b.rows(), 1); Matrix<double> x(b.rows(), 1); double rhoold, rho, wold, w, alpha, beta; double error, initres; A->multiply(xold, &t); // t = A*xold, initially (t is only a temp variable here) rold = b - t; initres = error = rold.l2norm(); int steps = 0; int i; vold.zeros(); pold.zeros(); rhat = rold; rhoold = alpha = wold = 1.0; while(error > tol && steps <= maxiter) { if(steps % 10 == 0 || steps == 1) cout << "sparse_bicgstab(): Iteration " << steps << ": relative error = " << error << endl; rho = rhat.dot_product(rold); beta = rho*alpha/(rhoold*wold); for(i = 0; i < b.rows(); i++) p(i) = rold.get(i) + beta * (pold.get(i) - wold*vold.get(i)); A->multiply(p, &v); // v = A*p alpha = rho / rhat.dot_product(v); for(i = 0; i < b.rows(); i++) s(i) = rold.get(i) - alpha*v.get(i); if(s.dabsmax() < tol*tol) { x = xold + p*alpha; break; } A->multiply(s, &t); // t = A*s w = t.dot_product(s)/t.dot_product(t); for(i = 0; i < b.rows(); i++) { x(i) = xold.get(i) + alpha*p.get(i) + w*s.get(i); error += (x.get(i) - xold.get(i)) * (x.get(i)-xold.get(i)); } error = sqrt(error); for(i = 0; i < b.rows(); i++) r(i) = s.get(i) - w*t.get(i); for(i = 0; i < b.rows(); i++) { xold(i) = x.get(i); rold(i) = r.get(i); vold(i) = v.get(i); pold(i) = p.get(i); } rhoold = rho; wold = w; steps++; } cout << "sparse_bicgstab(): Done. Iterations: " << steps << ", final relative error: " << error << endl; return x; }
Matrix<double> sparsePCG(SpMatrix* A, Matrix<double> b, Matrix<double> xold, string precon, double tol, int maxiter) /* Calculates solution of Ax=b where A is a SPD matrix in sparse format. The preconditioner is supplied by a function pointer.*/ { cout << "sparsePCG(): Solving " << A->rows() << "x" << A->cols() << " system by conjugate gradient method with diagonal preconditioner\n"; void (*precond)(SpMatrix* lhs, const Matrix<double>& r, Matrix<double>& z); //const Matrix<double>& z_initial, if(precon == "jacobi") precond = &precon_jacobi; else if(precon == "lusgs") precond = &precon_lusgs; // check //if(A->rows() != b.rows() || A->rows() != xold.rows()) cout << "sparseCG_d(): ! Mismatch in number of rows!!" << endl; Matrix<double> x(A->rows(),1); // solution vector Matrix<double> M(A->rows(), 1); // diagonal preconditioner, or soon, inverse of preconditioner Matrix<double> rold(A->rows(),1); // initial residual = b - A*xold Matrix<double> r(A->rows(),1); // residual = b - A*x Matrix<double> z(A->rows(),1); Matrix<double> zold(A->rows(),1); Matrix<double> p(A->rows(),1); Matrix<double> pold(A->rows(),1); Matrix<double> temp(A->rows(),1); Matrix<double> diff(A->rows(),1); double temp1, temp2; double theta; double beta; double error = 1.0; double initres; //cout << "sparseCG_d(): Declared everything" << endl; //M.ones(); // disable preconditioner //cout << "sparseCG_d(): preconditioner enabled" << endl; A->multiply(xold, &temp); // temp := A*xold rold = b - temp; error = initres = rold.l2norm(); // initial residue if(error < tol) { cout << "sparsePCG(): Initial residual is very small. Nothing to do." << endl; //x.zeros(); return xold; } for(int i = 0; i < A->rows(); i++) //zold(i) = M(i)*rold(i); // zold = M*rold zold(i) = rold(i); pold = zold; int steps = 0; do { if(steps % 10 == 0 || steps == 1) cout << "sparsePCG(): Iteration " << steps << ", relative residual = " << error << endl; int i; temp1 = rold.dot_product(zold); A->multiply(pold, &temp); //temp.mprint(); temp2 = pold.dot_product(temp); if(temp2 <= 0) cout << "sparsePCG: ! Matrix A is not positive-definite!! temp2 is " << temp2 << "\n"; theta = temp1/temp2; //#pragma omp parallel for default(none) private(i) shared(x,r,xold,rold,pold,temp,theta) //num_threads(nthreads_linalg) for(i = 0; i < x.rows(); i++) { //cout << "Number of threads " << omp_get_num_threads(); x(i) = xold.get(i) + pold.get(i)*theta; rold(i) = rold.get(i) - temp.get(i)*theta; //diff(i) = x(i) - xold(i); } //cout << "x:\n"; x.mprint(); //cout << "r:\n"; r.mprint(); if(steps > 5) { // calculate zold as (M^-1)*rold precond(A, rold, zold); } else { //#pragma omp parallel for default(none) private(i) shared(zold,M,rold,A) for(i = 0; i < A->rows(); i++) zold(i) = rold(i); } beta = rold.dot_product(zold) / temp1; //#pragma omp parallel for default(none) private(i) shared(zold,x,p,pold,beta) for(i = 0; i < x.rows(); i++) pold(i) = zold.get(i) + pold.get(i)*beta; //calculate ||b - A*x|| error = rold.l2norm(); //calculate ||x - xold|| //error = diff.l2norm(); //if(steps == 0) initres = error; // set old variables xold = x; /*rold = r; zold = z; pold = p;*/ if(steps > maxiter) { cout << "! sparsePCG(): Max iterations reached!\n"; break; } steps++; } while(error > tol); cout << "sparsePCG(): Done. Number of iterations: " << steps << "; final residual " << error << ".\n"; return xold; }