- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to use a numerical library called UMFPACK. 20 years ago it was all fortran, but today it's in C. The attached fortran file is a supplied sample Main program to demonstrate calling umfpack from a fortran program. The attached C file contains C wrapper routines being called from fortran. When I build it, I get unresolved externals for all the C routines being called from fortran.
I looked at the Intel sample project called "Fortran-Calls-C", but the Microsoft C compiler wouldn't let me put extern "C" into umfpack's c file. Maybe that's a good thing, because I really don't want to be editing their C files because there is a large number of them.
How do I get this to work?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since it's a *.c file, extern "C" is already implicit. You could write your own wrappers in Fortran. Here is a start:
module M use ISO_C_BINDING implicit none private integer, parameter, public :: K1 = C_INT64_T integer, parameter, public :: UMFPACK_CONTROL = 17 ! Or whatever integer, parameter, public :: UMFPACK_INFO = 5 ! Or whatever end module M module N use M use ISO_C_BINDING implicit none private character(*), parameter, public :: CODE = merge('di','dl',K1 == C_INT) public umf4def interface subroutine umf4def(Control) bind(C,name='umfpack_'//CODE//'_defaults') import implicit none real(C_DOUBLE) Control(UMFPACK_CONTROL) end subroutine umf4def end interface public umf4pcon interface subroutine UMFPACK_report_control(Control) bind(C,name='umfpack_'//CODE//'report_control') import implicit none real(C_DOUBLE) Control(UMFPACK_CONTROL) end subroutine UMFPACK_report_control end interface public umf4sym interface subroutine umf4sym(m,n,Ap,Ai,Ax,Symbolic,Control,Info) import implicit none integer(K1) m,n,Ap(*),Ai(*) real(C_DOUBLE) Ax(*) type(C_PTR) Symbolic(*) ! Need context to be sure of translation real(C_DOUBLE) Control(UMFPACK_CONTROL) real(C_DOUBLE) Info(UMFPACK_INFO) end subroutine umf4sym end interface contains subroutine make_filename(filenum,prefix,filename) bind(C,name='make_filename') use ISO_C_BINDING use M implicit none integer(K1), value :: filenum character(kind=C_CHAR) prefix(*) character(kind=C_CHAR) filename(*) character(len=40,kind=C_CHAR) number integer i, j write(number,'(i0,a)') filenum,C_NULL_CHAR i = 1 j = 1 do if(prefix(i) == C_NULL_CHAR) then exit else if(any(prefix(i) == & [C_FORM_FEED,C_NEW_LINE,C_CARRIAGE_RETURN,C_HORIZONTAL_TAB])) then else filename(j) = filename(i) j = j+1 end if i = i+1 end do filename(i:i+len_trim(number)-1) = transfer(number,C_NULL_CHAR,len_trim(number)) end subroutine make_filename subroutine umf4pcon(Control) use ISO_FORTRAN_ENV implicit none real(C_DOUBLE) Control(UMFPACK_CONTROL) flush(OUTPUT_UNIT) call UMFPACK_report_control(Control) flush(OUTPUT_UNIT) end subroutine umf4pcon end module N
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have to select one of several routes, depending on your objectives. Typically, open-source packages tell you how to build mixed-language programs using GNU compilers.
If you are using the 64-bit versions of IFort and VC, for example, it should suffice to use the /names:lowercase option when compiling your Fortran sources.
The extern "C" {} mechanism is meant to be used in C++ source code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks to both for the replies (and on the weekend, too!).
My intel fortran is installed in Program Files (x86), so I think that means it must be a 32-bit version. So I guess /names:lowercase won't work.
I put in an INTERFACE thing for the first umfpack routine which is called, and that got rid of the unresolved external for that item.
I did some more googling thinking plenty of people must have already tackled this problem. I found http://geo.mff.cuni.cz/~lh/Fortran/UMFPACK/README.html# ; where this fellow says he's made f90 style interfaces. I have downloaded them, but have not yet tried them. Even with this, though, there's a lot of work to do for me to figure it all out.
Another option is to go back to the fortran version of umfpack and try to fix what appears to be a bug that popped up while I was running a set of test cases. The fortran version worked really well with compaq fortran.
At this point I will try to find the fortran bug. Depending on how that goes, I might again tackle trying to use the C version of umfpack.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Following the link in Quote #4 I see that the interfaces are f2003 rather than f90. I recommend that you try to make them fly because f2003 interfaces are in the opinion of many (see Quote #2) the easy way for a Fortran programmer to perform this sort of task.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, RO. I'm going to try that guy's stuff today.
BTW. I'm a runner, too, and my hair's as white as yours. May your miles bring smiles.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Error 106 error LNK2019: unresolved external symbol _umfpack_zi_symbolic referenced in function _MUMFPACK_mp_UMFPACK_ZI_SYMBOLIC umfpack.obj
I've spent the last hour trying to build one of the umfpack example programs. I can't figure out why I'm getting build errors like the above. What does this error mean? There is a file named umfpack.f90. It compiles without errors, and it has a CONTAINS block containing a routine named umfpack_zi_symbolic. I have no clue what _MUMFPACK_mp_UMFPACK_ZI_SYMBOLIC refers to as there is no routine by that name or anything close to it that I can find.
The VS 2012 project is attached. I hope it's something really simple I'm doing wrong.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The ..._mp_ refers to a module variable and/or entry point (subroutine or function).
My guess is a library that you created is NOT including an .OBJ file produced when compiling a Fortran source that contains a module (whose module name is mumfpack). The fix, is to add the .OBJ produced when compiling the source containing the memfpack (either to the library or to the link).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One other oddity, the error message contains "_umfpack_zi_symbolic"
Note the zi
The source code listed above concatenates \\CODE\\ in the middle of the name (none of which contains suffix of symbolic). The oddity is the values for CODE are 'di' and 'dl'. So... this is coming in from something else linked into your program.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim, you are conflating the code I posted in Quote #2 (and which the O.P. is not using) with the umfpack.f90 which he is using in the umfpack_simple.zip file from Quote #7. There is a function umfpack_zi_symbolic in there which is being compiled and the linker is calling _MUMFPACK_mp_UMFPACK_ZI_SYMBOLIC because it is a module procedure of module mUMFPACK. That function references function c_umfpack_zi_symbolic which is actually the name of a Fortran interface to umfpack_zi_symbolic from the library he is trying to interface to. So the library isn't getting included in the linking phase or the linker is seeing a 64-bit library (the mangled name for the symbol umfpack_zi_symbolic indicates the Fortran is getting compiled for 32 bits).
MK200 Brian Murphy M59 29315 147/222 15372/21032 12:05 - - 14:02 12:40 14:46 1:22:10 13:13
(?)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The \\CODE\\ stuff was something proposed by RO. I'm not using that approach. Instead I'm trying to use the f2003 interface downloaded from the link in Quote #4.
I've continued trying whatever I can think of, but I only get more build errors instead of fewer. I really don't know what I'm doing. If it were all fortran, I'd stand half chance. But trying to use the C version of umfpack is over my head.
The only thing I'm using from this library is to LU factor (and solve) real and complex asymmetric matrices which are very sparse and are stored that way. Does the Intel MKL have routines for this? I have IMSL, but I can't use it because the IMSL salesman told me to forget it because he said an IMSL distribution license is too expensive.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is a way of working around the problem.
The undefined _umfpack_zi_* symbols are a nuisance in the present circumstances. They probably would only be needed if you were using UmfPack to solve equations whose coefficients are complex numbers. The example code does not actually call those routines, but the Fortran 90 interfaces include them, so the linker wants them. However, the libraries that you have produced may not include these unnecessary routines.
How to tell the linker not to bother about these routines? I can think of two simple solutions. One is to edit (or add #ifdef COMPLEX...#endif) umfpack.f90 to remove/hide the _zi_ interface blocks and declarations. The other is to provide dummy code for the missing routines, relying upon the assumption that those are never called in the example code. I chose the latter option since it required less work.
Here is the dummy.c source code:
void umfpack_zi_symbolic(){} void umfpack_zi_numeric(){} void umfpack_zi_solve(){} void umfpack_zi_free_symbolic(){} void umfpack_zi_free_numeric(){} void umfpack_zi_scale(){} void umfpack_zi_defaults(){} void umfpack_zi_report_control(){} void umfpack_zi_report_info(){} void umfpack_zi_save_numeric(){} void umfpack_zi_save_symbolic(){} void umfpack_zi_load_numeric(){} void umfpack_zi_load_symbolic(){}
Just to test this, I downloaded SuiteSparse-2.4.0.tar.gz (old, but smaller than the huge current release, and sufficient for the present test) and built the umfpack.lib and amd.lib using Intel C. I then compiled umfpack.f90 and umfpack_simple_1basic.f90 (files in your zip file) using Intel Fortran and linked all of these with mkl_rt.lib. The EXE that was produced ran and output seemingly good results.
If you want to add an extra measure of safety, you can print a "missing routine called" message to stderr and return or call exit(1) in the body of each of these dummy routines.
Of course, the proper solution is to build a version of the UmfPack library that includes the umfpack_zi* routines. To me, that would be something that should be done only if it turns out to be necessary. Your zip files contained amd.lib but not umfpack.lib, so I don't know if the complex routines are actually within umfpack.lib. I was unable to build these libraries from the C sources in your zip since some required C header files were missing.
Intel MKL contains the Pardiso solver, which can solve linear equations with complex coefficients, and the MKL libraries have good support for multiple threads and high performance. See https://software.intel.com/en-us/node/470284 .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
mecej4, you're amazing! I wish I knew this stuff like you do.
When you built and ran 2.4.0 did you need to put in placeholder code for the "zi" routines?
I need to do Complex*16 matrices, but I think the "ci" versions are what I want, and not the "zi".
Tomorrow I will try to retrace your steps using 2.4.0. I will be using Microsoft C and Intel Fortran in either visual studio 2010 or 2012. If there was anything else you needed to do to get an error-free build, please let me know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The 2.4.0 distribution did not contain any Fortran 90 examples or interface code. It came with Fortran 77 examples, and I could build one of them without needing any dummy routines, but I needed to provide an interface to account for the different name mangling of GNU and Intel compilers.
The Lapack naming conversion is to use 's' as an indicator for single-precision-real, 'd' for double-precision-real, 'c' for single-precision complex and 'z' for double-precision complex.
Which version of SuiteSparse did you use? Older versions are easier to build but have fewer features, so a compromise would help. Users, of course, want the latest version, but building Unix/Linux-oriented packages on Windows sometimes takes quite a bit of work. Are you building for IA32 or X64?
I urge you to consider using MKL-Pardiso instead, unless you know reasons for preferring UmfPack over Pardiso. Pardiso is already available in pre-built libraries, and can be called from source code that is compiled with Intel Fortran and Intel C.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need to build for Windows only, but for both 32 and 64 bit. My eventual build target is a DLL which will be called from Excel visual basic, both 32 and 64 bit versions of Excel.
I have been trying with the "latest" SparseSuite which goes by 4.4.5. I thought their naming convention was "ci" for regular fortran style complex variables (re/im interleaved), and "zi" stood for the real and imag components being passed in using separate real arrays. But I have seen that other libraries like Lapack use "c" and "z" the way you described it.
Anyhow, if tomorrow I can get 2.4.0 to build and run, I will try to use that with my app.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just noticed your comment about MKL-Pardiso. I've heard of Pardiso but I don't know what it is. I will look for documentation about it. I hope it's royalty-free.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A version of Pardiso is included in MKL. If you have the Intel Fortran and/or C compilers, you have MKL, therefore you have Pardiso. See https://software.intel.com/en-us/node/470282#88F30007-9094-42EB-A4B1-8401F0C43ABE .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, mecej4. I do have intel fortran, and I found the examples folder containing DSS and Pardiso examples. If I understand it right, DSS is just an alternative interface to running the Pardiso algorithms. I will try to run the examples, hopefully tomorrow.
One of the things I use the sparse LU factorization for is to compute eigensolutions with Arnoldi reverse communication. For my particular field (dynamics of damped rotating systems like compressors and turbines), it works great.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just today, Intel announced that MKL would be available as a free download (with registration), see https://software.intel.com/en-us/articles/free_mkl .
For solving sparse eigenvalue problems, MKL now provides the FEAST algorithm, see https://software.intel.com/en-us/node/470372 .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using PARDISO for solving a band matrix linear system. It replace another library algorithm. Improve in the solution speed is significant. No problems in writing the calling interface.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My eigenvalue situation is with asymmetric matrices. The FEAST web pages say it is for symmetric matrices only. I have been using an Arnoldi algorithm which, when coupled with LU factoring, is blazing fast for the matrix types I work with.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page