void MatMult(const FullMatrix& A, const dTensor1& invec, dTensor1& outvec) { for (int i=1; i<=A.get_NumRows(); i++) { int jmax = A.get_NZrow(i); double tmp = 0.0; for (int j=1; j<=jmax; j++) { int ind = A.get_Index(i,j); double val = A.get_Value(i,j); tmp = tmp + val*invec.get(ind); } outvec.set(i, tmp ); } }
void ConstructA_CG2(const mesh& Mesh, FullMatrix& A) { const int NumPhysElems = Mesh.get_NumPhysElems(); const int NumBndNodes = Mesh.get_SubNumBndNodes(); const int Asize = Mesh.get_SubNumPhysNodes(); assert_eq(Asize,A.get_NumRows()); assert_eq(Asize,A.get_NumCols()); dTensor1 A1(6); dTensor1 A2(6); dTensor1 A3(6); dTensor1 A4(6); dTensor1 A5(6); dTensor1 A6(6); A1.set(1, -oneninth ); A1.set(2, 4.0*oneninth ); A1.set(3, -oneninth ); A1.set(4, 4.0*oneninth ); A1.set(5, 4.0*oneninth ); A1.set(6, -oneninth ); A2.set(1, -onethird ); A2.set(2, 0.0 ); A2.set(3, onethird ); A2.set(4, -4.0*onethird ); A2.set(5, 4.0*onethird ); A2.set(6, 0.0 ); A3.set(1, -onethird ); A3.set(2, -4.0*onethird ); A3.set(3, 0.0 ); A3.set(4, 0.0 ); A3.set(5, 4.0*onethird ); A3.set(6, onethird ); A4.set(1, 4.0 ); A4.set(2, -4.0 ); A4.set(3, 0.0 ); A4.set(4, -4.0 ); A4.set(5, 4.0 ); A4.set(6, 0.0 ); A5.set(1, 2.0 ); A5.set(2, -4.0 ); A5.set(3, 2.0 ); A5.set(4, 0.0 ); A5.set(5, 0.0 ); A5.set(6, 0.0 ); A6.set(1, 2.0 ); A6.set(2, 0.0 ); A6.set(3, 0.0 ); A6.set(4, -4.0 ); A6.set(5, 0.0 ); A6.set(6, 2.0 ); dTensor2 spts(3,2); spts.set(1,1, 1.0/3.0 ); spts.set(1,2, -1.0/6.0 ); spts.set(2,1, -1.0/6.0 ); spts.set(2,2, -1.0/6.0 ); spts.set(3,1, -1.0/6.0 ); spts.set(3,2, 1.0/3.0 ); dTensor1 wgts(3); wgts.set(1, 1.0/6.0 ); wgts.set(2, 1.0/6.0 ); wgts.set(3, 1.0/6.0 ); // Loop over all elements in the mesh for (int i=1; i<=NumPhysElems; i++) { // Information for element i iTensor1 tt(6); for (int k=1; k<=6; k++) { tt.set(k, Mesh.get_node_subs(i,k) ); } // Evaluate gradients of the Lagrange polynomials on Gauss quadrature points dTensor2 gpx(6,3); dTensor2 gpy(6,3); for (int m=1; m<=3; m++) { double xi = spts.get(m,1); double eta = spts.get(m,2); for (int k=1; k<=6; k++) { double gp_xi = A2.get(k) + 2.0*A5.get(k)*xi + A4.get(k)*eta; double gp_eta = A3.get(k) + A4.get(k)*xi + 2.0*A6.get(k)*eta; gpx.set(k,m, Mesh.get_jmat(i,1,1)*gp_xi + Mesh.get_jmat(i,1,2)*gp_eta ); gpy.set(k,m, Mesh.get_jmat(i,2,1)*gp_xi + Mesh.get_jmat(i,2,2)*gp_eta ); } } // Entries of the stiffness matrix A double Area = Mesh.get_area_prim(i); for (int j=1; j<=6; j++) for (int k=1; k<=6; k++) { double tmp = A.get(tt.get(j),tt.get(k)); for (int m=1; m<=3; m++) { tmp = tmp + 2.0*Area*wgts.get(m)*(gpx.get(j,m)*gpx.get(k,m)+gpy.get(j,m)*gpy.get(k,m)); } A.set(tt.get(j),tt.get(k), tmp ); } } // Replace boundary node equations by Dirichlet boundary condition enforcement for (int i=1; i<=NumBndNodes; i++) { const int j=Mesh.get_sub_bnd_node(i); for (int k=1; k<=A.get_NumCols(); k++) { A.set(j,k, 0.0 ); } for (int k=1; k<=A.get_NumRows(); k++) { A.set(k,j, 0.0 ); } A.set(j,j, 1.0 ); } // Get sparse structure representation A.Sparsify(); }
void ConjugateGradient(const int MaxIters, const double TOL, const FullMatrix& A, const dTensor1& rhs, dTensor1& phi) { double DotProd(const dTensor1& avec, const dTensor1& bvec); void MatMult(const FullMatrix& A, const dTensor1& invec, dTensor1& outvec); const int size = A.get_NumRows(); int NumIters = 0; int mflag = 0; dTensor1 r(size); dTensor1 d(size); dTensor1 Ad(size); for (int i=1; i<=size; i++) { phi.set(i, 0.0 ); } MatMult(A,phi,r); for (int i=1; i<=size; i++) { r.set(i, rhs.get(i)-r.get(i) ); } for (int i=1; i<=size; i++) { d.set(i, r.get(i) ); } double rhs_norm = sqrt(DotProd(rhs,rhs)); if (fabs(rhs_norm)<=1.0e-12) { rhs_norm = 1.0; } //printf(" rhs_norm = %e\n",rhs_norm); double rdotr = DotProd(r,r); //printf(" sqrt(rdotr) = %e\n",sqrt(rdotr)); double rel_res_norm = sqrt(rdotr)/rhs_norm; if(rel_res_norm < TOL) { mflag = 1; } NumIters = 1; while(mflag==0) { MatMult(A,d,Ad); double alpha = rdotr/DotProd(d,Ad); for (int i=1; i<=size; i++) { phi.set(i, phi.get(i)+alpha*d.get(i) ); } for (int i=1; i<=size; i++) { r.set(i, r.get(i)-alpha*Ad.get(i) ); } double rdotr_old = rdotr; rdotr = DotProd(r,r); rel_res_norm = sqrt(rdotr)/rhs_norm; if(rel_res_norm < TOL) { mflag = 1; } //printf(" NumIters = %i, rel_res_norm = %e\n",NumIters,rel_res_norm); if (NumIters==MaxIters) { mflag = 1; } if (mflag==0) { double beta = rdotr/rdotr_old; for (int i=1; i<=size; i++) { d.set(i, r.get(i)+beta*d.get(i) ); } NumIters = NumIters+1; } } printf(" |----------------------------\n"); printf(" | Conjugate Gradient Results:\n"); printf(" |----------------------------\n"); printf(" | MaxIters = %i\n",MaxIters); printf(" | TOL = %e\n",TOL); printf(" | NumIters = %i\n",NumIters); printf(" | residual = %e\n",rel_res_norm); printf(" |----------------------------\n"); printf("\n"); }