从C ++调用FORTRAN子例程会产生非法的参数值

诺克斯

我目前正在尝试使用大型稀疏矩阵(来自FEM离散化)来解决特定的特征值问题(所谓的陀螺仪特征值问题)。编程语言是C ++。

EVP的标准参考是ARPACK。las,它仅实现“经典” Arnoldi流程,不适用于此类问题(参见“结构保留方法”)。

最近,我发现了这个Algorithm 961参考,该参考还提供了一些代码-FORTRAN!因此,我尝试将DGHUTR例程包含在C ++中,但无济于事。以下是MWE,它是对C ++中DGHUTR(TDGHUTR.f)的测试的改编:

#include <Eigen/Dense>
#include <Eigen/Sparse>
//definition stolen from ARPACK++
#define F77NAME(x) x ## _

//Interface to the SHEIG library function DGHUTR
#ifdef __cplusplus
extern "C"
{
#endif
  void F77NAME(dghutr)( char* JOB, char* COMPQ1, char* COMPQ2, int* N, double* A, int* LDA,
                        double* DE, int* LDDE, double* C1, int* LDC1, double* VW, int* LDVW,
                        double* Q1, int* LDQ1, double* Q2, int* LDQ2, double* B, int* LDB,
                        double* F, int* LDF, double* C2, int* LDC2, double* ALPHAR, double* ALPHAI,
                        double* BETA, int* IWORK, int* LIWORK, double* DWORK,int* LDWORK, int* INFO );
#ifdef __cplusplus
}
#endif


int main(void){
  // define system sizes
  int N(8),  M(N/2);
  std::cout << "Sizes: " << N << '\t' << M << std::endl;


  char job('E'),  compq1('I'),  compq2('I');
  int lda(M),  ldde(M),  ldq1(N),  ldq2(N),  ldb(M),  ldc1(M),  ldc2(M),  ldf(M),  ldvw(M);

  int ldwork = 2*N*N+std::max(4*N+4, 32);
  int liwork = N+12;


  // workspace arrays
  int* iwork = new int[liwork];
  double* dwork = new double[ldwork];
  int info(0);
  // auxiliary matrices and  vectors
  Eigen::MatrixXd F(ldf, M),  C2(ldc2, M),  Q1(ldq1, N),  Q2(ldq2, N),  B(ldb, M);
  Eigen::VectorXd alphaR(M),  alphaI(M),  beta(M);

  //matrices with data
  Eigen::MatrixXd A(lda,M), DE(ldde,M+1), C1(ldc1,M), VW(ldvw,M+1);

     A << 3.1472,   1.3236,   4.5751,   4.5717,
   4.0579,  -4.0246,   4.6489,  -0.1462,
  -3.7301,  -2.2150,  -3.4239,   3.0028,
   4.1338,   0.4688,   4.7059,  -3.5811;

   DE << 0.0000,   0.0000,  -1.5510,  -4.5974,  -2.5127,
   3.5071,   0.0000,   0.0000,   1.5961,   2.4490,  
  -3.1428,   2.5648,   0.0000,   0.0000,  -0.0596, 
   3.0340,   2.4892,  -1.1604,   0.0000,   0.0000;

   C1 <<  0.6882,  -3.3782,  -3.3435,   1.8921,
  -0.3061,   2.9428,   1.0198,   2.4815,
  -4.8810,  -1.8878,  -2.3703,  -0.4946,
  -1.6288,   0.2853,   1.5408,  -4.1618;

   VW <<  -2.4013,  -2.7102,   0.3834,  -3.9335,   3.1730,
  -3.1815,  -2.3620,   4.9613,   4.6190,   3.6869,
   3.6929,   0.7970,  0.4986,  -4.9537,  -4.1556,
   3.5303,   1.2206,  -1.4905,   0.1325,  -1.0022;

  /* outputs of each parameter save for dwork,iwork to check correctness. */

  F77NAME(dghutr)( &job, &compq1, &compq2, &N, A.data(), &lda, DE.data(), &ldde,  C1.data(), &ldc1, VW.data(), &ldvw,
                         Q1.data(), &ldq1,  Q2.data(), &ldq2,  B.data(), &ldb,
                         F.data(), &ldf,  C2.data(), &ldc2, alphaR.data(),  alphaI.data(),
                         beta.data(), iwork, &liwork, dwork, &ldwork, &info );
  std::cout << "result: " << info << std::endl;
  delete[] iwork;
  delete[] dwork;
}

编译完成(它使用很多其他东西):

g++ -o eigensolver EigenSHEIGSolver.cpp -I/home/shared/eigen-eigen-1306d75b4a21  /home/shared/SHIRA/SHEVP/src/shheig64.a /home/shared/SHIRA/SLICOT_Lib/slicot64.a /home/shared/SHIRA/SLICOT_Lib/lpkaux64.a /home/shared/ATLAS/builddir/lib/libptlapack.a /home/shared/ATLAS/builddir/lib/libptcblas.a /home/shared/ATLAS/builddir/lib/libptf77blas.a /home/shared/ATLAS/builddir/lib/libatlas.a /home/shared/ATLAS/builddir/lib/libptcblas.a -lgfortran -lpthread

,每当我运行生成的可执行文件时,它就会给我:

 ** On entry to DGHUTR parameter number  8 had an illegal value

我的FORTRAN知识非常有限,上面的代码主要是使用YoLinux教程编写的,其中混合了FORTRAN和CCRAY Docs作为参考。据我了解,例程会报告ldde变量错误我不知道为什么。

请问有人可以帮我一下吗?

注意根据Eigen Docs:存储顺序Eigen默认以大写顺序存储矩阵,因此它应可与FORTRAN进行接口。FORTRAN子程序DGHUTR是

SUBROUTINE DGHUTR( JOB, COMPQ1, COMPQ2, N, A, LDA, DE, LDDE, C1,
 $                   LDC1, VW, LDVW, Q1, LDQ1, Q2, LDQ2, B, LDB, F,
 $                   LDF, C2, LDC2, ALPHAR, ALPHAI, BETA, IWORK,
 $                   LIWORK, DWORK, LDWORK, INFO )

更新:这是修改后的DGHUTR子例程(基本添加的打印)的输出:

 JOB T
 COMPQ1 I
 COMPQ2 I
 LDA          17179869188
 LDDE          34359738372
 LDC1          17179869188
 LDVW         704374636548
 LDQ1          34359738376
 LDB          17179869188
 LDF          17179869188
 LDC2          17179869188
 LIWORK                   20
 LDWORK          85899346084
 N          17179869192
 LDDE          34359738372
 INFO  6227620798727716864

就像我看到的那样LIWORK,只要我用-O2set编译,就可以正确接收到字符我猜想有什么事情g++会破坏参数。尝试从还原gcc-5gcc-4.8不能解决问题。在没有优化的情况下,该LDA值似乎在程序的每次运行时都在变化,而在使用编译时,该值保持不变-O2

诺克斯

我想我已经找到困扰我的问题根源。fortran例程接收到的值对优化标志的依赖性有点暗示,C ++和FORTRAN解释存储的变量的方式可能有问题。在查找的特定值17179869188并找到此SO帖子之后,我尝试使用这些库的编译器标志

当我获取SLICOT时,我获取了源代码和一个使用gfortran针对Linux(slicot_linux_gfortran.tar.gz预编译的库后一个带有make.incOPTS = -O2 -fpic -fdefault-integer-8的SHHEVP例程在make.inc中包含以下注释

IMPORTANT: Use the options -fPIC -fdefault-integer-8 for 64bit
architectures.

因此,我按照建议进行了操作-那就是问题所在!

删除-fdefault-integer-8并重新编译SLICOT和DGHUTR都解决了我的问题。现在,上面给出的代码将进行编译,并且FORTRAN子例程将接收正确的值。计算结果与DGHUTR源提供的参考结果一致。

顺便说一下,大多数SLICOT测试现在都可以使用。使用旧的标志时,示例的编译在TAB01ND处停止,该操作将始终挂起。现在我来看看TMB03LD,它的编译失败并带有

IF( LSAME( COMPQ, 'C' ) .AND. NEIG.GT.0 ) THEN              
                             1
Error: Operands of logical operator '.and.' at (1) are INTEGER(4)/LOGICAL(4)

但是,就目前而言,我不关心。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

从C#调用FORTRAN子例程

来自分类Dev

如何使用C中的单位编号参数调用Fortran例程

来自分类Dev

从C ++调用Fortran子例程,链接时未定义引用

来自分类Dev

从Fortran调用的子例程C ++:如何处理动态内存分配?

来自分类Dev

从C调用模块中的子例程

来自分类Dev

调用C / Fortran例程时忽略evalWithTimeout吗?

来自分类Dev

将Fortran子例程链接到C ++程序时出错

来自分类Dev

C中是否有类似于Fortran中的子例程的子例程?

来自分类Dev

C中是否有类似于Fortran中的子例程的子例程?

来自分类Dev

R使用字符参数调用Fortran子例程

来自分类Dev

R调用Fortran子例程

来自分类Dev

ISO_C_BINDING从Fortran调用C例程(具有双精度和数组)

来自分类Dev

从MATLAB调用.c文件会产生分段违规

来自分类Dev

调用重载的构造函数会产生歧义错误C ++

来自分类Dev

用ctypes调用C库模块会产生错误的结果

来自分类Dev

如何在C语言中使用fortran模块子例程

来自分类Dev

如何在C语言中使用fortran模块子例程

来自分类Dev

从R调用并行的fortran MPI子例程

来自分类Dev

在Matlab中调用C ++例程

来自分类Dev

c ++复制参数值

来自分类Dev

C-以十六进制形式打印负整数值会产生太多字符

来自分类Dev

Fortran是否通过子例程多次调用来修改输入参数?

来自分类Dev

Fortran是否通过子例程多次调用来修改输入参数?

来自分类Dev

从Fortran中使用** int参数调用C函数

来自分类Dev

C ++如何使函数(子例程)参数为double的向量或ints的向量

来自分类Dev

从Qt C ++调用已编译的C库函数会产生意外行为

来自分类Dev

调用参数为指针别名的子例程

来自分类Dev

使用参数调用Excel VBA子例程

来自分类Dev

整数值在调用和子例程之间变化

Related 相关文章

  1. 1

    从C#调用FORTRAN子例程

  2. 2

    如何使用C中的单位编号参数调用Fortran例程

  3. 3

    从C ++调用Fortran子例程,链接时未定义引用

  4. 4

    从Fortran调用的子例程C ++:如何处理动态内存分配?

  5. 5

    从C调用模块中的子例程

  6. 6

    调用C / Fortran例程时忽略evalWithTimeout吗?

  7. 7

    将Fortran子例程链接到C ++程序时出错

  8. 8

    C中是否有类似于Fortran中的子例程的子例程?

  9. 9

    C中是否有类似于Fortran中的子例程的子例程?

  10. 10

    R使用字符参数调用Fortran子例程

  11. 11

    R调用Fortran子例程

  12. 12

    ISO_C_BINDING从Fortran调用C例程(具有双精度和数组)

  13. 13

    从MATLAB调用.c文件会产生分段违规

  14. 14

    调用重载的构造函数会产生歧义错误C ++

  15. 15

    用ctypes调用C库模块会产生错误的结果

  16. 16

    如何在C语言中使用fortran模块子例程

  17. 17

    如何在C语言中使用fortran模块子例程

  18. 18

    从R调用并行的fortran MPI子例程

  19. 19

    在Matlab中调用C ++例程

  20. 20

    c ++复制参数值

  21. 21

    C-以十六进制形式打印负整数值会产生太多字符

  22. 22

    Fortran是否通过子例程多次调用来修改输入参数?

  23. 23

    Fortran是否通过子例程多次调用来修改输入参数?

  24. 24

    从Fortran中使用** int参数调用C函数

  25. 25

    C ++如何使函数(子例程)参数为double的向量或ints的向量

  26. 26

    从Qt C ++调用已编译的C库函数会产生意外行为

  27. 27

    调用参数为指针别名的子例程

  28. 28

    使用参数调用Excel VBA子例程

  29. 29

    整数值在调用和子例程之间变化

热门标签

归档