I am not too familiar with Makefiles, so I would just list out the “hack” method. We will look into the “hack” method in this text later on. I have a Makefile and a sample source code, ex1.cpp that uses few PETSc arrays, vectors, functions along with my own regular C/C++ array that does data exchange with PETSc array and vectors. This could be thought of as a miniature version of your case.
My Makefile –
PETSC_DIR=/usr/local/petsc
include ${PETSC_DIR}/conf/variables
include ${PETSC_DIR}/conf/rules
include ${PETSC_DIR}/conf/test
CLINKER=g++
ex1 : ex1.o chkopts
${CLINKER} -w -o ex1 ex1.o ${PETSC_LIB}
${RM} ex1.o
./ex1
Of course you need to edit PETSC_DIR to the PETSc directory location on your system. Typing “make ex1” would compile and link the source code to create an executable and execute it.
After I do “make ex1” on my system, the two process outputs of compilation and linking are shown, that are listed here as follows:
Compilation -
/usr/local/petsc/arch-linux2-c-debug/bin/mpicc -o ex1.o -c -fPIC -Wall
-Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -g3 -fno-inline -O0 -I/usr/local/petsc/include -I/usr/local/petsc/arch-linux2-c-debug/include ex1.cpp
Linking -
g++ -w -o ex1 ex1.o
-Wl,-rpath,/usr/local/petsc/arch-linux2-c-debug/lib -L/usr/local/petsc/arch-linux2-c-debug/lib -lpetsc -Wl,-rpath,/usr/local/petsc/arch-linux2-c-debug/lib -lflapack -lfblas -lX11 -lpthread -lm -Wl,-rpath,/usr/lib/gcc/x86_64-linux-gnu/4.6 -L/usr/lib/gcc/x86_64-linux-gnu/4.6 -Wl,-rpath,/usr/lib/x86_64-linux-gnu -L/usr/lib/x86_64-linux-gnu -Wl,-rpath,/lib/x86_64-linux-gnu -L/lib/x86_64-linux-gnu -lmpichf90 -lgfortran -lm -lgfortran -lm -lquadmath -lm -lmpichcxx -lstdc++ -ldl -lmpich -lopa -lmpl -lrt -lpthread -lgcc_s –ldl
So the “hack” trick is that you run the Makefile and separate the compilation and linking process outputs with this PETSc case. You do the same with your original source code that is PETSc-free and note down compilation and linking process outputs with it.
Let’s suppose with PETSc-free version, the compilation process output is g++ -o ex1.o –I/random_path ex1.cpp and linking process output is g++ -w -o ex1 ex1.o –llib1 –L/random_lib2.
Next step is to merge the compilation paths for PETSc code and PETSc-free code and same with linking.
Thus, the modified compilation and linking processes would be:
Modified Compilation -
/usr/local/petsc/arch-linux2-c-debug/bin/mpicc -o ex1.o -c -fPIC -Wall
-Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -g3 -fno-inline -O0 -I/usr/local/petsc/include -I/usr/local/petsc/arch-linux2-c-debug/include –I/random_path ex1.cpp
Modified Linking –
g++ -w -o ex1 ex1.o
-Wl,-rpath,/usr/local/petsc/arch-linux2-c-debug/lib -L/usr/local/petsc/arch-linux2-c-debug/lib -lpetsc -Wl,-rpath,/usr/local/petsc/arch-linux2-c-debug/lib -lflapack -lfblas -lX11 -lpthread -lm -Wl,-rpath,/usr/lib/gcc/x86_64-linux-gnu/4.6 -L/usr/lib/gcc/x86_64-linux-gnu/4.6 -Wl,-rpath,/usr/lib/x86_64-linux-gnu -L/usr/lib/x86_64-linux-gnu -Wl,-rpath,/lib/x86_64-linux-gnu -L/lib/x86_64-linux-gnu -lmpichf90 -lgfortran -lm -lgfortran -lm -lquadmath -lm -lmpichcxx -lstdc++ -ldl -lmpich -lopa -lmpl -lrt -lpthread -lgcc_s –ldl –llib1 –L/random_lib2
You may type the modified commands directly onto the terminal or make a BASH script to run them.
The PETSc example code that calculates reciprocal of the numbers in an array is listed below for the sake of reference:
// EX1.CPP
#include <petscvec.h>
#include <petscmat.h>
#include <petscksp.h>
Vec Arr2Vec(double *arr2, int SIZE);
// MAIN FUNCTION
int main(int argc,char **argv)
{
// Initialize PetSc
PetscInitialize(&argc,&argv,(char*)0,"Testing a program!");
// Initialize parameters
int SIZE = 3;
PetscErrorCode ierr;
// **** Create a regular arary and set it with random numbers
double * arr2;
arr2 = new double [SIZE];
arr2[0] = 0.1;
arr2[1] = 0.4;
arr2[2] = 0.2;
// Convert regular arary to PETSc vector [Note that this must do the same effect as the two-step process of conversion from regular array to PETSc arary and that to PETSc vector as listed above]
Vec x = Arr2Vec(arr2, SIZE);
printf("Reciprocal Vector : \n"); VecReciprocal(x);
VecView(x,PETSC_VIEWER_STDOUT_WORLD);
//Cleanup
ierr = VecDestroy(&x);
CHKERRQ(ierr);
PetscFinalize();
return 0;
}
Vec Arr2Vec(double *arr2, int SIZE)
{
PetscScalar *array1;
PetscMalloc(SIZE*sizeof(PetscScalar),&array1);
for(int i=0;i<SIZE;i++)
array1[i]=arr2[i];
// Setup vector
Vec x;
VecCreate(PETSC_COMM_WORLD,&x);
VecSetSizes(x,PETSC_DECIDE,SIZE);
VecSetFromOptions(x);
// Place PetSc array as Vector
VecPlaceArray(x,array1);
return x;
}