Re: Calling MATLAB from Fortran



"amir " <raoof_amir@xxxxxxxxx> wrote in message <gd2unt$2b2$1@xxxxxxxxxxxxxxxxxx>...
"James Tursa" <aclassyguywithaknotac@xxxxxxxxxxx> wrote in message <gd2dgm$a9s$1@xxxxxxxxxxxxxxxxxx>...
"amir " <raoof_amir@xxxxxxxxx> wrote in message <gd1mup$j84$1@xxxxxxxxxxxxxxxxxx>...
Hi!
I am trying to call a MATLAB m-file from my Fortran.
I used the simple way! Fortran saves the data which Matlab m-file needs and then Matlab would read them as input from the file and after calculation save then in a file for Fortran.

Just be aware, this may sound like the *simple* way, but file i/o can have a lot headaches when dealing with inf and NaN, complex numbers, etc.

Now I need only run the Matlab file in my Fortran (but no data exchange between them). I have tried to do it, but I was not successful! any help is appreciated.
My Matlab version is: 7.6.0.324 (R2008a)
And my Fortran version: CVF 6.6.0


You need to post some code so we can see what you are trying to do. We can't find your problems without seeing your code.

James Tursa
Hi James,
my problem is about reactive solute transport. i am calculating concentration due to advection using my own Fortran code and then transfer concentration to matlab to do the reaction part. MATLAB would do reaction and give back the new concentrations to Fortran to do the process again and again. this transfer should be done for SEVERAL time steps. so do i need MATLAB engine to make it faster?
thanks,
Amir

the program is like:
!!!!!!!!!!!!!!!!!!!!
PROGRAM TRANSPORT !in CVF6.6
real::velocity, conductvity
real::concentration(:,:) !concentation contains always zero or positive real values

READ (N) !N is number of pore space nodes; e.g.: N=1000
ALLOCATE (CONCENTRATION(7,N))
READ (initial_concentration)

!NOW START THE TIME STEPS
Do i=1,NumberOfTimeSteps !e.g.,NumberOfTimeSteps=10000
--advection would take place on concentration using Fortran subroutines
--Call matlab m.fle and give the concentation matrix to it
-- matlab should do reaction and give the concentration matrix back to fortran
END DO
END PROGRAM TRANPORT

I would certainly recommend using the MATLAB Engine over doing file reads & writes several thousand times. I went ahead and cooked up a very simple example for you using your outline above. The program asks the user for a size input N (I used a very small number for testing because it was interactive), allocates concentration, reads in initial values for concentration, and then starts a loop. Inside the loop concentration is constantly being changed by a Fortran subroutine advection, the result is passed into the Engine, an m-file reaction.m is called to work on concentration, and the result is passed back into the Fortran code and copied into concentration for the next iteration. Hope this is a good enough example to get you started.

James Tursa

------------------------------------------------------

You can use the following m-file on a win32 system to compile the program (e.g., call this compile_cvf66.m):

% Compiles a Fortran main source file. Assumes engine routines are used.
% Compaq Visual Fortran 6.6 compiler
function compile_cvf66(name)
options = [matlabroot '\bin\win32\mexopts\cvf66engmatopts.bat'];
disp(['Options = ' options]);
mex('-f', options, name, '-v');
end

Then type at the MATLAB command prompt:

compile_cvf66('transport.for')

-----------------------------------------------------

Here is the sample reaction.m file I used for testing:

function result = reaction(x)
result = x + 1;
end

-----------------------------------------------------

Once the source code is compiled, you can run it from the MATLAB command prompt using the bang:

!transport

Here is the sample output I got for a run:

!transport
Enter number of pore space nodes:
2
Enter initial concentration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Iteration 100
Iteration 200
: :
Iteration 9900
Iteration 10000
Result =
2.1946772E+07 2.1968704E+07 2.1990640E+07 2.2012544E+07 2.2034532E+07
2.2056440E+07 2.2078396E+07 2.2100328E+07 2.2122316E+07 2.2144224E+07
2.2166012E+07 2.2187952E+07 2.2209908E+07 2.2231904E+07


Here is the compare result I got from doing it entirely in MATLAB (got same result as Fortran):

c = single([1 2 3 4 5 6 7;8 9 10 11 12 13 14]')

c =

1 8
2 9
3 10
4 11
5 12
6 13
7 14

for k=1:10000
c=c*single(1.001);
c=reaction(c);
end
c

c =

21946772 22100328
21968704 22122316
21990640 22144224
22012544 22166012
22034532 22187952
22056440 22209908
22078396 22231904




Here is the source code for transport.for:

#include "fintrf.h"

#ifndef mwPointer
#define mwPointer integer*4
#endif

#ifndef mwSize
#define mwSize integer*4
#endif

PROGRAM TRANSPORT !in CVF6.6
implicit none
!-FUN
mwPointer engOpen ! returns Engine *
mwPointer engGetVariable ! returns mxArray *
mwPointer mxCreateNumericMatrix ! returns mxArray *
mwPointer mxGetPr ! returns double *
integer*4 engClose
integer*4 engEvalString
integer*4 engPutVariable
integer*4 mxIsDouble
integer*4 mxClassIDFromClassName
integer*4 mxGetClassID
mwSize mxGetM
mwSize mxGetN
!-LOC
real :: velocity, conductvity
real, allocatable :: concentration(:,:) !concentation contains always zero or positive real values
integer i, k, N, istat
integer :: NumberOfTimeSteps = 10000
character c
mwPointer ep ! really Engine *
mwPointer mx ! really mxArray *
mwPointer my ! really mxArray *
mwPointer px ! really double *
mwPointer py ! really double *
mwSize N7
integer*4 classid, singleid
!-----
!\
! Open MATLAB engine
!/
ep = engOpen("")
if( ep == 0 ) then
write(*,*) "Engine did not open. One possible reason is"
write(*,*) "MATLAB is not a registered server."
write(*,*) "From Windows, open a Command Prompt and enter:"
write(*,*) ">matlab /regserver"
read(*,'(a)') c
stop
endif
!\
! Get info from user
!/
write(*,*) 'Enter number of pore space nodes: '
READ(*,*) N !N is number of pore space nodes; e.g.: N=1000
ALLOCATE (CONCENTRATION(7,N),stat=istat)
if( istat /= 0 ) then
write(*,*) 'Allocation error'
read(*,'(a)') c
stop
endif
!\
! Create MATLAB mxArray variable for putting into engine
!/
singleid = mxClassIDFromClassName("single")
mx = mxCreateNumericMatrix(7, N, singleid, 0)
if( mx == 0 ) then
write(*,*) 'Unable to create mxArray variable'
read(*,'(a)') c
stop
endif
px = mxGetPr(mx)
N7 = 7 * N
!\
! READ initial concentration
!/
write(*,'(a)') 'Enter initial concentration: '
READ(*,*) CONCENTRATION
!\
! NOW START THE TIME STEPS
!/
Do i=1,NumberOfTimeSteps !e.g.,NumberOfTimeSteps=10000
if( mod(i,100) == 0 ) write(*,*) 'Iteration ',i
!\
! advection would take place on concentration using Fortran subroutines
!/
call advection(concentration)
!\
! Call matlab m.fle and give the concentation matrix to it
!/
call mxCopyReal4ToPtr(concentration, px, N7)
if( engPutVariable(ep, "concentration", mx) /= 0 ) then
write(*,*) 'Unable to put mxArray into MATLAB Engine'
read(*,'(a)') c
deallocate(concentration)
call mxDestroyArray(mx)
k = engClose(ep)
stop
endif
!\
! matlab should do reaction and give the concentration matrix back to fortran
!/
if( engEvalString(ep,"r=reaction(concentration);")/= 0) then
write(*,*) 'MATLAB Engine no longer running'
read(*,'(a)') c
deallocate(concentration)
call mxDestroyArray(mx)
k = engClose(ep)
stop
endif

my = engGetVariable(ep, "r")
if( my == 0 ) then
write(*,*) 'Unable to get mxArray from MATLAB Engine'
read(*,'(a)') c
deallocate(concentration)
call mxDestroyArray(mx)
k = engClose(ep)
stop
endif
classid = mxGetClassID(my)
if( classid /= singleid .or. &
& mxGetM(my) / =7 .or. mxGetN(my) /= N ) then
write(*,*) 'mxArray from Engine is not single 7 x ',N
read(*,'(a)') c
deallocate(concentration)
call mxDestroyArray(mx)
call mxDestroyArray(my)
k = engClose(ep)
stop
endif
py = mxGetPr(my)
call mxCopyPtrToReal4(py, concentration, N7)
call mxDestroyArray(py)
END DO

write(*,*) 'Result = '
write(*,*) concentration

contains
!--------------------------------------------------------------------------
subroutine advection(concentration)
real :: concentration(:,:)
concentration = concentration * 1.001
end subroutine advection

END PROGRAM TRANSPORT

.



Relevant Pages

  • Re: Calling MATLAB from Fortran
    ... Fortran saves the data which Matlab m-file needs and then Matlab would read them as input from the file and after calculation save then in a file for Fortran. ... Assumes engine routines are used. ...
    (comp.soft-sys.matlab)
  • Re: MATLAB <-> FORTRAN
    ... When you do A\b it just calls the basic solvers Matlab knows, ... in some cases Gauss Elimination. ... In this case you can find a Gauss Solver, ... I've bitten the bullet and converted to Fortran ...
    (comp.soft-sys.matlab)
  • Re: Matlab Vectorisation Speed - How is it done in c++?
    ... Beating the performance of vectorized Matlab code is very ... Matlab makes calls to optimized C and Fortran libraries ... Use optimization level 3 on numerical code and level 2 on non- ...
    (comp.soft-sys.matlab)
  • Re: pass 1D vector from matlab to fortran
    ... matlab to fortran: ... %input: timeseries ts and constants ... polynomial in seasonal smoothing ...
    (comp.soft-sys.matlab)
  • Re: Problems when calling functions from a .dll
    ... > I have quite some problems with calling functions from a .dll. ... originally written in Fortran and compiled by ... > PRECISION (double in Matlab); ... > as a basic for my header file, which is based on the example file ...
    (comp.soft-sys.matlab)