mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			176 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable file
		
	
	
	
	
| // This file is part of libigl, a simple c++ geometry processing library.
 | |
| // 
 | |
| // Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
 | |
| // 
 | |
| // This Source Code Form is subject to the terms of the Mozilla Public License 
 | |
| // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 | |
| // obtain one at http://mozilla.org/MPL/2.0/.
 | |
| #include "eigs.h"
 | |
| 
 | |
| #include "cotmatrix.h"
 | |
| #include "sort.h"
 | |
| #include "slice.h"
 | |
| #include "massmatrix.h"
 | |
| #include <iostream>
 | |
| 
 | |
| template <
 | |
|   typename Atype,
 | |
|   typename Btype,
 | |
|   typename DerivedU,
 | |
|   typename DerivedS>
 | |
| IGL_INLINE bool igl::eigs(
 | |
|   const Eigen::SparseMatrix<Atype> & A,
 | |
|   const Eigen::SparseMatrix<Btype> & iB,
 | |
|   const size_t k,
 | |
|   const EigsType type,
 | |
|   Eigen::PlainObjectBase<DerivedU> & sU,
 | |
|   Eigen::PlainObjectBase<DerivedS> & sS)
 | |
| {
 | |
|   using namespace Eigen;
 | |
|   using namespace std;
 | |
|   const size_t n = A.rows();
 | |
|   assert(A.cols() == n && "A should be square.");
 | |
|   assert(iB.rows() == n && "B should be match A's dims.");
 | |
|   assert(iB.cols() == n && "B should be square.");
 | |
|   assert(type == EIGS_TYPE_SM && "Only low frequencies are supported");
 | |
|   DerivedU U(n,k);
 | |
|   DerivedS S(k,1);
 | |
|   typedef Atype Scalar;
 | |
|   typedef Eigen::Matrix<typename DerivedU::Scalar,DerivedU::RowsAtCompileTime,1> VectorXS;
 | |
|   // Rescale B for better numerics
 | |
|   const Scalar rescale = std::abs(iB.diagonal().maxCoeff());
 | |
|   const Eigen::SparseMatrix<Btype> B = iB/rescale;
 | |
| 
 | |
|   Scalar tol = 1e-4;
 | |
|   Scalar conv = 1e-14;
 | |
|   int max_iter = 100;
 | |
|   int i = 0;
 | |
|   //std::cout<<"start"<<std::endl;
 | |
|   while(true)
 | |
|   {
 | |
|     //std::cout<<i<<std::endl;
 | |
|     // Random initial guess
 | |
|     VectorXS y = VectorXS::Random(n,1);
 | |
|     Scalar eff_sigma = 0;
 | |
|     if(i>0)
 | |
|     {
 | |
|       eff_sigma = 1e-8+std::abs(S(i-1));
 | |
|     }
 | |
|     // whether to use rayleigh quotient method
 | |
|     bool ray = false;
 | |
|     Scalar err = std::numeric_limits<Scalar>::infinity();
 | |
|     int iter;
 | |
|     Scalar sigma = std::numeric_limits<Scalar>::infinity();
 | |
|     VectorXS x;
 | |
|     for(iter = 0;iter<max_iter;iter++)
 | |
|     {
 | |
|       if(i>0 && !ray)
 | |
|       {
 | |
|         // project-out existing modes
 | |
|         for(int j = 0;j<i;j++)
 | |
|         {
 | |
|           const VectorXS u = U.col(j);
 | |
|           y = (y - u*u.dot(B*y)/u.dot(B * u)).eval();
 | |
|         }
 | |
|       }
 | |
|       // normalize
 | |
|       x = y/sqrt(y.dot(B*y));
 | |
| 
 | |
|       // current guess at eigen value
 | |
|       sigma = x.dot(A*x)/x.dot(B*x);
 | |
|       //x *= sigma>0?1.:-1.;
 | |
| 
 | |
|       Scalar err_prev = err;
 | |
|       err = (A*x-sigma*B*x).array().abs().maxCoeff();
 | |
|       if(err<conv)
 | |
|       {
 | |
|         break;
 | |
|       }
 | |
|       if(ray || err<tol)
 | |
|       {
 | |
|         eff_sigma = sigma;
 | |
|         ray = true;
 | |
|       }
 | |
| 
 | |
|       Scalar tikhonov = std::abs(eff_sigma)<1e-12?1e-10:0;
 | |
|       switch(type)
 | |
|       {
 | |
|         default:
 | |
|           assert(false && "Not supported");
 | |
|           break;
 | |
|         case EIGS_TYPE_SM:
 | |
|         {
 | |
|           SimplicialLDLT<SparseMatrix<Scalar> > solver;
 | |
|           const SparseMatrix<Scalar> C = A-eff_sigma*B+tikhonov*B;
 | |
|           //mw.save(C,"C");
 | |
|           //mw.save(eff_sigma,"eff_sigma");
 | |
|           //mw.save(tikhonov,"tikhonov");
 | |
|           solver.compute(C);
 | |
|           switch(solver.info())
 | |
|           {
 | |
|             case Eigen::Success:
 | |
|               break;
 | |
|             case Eigen::NumericalIssue:
 | |
|               cerr<<"Error: Numerical issue."<<endl;
 | |
|               return false;
 | |
|             default:
 | |
|               cerr<<"Error: Other."<<endl;
 | |
|               return false;
 | |
|           }
 | |
|           const VectorXS rhs = B*x;
 | |
|           y = solver.solve(rhs);
 | |
|           //mw.save(rhs,"rhs");
 | |
|           //mw.save(y,"y");
 | |
|           //mw.save(x,"x");
 | |
|           //mw.write("eigs.mat");
 | |
|           //if(i == 1)
 | |
|           //return false;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if(iter == max_iter)
 | |
|     {
 | |
|       cerr<<"Failed to converge."<<endl;
 | |
|       return false;
 | |
|     }
 | |
|     if(
 | |
|       i==0 || 
 | |
|       (S.head(i).array()-sigma).abs().maxCoeff()>1e-14 ||
 | |
|       ((U.leftCols(i).transpose()*B*x).array().abs()<=1e-7).all()
 | |
|       )
 | |
|     {
 | |
|       //cout<<"Found "<<i<<"th mode"<<endl;
 | |
|       U.col(i) = x;
 | |
|       S(i) = sigma;
 | |
|       i++;
 | |
|       if(i == k)
 | |
|       {
 | |
|         break;
 | |
|       }
 | |
|     }else
 | |
|     {
 | |
|       //std::cout<<"i: "<<i<<std::endl;
 | |
|       //std::cout<<"  "<<S.head(i).transpose()<<" << "<<sigma<<std::endl;
 | |
|       //std::cout<<"  "<<(S.head(i).array()-sigma).abs().maxCoeff()<<std::endl;
 | |
|       //std::cout<<"  "<<(U.leftCols(i).transpose()*B*x).array().abs().transpose()<<std::endl;
 | |
|       // restart with new random guess.
 | |
|       cout<<"igl::eigs RESTART"<<endl;
 | |
|     }
 | |
|   }
 | |
|   // finally sort
 | |
|   VectorXi I;
 | |
|   igl::sort(S,1,false,sS,I);
 | |
|   igl::slice(U,I,2,sU);
 | |
|   sS /= rescale;
 | |
|   sU /= sqrt(rescale);
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| #ifdef IGL_STATIC_LIBRARY
 | |
| // Explicit template instantiation
 | |
| template bool igl::eigs<double, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&, const size_t, igl::EigsType, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 | |
| #ifdef WIN32
 | |
| template bool igl::eigs<double, double, Eigen::Matrix<double,-1,-1,0,-1,-1>, Eigen::Matrix<double,-1,1,0,-1,1> >(Eigen::SparseMatrix<double,0,int> const &,Eigen::SparseMatrix<double,0,int> const &, const size_t, igl::EigsType, Eigen::PlainObjectBase< Eigen::Matrix<double,-1,-1,0,-1,-1> > &, Eigen::PlainObjectBase<Eigen::Matrix<double,-1,1,0,-1,1> > &);
 | |
| #endif
 | |
| #endif
 | 
