A
Interfacing with Other Languages

(Note: The MATLAB coding described in this appendix has been tested on a Windows 7 computer. The equivalent system calls should work on a Unix or Mac computer, but have not been tested.)

Sometimes it is desirable to perform some calculations in a language other than MATLAB. Possible reasons for this are that (1) a complicated, working, calculation program already exists; or (2) it is difficult or even impossible to vectorize a MATLAB program but desirable to utilize the calculation speed of some fully compiled optimized code in a language such as C or FORTRAN.

MATLAB has built-in capabilities for doing this.1,2 The MATLAB capabilities are significant and merit investigation if this type of interface is desired. There are limitations, however, as to what compilers and languages are supported. The technique described in this appendix is a “quick and dirty” patch that works well provided you can write or modify and compile code with a compiler and language of your choice into an executable program.

The procedure is very straightforward and utilizes MATLAB's capability of executing a system command and then waiting for its completion:

  • 1 Prepare data in MATLAB using whatever script or functions are necessary.
  • 2 Save the necessary data to a file.
  • 3 Execute the external program.
  • 4 The external program reads the data file, does its work, and writes its results to a second data file. The external program may open and read and/or write other files if necessary.
  • 5 MATLAB reads the results from the appropriate data file(s) and proceeds with calculations, graphics, and so on.

Following is the MATLAB script run_ppt4.m, with a calling program for different versions of ppt4.m:

% run_ppt4.m a convenience script for running and plotting ppt4 results
% with a Fortran interface

rad = 0.25; step = .1;
y1 = 15 + rad + step; y2 = 40;
y = [y1];
while y(end) < y2
  y = [y, y(end) + step];
  step = 1.25*step;
end
y = y(1 : end-1)

tic
% Comment out the undesired choice below

% This section calls the fortran program --------------

x = 0
xy_fortran = [x, y]'
save ppt4_data.dat xy_fortran -ascii
dos 'ppt4_fortran.exe'
fid = fopen('ppt4_ftn_out.dat','rt'), % open the file
volts = (fscanf(fid, '%g'))'; % read the file

% This section runs the program in Matlab ----------------

% volts = ppt4(x, y)

% ---------------------------------------------
toc

y = [15 + rad, y, 40]; volts = [1.0, volts, 0];

coefs = polyfit(y, volts, 3)
curve = polyval(coefs,y);

figure(1);
plot(y, volts, 'xk', y, curve, 'k')

figure(2);
E_curve = -(3*coefs(1)*y.^2 + 2*coefs(2)*y + coefs(3));
plot (y, E_curve, 'k')

MATLAB script run_ppt4.m is an example of this procedure, using the probabilistic potential theory program ppt4.m, from Chapter 11, as an example. The run_ppt4.m program is written to call either the MATLAB or FORTRAN version of the program (simply comment out the undesired choice).

The FORTRAN source code ppt4_ftn.f90, the FORTRAN version of ppt4.m, is as follows:

! fortran version of ppt4.m

implicit integer (t)
implicit real*8 (a-h, o-s, u-z)
real*8 y_pt(1000) ! y scan data points
real*8 walls(100,5) ! wall data
real*8, allocatable :: volts(:), dists(:,:), results(:)
real*8 stuff(3) ! return from boundary checkers: 1 = distance, 2,3 = closest point
integer hit_boundary

pi = 4*atan(1.0)
call srand(12345)

! get the data
call gather_data(x_pt, nr_pts, y_pt, nr_walls, walls)
allocate (volts(nr_pts), dists(nr_walls,4), results(nr_pts))

print *, 'nr_pts = ', nr_pts
print *, 'x_pt = ', x_pt
do i = 1, nr_pts
 print *, i, y_pt(i)
end do

do i = 1, nr_walls
 print '(5f10.3)', (walls(i,j), j = 1,5)
end do

tic = time8()
do i_nr = 1, nr_pts       ! starting point counter
 nr_iters = 50000
 nr_ones = 0

 do iter = 1, nr_iters    ! iteration counter
  hit_boundary = 0
  x = x_start
  y = y_pt(i_nr)

  do while (hit_boundary < = 0) ! wandering point loop
   do i_wall = 1, nr_walls ! examine all the boundary conditions
    if (walls(i_wall,1) .eq. 1) then
     call hor_line(i_wall, walls, x, y, stuff)
    else if (walls(i_wall,1) .eq. 2) then
     call vert_line(i_wall, walls, x, y, stuff)
    else
     call circle_dist(i_wall, walls, x, y, stuff)
    end if
    do j = 1, 3
     dists(i_wall,j) = stuff(j)
    end do
    dists(i_wall,4) = walls(i_wall,5) ! keep the voltage with us
   end do

   d = 1.e20
   index = 0
   do i = 1, nr_walls
    if (dists(i,1) < d) then
     d = dists(i,1)
     index = i
    end if
   end do

   rad_step = dists(index,1)
   p1x = dists(index,2)
   p1y = dists(index,3)
   v = dists(index,4)
   phi = atan2(p1y-y , p1x-x)
   p2x = x + rad_step*cos(phi + pi/2)
   p2y = y + rad_step*sin(phi + pi/2)
   p3x = x + rad_step*cos(phi + pi)
   p3y = y + rad_step*sin(phi + pi)
   p4x = x + rad_step*cos(phi + 3*pi/2)
   p4y = y + rad_step*sin(phi + 3*pi/2)
   volts = dists(index,4);

   prob = rand(0)
   if (prob < 1./4.) then
    x = p1x
    y = p1y
   else if (prob < 1./2.) then
    x = p2x
    y = p2y
   else if (prob < 3./4.) then
    x = p3x
    y = p3y
   else
    x = p4x
    y = p4y
   end if

!   print *, prob, x, y

! if prob < 1/4 we hve an extraction

   if (prob < 1./4.) then
    if (v .eq. 0) then ! check for voltage
     hit_boundary = 1
    else
     hit_boundary = 2
    end if
   end if
  end do

 if (hit_boundary .eq. 2) nr_ones = nr_ones + 1
!  print *, 'hit_boundary = ', hit_boundary
!  pause

 end do

 v_at_point = (1.*nr_ones)/nr_iters
 print *, 'y, v = ', y_pt(i_nr), v_at_point

 results(i_nr) = v_at_point
end do
toc = time8() - tic
print *, 'execution time = ', toc

open (3, file = 'ppt4_ftn_out.dat')
do i = 1, nr_pts
 print '(2f12.5)', y_pt(i), results(i)
 write (3,'(f12.5)') results(i)
end do
close (3)

stop
end

! ---------------------------------------------

subroutine circle_dist(i_wall, walls, pt_x, pt_y, stuff)

implicit real*8 (a-h, o-z)
real*8 walls(100,5), stuff(3)

rad = walls(i_wall,2)
x0 = walls(i_wall,3)
y0 = walls(i_wall,4)

stuff(1) = sqrt((pt_x - x0)**2 + (pt_y - y0)**2) - rad
theta = atan2(pt_y - y0, pt_x - x0)
stuff(2) = x0 + rad*cos(theta)
stuff(3) = y0 + rad*sin(theta)

return
end

! ---------------------------------------------

subroutine hor_line(i_wall, walls, pt_x, pt_y, stuff)

implicit real*8 (a-h, o-z)
real*8 walls(100,5), stuff(3)
y = walls(i_wall,2)
xl = walls(i_wall,3)
xr = walls(i_wall,4)

if ((pt_x > = xl) .and. (pt_x < = xr)) then
 stuff(1) = abs(y - pt_y)
 stuff(2) = pt_x
else if (pt_x < xl) then
 stuff(1) = sqrt((xl - pt_x)**2 + (y - pt_y)**2)
 stuff(2) = xl
else
 stuff(1) = sqrt((xr - pt_x)**2 + (y - pt_y)**2)
 stuff(2) = xr
end if
stuff(3) = y

return
end

! --------------------------------------------

subroutine vert_line(i_wall, walls, pt_x, pt_y, stuff)

implicit real*8 (a-h, o-z)
real*8 walls(100,5), stuff(3)

x = walls(i_wall,2)
yd = walls(i_wall,3)
yu = walls(i_wall,4)

if ((pt_y > = yd) .and. (pt_y < = yu)) then
 stuff(1) = abs(x - pt_x)
 stuff(3) = pt_y
else if (pt_y < yd) then
 stuff(1) = sqrt((x - pt_x)**2 + (yd - pt_y)**2)
 stuff(3) = yd
else
 stuff(1) = sqrt((x - pt_x)**2 + (yu - pt_y)**2)
 stuff(3) = yu
end if
stuff(2) = x

return
end

! ---------------------------------------------

subroutine gather_data(x_pt, nr_pts, y_pt, nr_walls, walls)

implicit real*8 (a-h, o-z)
real*8 y_pt(1000) ! y scan data points
real*8 walls(100,5) ! wall data
open (3, file = 'ppt4_data.dat')
read (3,*), x_pt
nr_pts = 0
do
 nr_pts = nr_pts + 1
 read (3,*, end = 100) y_pt(nr_pts)
end do
100 close (3)
nr_pts = nr_pts - 1

open (3, file = 'data1.txt')
nr_walls = 0
do
 nr_walls = nr_walls + 1
 read (3,*, end = 200) (walls(nr_walls,j), j = 1,5)
end do
200 close (3)
nr_walls = nr_walls - 1

return
end

The FORTRAN program ppt4_ftn.f90 was written to mimic the programming of the MATLAB code.

Additional notes are as follows:

  • 1 The FORTRAN version runs almost 100 times faster than the MATLAB version. This doesn’t mean that neither version has room for improvement; this is simply an example of what can be done quickly and easily.
  • 2 Separate tests showed that the disk read–write times consume only ~ 0.1 second for relatively small files.
  • 3 This technique could be used for large data files and/or multiple read–write operations by creating a RAM disk rather than by using the actual disk drive. In the case of SSD drives, individual judgment calls are necessary.

Reference

  1. 1. http://www.mathworks.com/support/compilers/interface.html.
  2. 2. http://www.karenkopecky.net/Teaching/Cclass/MatlabCallsC.pdf.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.164.24