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

时间:2014-01-24 17:26:13

标签: c++ linux makefile include-path petsc

我是PETSc的新人。我有一个很大的c ++代码,我想将PETSc添加到我已经拥有的一些文件中,所以我必须以一种可以编译PETSc的方式更改我的makefile。

是否可以有两个不同的makefile,然后在我自己的makefile中调用PETSc makefile?如果是的话,我该怎么做?

是否有人将PETSc与自己的代码相关联?

顺便说一下,我使用Linux作为我的操作系统。

4 个答案:

答案 0 :(得分:3)

我对Makefiles不太熟悉,所以我只列出“黑客”方法。我们稍后将在本文中研究“hack”方法。我有一个Makefile和一个示例源代码,ex1.cpp使用了很少的PETSc数组,向量,函数以及我自己的常规C / C ++数组,它与PETSc数组和向量进行数据交换。这可以被认为是你案件的缩影版。

我的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

当然,您需要将PETSC_DIR编辑到系统上的PETSc目录位置。键入“make ex1”将编译并链接源代码以创建可执行文件并执行它。

在我的系统上执行“make ex1”之后,会显示编译和链接的两个过程输出,如下所示:

编译 -

  

/ 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 /包括ex1.cpp

链接 -

  

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

所以“黑客”技巧是你运行Makefile并将编译和链接过程输出与这个PETSc案例分开。您对原始的无PETSc源代码执行相同的操作,并记下编译和链接过程输出。

假设使用无PETSc版本,编译过程输出为 g ++ -o ex1.o -I / random_path ex1.cpp ,链接过程输出为 g ++ -w -o ex1 ex1.o -llib1 -L / random_lib2

下一步是合并PETSc代码和无PETSc代码的编译路径,并与链接相同。 因此,修改后的编译和链接过程将是:

修改编译 -

  

/ 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

修改链接 -

  

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

您可以直接在终端上键入修改后的命令,或者创建一个BASH脚本来运行它们。

下面列出了计算数组中数字倒数的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;

}

答案 1 :(得分:3)

编辑:虽然这是一篇很老的帖子,但我确信仍有人在努力解决这个问题。

此外,对于petsc 3.6.x(和slepc 3.6.x),情况显然略有改变。

我目前在我的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

使用这个我可以构建

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

其中COMP_DIR必须手动设置(例如COMP_DIR = /usr/bin/mpif90COMP_DIR = /usr/bin/gfortran)和COMP_FLAGS是其他标志(例如'-g O0'),以及

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

再次LINK_DIR必须手动设置(例如/usr/bin/g++),LINK_FLAGS包含其他标记(例如-fPIC)。

然后可以使用这些来创建编译F90文​​件的规则(我确信C非常相似):

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

和主程序:

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

其中ObjectFiles包含项目中所有文件的列表,LINK_LIB对应其他链接(例如-lgfortran)。

这对我来说很好,但欢迎提出改进建议。

原帖: 而不是Divakar描述的hack,您可以通过运行

轻松找到链接标志和包含目录以进行编译。
make getlinklibs
make getincludedirs
主要的petsc目录中的

,如here ...

所述

答案 2 :(得分:1)

我遇到了同样的问题,为此我做了一个简单而全面的makefile(在Linux操作系统下使用)。 假设代码存储在ex_1.cpp中。假设PETSc安装在/usr/local/petsc/petsc-3.7.4中。安装PETSc后,可以在configure.log文件中找到适当的环境变量。

然后可以使用以下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

请注意,chkoptsclean规则已由PETSc定义。 可执行文件将存储为ex_1.out。 要编译和链接代码,请使用make ex_1并运行可执行文件,使用make run_1

答案 3 :(得分:1)

这是一个旧帖子,但是我相信仍然有人为此而苦苦挣扎

我没有在C / C ++中尝试过,但是在Fortran中,在编译器/链接器命令中添加正确的文件夹和库对我有用:

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

不需要包含变量/规则/测试文件,这破坏了我的makefile。

希望有帮助...