amleto, your idea is great. In C++, there is no problem, but I have no idea yet how to pass or apply your fortran interface (below)to Fortran:
// fortran interface - transpose it
T& operator()(unsigned int x, unsigned int y)
{
return (array_)[y][x];
}
// fortran interface - transpose it
T& operator()(unsigned int x, unsigned int y)
{
return (array_)[y][x];
}
To copy to clipboard, switch view to plain text mode
Added after 15 minutes:
For 2D array, I want to use Boost library, which provides contiguous blocks for 2D and 3D arrays.
For the array transfer, I tried the following way:
- Generate "Column-major" memory space in C++, to facilitate the access from Fortran codes.
- In C++, use an operator () to access the memory in [j][i] pattern.
(My situation is: I wrote C++ codes, and have already-written Fortran codes using multi-dimension arrays.)
- In C++, (i,j) should be used for [i][j], not directly using [i][j]. (It is easy for me now).
- In Fortran, (i,j) is used (without any code modification).
Here is the codes: ( I finally found "Code" tag. )
// File: *.h
/* Boost library. */
#ifndef Q_MOC_RUN // To avoid an error regarding "Boost_JOIN "
#include <boost/multi_array.hpp>
#endif
typedef boost::multi_array<double, 2> btArrayDbl2D_type;
/*-----*
Double-type 2D array.
- In C/C++, use MATDBL2D(i=0..., j=0...), not A, not A[i][j].
- In Fortran, use A(i=1..., j=1...).
*-----*/
struct MATDBL2D
{
public:
MATDBL2D() : szI_(0), szJ_(0) {}
btArrayDbl2D_type A;
private:
uint szI_, szJ_;
public:
// "Column-major" memory storage is used herein to transfer data to Fortran codes: A[1][1],A[2][1],A[3][1],A[1][2]...
// [Note] C++ uses a "Row-major" memory storage system: A[1][1],A[1][2],A[1][3],A[2][1]...
void makeMem(uint szI, uint szJ)
{
szI_ = szI;
szJ_ = szJ;
A.resize(boost::extents[szJ_][szI_]); // "Column-major" memory storage.
}
// For C++ interface.
// - NEVER access directly to A[][], which contains data as "Column-major" memory storage.
double & operator()(uint i, uint j) { return A[j][i]; }
const double & operator()(uint i, uint j) const { return A[j][i]; }
uint szI() { return szI_;} // For C/C++ & // To pass its size to Fortran subroutines.
uint szJ() { return szJ_;} // For C/C++ & // To pass its size to Fortran subroutines.
// For Fortran.
// "A" will be directly accessed: ex) A(i,j): i,j=1-based number.
// So "A" is set as a public variable.
};
/* Boost library. */
#ifndef Q_MOC_RUN // To avoid an error regarding "Boost_JOIN "
#include <boost/multi_array.hpp>
#endif
typedef boost::multi_array<double, 2> btArrayDbl2D_type;
/*-----*
Double-type 2D array.
- In C/C++, use MATDBL2D(i=0..., j=0...), not A, not A[i][j].
- In Fortran, use A(i=1..., j=1...).
*-----*/
struct MATDBL2D
{
public:
MATDBL2D() : szI_(0), szJ_(0) {}
btArrayDbl2D_type A;
private:
uint szI_, szJ_;
public:
// "Column-major" memory storage is used herein to transfer data to Fortran codes: A[1][1],A[2][1],A[3][1],A[1][2]...
// [Note] C++ uses a "Row-major" memory storage system: A[1][1],A[1][2],A[1][3],A[2][1]...
void makeMem(uint szI, uint szJ)
{
szI_ = szI;
szJ_ = szJ;
A.resize(boost::extents[szJ_][szI_]); // "Column-major" memory storage.
}
// For C++ interface.
// - NEVER access directly to A[][], which contains data as "Column-major" memory storage.
double & operator()(uint i, uint j) { return A[j][i]; }
const double & operator()(uint i, uint j) const { return A[j][i]; }
uint szI() { return szI_;} // For C/C++ & // To pass its size to Fortran subroutines.
uint szJ() { return szJ_;} // For C/C++ & // To pass its size to Fortran subroutines.
// For Fortran.
// "A" will be directly accessed: ex) A(i,j): i,j=1-based number.
// So "A" is set as a public variable.
};
To copy to clipboard, switch view to plain text mode
File: *.cpp
int testFN()
{
int szI = 3;
int szJ = 4;
double b, X[3][4];
MATDBL2D A2D;
A2D.makeMem(szI, szJ);
for(int i=0; i<szI; ++i){
for(int j=0; j<szJ; ++j){
X[i][j] = i*10. + j;
A2D(i,j) = X[i][j];
}
}
// Testing......
// 2D Sum.
b=0.;
b=A2D(0,0)+A2D(1,2)+A2D(2,0); // C++
b = 0.;
int szFI = A2D.szI();
int szFJ = A2D.szJ();
SUM2D(A2D.A.data(), &b, &szFI, &szFJ); // Fortran subroutine.
}
int testFN()
{
int szI = 3;
int szJ = 4;
double b, X[3][4];
MATDBL2D A2D;
A2D.makeMem(szI, szJ);
for(int i=0; i<szI; ++i){
for(int j=0; j<szJ; ++j){
X[i][j] = i*10. + j;
A2D(i,j) = X[i][j];
}
}
// Testing......
// 2D Sum.
b=0.;
b=A2D(0,0)+A2D(1,2)+A2D(2,0); // C++
b = 0.;
int szFI = A2D.szI();
int szFJ = A2D.szJ();
SUM2D(A2D.A.data(), &b, &szFI, &szFJ); // Fortran subroutine.
}
To copy to clipboard, switch view to plain text mode
Fortran subroutine.
subroutine SUM2D(a,b,I,J)
real*8 a(I,J),b
real*8 x(I,J)
integer I,J
do L=1,I
do M=1,J
x(L,M)=a(L,M)
enddo
enddo
b=a(1,1)+a(2,3)+a(3,1)
end subroutine
subroutine SUM2D(a,b,I,J)
real*8 a(I,J),b
real*8 x(I,J)
integer I,J
do L=1,I
do M=1,J
x(L,M)=a(L,M)
enddo
enddo
b=a(1,1)+a(2,3)+a(3,1)
end subroutine
To copy to clipboard, switch view to plain text mode
If you or someone have any better or easy methods or comments, please let me know.
Thanks.
Bookmarks