Question

The following question might be easy to answer, but I did not find any solution in the Internet. To put it in a nutshell, I put some petsc function calls in a class.

The following equation solver script works without any problems:

static char help[] = "3x3-Equation system\n\n";


#include <petscksp.h>

#undef __FUNCT__
#define __FUNCT__ "main"
int main(int argc,char **argv)
{
  PetscErrorCode ierr;
  PetscMPIInt    rank;
  PetscInt       i,j,N;
  PetscInt   l[] = {0,1,2}; // indices for right hand vector (rhv)
  PetscScalar    vec[] = {0.0,5.0,3.0}; //values of rhv
  PetscScalar    matrix[3][3]= {{-1.0,1.0,1.0},{1.0,-3.0,-2.0},{5.0,1.0,4.0}};
  Vec            b,x;
  Mat            A; 
  KSP            ksp;         /* linear solver context */
  PC             pc;           /* preconditioner context */

  PetscInitialize(&argc,&argv,(char*)0,help);
  ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
  PetscPrintf(PETSC_COMM_SELF,"[%d] rank\n",rank);

//Init vector
  ierr = VecCreate(PETSC_COMM_WORLD,&b);CHKERRQ(ierr);
  ierr = VecSetSizes(b,3,PETSC_DECIDE);CHKERRQ(ierr);
  ierr = VecSetFromOptions(b);CHKERRQ(ierr);
  ierr = VecDuplicate(b,&x);CHKERRQ(ierr);
  //ierr = VecGetSize(x,&N);CHKERRQ(ierr);
  //ierr = VecSet(x,vec[2]);CHKERRQ(ierr);
  ierr = VecSetValues(b,3,l,vec,INSERT_VALUES);CHKERRQ(ierr);

  ierr = VecAssemblyBegin(b);CHKERRQ(ierr);
  ierr = VecAssemblyEnd(b);CHKERRQ(ierr);

//Init matrix
  ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
  ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,3,3);CHKERRQ(ierr);
  ierr = MatSetFromOptions(A);CHKERRQ(ierr);
  ierr = MatSetUp(A);CHKERRQ(ierr);
  for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
      ierr = MatSetValues(A,1,&i,1,&j,&matrix[i][j],INSERT_VALUES);CHKERRQ(ierr);
    }
  }
  ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
  ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);  

 //Solve
    ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);
    ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
    ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
    ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr);
    ierr = KSPSetTolerances(ksp,1.e-5,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
    ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
    ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr);
    ierr = KSPView(ksp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);

//View rhv 
  PetscPrintf(PETSC_COMM_SELF,"right hand vector:\n");
  ierr = VecView(b,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);


//View matrix
  PetscPrintf(PETSC_COMM_SELF,"matrix:\n");
  ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);

//View solution 
  PetscPrintf(PETSC_COMM_SELF,"solution:\n");
  ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);

 //Clean all
  /*ierr = VecDestroy(&b);CHKERRQ(ierr);
  ierr = VecDestroy(&x);CHKERRQ(ierr);
  ierr = MatDestroy(&A);CHKERRQ(ierr);
  */
  ierr = PetscFinalize();
  return 0;
}

But when I outsource the code in a class, it causes several mistakes:

#include <petscksp.h>
static char help[] = "Easy equation solver\n\n";

class externSolver
{
  public:                              
  PetscErrorCode ierr;  
  PetscMPIInt    rank;
  Vec            b,x;
  Mat            A; 
  KSP            ksp;         /* linear solver context */
  PC             pc;           /* preconditioner context */
    externSolver(int argc,char **argv)
    {
        ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr);
    ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] rank\n",rank);CHKERRQ(ierr);
    return;
    }
    ~externSolver()
    {

    }
    void generateMatrix(int cols, int rows)
    {
        ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
    ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,cols,rows);CHKERRQ(ierr);
    ierr = MatSetFromOptions(A);CHKERRQ(ierr);
    ierr = MatSetUp(A);CHKERRQ(ierr);
    }
    void MatSetValues(PetscInt num_rows,PetscInt* rows,PetscInt num_cols,PetscInt* cols,PetscScalar* Value)
    {
      ierr = MatSetValues(A,num_rows,rows,num_cols,cols,Value,INSERT_VALUES);CHKERRQ(ierr);
    }
    void assemblyMatrix()
    {
      ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
      ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);  
    }
    void generateVectors()
    {
      ierr = VecCreate(PETSC_COMM_WORLD,&b);CHKERRQ(ierr);
      ierr = VecSetSizes(b,3,PETSC_DECIDE);CHKERRQ(ierr);
      ierr = VecSetFromOptions(b);CHKERRQ(ierr);
      ierr = VecDuplicate(b,&x);CHKERRQ(ierr);
    }
    void VecSetValues(PetscInt num_rows,PetscInt* rows,PetscScalar* Value)
    {
       ierr = VecSetValues(b,num_rows,rows,Value,INSERT_VALUES);CHKERRQ(ierr);
    }
    void assemblyVectors()
    {
        ierr = VecAssemblyBegin(b);CHKERRQ(ierr);
        ierr = VecAssemblyEnd(b);CHKERRQ(ierr);
    }
    void solve()
    {
      ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);
      ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
      ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
      ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr);
      ierr = KSPSetTolerances(ksp,1.e-5,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
      ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);
      ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr);
      ierr = KSPView(ksp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
    }
    void showAll()
    {
      //View right hand vec
      PetscPrintf(PETSC_COMM_SELF,"right hand vec:\n");
      ierr = VecView(b,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);


      //View matrix
      PetscPrintf(PETSC_COMM_SELF,"matrix:\n");
      ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);

      //View solution
      PetscPrintf(PETSC_COMM_SELF,"solution:\n");
      ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
    }
  void close()
  {
        //Clean up
      ierr = VecDestroy(&b);CHKERRQ(ierr);
      ierr = VecDestroy(&x);CHKERRQ(ierr);
      ierr = MatDestroy(&A);CHKERRQ(ierr);
      ierr = PetscFinalize();
  }
};

And this is the script which calls the class:

#include "externSolver.h"

int main(int argc,char **argv)
{
  PetscInt   l[] = {0,1,2}; 
  PetscScalar    vec[] = {0.0,5.0,3.0};
  PetscScalar    matrix[3][3]= {{-1.0,1.0,1.0},{1.0,-3.0,-2.0},{5.0,1.0,4.0}};


  externSolver eS(argc,argv);


//Vector
  eS.generateVectors();
  eS.VecSetValues(3,l,vec);
  eS.assemblyVectors();


//Matrix
  eS.generateMatrix(3,3);
  for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
      eS.MatSetValues(1,&i,1,&j,&matrix[i][j]);
    }
  }
  eS.assemblyMatrix();

 //Solve Problem
  eS.solve();

  eS.showAll();
  eS.close();



  return 0;
}

These are the building mistakes:

In file included from ex2_extern.cc:5:

externSolver.h: In constructor ‘externSolver::externSolver(int, char**)’:
externSolver.h:15: error: returning a value from a constructor
externSolver.h:16: error: returning a value from a constructor
externSolver.h:17: error: returning a value from a constructor
externSolver.h: In member function ‘void externSolver::generateMatrix(int, int)’:
externSolver.h:26: error: return-statement with a value, in function returning 'void'
externSolver.h:27: error: return-statement with a value, in function returning 'void'
externSolver.h:28: error: return-statement with a value, in function returning 'void'
externSolver.h:29: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::MatSetValues(PetscInt, PetscInt*, PetscInt, PetscInt*, PetscScalar*)’:
externSolver.h:33: error: no matching function for call to ‘externSolver::MatSetValues(_p_Mat*&, PetscInt&, PetscInt*&, PetscInt&, PetscInt*&, PetscScalar*&, InsertMode)’
externSolver.h:31: note: candidates are: void externSolver::MatSetValues(PetscInt, PetscInt*, PetscInt, PetscInt*, PetscScalar*)
externSolver.h:33: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::assemblyMatrix()’:
externSolver.h:37: error: return-statement with a value, in function returning 'void'
externSolver.h:38: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::generateVectors()’:
externSolver.h:42: error: return-statement with a value, in function returning 'void'
externSolver.h:43: error: return-statement with a value, in function returning 'void'
externSolver.h:44: error: return-statement with a value, in function returning 'void'
externSolver.h:45: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::VecSetValues(PetscInt, PetscInt*, PetscScalar*)’:
externSolver.h:49: error: no matching function for call to ‘externSolver::VecSetValues(_p_Vec*&, PetscInt&, PetscInt*&, PetscScalar*&, InsertMode)’
externSolver.h:47: note: candidates are: void externSolver::VecSetValues(PetscInt, PetscInt*, PetscScalar*)
externSolver.h:49: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::assemblyVectors()’:
externSolver.h:53: error: return-statement with a value, in function returning 'void'
externSolver.h:54: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::solve()’:
externSolver.h:58: error: return-statement with a value, in function returning 'void'
externSolver.h:59: error: return-statement with a value, in function returning 'void'
externSolver.h:60: error: return-statement with a value, in function returning 'void'
externSolver.h:61: error: return-statement with a value, in function returning 'void'
externSolver.h:62: error: return-statement with a value, in function returning 'void'
externSolver.h:63: error: return-statement with a value, in function returning 'void'
externSolver.h:64: error: return-statement with a value, in function returning 'void'
externSolver.h:65: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::showAll()’:
externSolver.h:71: error: return-statement with a value, in function returning 'void'
externSolver.h:76: error: return-statement with a value, in function returning 'void'
externSolver.h:80: error: return-statement with a value, in function returning 'void'
externSolver.h: In member function ‘void externSolver::close()’:
externSolver.h:85: error: cannot convert ‘_p_Vec**’ to ‘_p_Vec*’ for argument ‘1’ to ‘PetscErrorCode VecDestroy(_p_Vec*)’
externSolver.h:85: error: return-statement with a value, in function returning 'void'
externSolver.h:86: error: cannot convert ‘_p_Vec**’ to ‘_p_Vec*’ for argument ‘1’ to ‘PetscErrorCode VecDestroy(_p_Vec*)’
externSolver.h:86: error: return-statement with a value, in function returning 'void'
externSolver.h:87: error: cannot convert ‘_p_Mat**’ to ‘_p_Mat*’ for argument ‘1’ to ‘PetscErrorCode MatDestroy(_p_Mat*)’
externSolver.h:87: error: return-statement with a value, in function returning 'void'
ex2_extern.cc: In function ‘int main(int, char**)’:
ex2_extern.cc:14: error: ‘ierr’ was not declared in this scope
ex2_extern.cc:11: warning: unused variable ‘l’
ex2_extern.cc:12: warning: unused variable ‘vec’
ex2_extern.cc:13: warning: unused variable ‘matrix’
make: [ex2_extern.o] Error 1 (ignored)

Where is the problem?

Kind regards, Sebastian

Was it helpful?

Solution 2

I can only presume that your CHKERRQ macro expands to something like

   if (ierr != 0) return ierr;

Which you could have determined by looking at the lines the compiler message worked out and then finding out what that macro did.

I don't think I dare comment on the style of this code. It just needs a serious rewrite. Taking C code and wrapping it with method calls in a class does not make it C++ code.

OTHER TIPS

According to CHKERRQ doc you need to use rather CHKERRV inside functions returning void or any other non-integer datatype.

PETSc has provided another way to check error in function without return valus: CHKERRABORT(comm,n).

CHKERRABORT: Checks error code returned from PETSc function. If non-zero it aborts immediately.

As following said, CHKERRV will ignore error and is not recommend.

You can use CHKERRV() which returns without an error code (bad idea since the error is ignored) or CHKERRABORT(comm,n) to have MPI_Abort() returned immediately.

reference: [1]https://petsc.org/release/docs/manualpages/Sys/CHKERRXX.html [2]https://petsc.org/release/docs/manualpages/Sys/CHKERRABORT.html#CHKERRABORT

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top