Prev: plotregion
Next: how to send keyboard event
From: HIEU on 27 Dec 2009 01:26 Hello, After fighting the problem the whole Saturday, I think I need some experts' help. My problem: a 3-dimensional array, say data(m,n,p) where m,n,p are positive integers, is written to a MAT-file in Matlab. Question: How to read the MAT-file in Fortran F90 and store the data in a similar 3-dimensional array? I am, a novice of course, using Intel Visual Fortran Compiler on XP 32bit. I tried to use the module MatData.f90 by Chen at: http://www.mathworks.fr/matlabcentral/fileexchange/4902-matdata-ver-1-02 but was unable to get it to work and received a message "error LNK2019: unresolved external symbol _READ referenced in function _MAIN_" Below is my simple fortran code to use the module: PROGRAM READINPUT USE MatData IMPLICIT NONE DOUBLE PRECISION, DIMENSION(2,2,2) :: localvar CALL READ('test.mat','wind',localvar) END PROGRAM READINPUT where test.mat is a MAT-file stores a 2x2x2 array created by MATLAB. It seems the module MatData.f90 by Chen does not work with Intel Fortran Compiler. Do you have any idea or suggestion to solve the problem (read 3-dimensional array from a MAT-file in Fortran 90)? Any helpwould be highly appreciated. Thanks Hieu
From: Rune Allnor on 27 Dec 2009 01:41 On 27 Des, 07:26, "HIEU " <nguyenhuyh...(a)gmail.com> wrote: > Hello, > After fighting the problem the whole Saturday, I think I need some experts' help. > > My problem: a 3-dimensional array, say data(m,n,p) where m,n,p are positive integers, is written to a MAT-file in Matlab. > > Question: How to read the MAT-file in Fortran F90 and store the data in a similar 3-dimensional array? I am, a novice of course, using Intel Visual Fortran Compiler on XP 32bit. You might be able to use a matlab engine, if this kind of thing is available for fortran. Check the "External Interfaces" section of the matlab documentation. A quick'n dirty solution is to skip the .mat format alltogether, and instead write the array to a text file from matla, that is read from fortran. Write the data as p tables of size m x n, either consecutively in the same file, or in p files. This kind of thing is fast to implement, but might be a bit slow to run if the array is large. Rune
From: James Tursa on 27 Dec 2009 04:57 "HIEU " <nguyenhuyhieu(a)gmail.com> wrote in message <hh6ulr$e38$1(a)fred.mathworks.com>... > Hello, > After fighting the problem the whole Saturday, I think I need some experts' help. > > My problem: a 3-dimensional array, say data(m,n,p) where m,n,p are positive integers, is written to a MAT-file in Matlab. > > Question: How to read the MAT-file in Fortran F90 and store the data in a similar 3-dimensional array? I am, a novice of course, using Intel Visual Fortran Compiler on XP 32bit. > > I tried to use the module MatData.f90 by Chen at: > http://www.mathworks.fr/matlabcentral/fileexchange/4902-matdata-ver-1-02 > but was unable to get it to work and received a message "error LNK2019: unresolved external symbol _READ referenced in function _MAIN_" > > Below is my simple fortran code to use the module: > > PROGRAM READINPUT > USE MatData > IMPLICIT NONE > DOUBLE PRECISION, DIMENSION(2,2,2) :: localvar > CALL READ('test.mat','wind',localvar) > END PROGRAM READINPUT > > where test.mat is a MAT-file stores a 2x2x2 array created by MATLAB. > It seems the module MatData.f90 by Chen does not work with Intel Fortran Compiler. > > Do you have any idea or suggestion to solve the problem (read 3-dimensional array from a MAT-file in Fortran 90)? > Any helpwould be highly appreciated. > Thanks > Hieu I wrote a Fortran 95 interface to the MATLAB API that should solve your problem. It has been tested with the Intel Fortran compiler. You can find the submission here: http://www.mathworks.com/matlabcentral/fileexchange/25934-fortran-95-interface-to-matlab-api-with-extras In particular, look at the MatlabAPI_matfile.f file for an example of loading variables from a mat file, and MatlabAPI_real.f for examples of turning mxArray variables into Fortran arrays and vice-versa. e.g., this line in the code loads an mxArray variable from the mat file: mx = matGetVariable(matfile, names(i)) To turn that mxArray variable mx into a regular Fortran array that you can use downstream, I supply two functions. The first function points directly at the mxArray data area, so changes to the target array will be direct changes to the mxArray data area. It can be used like this for a 3D mxArray: use MatlabAPImx use MatlabAPImat : real(8), pointer :: fp(:,:,:) : mx = matGetVariable(matfile, names(i)) if( mx == 0 ) error, so do something fp => fpGetPr(mx) if( .not.associated(fp) ) error, so do something fp(1,2,3) = 5.d0 ! <-- This will change the data area of mx Then the Fortran pointer fp can be used just like a regular 3D Fortran array in all your downstream code, with changes to the fp target being direct changes to the data area of the mxArray mx. After you are done with the data, destroy the mxArray variable mx: mxDestroyArray(mx) The other method is to make a copy of the mxArray mx data area and get a pointer to that. Changes to the target array of this pointer will *not* affect the mxArray mx data area. The use for a 3D array is as follows: use MatlabAPImx use MatlabAPImat : real(8), pointer :: fp(:,:,:) : mx = matGetVariable(matfile, names(i)) if( mx == 0 ) error, so do something fp => fpGetPrCopy(mx) if( .not.associated(fp) ) error, so do something fp(1,2,3) = 5.d0 ! <-- This will *not* change the data area of mx Like above, this fp can be used downstream in your code just like it was a regular 3D Fortran array. When you are done with the target array of fp and the mxArray mx variable, deallocate fp and destroy mx as follows: fpDeallocate(fp) mxDestroyArray(mx) Take special note ... when you point at the data area of an mxArray directly, you do *not* deallocate the pointer fp. But when you point at a *copy* of the data area of an mxArray, there is newly allocated memory involved that needs to be deallocated with the fpDeallocate function. If you need help please don't hesitate to post more questions. James Tursa
From: James Tursa on 27 Dec 2009 05:03 "James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <hh7b1e$t60$1(a)fred.mathworks.com>... > > fp => fpGetPr(mx) Typo, that should be fp => fpGetPr3(mx) > fp => fpGetPrCopy(mx) and that should be fp => fpGetPrCopy3(mx) James Tursa
From: HIEU on 28 Dec 2009 01:53
@James Tursa: I realized you have been doing a great job on Fortran Interface to MATLAB API. Thanks for your hard work. But I am just a beginner and I need more help on this if you don't mind. So by copying your routines, I have a Fortran program named readinput.f90 like this: #include "mex.h" #include "fintrf.h" PROGRAM readinput use MatlabAPImx use MatlabAPImat character(len=NameLengthMaxMex), pointer :: names(:) mwPointer mx, matfile integer*4 i, k real(8), pointer :: fp(:,:,:) !\ ! Open the mat file in read-only mode. !/ k = mexPrint("... Opening mat file test.mat") matfile = matOpen("test.mat","r") if( matfile == 0 ) then call mexErrMsgTxt("Unable to open mat file") endif !\ ! Get a list of variable names in the mat file. !/ k = mexPrint("... List of variable names in the file:") names => fpMatGetNames(matfile) if( associated(names) ) then do i=1,size(names) k = mexPrint(names(i)) enddo else call mexErrMsgTxt("Unable to read the variable names") endif !\ ! Go get the variables and print out some info !/ k = mexPrint("... Getting all the variables from the file") do i=1,size(names) mx = matGetVariable(matfile, names(i)) if( mx /= 0 ) then k = mexPrint("Got the variable "//names(i)) !call mxDestroyArray(mx) else call mexErrMsgTxt("Unable to get variable "//names(i)) endif enddo !call fpDeallocate1CharacterMex(names) mx = matGetVariable(matfile, wind) if( mx /= 0 ) then k = mexPrint("Got the variable "//names(i)) call mxDestroyArray(mx) else call mexErrMsgTxt("Unable to get variable "//names(i)) endif fp => fpGetPr3(mx) if( .not.associated(fp) ) then call mxDestroyArray(mx) call mexErrMsgTxt("Unable to associate pointer fp") endif write (*,*) 'Hello, world!' ! This is an inline comment write (*,*) , fp ! After you are done with the data, destroy the mxArray variable mx: ! mxDestroyArray(mx) k = mexPrint("... Done.") k = matClose(matfile) END PROGRAM readinput Then I did the followings in Matlab: 1. > mex -setup % set Intel Fortran 11 + Visual Studio 2005 as compiler 2. > options = [matlabroot '\bin\win32\mexopts\intelf11msvs2005opts.bat'] % intelf11msvs2005opts.bat is from the FEX http://www.mathworks.com/matlabcentral/fileexchange/22290-windows-mex-setup-with-ifort-11-0 3. > mex('-f',options,'readinput.f90') All I get is a bunch of: "sal.h(502): #error: macro recursion: __pre" So could you please take a look at my code and point out what I am missing or any error I made? Also, what do I need to do with linking (and compiling)? many thanks, Hieu |