NM_Status SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) // // this function solve the generalized eigenproblem using the Generalized // jacobi iteration // { if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } FloatArray temp, w, d, tt, f, rtolv, eigv; FloatMatrix r; int nn, nc1, ij = 0, is; double rt, art, brt, eigvt; FloatMatrix ar, br, vec; std :: unique_ptr< SparseLinearSystemNM > solver( GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel) ); GJacobi mtd(domain, engngModel); int nc = min(2 * nroot, nroot + 8); nn = a.giveNumberOfColumns(); if ( nc > nn ) { nc = nn; } ar.resize(nc, nc); ar.zero(); br.resize(nc, nc); br.zero(); // // creation of initial iteration vectors // nc1 = nc - 1; w.resize(nn); w.zero(); d.resize(nc); d.zero(); tt.resize(nn); tt.zero(); rtolv.resize(nc); rtolv.zero(); vec.resize(nc, nc); vec.zero(); // eigen vectors of reduced problem // // create work arrays // r.resize(nn, nc); r.zero(); eigv.resize(nc); eigv.zero(); FloatArray h(nn); for ( int i = 1; i <= nn; i++ ) { h.at(i) = 1.0; w.at(i) = b.at(i, i) / a.at(i, i); } b.times(h, tt); r.setColumn(tt, 1); for ( int j = 2; j <= nc; j++ ) { rt = 0.0; for ( int i = 1; i <= nn; i++ ) { if ( fabs( w.at(i) ) >= rt ) { rt = fabs( w.at(i) ); ij = i; } } tt.at(j) = ij; w.at(ij) = 0.; for ( int i = 1; i <= nn; i++ ) { if ( i == ij ) { h.at(i) = 1.0; } else { h.at(i) = 0.0; } } b.times(h, tt); r.setColumn(tt, j); } // (r = z) # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Degrees of freedom invoked by initial vectors :\n"); tt.printYourself(); OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: initial vectors for iteration:\n"); r.printYourself(); # endif //ish = 0; a.factorized(); // // start of iteration loop // for ( int nite = 0; ; ++nite ) { // label 100 # ifdef DETAILED_REPORT printf("SubspaceIteration :: solveYourselfAt: Iteration loop no. %d\n", nite); # endif // // compute projection ar and br of matrices a , b // for ( int j = 1; j <= nc; j++ ) { f.beColumnOf(r, j); solver->solve(a, f, tt); for ( int i = j; i <= nc; i++ ) { art = 0.; for ( int k = 1; k <= nn; k++ ) { art += r.at(k, i) * tt.at(k); } ar.at(j, i) = art; } r.setColumn(tt, j); // (r = xbar) } ar.symmetrized(); // label 110 #ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix ar\n"); ar.printYourself(); #endif // for ( int j = 1; j <= nc; j++ ) { tt.beColumnOf(r, j); b.times(tt, temp); for ( int i = j; i <= nc; i++ ) { brt = 0.; for ( int k = 1; k <= nn; k++ ) { brt += r.at(k, i) * temp.at(k); } br.at(j, i) = brt; } // label 180 r.setColumn(temp, j); // (r=zbar) } // label 160 br.symmetrized(); #ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix br\n"); br.printYourself(); #endif // // solution of reduced eigenvalue problem // mtd.solve(ar, br, eigv, vec); // START EXPERIMENTAL #if 0 // solve the reduced problem by Inverse iteration { FloatMatrix x(nc,nc), z(nc,nc), zz(nc,nc), arinv; FloatArray w(nc), ww(nc), tt(nc), t(nc); double c; // initial setting for ( int i = 1;i <= nc; i++ ) { ww.at(i)=1.0; } for ( int i = 1;i <= nc; i++ ) for ( int j = 1; j <= nc;j++ ) z.at(i,j)=1.0; arinv.beInverseOf (ar); for ( int i = 0;i < nitem; i++ ) { // copy zz=z zz = z; // solve matrix equation K.X = M.X x.beProductOf(arinv, z); // evaluation of Rayleigh quotients for ( int j = 1;j <= nc; j++ ) { w.at(j) = 0.0; for (k = 1; k<= nc; k++) w.at(j) += zz.at(k,j) * x.at(k,j); } z.beProductOf (br, x); for ( int j = 1;j <= nc; j++ ) { c = 0; for ( int k = 1; k<= nc; k++ ) c += z.at(k,j) * x.at(k,j); w.at(j) /= c; } // check convergence int ac = 0; for ( int j = 1;j <= nc; j++ ) { if (fabs((ww.at(j)-w.at(j))/w.at(j))< rtol) ac++; ww.at(j) = w.at(j); } //printf ("\n iterace cislo %d %d",i,ac); //w.printYourself(); // Gramm-Schmidt ortogonalization for ( int j = 1;j <= nc;j++ ) { for ( int k = 1; k<= nc; k++ ) tt.at(k) = x.at(k,j); t.beProductOf(br,tt) ; for ( int ii = 1;ii < j; ii++ ) { c = 0.0; for ( int k = 1; k<= nc; k++ ) c += x.at(k,ii) * t.at(k); for ( int k = 1; k<= nc; k++ ) x.at(k,j) -= x.at(k,ii) * c; } for ( int k = 1; k<= nc; k++) tt.at(k) = x.at(k,j); t.beProductOf(br, tt); c = 0.0; for ( int k = 1; k<= nc; k++) c += x.at(k,j)*t.at(k); for ( int k = 1; k<= nc; k++) x.at(k,j) /= sqrt(c); } if ( ac > nroot ) { break; } // compute new approximation of Z z.beProductOf(br,x); } eigv = w; vec = x; } #endif // // sorting eigenvalues according to their values // do { is = 0; // label 350 for ( int i = 1; i <= nc1; i++ ) { if ( fabs( eigv.at(i + 1) ) < fabs( eigv.at(i) ) ) { is++; eigvt = eigv.at(i + 1); eigv.at(i + 1) = eigv.at(i); eigv.at(i) = eigvt; for ( int k = 1; k <= nc; k++ ) { rt = vec.at(k, i + 1); vec.at(k, i + 1) = vec.at(k, i); vec.at(k, i) = rt; } } } // label 360 } while ( is != 0 ); # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen values of reduced problem \n"); eigv.printYourself(); OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen vectors of reduced problem \n"); vec.printYourself(); # endif // // compute eigenvectors // for ( int i = 1; i <= nn; i++ ) { // label 375 for ( int j = 1; j <= nc; j++ ) { tt.at(j) = r.at(i, j); } for ( int k = 1; k <= nc; k++ ) { rt = 0.; for ( int j = 1; j <= nc; j++ ) { rt += tt.at(j) * vec.at(j, k); } r.at(i, k) = rt; } } // label 420 (r = z) // // convergency check // for ( int i = 1; i <= nc; i++ ) { double dif = ( eigv.at(i) - d.at(i) ); rtolv.at(i) = fabs( dif / eigv.at(i) ); } # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Reached precision of eigenvalues:\n"); rtolv.printYourself(); # endif for ( int i = 1; i <= nroot; i++ ) { if ( rtolv.at(i) > rtol ) { goto label400; } } OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Convergence reached for RTOL=%20.15f\n", rtol); break; label400: if ( nite >= nitem ) { OOFEM_WARNING("SubspaceIteration :: solveYourselfAt: Convergence not reached in %d iteration - using current values", nitem); break; } d = eigv; // label 410 and 440 continue; } // compute eigenvectors for ( int j = 1; j <= nc; j++ ) { tt.beColumnOf(r, j); a.backSubstitutionWith(tt); r.setColumn(tt, j); // r = xbar } // one cad add a normalization of eigen-vectors here // initialize original index locations _r.resize(nn, nroot); _eigv.resize(nroot); for ( int i = 1; i <= nroot; i++ ) { _eigv.at(i) = eigv.at(i); for ( int j = 1; j <= nn; j++ ) { _r.at(j, i) = r.at(j, i); } } return NM_Success; }
namespace oofem { ClassFactory &GiveClassFactory() { static ClassFactory ans; return ans; } ClassFactory &classFactory = GiveClassFactory(); std :: string conv2lower(const char *input) { std :: string line(input); for ( std :: size_t i = 0; i < line.size(); i++ ) { line [ i ] = std :: tolower(line [ i ]); } return line; } ClassFactory :: ClassFactory() { // Fixed list for DOF types. No new components can register for these since these are part of the internal structure in OOFEM. dofList [ DT_master ] = dofCreator< MasterDof >; dofList [ DT_simpleSlave ] = dofCreator< SimpleSlaveDof >; dofList [ DT_slave ] = dofCreator< SlaveDof >; dofList [ DT_active ] = dofCreator< ActiveDof >; #ifdef __PARALLEL_MODE loadBalancerList [ "parmetis" ] = loadBalancerCreator< ParmetisLoadBalancer >; loadMonitorList [ "wallclock" ] = loadMonitorCreator< WallClockLoadBalancerMonitor >; #endif } SparseMtrx *ClassFactory :: createSparseMtrx(SparseMtrxType name) { return ( sparseMtrxList.count(name) == 1 ) ? sparseMtrxList [ name ]() : NULL; } bool ClassFactory :: registerSparseMtrx( SparseMtrxType name, SparseMtrx * ( *creator )( ) ) { sparseMtrxList [ name ] = creator; return true; } Dof *ClassFactory :: createDof(dofType name, int num, DofManager *dman) { return ( dofList.count(name) == 1 ) ? dofList [ name ](num, dman) : NULL; } SparseLinearSystemNM *ClassFactory :: createSparseLinSolver(LinSystSolverType name, Domain *d, EngngModel *m) { return ( sparseLinSolList.count(name) == 1 ) ? sparseLinSolList [ name ](d, m) : NULL; } bool ClassFactory :: registerSparseLinSolver( LinSystSolverType name, SparseLinearSystemNM * ( *creator )( Domain *, EngngModel * ) ) { sparseLinSolList [ name ] = creator; return true; } ErrorEstimator *ClassFactory :: createErrorEstimator(ErrorEstimatorType name, int num, Domain *d) { return ( errEstList.count(name) == 1 ) ? errEstList [ name ](num, d) : NULL; } bool ClassFactory :: registerErrorEstimator( ErrorEstimatorType name, ErrorEstimator * ( *creator )( int, Domain * ) ) { errEstList [ name ] = creator; return true; } InitialCondition *ClassFactory :: createInitialCondition(const char *name, int num, Domain *d) { if ( conv2lower(name).compare("initialcondition") == 0 ) { return new InitialCondition(num, d); } return NULL; } NodalRecoveryModel *ClassFactory :: createNodalRecoveryModel(NodalRecoveryModel :: NodalRecoveryModelType type, Domain *d) { if ( type == NodalRecoveryModel :: NRM_NodalAveraging ) { return new NodalAveragingRecoveryModel(d); } else if ( type == NodalRecoveryModel :: NRM_ZienkiewiczZhu ) { return new ZZNodalRecoveryModel(d); } else if ( type == NodalRecoveryModel :: NRM_SPR ) { return new SPRNodalRecoveryModel(d); } return NULL; } Element *ClassFactory :: createElement(const char *name, int number, Domain *domain) { return ( elemList.count(name) == 1 ) ? elemList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerElement( const char *name, Element * ( *creator )( int, Domain * ) ) { elemList [ conv2lower(name) ] = creator; return true; } DofManager *ClassFactory :: createDofManager(const char *name, int number, Domain *domain) { return ( dofmanList.count(name) == 1 ) ? dofmanList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerDofManager( const char *name, DofManager * ( *creator )( int, Domain * ) ) { dofmanList [ conv2lower(name) ] = creator; return true; } GeneralBoundaryCondition *ClassFactory :: createBoundaryCondition(const char *name, int number, Domain *domain) { return ( bcList.count(name) == 1 ) ? bcList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerBoundaryCondition( const char *name, GeneralBoundaryCondition * ( *creator )( int, Domain * ) ) { bcList [ conv2lower(name) ] = creator; return true; } CrossSection *ClassFactory :: createCrossSection(const char *name, int number, Domain *domain) { return ( csList.count(name) == 1 ) ? csList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerCrossSection( const char *name, CrossSection * ( *creator )( int, Domain * ) ) { csList [ conv2lower(name) ] = creator; return true; } Material *ClassFactory :: createMaterial(const char *name, int number, Domain *domain) { return ( matList.count(conv2lower(name).c_str()) == 1 ) ? matList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerMaterial( const char *name, Material * ( *creator )( int, Domain * ) ) { matList [ conv2lower(name) ] = creator; return true; } EngngModel *ClassFactory :: createEngngModel(const char *name, int number, EngngModel *master) { return ( engngList.count(name) == 1 ) ? engngList [ conv2lower(name) ](number, master) : NULL; } bool ClassFactory :: registerEngngModel( const char *name, EngngModel * ( *creator )( int, EngngModel * ) ) { engngList [ conv2lower(name) ] = creator; return true; } Function *ClassFactory :: createFunction(const char *name, int number, Domain *domain) { return ( funcList.count(name) == 1 ) ? funcList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerFunction( const char *name, Function * ( *creator )( int, Domain * ) ) { funcList [ conv2lower(name) ] = creator; return true; } NonlocalBarrier *ClassFactory :: createNonlocalBarrier(const char *name, int number, Domain *domain) { return ( nlbList.count(name) == 1 ) ? nlbList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerNonlocalBarrier( const char *name, NonlocalBarrier * ( *creator )( int, Domain * ) ) { nlbList [ conv2lower(name) ] = creator; return true; } RandomFieldGenerator *ClassFactory :: createRandomFieldGenerator(const char *name, int number, Domain *domain) { return ( rfgList.count(name) == 1 ) ? rfgList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerRandomFieldGenerator( const char *name, RandomFieldGenerator * ( *creator )( int, Domain * ) ) { rfgList [ conv2lower(name) ] = creator; return true; } ExportModule *ClassFactory :: createExportModule(const char *name, int number, EngngModel *emodel) { return ( exportList.count(name) == 1 ) ? exportList [ conv2lower(name) ](number, emodel) : NULL; } bool ClassFactory :: registerExportModule( const char *name, ExportModule * ( *creator )( int, EngngModel * ) ) { exportList [ conv2lower(name) ] = creator; return true; } SparseNonLinearSystemNM *ClassFactory :: createNonLinearSolver(const char *name, Domain *d, EngngModel *emodel) { return ( nonlinList.count(name) == 1 ) ? nonlinList [ conv2lower(name) ](d, emodel) : NULL; } bool ClassFactory :: registerSparseNonLinearSystemNM( const char *name, SparseNonLinearSystemNM * ( *creator )( Domain *, EngngModel * ) ) { nonlinList [ conv2lower(name) ] = creator; return true; } InitModule *ClassFactory :: createInitModule(const char *name, int number, EngngModel *emodel) { return ( initList.count(name) == 1 ) ? initList [ conv2lower(name) ](number, emodel) : NULL; } bool ClassFactory :: registerInitModule( const char *name, InitModule * ( *creator )( int, EngngModel * ) ) { initList [ conv2lower(name) ] = creator; return true; } TopologyDescription *ClassFactory :: createTopology(const char *name, Domain *domain) { return ( topologyList.count(name) == 1 ) ? topologyList [ conv2lower(name) ](domain) : NULL; } bool ClassFactory :: registerTopologyDescription( const char *name, TopologyDescription * ( *creator )( Domain * ) ) { topologyList [ conv2lower(name) ] = creator; return true; } // XFEM: EnrichmentItem *ClassFactory :: createEnrichmentItem(const char *name, int number, XfemManager *xm, Domain *domain) { return ( enrichItemList.count(name) == 1 ) ? enrichItemList [ conv2lower(name) ](number, xm, domain) : NULL; } bool ClassFactory :: registerEnrichmentItem( const char *name, EnrichmentItem * ( *creator )( int, XfemManager *, Domain * ) ) { enrichItemList [ conv2lower(name) ] = creator; return true; } EnrichmentFunction *ClassFactory :: createEnrichmentFunction(const char *name, int number, Domain *domain) { return ( enrichFuncList.count(name) == 1 ) ? enrichFuncList [ conv2lower(name) ](number, domain) : NULL; } bool ClassFactory :: registerEnrichmentFunction( const char *name, EnrichmentFunction * ( *creator )( int, Domain * ) ) { enrichFuncList [ conv2lower(name) ] = creator; return true; } EnrichmentDomain *ClassFactory :: createEnrichmentDomain(const char *name) { return ( enrichmentDomainList.count(name) == 1 ) ? enrichmentDomainList [ conv2lower(name) ]() : NULL; } bool ClassFactory :: registerEnrichmentDomain( const char *name, EnrichmentDomain * ( *creator )( ) ) { enrichmentDomainList [ conv2lower(name) ] = creator; return true; } EnrichmentFront *ClassFactory :: createEnrichmentFront(const char *name) { return ( enrichmentFrontList.count(name) == 1 ) ? enrichmentFrontList [ conv2lower(name) ]() : NULL; } bool ClassFactory :: registerEnrichmentFront( const char *name, EnrichmentFront * ( *creator )( ) ) { enrichmentFrontList [ conv2lower(name) ] = creator; return true; } PropagationLaw *ClassFactory :: createPropagationLaw(const char *name) { return ( propagationLawList.count(name) == 1 ) ? propagationLawList [ conv2lower(name) ]() : NULL; } bool ClassFactory :: registerPropagationLaw( const char *name, PropagationLaw * ( *creator )( ) ) { propagationLawList [ conv2lower(name) ] = creator; return true; } BasicGeometry *ClassFactory :: createGeometry(const char *name) { return ( geometryList.count(name) == 1 ) ? geometryList [ conv2lower(name) ]() : NULL; } bool ClassFactory :: registerGeometry( const char *name, BasicGeometry * ( *creator )( ) ) { geometryList [ conv2lower(name) ] = creator; return true; } XfemManager *ClassFactory :: createXfemManager(const char *name, Domain *domain) { return ( xManList.count(name) == 1 ) ? xManList [ conv2lower(name) ](domain) : NULL; } bool ClassFactory :: registerXfemManager( const char *name, XfemManager * ( *creator )( Domain * ) ) { xManList [ conv2lower(name) ] = creator; return true; } // Failure module: FailureCriteria *ClassFactory :: createFailureCriteria(const char *name, int number, FractureManager *fracManager) { return ( failureCriteriaList.count(name) == 1 ) ? failureCriteriaList [ conv2lower(name) ](number, fracManager) : NULL; } bool ClassFactory :: registerFailureCriteria( const char *name, FailureCriteria * ( *creator )( int, FractureManager * ) ) { failureCriteriaList [ conv2lower(name) ] = creator; return true; } FailureCriteriaStatus *ClassFactory :: createFailureCriteriaStatus(const char *name, int number, FailureCriteria *fc) { return ( failureCriteriaList.count(name) == 1 ) ? failureCriteriaStatusList [ conv2lower(name) ](number, fc) : NULL; } bool ClassFactory :: registerFailureCriteriaStatus( const char *name, FailureCriteriaStatus * ( *creator )( int, FailureCriteria * ) ) { failureCriteriaStatusList [ conv2lower(name) ] = creator; return true; } SparseGeneralEigenValueSystemNM *ClassFactory :: createGeneralizedEigenValueSolver(GenEigvalSolverType st, Domain *d, EngngModel *m) { if ( st == GES_SubspaceIt ) { return new SubspaceIteration(d, m); } else if ( st == GES_InverseIt ) { return new InverseIteration(d, m); } #ifdef __SLEPC_MODULE else if ( st == GES_SLEPc ) { return new SLEPcSolver(d, m); } #endif return NULL; } IntegrationRule *ClassFactory :: createIRule(IntegrationRuleType type, int number, Element *e) { if ( type == IRT_Gauss ) { return new GaussIntegrationRule(number, e); } else if ( type == IRT_Lobatto ) { return new LobattoIntegrationRule(number, e); } return NULL; } MaterialMappingAlgorithm *ClassFactory :: createMaterialMappingAlgorithm(MaterialMappingAlgorithmType type) { if ( type == MMA_ClosestPoint ) { return new MMAClosestIPTransfer(); } else if ( type == MMA_LeastSquareProjection ) { return new MMALeastSquareProjection(); } else if ( type == MMA_ShapeFunctionProjection ) { return new MMAShapeFunctProjection(); } return NULL; } MesherInterface *ClassFactory :: createMesherInterface(MeshPackageType type, Domain *d) { if ( type == MPT_T3D ) { return new T3DInterface(d); } else if ( type == MPT_TARGE2 ) { return new Targe2Interface(d); } else if ( type == MPT_FREEM ) { return new FreemInterface(d); } else if ( type == MPT_SUBDIVISION ) { return new Subdivision(d); } return NULL; } #ifdef __PARALLEL_MODE LoadBalancerMonitor *ClassFactory :: createLoadBalancerMonitor(const char *name, EngngModel *e) { return ( loadMonitorList.count(name) == 1 ) ? loadMonitorList [ conv2lower(name) ](e) : NULL; } LoadBalancer *ClassFactory :: createLoadBalancer(const char *name, Domain *d) { return ( loadBalancerList.count(name) == 1 ) ? loadBalancerList [ conv2lower(name) ](d) : NULL; } #endif } // End namespace oofem
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; }
auto creator = list.find(conv2lower(name));\ return creator != list.end() ? creator->second(__VA_ARGS__) : nullptr; // Helper macro for storing objects #define CF_STORE(list) \ list[ conv2lower(name) ] = creator;\ return true; namespace oofem { ClassFactory &GiveClassFactory() { static ClassFactory ans; return ans; } ClassFactory &classFactory = GiveClassFactory(); std :: string conv2lower(std :: string input) { for ( std :: size_t i = 0; i < input.size(); i++ ) { input [ i ] = (char)std :: tolower(input [ i ]); } return input; } ClassFactory :: ClassFactory() { // Fixed list for DOF types. No new components can register for these since these are part of the internal structure in OOFEM. dofList [ DT_master ] = dofCreator< MasterDof >; dofList [ DT_simpleSlave ] = dofCreator< SimpleSlaveDof >; dofList [ DT_slave ] = dofCreator< SlaveDof >;