Использование PETSc на make-файле в моем пользовательском make-файле
Я новичок в PETSc
, У меня большой код на C++, и я хочу добавить PETSc
к некоторым файлам, которые у меня уже есть, поэтому я должен изменить свой make-файл так, чтобы он также мог компилировать PETSc.
Можно ли иметь два разных make-файла и затем вызвать PETSc
makefile в моем собственном make-файле? если так, как я могу это сделать?
У кого-нибудь есть опыт связывания PETSc
к собственному коду?
Кстати, я использую Linux в качестве операционной системы.
4 ответа
Я не слишком знаком с Makefiles, поэтому я бы просто перечислил метод "взлома". Мы рассмотрим метод "взломать" в этом тексте позже. У меня есть 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 -Write-strings -Wno-строго-псевдонимы -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
Таким образом, хитрость заключается в том, что вы запускаете 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 -Write-strings -Wno-строго-псевдонимы -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
Модифицированные ссылки -
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).
В настоящее время я использую следующие строки в моем make-файле Ubuntu 14.04 LTS для файлов 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, вы можете легко найти флаги ссылок и каталоги включения для компиляции, запустив
make getlinklibs
make getincludedirs
в главном каталоге petsc, как описано здесь...
Это старый пост, но я уверен, что есть еще люди, которые борются с этим
Я не пробовал в C/C++, но в Fortran добавление правильных папок и библиотек в командах компилятора / компоновщика работало для меня:
-I${PETSC_DIR}/include
-L${PETSC_DIR}/lib -lpetscsys -lpetscXXX
без необходимости включать переменные / правила / тестовый файл, который сломал мой make-файл.
Надеюсь, поможет...
Я столкнулся с той же проблемой, и для этого я сделал простой, но всеобъемлющий makefile
(для использования под ОС Linux). Предположим, что код хранится в 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
,