I would like to make (a subset of) the PETSc library available from Haskell via a FFI interface in order to hide the memory and error management from the user;
- built PETSc 3.5.3 with shared libraries with the command shown below, the test suite runs successfully
- prepared a .hsc file #2 with the header imports, types and two example foreign function interfaces
- prepared a Makefile #3 to automate the build;
make test1
passes and fires up GHCi with the loaded module.
Since the library shines on parallel operations, enabled by MPI and fully distributed data structures, one should not expect much traffic of data with Haskell during most operations (all data assembly, computation and deallocation should be done by the library primitives) but only at "data ready". The PETSc-related Haskell functions will mostly have values in the IO monad, since we cannot guarantee purity (e.g. returned C error codes can vary due to reasons external to the program)
Bad ideaunsafePerformIO
would be needed to wrap the memoryalloca
tion and the error management. Is this line of thought correct?Can a binary compiled with GHC be executed withYesmpirun
?
I am open to all suggestions and remarks. Thank you in advance
-- NOTES:
We want GHC to produce a binary that mpirun
can execute: Since one can pass options from the GHC command line to the linker with the -optl
flag (reference here), I've been suggested a combination such as ghc -optl-static -lmpich
. I'll add more about this as soon as I can try it out.
1) config command:
$ ./configure --with-cc=gcc --with-cxx=g++ --with-fc=gfortran --with-shared-libraries=1 --download-mpich --download-fblaslapack
2) PETSC.hsc
{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}
module PETSc where
import Foreign
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
#include <petscksp.h>
#include <petscsys.h>
newtype PetscErrCode = PetscErrCode {unPetscErrCode :: CInt} deriving (Eq, Show)
newtype PetscInt = PetscInt {unPetscInt :: CInt} deriving (Eq, Show)
data Petsc
-- PetscErrorCode PetscInitialize(int *argc,char ***args,const char file[],const char help[])
foreign import ccall unsafe "petscsys.h PetscInitialize"
c_petscInitialize :: Ptr CInt -> Ptr (Ptr CString) -> CString -> CString -> IO PetscErrCode
-- PetscErrorCode PetscFinalize(void)
foreign import ccall unsafe "petscsys.h PetscFinalize"
c_petscFinalize :: IO PetscErrCode
3) Makefile
PETSC_DIR_ARCH = ${PETSC_DIR}/arch-darwin-c-debug
PETSc.hs:
hsc2hs PETSc.hsc -I ${PETSC_DIR}/include -I ${PETSC_DIR_ARCH}/include
test1: PETSc.hs
ghci -dynamic PETSc.hs -L${PETSC_DIR_ARCH}/lib