简体   繁体   English

在我的用户定义的makefile中使用makefile上的PETSc

[英]Using PETSc on makefile within my user-defined makefile

I am new in PETSc . 我是PETSc新人。 I have a big c++ code and I want to add PETSc to some of the files that I already have, so I have to change my makefile in a way that it can compile PETSc as well. 我有一个很大的c ++代码,我想将PETSc添加到我已经拥有的一些文件中,所以我必须以一种可以编译PETSc的方式更改我的makefile。

Is it possible to have two different makefiles and then call PETSc makefile within my own makefile? 是否有可能有两个不同的makefile,然后在我自己的makefile中调用PETSc makefile? if so, how can I do this? 如果是的话,我怎么能这样做?

Does anyone have any experience in linking PETSc to their own code? 有没有人有任何将PETSc链接到他们自己的代码的经验?

By the way, I am using Linux as my operating system. 顺便说一句,我使用Linux作为我的操作系统。

I am not too familiar with Makefiles, so I would just list out the “hack” method. 我对Makefiles不太熟悉,所以我只列出“hack”方法。 We will look into the “hack” method in this text later on. 我们稍后将在本文中研究“hack”方法。 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. 我有一个Makefile和一个示例源代码,ex1.cpp使用了很少的PETSc数组,向量,函数以及我自己的常规C / C ++数组,它与PETSc数组和向量进行数据交换。 This could be thought of as a miniature version of your case. 这可以被认为是你案件的缩影版。

My Makefile – 我的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. 当然,您需要将PETSC_DIR编辑到系统上的PETSc目录位置。 Typing “make ex1” would compile and link the source code to create an executable and execute it. 键入“make ex1”将编译并链接源代码以创建可执行文件并执行它。

After I do “make ex1” on my system, the two process outputs of compilation and linking are shown, that are listed here as follows: 在我的系统上执行“make ex1”后,会显示编译和链接的两个过程输出,如下所示:

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 / 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 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. 因此,“黑客”技巧是您运行Makefile并将编译和链接过程输出与此PETSc案例分开。 You do the same with your original source code that is PETSc-free and note down compilation and linking process outputs with it. 您对原始的无PETSc源代码执行相同的操作,并记下编译和链接过程输出。

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 . 假设使用无PETSc版本,编译过程输出为g ++ -o ex1.o -I / random_path ex1.cpp ,链接过程输出为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. 下一步是合并PETSc代码和无PETSc代码的编译路径,并与链接相同。 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 / 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 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. 您可以直接在终端上键入修改后的命令,也可以创建BASH脚本来运行它们。

The PETSc example code that calculates reciprocal of the numbers in an array is listed below for the sake of reference: 下面列出了计算数组中数字倒数的PETSc示例代码,以供参考:

// 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;

}

edit: Though this is an old post, I am sure there are still people struggling with this. 编辑:虽然这是一个老帖子,但我确信仍有人在努力解决这个问题。

Furthermore, things apparently changed slightly for petsc 3.6.x (and slepc 3.6.x). 此外,对于petsc 3.6.x(和slepc 3.6.x),事情显然略有改变。

I currently use the following lines in my ubuntu 14.04 LTS makefile for F90 files (using both petsc 3.6.1 and slepc 3.6.0): 我目前在我的ubuntu 14.04 LTS makefile中使用以下行来获取F90文件(使用petsc 3.6.1和slepc 3.6.0):

# PETSC and SLEPC directories
PETSC_DIR = /opt/petsc-3.6.1
SLEPC_DIR = /opt/slepc-3.6.0
include  $(PETSC_DIR)/lib/petsc/conf/variables
include  $(SLEPC_DIR)/lib/slepc/conf/slepc_variables

Using this I can construct the 使用这个,我可以构建

# Compiler command
COMPILE = $(COMP_DIR) $(COMP_FLAGS) $(PETSC_FC_INCLUDES) $(SLEPC_INCLUDE)

where COMP_DIR has to be set manually (eg COMP_DIR = /usr/bin/mpif90 or COMP_DIR = /usr/bin/gfortran ) and COMP_FLAGS are additional flags (eg '-g O0'), as well as the 其中COMP_DIR必须手动设置(例如COMP_DIR = /usr/bin/mpif90COMP_DIR = /usr/bin/gfortran ), COMP_FLAGS是附加标志(例如'-g O0'),以及

# Link command
LINK = $(LINK_DIR) &(LINK_FLAGS)

where again LINK_DIR has to be set manually (eg /usr/bin/g++ ) and LINK_FLAGS contains additional flags (eg -fPIC ). 其中LINK_DIR必须手动设置(例如/usr/bin/g++ ), LINK_FLAGS包含其他标志(例如-fPIC )。

These can then be used to create rules to compile the F90 files (I am sure C is pretty similar): 然后可以使用它们来创建编译F90文​​件的规则(我确信C非常相似):

%.o : %.f90
$(COMPILE) -c $<

and the main program: 和主程序:

main:   $(ObjectFiles) main.o
$(LINK) -o $@ $(ObjectFiles) main.o $(LINK_LIB) $(PETSC_LIB) $(SLEPC_LIB)

where ObjectFiles contains a list of all the files in the project and LINK_LIB corresponds to other links (eg -lgfortran ). 其中ObjectFiles包含项目中所有文件的列表, LINK_LIB对应于其他链接(例如-lgfortran )。

This works fine for me, yet suggestions for improvements are always welcome. 这对我来说很好,但总是欢迎改进建议。

original post: Instead of the hack described by Divakar, you can easily find out the link flags and the include directories for compilation by running 原帖:除了Divakar描述的黑客,你可以通过运行轻松找到链接标志和包含目录进行编译

make getlinklibs
make getincludedirs

in the main petsc directory, as described here ... 在主PETSc的目录,描述在这里 ...

I have met with the same problem, and for that I made a simple but comprehensive makefile (to be used under Linux OS). 我遇到了同样的问题,为此我制作了一个简单但全面的makefile (在Linux OS下使用)。 Suppose that the code is stored in ex_1.cpp . 假设代码存储在ex_1.cpp PETSc is assumed to be installed in /usr/local/petsc/petsc-3.7.4 . 假设PETSc安装在/usr/local/petsc/petsc-3.7.4 One can find the proper environmental variables in configure.log file after installation of PETSc. 安装PETSc后,可以在configure.log文件中找到适当的环境变量。

One can then use the following makefile to compile and link the C++ code: 然后可以使用以下makefile来编译和链接C ++代码:

# PETSC 3.7.4 Makefile (Linux)
#----------------------------------------

# NOTE: look up `configure.log` in PETSc folder to obtain
# the proper environmental parametres
PETSC_DIR=/usr/local/petsc/petsc-3.7.4
PETSC_ARCH=arch-linux2-c-debug
PETSC_CONFIGDIR=${PETSC_DIR}/lib/petsc/

include ${PETSC_CONFIGDIR}/conf/variables
include ${PETSC_CONFIGDIR}/conf/rules
include ${PETSC_CONFIGDIR}/conf/test

# compile and link options
LOCDIR= ./
DIRS =
CXX_STD = -std=c++11
CXX_CFLAGS = ${CXX_STD} ${CXX_FLAGS} ${PETSC_CCPPFLAGS} 
LIBS = ${PETSC_LIB}
CXX_LFLAGS = ${CXX_STD}

#OBJS = $(SRC1:.cpp=.o)
#----------------------------------------

.PHONY: default allclean run_1

default: chkopts
    @echo "--- PETSC CONFIGURATION -----------------"
    @if [ "${CUDAC}" != "" ]; then \
        echo "Using CUDA compile: ${PETSC_CUCOMPILE}";\
    fi
    @echo "Using C/C++ linker: ${PCC_LINKER}"
    @echo "Using C/C++ flags: ${PCC_LINKER_FLAGS}"
    @echo "Using C++ flags: ${CXX_FLAGS}"
    @echo "-----------------------------------------"
    @echo "Using libraries: ${PETSC_LIB}"
    @echo "-----------------------------------------"
    @echo "Using mpiexec: ${MPIEXEC}"
    @echo "========================================="

ex_1: default ex_1.o 
    @echo "---- LINK -----"
    ${CXX} -w -o ex_1.out ex_1.o ${LIBS} ${CXX_LFLAGS}
    -${RM} ex_1.o
    @echo "==============="

ex_1.o:
    @echo "--- COMPILE ---"
    ${CXX} -o ex_1.o -c ex_1.cpp ${CXX_CFLAGS}
    @echo "==============="

run_1:
    @echo "==============="
    @echo "--- EXECUTE ---"
    @echo "starting on `hostname` at `date`"
    @echo "machine characteristics: `uname -a`"
    @echo "==============="
    ${MPIEXEC} -n 1 ./ex_1.out #-info
    @echo "==============="

 allclean: clean
    -@${RM} *.out

Note that chkopts and clean rules are already defined by PETSc. 请注意,PETSc已经定义了chkoptsclean规则。 The executable file will be stored as ex_1.out . 可执行文件将存储为ex_1.out To compile and link the code, use make ex_1 and to run the executable file, use make run_1 . 要编译和链接代码,请使用make ex_1并运行可执行文件,使用make run_1

This is an old post, however I am sure there are still people struggling with this 这是一个古老的帖子,但我相信仍然有人在努力解决这个问题

I didn't tried in C/C++ but in Fortran, adding the correct folders and libraries, in the compiler/linker commands, worked for me: 我没有尝试过C / C ++,但是在Fortran中,在编译器/链接器命令中添加正确的文件夹和库对我有用:

-I${PETSC_DIR}/include
-L${PETSC_DIR}/lib -lpetscsys -lpetscXXX

without the need of including variables/rules/test file, that broke my makefile. 不需要包含变量/规则/测试文件,这破坏了我的makefile。

Hope it helps... 希望能帮助到你...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM