我是新来的PETSc
。我有一个很大的 c++ 代码,我想添加PETSc
到我已经拥有的一些文件中,所以我必须更改我的 makefile 以使其也可以编译 PETSc。
是否可以有两个不同的makefile,然后PETSc
在我自己的makefile中调用makefile?如果是这样,我该怎么做?
有没有人有任何链接PETSc
到自己的代码的经验?
顺便说一句,我使用 Linux 作为我的操作系统。
我是新来的PETSc
。我有一个很大的 c++ 代码,我想添加PETSc
到我已经拥有的一些文件中,所以我必须更改我的 makefile 以使其也可以编译 PETSc。
是否可以有两个不同的makefile,然后PETSc
在我自己的makefile中调用makefile?如果是这样,我该怎么做?
有没有人有任何链接PETSc
到自己的代码的经验?
顺便说一句,我使用 Linux 作为我的操作系统。
我对 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;
}
编辑:虽然这是一篇旧帖子,但我相信仍然有人为此而苦苦挣扎。
此外,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/mpif90
or 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 主目录中,如此处所述...
我遇到了同样的问题,为此我做了一个简单但全面的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
请注意,chkopts
和clean
规则已经由 PETSc 定义。可执行文件将存储为ex_1.out
. 要编译和链接代码,请使用make ex_1
和运行可执行文件,请使用make run_1
.
这是一个旧帖子,但我相信仍有人为此苦苦挣扎
我没有在 C/C++ 中尝试过,但在 Fortran 中,在编译器/链接器命令中添加正确的文件夹和库对我有用:
-I${PETSC_DIR}/include
-L${PETSC_DIR}/lib -lpetscsys -lpetscXXX
不需要包含变量/规则/测试文件,这破坏了我的makefile。
希望能帮助到你...