我使用“sudo apt install libarpack2-dev”安装了 Arpack。
下一个库位于 /usr/lib 中:
libarpack.a,
libarpack.so,
libarpack.so.2,
libarpack.so.2.0.0
我想从名为 ising.cpp 的 cpp 文件中调用此库中的 dsaupd 子例程。
运行“make --debug”时出现错误
undefined reference to `dsaupd_'
collect2: error: ld returned 1 exit status
我在从 fortran 库中调用子例程方面经验不足,无法弄清楚问题出在哪里。
需要哪些修改:
- 解决未定义的引用错误
- 成功调用子程序
编辑:第一部分似乎通过将 l 标志放在 cpp 文件之后来解决。这会将 g++ 命令更改为
g++ -g -O3 -mavx2 -funroll-loops -std=c++17 -o ising.exe ising.cpp -lblas -llapack -larpack -lgfortran
这与这个问题有关。
在能够编译代码之后,我仍然难以调用子例程。运行程序时出现“17713 Segmentation fault (core dumped)”
似乎这个问题与这个问题有关,它基本上归结为按值传递(C++)VS按引用传递(fortran)的不匹配。
make 命令的完整输出(包括实际的 g++ 调用)是 (was)
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'ising.exe' does not exist.
Must remake target 'ising.exe'.
g++ -g -O3 -mavx2 -funroll-loops -std=c++17 -lblas -llapack -larpack -lgfortran -o ising.exe ising.cpp
/tmp/ccyV1Kcn.o: In function `main':
/home/josja/Programs/Ising/ising.cpp:45: undefined reference to `dsaupd_'
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target 'ising.exe' failed
make: *** [ising.exe] Error 1
我要调用的 arpack 例程是这个例程:
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsaupd
c
c\Description:
...
c dsaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x, A symmetric
c ===> OP = A and B = I.
...
c\Usage:
c call dsaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
...
c BMAT Character*1. (INPUT)
...
c N Integer. (INPUT)
...
c WHICH Character*2. (INPUT)
...
c NEV Integer. (INPUT)
...
c TOL Double precision scalar. (INPUT)
...
c RESID Double precision array of length N. (INPUT/OUTPUT)
...
c NCV Integer. (INPUT)
...
c V Double precision N by NCV array. (OUTPUT)
...
c LDV Integer. (INPUT)
...
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
...
c IPNTR Integer array of length 11. (OUTPUT) -------------------------------------------------------------
...
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
...
c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
...
c LWORKL Integer. (INPUT)
...
c INFO Integer. (INPUT/OUTPUT)
...
c-----------------------------------------------------------------------
c
subroutine dsaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(11)
Double precision
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0 , zero = 0.0D+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz, j
save bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz
我要从中调用例程的 cpp 文件是 ising.cpp。这是一个避免上述分段错误的版本。
#include <iostream>
#include <bitset>
#include <string>
#include <vector>
using namespace std;
...
extern"C" {
void dsaupd_(int & IDO, char & BMAT, int & N, char WHICH[2], int & NEV,
double & TOL, double * RESID, int & NCV, double * V, int & LDV,
int IPARAM[11], int IPNTR[11], double * WORKD,
double * WORKL, int & LWORKL, int & INFO );
}
int main(int argc, char *argv[]) {
...
int ido = 0; // Reverse communication flag. (in/out-)
char bmat = 'I'; // Normal eigenvalue equation. (in)
int n = 1<<L; // Dimension of the eigenproblem. (in)
char which[3] = "SM"; // Compute smallest (in magnitude) eigenvalues. (in)
int nev = 4; // Number of eigenvalues to be computed. (in)
double tol = 0; // Tolerated error on the eigenvalues. (in)
double resid[n]; // Will contain the final residual vector. (in/out)
int ncv = min(n, max(2*nev + 1, 20)); // Number of Lanczos vectors. (in)
double v[n*ncv]; // Will contain the Lanczos vectors. (out)
int ldv = n; //???? Leading dimension of v.??? (in)
int iparam[11]; // Itaration parameters: (in)
iparam[0] = 1; // Exact shifts are used.
iparam[2] = 300; // Maximum number of Arnoldi iterations allowed.
iparam[6] = 1; // Mode 1 of dsaupd (normal eigenvalue equation).
int ipntr[11]; // Pointers inside working spaces. (work)
double workd[3*n]; // Workspace that will contain residuals. (out/work)
int lworkl = ncv*(ncv+8); // Size of private workspace. (in/work)
double workl[lworkl]; // Private workspace. (work)
int info = 0; // Randomly initial residual vector is used. (in/out)
dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
iparam, ipntr, workd, workl, lworkl, info );
...
}
...
对于stackoverflow:请允许提交问题。您正确识别代码块的工具不起作用,并导致拒绝有用的问题并破坏问题的布局。