// this is not very polished but it works well enough // for a mesh based method // for high eigenvalues, the multiplicities become higher // and higher and the steepest descent algorithm implemented here // is not capable to go beyond some local minima // choosing different starting points may help // the eigenvalue computation is made using an adaptation // of the code from the FreeFem++ manual func ffff = 1; func real[int] f(int kk, real[int] VV,int meshpar){ real[int] vec = VV; int i; real t; real beta = 2; int m = vec.n; int n = (m-1)/2; //vec = [0.9719, 0.0155, -0.0083, -0.0298, 0.0415, // -0.0199, 0.0168, -0.0001, -0.0003, 0.0000, -0.0001, // 0.0165, -0.0036, -0.0299, 0.0414, -0.0202, 0.0174, // -0.0006, 0.0008, -0.0007, 0.0005]; //cout << n << endl; real[int] as = vec(1:n) ; //cout << as << endl; //as.resize(50); //as(n:49)=0; real[int] bs = vec(n+1:2*n); //bs.resize(50); //bs(n:49)=0; real a0 =vec(0); border C(t=0,2* pi){x=cos(t)*(a0+as[0]*cos(t)+ as[1]*cos(2*t)+ as[2]*cos(3*t)+ as[3]*cos(4*t)+ as[4]*cos(5*t)+ as[5]*cos(6*t)+ as[6]*cos(7*t)+ as[7]*cos(8*t)+ as[8]*cos(9*t)+ as[9]*cos(10*t)+ as[10]*cos(11*t)+ as[11]*cos(12*t)+ as[12]*cos(13*t)+ as[13]*cos(14*t)+ as[14]*cos(15*t)+ as[15]*cos(16*t)+ as[16]*cos(17*t)+ as[17]*cos(18*t)+ as[18]*cos(19*t)+ as[19]*cos(20*t)+ bs[0]*sin(t)+ bs[1]*sin(2*t)+ bs[2]*sin(3*t)+ bs[3]*sin(4*t)+ bs[4]*sin(5*t)+ bs[5]*sin(6*t)+ bs[6]*sin(7*t)+ bs[7]*sin(8*t)+ bs[8]*sin(9*t)+ bs[9]*sin(10*t)+ bs[10]*sin(11*t)+ bs[11]*sin(12*t)+ bs[12]*sin(13*t)+ bs[13]*sin(14*t)+ bs[14]*sin(15*t)+ bs[15]*sin(16*t)+ bs[16]*sin(17*t)+ bs[17]*sin(18*t)+ bs[18]*sin(19*t)+ bs[19]*sin(20*t)); y=sin(t)*(a0+as[0]*cos(t)+ as[1]*cos(2*t)+ as[2]*cos(3*t)+ as[3]*cos(4*t)+ as[4]*cos(5*t)+ as[5]*cos(6*t)+ as[6]*cos(7*t)+ as[7]*cos(8*t)+ as[8]*cos(9*t)+ as[9]*cos(10*t)+ as[10]*cos(11*t)+ as[11]*cos(12*t)+ as[12]*cos(13*t)+ as[13]*cos(14*t)+ as[14]*cos(15*t)+ as[15]*cos(16*t)+ as[16]*cos(17*t)+ as[17]*cos(18*t)+ as[18]*cos(19*t)+ as[19]*cos(20*t)+ bs[0]*sin(t)+ bs[1]*sin(2*t)+ bs[2]*sin(3*t)+ bs[3]*sin(4*t)+ bs[4]*sin(5*t)+ bs[5]*sin(6*t)+ bs[6]*sin(7*t)+ bs[7]*sin(8*t)+ bs[8]*sin(9*t)+ bs[9]*sin(10*t)+ bs[10]*sin(11*t)+ bs[11]*sin(12*t)+ bs[12]*sin(13*t)+ bs[13]*sin(14*t)+ bs[14]*sin(15*t)+ bs[15]*sin(16*t)+ bs[16]*sin(17*t)+ bs[17]*sin(18*t)+ bs[18]*sin(19*t)+ bs[19]*sin(20*t));} mesh Th = buildmesh (C(meshpar)); Th= adaptmesh(Th,1./30,IsMetric=1,nbvx=10000); //plot(Th); fespace Vh(Th,P1); Vh u1,u2; real sigma = 00; // value of the shift varf a(u1,u2)= int2d(Th) ( dx(u1)*dx(u2) + dy(u1)*dy(u2) - sigma* u1*u2 ) + on(1,u1=0) ; // Boundary condition varf b([u1],[u2]) = int2d(Th)( u1*u2 ) ; // no Boundary condition matrix A= a(Vh,Vh,solver=Crout,factorize=1); matrix B= b(Vh,Vh,solver=CG,eps=1e-20); // important remark: // the boundary condition is make with exact penalisation: // we put 1e30=tgv on the diagonal term of the lock degre of freedom. // So take dirichlet boundary condition just on $a$ variationnal form // and not on $b$ variationnanl form. // because we solve // $$ w=A^-1*B*v $$ int nev=kk; // number of computed eigen valeu close to sigma real[int] ev(nev); // to store nev eigein value Vh[int] eV(nev); // to store nev eigen vector int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10, maxit=0,ncv=0); // tol= the tolerace // maxit= the maximal iteration see arpack doc. // ncv see arpack doc. // the return value is number of converged eigen value. k=min(k,nev); // some time the number of converged eigen value // can be greater than nev; //for (int i=0;i1e-12){ i=i+1; //real ar = far(0); //cout<< ar<< endl; //// gradient descent ///// real[int] tvect = vect-alpha*gradt; real[int] ggg = f(ke,tvect,meshref); real[int] far = farea(tvect); //cout << ggg << endl; real val = ggg(1); real arr = ggg(0); arr = far(0); cout << "Iteration " << i<< " Function value: " << val*arr << " previous " << pval << " alpha " << alpha <