Re: Calling MATLAB from Fortran
- From: "James Tursa" <aclassyguywithaknotac@xxxxxxxxxxx>
- Date: Wed, 15 Oct 2008 08:15:03 +0000 (UTC)
"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 James,
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
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:
Enter number of pore space nodes:!transport
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
c=c*single(1.001);for k=1:10000
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
.
- Follow-Ups:
- Re: Calling MATLAB from Fortran
- From: amir
- Re: Calling MATLAB from Fortran
- References:
- Calling MATLAB from Fortran
- From: amir
- Re: Calling MATLAB from Fortran
- From: James Tursa
- Re: Calling MATLAB from Fortran
- From: amir
- Calling MATLAB from Fortran
- Prev by Date: Re: matlab 7.1 faster than 7.6 !
- Next by Date: Re: Optimizing a system of non-linear odes
- Previous by thread: Re: Calling MATLAB from Fortran
- Next by thread: Re: Calling MATLAB from Fortran
- Index(es):
Relevant Pages
|