eigenvalue.cpp

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 803 行 · 第 1/2 页

CPP
803
字号
		}	      	    }	  	  if (evector)	    {	      FEbaseArray<K,v_fes> & ev(*evector);	      int m = Min(nconv,(long) ev.N);	      for(int i=0;i<m;i++)		{		  FEbase<K,v_fes> & xx= **(ev[i]);		    //if(xx.pVh->NbDoF != n)		    //ExecError("Wrong Type size of FEspace to store the eigen vector ");		    // if (xx.pVh != pOP1->pUh) 		    //    ExecError("Wrong Type of FEspace to store the eigen vector ");		    //xx.Vh = pOP1->Uh;		  KN_<K> vi(Z(':',i)) ;		  xx= new KN<K>(vi);		  		}	    }	}    }  else       { 	// cas non symetrique ,        // Finding an Arnoldi basis.                                                                                                                       //int mode=3; //  Shift invert                                                                                                                       int ido=0;        char bmat='G';        char which[]="LM";        int ishift=1; // Auto Shift true by default                                                                                                        int iparam[12]= {0,ishift,0,maxit,1,nconv,0,mode,0,0,0,0};        int ipntr[15]={ 0,0,0, 0,0,0,  0,0,0, 0,0,0 ,0,0,0};        KN<double> workd(3*n+1);        int lworkl = 3*ncv*(ncv+2);	KN<double> workl(lworkl+1);        KN<double> vp(ncv*n+1);        int info= (residptr !=0);	KN<double> vresid(residptr? 1: n);	if(!residptr) residptr=&vresid[0];	if(verbosity>9)	  cout << " n " << n << " nbev "<< nbev << " tol =" << tol << " maxit =" << maxit << " ncv = " <<ncv << endl;			while (1)	{	  naupp(ido,bmat,n,which,nbev,tol,  residptr,  ncv,  vp, n,		iparam,  ipntr,  workd,   workl,  lworkl, info);	  if(ido==99) break;	  sauppError(info);	  KN_<double>  xx(&workd[ipntr[1]],n);	  KN_<double>  yy(&workd[ipntr[2]],n);	  KN_<double>  zz(&workd[ipntr[3]],n);	  DoIdoAction(ido,mode,xx,yy,zz,work,OP1,B);	}	nconv = iparam[5];	if(nconv)	  {	    KN<double> evr(nbev+1), evi(nbev+1);	    KNM<double> Z(n,nbev+1);	    KN<double> workev(3*ncv);	    int ldz=n;	    char HowMny ='A';	    int rvec=1;	    double sigmai=0;	    neupp( rvec, HowMny, evr,evi, Z , ldz, sigma,sigmai, workev,		   bmat, n,   which,  nbev,  tol,  residptr, ncv,		     vp, n, iparam , ipntr, workd, workl,lworkl,info);	    	    	    if (verbosity)	      {		cout << "Real non-symmetric eigenvalue problem: A*x - B*x*lambda" << endl;		cout << "mode " << mode << " sigma=" << sigma <<  endl << endl;						cout << "Dimension of the system            : " << n              << endl;		cout << "Number of 'requested' eigenvalues  : " << nbev  << endl;		cout << "Number of 'converged' eigenvalues  : " << nconv          << endl;		cout << "Number of Arnoldi vectors generated: " << ncv  << endl;		cout << "Number of iterations taken         : " << iparam[3] << endl;		cout << endl;		  		cout << "Eigenvalues:" << endl;		for (int i=0; i<nconv; i++) {		  cout << "  lambda[" << (i+1) << "]: " ;		  ios::fmtflags oldflag= cout.flags();		  cout.setf(ios::showpos);		  cout << evr(i) 		       <<  evi(i) << "i"<<  endl;		  cout.flags(oldflag); // restore flags     		  KN_<double> vi(Z(':',i)) ;		  if(verbosity>99)		    {		      cout <<" Eigenvector: :" << vi << endl;		      cout << endl;			    }    		  }	      }	    	    if (evalue)	      {		KN<double> & ev(*evalue);		int m = Min(nconv,ev.N());		for(int i=0;i<m;i++)		  ev[i]=evr(i);	      }	    	    if (evaluei)	      {		KN<double> & ev(*evaluei);		int m = Min(nconv,ev.N());		for(int i=0;i<m;i++)		  ev[i]=evi(i);	      }	    if(rawvector)	      {		//K*  rawev(prob.RawEigenvectors());		int m = Min(nconv,rawvector->M());	    ffassert(rawvector->N()==n);	    for(int i=0;i<m;i++)	      {		int k=i;		KN_<K> vi(Z(':',i)) ;		cout << " ------ EV--raw " << vi.min() << " " << vi.max() << endl;		(*rawvector)(':',i)=vi;	      }	    	      }		    if (evector)	      {		// K*  rawev(prob.RawEigenvectors());		// rawev + n*k is		//  iev = prob.EigenvalueImag(k)		//  iev==0 => the eigen vector 		//  iev> 0 => real 		//      start real :  rawev + n*k 		//      start imag :  ramev +n*(k+1)		//  iev < 0 =>  complex  		//      start real :  rawev + n*(k-1) 		//      -start imag :  ramev +n*(k)		FEbaseArray<K,v_fes> & ev(*evector);		int m = Min(nconv,(long) ev.N);		for(int i=0;i<m;i++)		  {		    // K ev_i=		    //prob.EigenvalueImag(i);		    FEbase<K,v_fes> & xx= **(ev[i]);		    // if (xx.pVh != pOP1->pUh) 		    //    ExecError("Wrong Type of FEspace to store the eigen vector ");		    // xx.Vh = pOP1->Uh;		    // int  k=(ev_i < 0) ? i-1 : i;		    //int k=i;		    KN_<K> vi(Z(':',i));//rawev+n*k,n) ;		    xx= new KN<K>(vi);		    		  }	      }	    	  }	}   	return (long) nconv;}  AnyType EigenValueC::E_EV::operator()(Stack stack)  const {  dddd = (verbosity>=200);    double tol=1e-6;  long nconv=0;   long nbev=1;  long ncv =0;  // the number of Arnoldi vectors generated   long maxit=0;  // the maximum number of Arnoldi iterations   long mode=3;  K sigma=0;  KN<K> * evalue=0;  KN<K> * resid=0;  KNM<K> * rawvector=0;    pfecarray  evector2;  pfecbasearray   evector=0;  tol=arg<double>(0,stack,0);  nbev=arg<long>(1,stack,0);  sigma=arg<K>(2,stack,0.0);  evalue=arg<KN<K> *>(3,stack,0);  evector2 =arg<pfecarray>(4,stack,make_pair<pfecbasearray,int>(0,0));   ncv= arg<long>(5,stack,0);  maxit= arg<long>(6,stack,0);  rawvector=arg<KNM<K> *>(7,stack,0);  resid=arg<KN<K> *>(8,stack,0);  mode = arg<long>(9,stack,3);  K * residptr= resid ? (K*) *resid : 0;  evector=evector2.first;  ffassert(mode>0 && mode <4) ;   Matrice_Creuse<K> *pOP1 =  GetAny<Matrice_Creuse<K> *>((*expOP1)(stack));  Matrice_Creuse<K> *pB =  GetAny<Matrice_Creuse<K> *>((*expB)(stack));    if(evalue) nbev=Max( (long)evalue->N(),nbev);  if(!maxit)  maxit = 100*nbev;        const MatriceCreuse<K> & OP1 = pOP1->A;  const MatriceCreuse<K> & B = pB->A;    long  n=OP1.n;  nbev=min(nbev,n-2);  if(!ncv)     ncv = nbev*2+1;    ncv = max(nbev+2,ncv);  ncv = min(ncv,n);  const char *serr[10];  int err=0;  if(nbev>= n-1)     serr[err++]="  Number of eigenvalues of OP to be computed <= n-2 ";   if( mode < 1 || mode > 3)         serr[err++]="  the mode = 1 ,2 ,3  ";  // 2 <= NCV-NEV and NCV <= N   if( ! ( 2 <= nbev && ncv <= n))        serr[err++]="   ( 2 <= nbve && nvc <= n) ";  if (n != OP1.m)    serr[err++]=" the first matrix in EigneValue is not Hermitien.";  if (n != B.n )     serr[err++]="Sorry the row's number of the secand matrix in EigneValue is wrong.";  if (n != B.m )     serr[err++]="Sorry the colum's number of the secand matrix in EigneValue is wrong.";    if(verbosity)	cout << "Real complex eigenvalue problem: A*x - B*x*lambda" << endl;  if(verbosity>9 ||  err)	cout << "   n " << n << " nev "<< nbev << " tol =" << tol << " maxit =" << maxit << " ncv = " <<ncv << " mode = " << mode << endl;	  if(err)     {	cerr << " list of the error " << endl;	for (int i=0;i<err;++i)	    cerr << "\n-  " <<  serr[i] << endl;	ExecError("Fatal Error in EigenValue (complex) ");    }           KN<K> work(n);  //  ARrcSymGenEig is a class that requires the user to provide a  //   way to perform the matrix-vector products w = OP*Bv =  //   inv(A-sigma*B)*B*v and w = B*v, where sigma is the adopted shift.  // OP1 = (A-sigma*B)  // OP = inv(OP)   /*  ffassert(0);         ARrcCompGenEig<R> prob( n, nbev, sigma,"LM",ncv,tol,maxit,residptr);            // OP = inv[A - sigma*I]            // Finding an Arnoldi basis.        while (!prob.ArnoldiBasisFound()) {            // Calling ARPACK FORTRAN code. Almost all work needed to            prob.TakeStep();  */  // cas non symetrique ,                                                                                                                      // Finding an Arnoldi basis.                                                                                                              \                                                                                                                                                    // int mode=3; //  Shift invert			\    int ido=0;  char bmat='G';  char which[]="LM";  int ishift=1; // Auto Shift true by default                                                                                               \                                                                                                                                                     int iparam[12]= {0,ishift,0,maxit,1,nconv,0,mode,0,0,0,0};  int ipntr[15]={ 0,0,0, 0,0,0,  0,0,0, 0,0,0 ,0,0,0};  KN<K> workd(3*n+1);  int lworkl = 3*ncv*ncv+5*ncv;  KN<K> workl(lworkl+1);  KN<K> vp(ncv*n+1);  int info= (residptr !=0);  KN<double> rwork(ncv+1);  KN<K> vresid(residptr? 1: n);  if(!residptr) residptr=&vresid[0];  while(1)    {      caupp(ido,bmat,n,which,nbev,	    tol,  residptr,  ncv,	    vp, n,   iparam,  ipntr,workd, workl,	    lworkl,rwork,  info);      if(ido==99) break;	if(verbosity>99) 	  cout << "    saupp ido: " << ido << " info : " << info << endl;	if(info<0) {cerr << " -- err arpack info = " << info << endl;}  	sauppError(info);	if(ido==99) break;		KN_<K>  xx(&workd[ipntr[1]],n);	KN_<K>  yy(&workd[ipntr[2]],n);	KN_<K>  zz(&workd[ipntr[3]],n);	DoIdoAction(ido,mode,xx,yy,zz,work,OP1,B);    }    nconv = iparam[5];  if(nconv)    {      KN<K> evc(nbev);      KNM<K> Z(n,nbev);      KN<K> workev(3*ncv);      int ldz=n;      char HowMny ='A';      int rvec=1;      ceupp( rvec, HowMny, evc, Z , n, sigma, workev,	     bmat, n,   which, 	     nbev,  tol,  residptr, ncv,	     vp, n, iparam , ipntr, workd, workl,lworkl,rwork,info);            if (verbosity)	{	  cout << "Complex eigenvalue problem: A*x - B*x*lambda" << endl;	  cout << "mode =" << mode << "  sigma=" << sigma <<  endl << endl;	  	  cout << "Dimension of the system            : " << n              << endl;	  cout << "Number of 'requested' eigenvalues  : " << nbev  << endl;	  cout << "Number of 'converged' eigenvalues  : " << nconv          << endl;	  cout << "Number of Arnoldi vectors generated: " << ncv << endl;	  cout << "Number of iterations taken         : " << iparam[3]  << endl;	  cout << endl;	  	  cout << "Eigenvalues:" << endl;	  for (int i=0; i<nconv; i++) {	    cout << "  lambda[" << (i+1) << "]: " << evc(i) << endl;	    KN_<K> vi(Z(':',i)) ;	    if(verbosity>99)	      cout <<" Eigenvector: :" << vi << endl;	  }		       cout << endl;	}                  if (evalue)	{	  KN<K> & ev(*evalue);	  int m = Min(nconv,ev.N());	  for(int i=0;i<m;i++)	    ev[i]=evc(i);	}      if (evector)	{	  FEbaseArray<K,v_fes> & ev(*evector);	  int m = Min(nconv,(long) ev.N);	  for(int i=0;i<m;i++)	    {	      FEbase<K,v_fes> & xx= **(ev[i]);	      KN_<K> vi(Z(':',i)) ;	      xx= new KN<K>(vi);	      	    }	  if(rawvector)	    {	      int m = Min(nconv,rawvector->M());	      ffassert(rawvector->N()==n);	      for(int i=0;i<m;i++)		{		  KN_<K> vi(Z(':',i)) ;		  (*rawvector)(':',i)=vi;		}	      	    }	  	}    }  return (long) nconv;}#ifndef DYNM_LOADvoid init_eigenvalue(){    if(verbosity) cout << "eigenvalue ";    Global.Add("EigenValue","(",new EigenValue(1));  //  j + dJ    Global.Add("EigenValue","(",new EigenValueC(1));  //  j + dJ    }#elseclass Init {public:  Init()  {    if(verbosity) cout << "eigenvalue ";    Global.Add("EigenValue2","(",new EigenValue(1));  //  j + dJ    Global.Add("EigenValue2","(",new EigenValueC(1));  //  j + dJ  }};Init init; #endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?