3

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

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

有没有人有任何链接PETSc到自己的代码的经验?

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

4

4 回答 4

3

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

我的 Makefile –</p>

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-内联 -O0 -I/usr/local/petsc/include -I/usr/local/petsc/arch-linux2-c-debug/include 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

因此,“hack”技巧是您运行 Makefile 并将编译和链接过程输出与此 PETSc 案例分开。您对不含 PETSc 的原始源代码执行相同操作,并记下编译和链接过程输出。

假设使用 PETSc-free 版本,编译过程输出为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-内联 -O0 -I/usr/local/petsc/include -I/usr/local/petsc/arch-linux2-c-debug/include –I/random_path ex1.cpp

修改后的链接——</p>

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;

}
于 2014-02-24T16:52:35.097 回答
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)

whereCOMP_DIR必须手动设置(例如COMP_DIR = /usr/bin/mpif90or COMP_DIR = /usr/bin/gfortran)并且COMP_FLAGS是附加标志(例如'-g O0'),以及

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

where 再次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 主目录中,如此处所述...

于 2014-07-09T13:01:18.743 回答
1

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

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

于 2016-12-07T15:13:18.413 回答
1

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

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

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

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

希望能帮助到你...

于 2018-10-12T06:48:09.267 回答