Использование PETSc на make-файле в моем пользовательском make-файле

Я новичок в PETSc, У меня большой код на C ++, и я хочу добавить PETSc к некоторым файлам, которые у меня уже есть, поэтому я должен изменить свой make-файл так, чтобы он также мог компилировать PETSc.

Можно ли иметь два разных make-файла и затем вызвать PETSc makefile в моем собственном make-файле? если так, как я могу это сделать?

У кого-нибудь есть опыт связывания PETSc к собственному коду?

Кстати, я использую Linux в качестве операционной системы.

3

Решение

Я не слишком знаком с 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;

}
3

Другие решения

редактировать: Хотя это старый пост, я уверен, что есть люди, которые борются с этим.

Кроме того, вещи, очевидно, немного изменились для 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, как описано Вот

3

Я столкнулся с той же проблемой, и для этого я сделал простой, но всеобъемлющий 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,

1

Это старый пост, но я уверен, что есть еще люди, которые борются с этим

Я не пробовал в C / C ++, но в Fortran добавление правильных папок и библиотек в команды компилятора / компоновщика работало для меня:

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

без необходимости включать переменные / правила / тестовый файл, который сломал мой make-файл.

Надеюсь, поможет…

0
По вопросам рекламы [email protected]