Использование 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,

Другие вопросы по тегам