Я новичок в PETSc
, У меня большой код на C ++, и я хочу добавить PETSc
к некоторым файлам, которые у меня уже есть, поэтому я должен изменить свой make-файл так, чтобы он также мог компилировать PETSc.
Можно ли иметь два разных make-файла и затем вызвать PETSc
makefile в моем собственном make-файле? если так, как я могу это сделать?
У кого-нибудь есть опыт связывания PETSc
к собственному коду?
Кстати, я использую Linux в качестве операционной системы.
Я не слишком знаком с 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-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
-Write-Strings -Wno-строгого псевдонима -Wno-unknown-pragmas -g3 -fno-inline -O0 -I / usr / local / petsc / include -I / usr / local / petsc / arch-linux2-c-debug /включают -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, как описано Вот…
Я столкнулся с той же проблемой, и для этого я сделал простой, но всеобъемлющий 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
,
Это старый пост, но я уверен, что есть еще люди, которые борются с этим
Я не пробовал в C / C ++, но в Fortran добавление правильных папок и библиотек в команды компилятора / компоновщика работало для меня:
-I${PETSC_DIR}/include
-L${PETSC_DIR}/lib -lpetscsys -lpetscXXX
без необходимости включать переменные / правила / тестовый файл, который сломал мой make-файл.
Надеюсь, поможет…