Unable to use f2py to link large PETSc/SLEPc Fortr

2020-08-01 15:46发布

问题:

I am attempting to use f2py to create a python module for my Fortran code that uses both PETSc and SLEPc (this question is very closely related to this post, but the discussion there was unable to solve my problem--see comments at bottom of this post). The code is made up of many files and subroutines, but I only need access to the outermost main/driver function in python. The first step I took was to use the SLEPc-provided makefile template to generate all object files (the final linking fails because the outer function is now a subroutine rather than a main program, but I'm not worrying about that for now since I'm just after the object files).

From there, I've tried two approaches. The first is to simply call f2py as follows:

f2py -c -m modname outer_driver.f90 file1.o file2.o file3.o...

This appears to work, but upon attempting to import to python, the SLEPc (and, I presume, PETSc) objects/functions cannot be found:

>>> import mod_name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(./mod_name.so, 2): Symbol not found: _epscreate_
  Referenced from: ./mod_name.so
  Expected in: flat namespace
 in ./mod_name.so

The second approach assumes that I need to link against the SLEPc/PETSc libraries as well. Thus, I've added a line to my makefile:

modname.so: outer_driver.f90
        f2py -c -m modname outer_driver.f90 file1.o file2.o file3.o ${SLEPC_EPS_LIB}

Upon running "make modname.so," f2py is unable to run completely. Here is the output from that:

running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "modname" sources
f2py options: []
f2py:> /tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7/modnamemodule.c
creating /tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7
Reading fortran codes...
    Reading file 'outer_driver.f90' (format:free)
Post-processing...
    Block: modname
            Block: outer_driver
Post-processing (stage 2)...
Building modules...
    Building module "modname"...
        Constructing wrapper function "outer_driver"...
          outer_driver()
    Wrote C/API module "modname" to file "/tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7/modnamemodule.c"
  adding '/tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7/fortranobject.c' to sources.
  adding '/tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7' to include_dirs.
copying /usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7
copying /usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmpIH70ZJ/src.macosx-10.10-x86_64-2.7
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/local/bin/gfortran
customize Gnu95FCompiler
customize Gnu95FCompiler using build_ext
building 'modname' extension
compiling C sources
C compiler: clang -fno-strict-aliasing -fno-common -dynamic -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes

error: unknown file type '' (from '-Wl,-rpath,/usr/local/Cellar/slepc/3.7.3_4/real/lib')
make: *** [modname.so] Error 1

The OP of the Using f2py on a fortran code linked to PETSc post states that he was able to bypass using the -Wl,-rpath flags, which appear to be a problem here as well, by setting the LD_LIBRARY_PATH environment variable to the PETSc library. However, if I do the same thing (set to SLEPc library, which I believe also implies the PETSc library), it is not helpful to me for either approach. Can anybody suggest an approach I might use?

UPDATE: A bit more information was requested about the -Wl,rpath error and where it comes from. From what I understand, those flags come from using the SLEPc/PETSc linking. So, in my makefile, they come from the ${SLEPC_EPS_LIB} variable. When interpreted, the full command is extremely long, but I'll include it anyways in case something can be mined from there. Keep in mind, I didn't use the actual file names in my examples above--I had just simplified for clarity. The file names will be different below.

f2py -c -m iga_blade_py run_analysis.f90 modules.o forces.o param.o cname.o curve_input_nrb_mc.o shell_input_nrb_mp.o shell_reduce_node.o shell_input_nrb.o material_input.o material_calculate.o shell_laminate2.o iosol.o shell_gp_info.o shell_profile_vector.o shell_genIEN_INN.o shell_genSparStruc.o shell_genGP_GW.o shell_eval_SHAPE.o shell_dersbasisfuns.o shell_e3LRhs_KLShell.o shell_e3LRhs_KLShell_pen_disp.o shell_e3LRhs_KLShell_pen_rot.o shell_KL_geo.o cross_prod.o shell_BCLhs_3D.o shell_FillSparseMat_3D.o shell_SparseMatLoc_3D.o shell_SparseCG.o shell_skyline.o shell_SparseProd.o shell_IntElmAss_post2.o shell_e3LRhs_KLShell_post.o curve_element_project.o shell_mnrb_find_search_locs.o shell_nrb_find_point.o patch_point_proj.o petsc_genSparStruc.o viz_read_mesh_points.o driver.o input_shell.o solflow.o shell_IntElmAss.o petsc_fillMat.o shell_IntElmAss_pen.o petsc_prepSolve.o shell_allocate_LRhs.o petsc_rank.o solflow_lin_buck.o solflow_vibr.o shell_IntElmAss_mass.o -Wl,-rpath,/usr/local/Cellar/slepc/3.7.3_4/real/lib -L/usr/local/Cellar/slepc/3.7.3_4/real/lib -lslepc -Wl,-rpath,/usr/local/opt/arpack/lib -L/usr/local/opt/arpack/lib -lparpack -larpack -Wl,-rpath,/usr/local/Cellar/petsc/3.7.5/real/lib -L/usr/local/Cellar/petsc/3.7.5/real/lib -lpetsc -L/usr/local/opt/superlu_dist/lib -lsuperlu_dist -Wl,-rpath,/usr/local/opt/mumps/libexec/lib -L/usr/local/opt/mumps/libexec/lib -lcmumps -ldmumps -lsmumps -lzmumps -lmumps_common -lpord -Wl,-rpath,/usr/local/opt/parmetis/lib -L/usr/local/opt/parmetis/lib -lparmetis -Wl,-rpath,/usr/local/opt/metis/lib -L/usr/local/opt/metis/lib -lmetis -Wl,-rpath,/usr/local/opt/hypre/lib -L/usr/local/opt/hypre/lib -lHYPRE -Wl,-rpath,/usr/local/opt/libevent/lib -L/usr/local/opt/libevent/lib -Wl,-rpath,/usr/local/Cellar/open-mpi/2.0.2/lib -L/usr/local/Cellar/open-mpi/2.0.2/lib -Wl,-rpath,/usr/local/lib -L/usr/local/lib -Wl,-rpath,/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries -L/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries -Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin -lclang_rt.osx -lc++ -Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin -lclang_rt.osx -Wl,-rpath,/usr/local/opt/scalapack/lib -L/usr/local/opt/scalapack/lib -lscalapack -Wl,-rpath,/usr/local/opt/suite-sparse/lib -L/usr/local/opt/suite-sparse/lib -lumfpack -lklu -lcholmod -lbtf -lccolamd -lcolamd -lcamd -lamd -lsuitesparseconfig -Wl,-rpath,/usr/local/opt/sundials/lib -L/usr/local/opt/sundials/lib -lsundials_cvode -lsundials_nvecserial -lsundials_nvecparallel -llapack -lblas -Wl,-rpath,/usr/local/opt/netcdf/lib -L/usr/local/opt/netcdf/lib -lnetcdf -Wl,-rpath,/usr/local/opt/hdf5/lib -L/usr/local/opt/hdf5/lib -lhdf5_hl -lhdf5 -Wl,-rpath,/usr/local/opt/hwloc/lib -L/usr/local/opt/hwloc/lib -lhwloc -Wl,-rpath,/usr/local/opt/fftw/lib -L/usr/local/opt/fftw/lib -lfftw3_mpi -lfftw3 -lmpi_usempif08 -lmpi_usempi_ignore_tkr -lmpi_mpifh -lgfortran -Wl,-rpath,/usr/local/Cellar/gcc/6.3.0_1/lib/gcc/6/gcc/x86_64-apple-darwin15.6.0/6.3.0 -L/usr/local/Cellar/gcc/6.3.0_1/lib/gcc/6/gcc/x86_64-apple-darwin15.6.0/6.3.0 -Wl,-rpath,/usr/local/Cellar/gcc/6.3.0_1/lib/gcc/6 -L/usr/local/Cellar/gcc/6.3.0_1/lib/gcc/6 -lgfortran -lgcc_ext.10.5 -lquadmath -lm -lclang_rt.osx -lc++ -lclang_rt.osx -Wl,-rpath,/usr/local/opt/libevent/lib -L/usr/local/opt/libevent/lib -Wl,-rpath,/usr/local/Cellar/open-mpi/2.0.2/lib -L/usr/local/Cellar/open-mpi/2.0.2/lib -Wl,-rpath,/usr/local/lib -L/usr/local/lib -Wl,-rpath,/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries -L/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries -ldl -lmpi -lSystem -Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin -lclang_rt.osx -ldl

SOLVED: I was ultimately able to find a couple different ways to get around this. The most straightforward is essentially the same as the second (makefile-based) approach I describe, but I manually remove every -Wl,rpath command from the SLEPC_EPS_LIB variable. Additionally, I learned through the PETSc mailing list that it is possible to use f2py only to generate the requisite .c, .f90, and .pyc files. You can then compile yourself, linking against the requisite libraries. Obviously this is more involved, but it is also an option.