Skip to content
Snippets Groups Projects
Select Git revision
  • 05d797047f5a715e4e42119ef5b9d309f7e2d36d
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

pyramidalBasis.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    eigenSolve.cpp 4.44 KiB
    // Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
    //
    // See the LICENSE.txt file for license information. Please report all
    // bugs and problems to <gmsh@geuz.org>.
    
    #include "eigenSolve.h"
    
    #if defined(HAVE_SLEPC)
    
    #include <slepceps.h>
    
    eigenSolve::eigenSolve(dofManager<double, double> *manager, std::string A, 
                           std::string B) : _A(0), _B(0)
    {
      if(A.size()){
        _A = dynamic_cast<linearSystemPETSc<double>*>(manager->getLinearSystem(A));
        if(!_A) Msg::Error("Could not find PETSc system '%s'", A.c_str());
      }
      if(B.size()){
        _B = dynamic_cast<linearSystemPETSc<double>*>(manager->getLinearSystem(B));
        if(!_B) Msg::Error("Could not find PETSc system '%s'", B.c_str());
      }
    }
    
    void eigenSolve::solve()
    {
      if(!_A) return;
      Mat A = _A->getMatrix();
      Mat B = _B ? _B->getMatrix() : PETSC_NULL;
    
      _try(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
      _try(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
      PetscInt N, M;
      _try(MatGetSize(A, &N, &M));
    
      // treatment of a generalized eigenvalue problem A x - \lambda B x = 0
      EPS eps;
      _try(EPSCreate(PETSC_COMM_WORLD, &eps));
      _try(EPSSetOperators(eps, A, B));
      // FIXME: check if hermitian (EPS_HEP or EPS_GHEP)
      _try(EPSSetProblemType(eps, _B ? EPS_GNHEP : EPS_NHEP));
    
      // set options
      _try(EPSSetWhichEigenpairs(eps, EPS_LARGEST_MAGNITUDE));
      //_try(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_MAGNITUDE));
      //_try(EPSSetTarget(eps, 2.)); // find eigenvalues close to given target
      PetscInt nev = 2; // number of eigenvalues to compute
      PetscInt mpd = nev; // max dim allowed for the projected problem
      PetscInt ncv = nev + mpd; // max dim of the subspace to be used by the solver
      _try(EPSSetDimensions(eps, nev, ncv, mpd));
    
      // override options at runtime, petsc-style
      _try(EPSSetFromOptions(eps));
    
      // print info
      const EPSType type;
      _try(EPSGetType(eps, &type));
      Msg::Info("SLEPc solution method: %s", type);
      _try(EPSGetDimensions(eps, &nev, &ncv, &mpd));
      Msg::Info("SLEPc number of requested eigenvalues: %d", nev);
      PetscReal tol;
      PetscInt maxit;
      _try(EPSGetTolerances(eps, &tol, &maxit));
      Msg::Info("SLEPc stopping condition: tol=%g, maxit=%d", tol, maxit);
     	
      Msg::Info("SLEPc solving...");
      _try(EPSSolve(eps));
    
      int its;
      _try(EPSGetIterationNumber(eps, &its));
      EPSConvergedReason reason;
      _try(EPSGetConvergedReason(eps, &reason));
      if(reason == EPS_CONVERGED_TOL)
        Msg::Info("SLEPc converged in %d iterations", its);
      else if(reason == EPS_DIVERGED_ITS)
        Msg::Error("SLEPc did not converge in %d iterations", its);
      else if(reason == EPS_DIVERGED_BREAKDOWN)
        Msg::Error("SLEPc generic breakdown in method");
      else if(reason == EPS_DIVERGED_NONSYMMETRIC)
        Msg::Error("The operator is nonsymmetric");
      
      // get number of converged approximate eigenpairs
      PetscInt nconv;
      _try(EPSGetConverged(eps, &nconv));
      Msg::Info("SLEPc number of converged eigenpairs: %d", nconv);
    
      // if number of converged solutions is greated than requested
      // discarded surplus solutions
      if(nconv > nev) nconv = nev;
      // if number of converged solutions is less than requested display
      // only converged solutions
      if(nconv < nev) nev = nconv;
    
      Vec xr, xi;
      _try(MatGetVecs(A, PETSC_NULL, &xr));
      _try(MatGetVecs(A, PETSC_NULL, &xi));
      Msg::Info("         Re[EigenValue]          Im[EigenValue]"
                "          Relative error");
      for (int i = nconv - 1; i > nconv - nev - 1; i--){
        std::vector<std::complex<double> > ev(N);
    
        PetscScalar kr, ki;
        _try(EPSGetEigenpair(eps, i, &kr, &ki, xr, xi));
        PetscReal error;
        _try(EPSComputeRelativeError(eps, i, &error));
    #if defined(PETSC_USE_COMPLEX)
        PetscReal re = PetscRealPart(kr);
        PetscReal im = PetscImaginaryPart(kr);
    #else
        PetscReal re = kr;
        PetscReal im = ki;
    #endif
        // Output eigenvalues and relative error (= ||Ax - eig*Bx||/||eig*x||)
        Msg::Info("EIG %03d %s%.16e %s%.16e  %3.6e", (nconv - i), 
                  (re < 0) ? "" : " ", re, (im < 0) ? "" : " ", im, error);
        _eigenValues.push_back(std::complex<double>(re, im));
    
        // Output eigenvector
        PetscScalar *tmpr, *tmpi;
        _try(VecGetArray(xr, &tmpr));
        _try(VecGetArray(xi, &tmpi));
        for(int i = 0; i < N; i++)
          ev[i] = std::complex<double>(PetscRealPart(tmpr[i]), 
                                       PetscRealPart(tmpi[i]));
        _eigenVectors.push_back(ev);
      }
      
      // Free work space
      _try(EPSDestroy(eps));
      _try(VecDestroy(xr));
      _try(VecDestroy(xi));
      _try(SlepcFinalize());
      Msg::Info("SLEPc done");
    }
    
    #endif