我是PETSc
的新人。我有一个很大的c ++代码,我想将PETSc
添加到我已经拥有的一些文件中,所以我必须以一种可以编译PETSc的方式更改我的makefile。
是否可以有两个不同的makefile,然后在我自己的makefile中调用PETSc
makefile?如果是的话,我该怎么做?
是否有人将PETSc
与自己的代码相关联?
顺便说一下,我使用Linux作为我的操作系统。
答案 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/mpif90
或COMP_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
请注意,chkopts
和clean
规则已由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。
希望有帮助...