void Quad10_2D_SUPG :: giveLocalVelocityDofMap(IntArray &map) { map.enumerate(8); }
NM_Status InverseIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) { FILE *outStream; if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } SparseLinearSystemNM *solver = GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel); int nn = a.giveNumberOfColumns(); int nc = min(2 * nroot, nroot + 8); nc = min(nc, nn); //// control of diagonal zeroes in mass matrix, to be avoided //int i; //for (i = 1; i <= nn; i++) { // if (b.at(i, i) == 0) { // b.at(i, i) = 1.0e-12; // } //} FloatArray w(nc), ww(nc), t; std :: vector< FloatArray > z(nc, nn), zz(nc, nn), x(nc, nn); outStream = domain->giveEngngModel()->giveOutputStream(); /* initial setting */ #if 0 ww.add(1.0); for ( int j = 0; j < nc; j++ ) { z[j].add(1.0); } #else { FloatArray ad(nn), bd(nn); for (int i = 1; i <= nn; i++) { ad.at(i) = fabs(a.at(i, i)); bd.at(i) = fabs(b.at(i, i)); } IntArray order; order.enumerate(nn); std::sort(order.begin(), order.end(), [&ad, &bd](int a, int b) { return bd.at(a) * ad.at(b) > bd.at(b) * ad.at(a); }); for (int i = 0; i < nc; i++) { x[i].at(order[i]) = 1.0; b.times(x[i], z[i]); ww.at(i + 1) = z[i].dotProduct(x[i]); } } #endif int it; for ( it = 0; it < nitem; it++ ) { /* copy zz=z */ for ( int j = 0; j < nc; j++ ) { zz[j] = z[j]; } /* solve matrix equation K.X = M.X */ for ( int j = 0; j < nc; j++ ) { solver->solve(a, z[j], x[j]); } /* evaluation of Rayleigh quotients */ for ( int j = 0; j < nc; j++ ) { w.at(j + 1) = zz[j].dotProduct(x[j]); } for ( int j = 0; j < nc; j++ ) { b.times(x[j], z[j]); } for ( int j = 0; j < nc; j++ ) { w.at(j + 1) /= z[j].dotProduct(x[j]); } /* check convergence */ int ac = 0; for ( int j = 1; j <= nc; j++ ) { if ( fabs( ww.at(j) - w.at(j) ) <= fabs( w.at(j) * rtol ) ) { ac++; } ww.at(j) = w.at(j); } //printf ("\n iteration %d %d",it,ac); //w.printYourself(); /* Gramm-Schmidt ortogonalization */ for ( int j = 0; j < nc; j++ ) { if ( j != 0 ) { b.times(x[j], t); } for ( int ii = 0; ii < j; ii++ ) { x[j].add( -x[ii].dotProduct(t), x[ii] ); } b.times(x[j], t); x[j].times( 1.0 / sqrt( x[j].dotProduct(t) ) ); } if ( ac > nroot ) { break; } /* compute new approximation of Z */ for ( int j = 0; j < nc; j++ ) { b.times(x[j], z[j]); } } // copy results IntArray order; order.enumerate(w.giveSize()); std :: sort(order.begin(), order.end(), [&w](int a, int b) { return w.at(a) < w.at(b); }); _eigv.resize(nroot); _r.resize(nn, nroot); for ( int i = 1; i <= nroot; i++ ) { _eigv.at(i) = w.at(order.at(i)); _r.setColumn(x[order.at(i) - 1], i); } if ( it < nitem ) { fprintf(outStream, "InverseIteration :: convergence reached in %d iterations\n", it); } else { fprintf(outStream, "InverseIteration :: convergence not reached after %d iterations\n", it); } return NM_Success; }