Showing posts with label Fortran. Show all posts
Showing posts with label Fortran. Show all posts

Thursday, September 3, 2015

Plotting From Fortran

Fortran does not automatically allow for plotting during execution.  There is a work around.  I touched on this with my previous post about plotting with gnuplot from python.  The same principles apply here.

From fortran call gnuplot.  For instance, to make a vector plot from fortran use the command

call system('gnuplot Vector.gp')

where Vector.gp is the gnuplot setup file for vector plotting.

This also requires a datafile that gnuplot can read.  I prefer a csv file because I can put that directly into other programs like excel as well.

So what I've done, is built an IO module with several subfunctions that will create a datafile for gnuplot and call the system for me.  More plot types are on the way.  See attached for details.

example scatter plot colored by the vorticity:
call cScatter(x,y,omegaz)

Fortran-GnuPlot Plotting.zip

By the way, I've switched to Atom text editor by github for my programming.  The .gp files I included save as .png files so I can use them with both word and latex.  Atom will open .png directly inside the editor and update as the figure updates.  This is approaching an IDE and it's a lot faster to update the figure than with Windows Image Viewer.  It should be a cross-platform solution too.

Tuesday, March 3, 2015

Fortran Dynamic Allocation on the Fly

This article from stackoverflow suggests linked lists (which I think are intended to be used with pointers) to append allocatable arrays on the fly with more or less elements.
http://stackoverflow.com/questions/8384406/how-to-increase-array-size-on-the-fly-in-fortran

That's all fine but ehh.  Those of us coming from Matlab background might not understand what's going on with pointers, linked lists, etc. nor do we understand how Matlab actually dynamically allocates arrays.  Since I don't care about the former (right now), the latter question can be answered easily.  An array is allocated according to the number of elements contained within.  If you want to add another element on the bottom, Matlab will allocate a new spot in memory with 1 more element, copy the old array to that physical memory location, then deallocate the original array.  This is poor programming and very inefficient but you'd never notice for small arrays.  For large arrays, your code will crawl.

C, fortran, most other languages of interest (I can't remember how python does it) force you to declare the exact number of elements you intend to store in an array before you can store any elements at all.  In the tutorial guides, you'll see whole sections about allocating and deallocating variables and think that it's all unnecessary - because matlab just works!  Except even really good matlab can be very slow.  I recently converted a code to Fortran and got a 99.4% increase in speed over a well written, matlab code.

So if you're in C or Fortran, what can we do if we need to allocate more space on the fly?  One option is (written in Fortran)

allocate(temp(size(myVariable)))
temp = myVariable
deallocate(myVariable)
allocate(myVariable(size(temp)+1))
myVariable(1:temp) = temp

This is doing exactly what Matlab does, but you have to code it yourself.  If this is in a loop, and you're doing this every iteration, things will be slowed down considerably but RAM conservation will be maximized.

Why not allocate for a large fixed size ahead of time?  allocate(myVariable(100)).  Because if you only have 10 elements to store, then 90 percent of your memory usage is waste.

Here's my solution
allocate with a number

allocate(myVariable(10))
counter = 10

then

pcounter = 0
do i=1,Total,1
  myVariable(i) = i
  pcounter = pcounter + 1
  if pcounter = counter then
    allocate(temp(size(myVariable)))
    temp = myVariable
    deallocate(myVariable)
    allocate(myVariable(size(temp)+10))
    myVariable(1:temp) = temp
    counter = counter + 10
  end if
end do

this gives a buffer of 10 so you don't reallocate every iteration, but at worst, only every 10 iterations

the opposite can be done to deallocate on the fly

if counter - 10 > pcounter then
  allocate(temp(size(myVariable)))
    temp = myVariable
    deallocate(myVariable)
    allocate(myVariable(size(temp)-10))
    myVariable(1:temp) = temp
    counter = counter - 10
end if

this approach isn't too computationally intensive and it saves a ton of RAM for large simulations.  Best of all, it's pretty straightforward in any language.  I've even used it in Matlab when reading experimental data from arduino boards.



Brief Intro to Structures in Fortran

In Matlab, the cell variable type can be very useful.  For those not familiar, a cell (in Matlab) is kinda like a variable inside a variable.  For instance I could have a cell called FieldVariables.  There are 4 elements inside this cell: 1 each for pressure, density, Vx, Vy.  Each of these 5 cell elements has Nx by Ny elements inside relating to the value of the variable at the gridpoints.  This can be a convenient way to collect related data while incurring minimal overhead.

In Fortran, something similar can be done in the form of structures.  A structure allows you to define a custom variable type that can be used similarly integer by coding integer:: i .  It's maybe not exactly the same.

For this example, I need a variable named PointsInCell
Inside PointsInCell, I want to store variables associated with x and y gridpoints.  So, at every gridpoint I want to store:
1) an integer counter NumInCell
2) an allocatable integer array called pIndex
3) an integer called pcounter

I want to do this because NumInCell, pIndex, and pcounter are all related to information local to a specific cell and it's convenient later in the code to have them all collected together.  So first, I define a type that declares NumInVox, pIndex, and pCounter

type CellIndex
        ! Contains:
        integer:: NumInCell ! # points in each Cell
        integer,dimension(:),allocatable:: pIndex ! array storing index of all points in Cell
        integer:: pcounter ! # counter for dynamic array sizing
end type
this takes care of defining what is to be stored AT each gridpoint

Next, I define another type to define the gridpoints where CellIndex will be stored:

type Cells
        type(CellIndex),dimension(:,:),allocatable:: Cell ! each element contains NumInVox, pIndex
end type

This defines the variable Cell as rows and columns were CellIndex will be stored

Lastly, I want to define a single variable that will contain all this information

type(Cells):: PointsInCell

Now to allocate these variables in the structure

allocate(PointsInCell % Cell(yNum,xNum))
do i=1,yNum,1
        do j=1,xNum,1
            allocate(PointsInCell % Cell(i,j) % pIndex(10))
        end do
end do
PointsInCell % Cell(:,:) % pcounter = 10

so if I want to change the pcounter at Cell(10,20) to 20, I'd write
PointsInCell % Cell(10,20) % pcounter = 20

the percent sign defines another level deeper in the structure.

Monday, February 16, 2015

Installing Fortran on Windows with MinGW

As a followup to the previous post using cygwin to emulate linux to install gfortran, this post is the same but using mingw.  From my own experience, cygwin worked on 2/3 of the computers I installed it on.  On the third, it was unusably slow - 2-3 minutes to open terminal.  The instructions online to speed things up were unhelpful - my problem was not addressed.  Fortunately, there is also minwg that does the same thing from the perspective of a scientist that needs a compiler (CS guys might disagree but their purpose would be different).  The biggest difference between the two is that mingw compiles programs to be run on windows while cygwin works on cygwin.

This post is more for me to aggregate the hard work of others so I have a single place to look when installing Fortran on Windows.

Here's the gist:

1) make sure you've got Java installed if you use Eclipse (or other Java-based IDEs) http://www.oracle.com/technetwork/java/javase/downloads/index.html

2) download MinGW from www.mingw.org .  Click Downloads on the left and Download the latest version setup.exe file from sourceforge

3) install minwg as administrator to the c:\ drive.

4) I installed all the packages in the basic setup options (developers kit, base, ada, fortran, c++, object c, msys base)

these will get you started.  The g++ compiler is also available and eventually, installing all pthreads packages will get openMP running.

5) Add path variables:
;C:\MinGW\bin;C:\MinGW\msys\1.0\bin\

5) Check that gfortran is installed by typing gfortran --version into windows command prompt or terminal.  The terminal is in C:\MinGW\msys\1.0  msys.bat opens it.

6) Install Eclipse Parallel tools developer kit (containing Photran) http://www.eclipse.org/ptp/
if you had a previous project running in cygwin, you'll probably have to open a new project so the new addresses for the compilers will be recognized.

Sunday, February 15, 2015

Installing Fortran on Windows with Cygwin

This post is more for me to aggregate the hard work of others so I have a single place to look when installing Fortran on Windows.

This set of instructions is where I got most of my help.  There are a couple tweaks that were necessary to keep everything up and running on 64bit with newer packages.  After all, the video is a couple years old.
https://www.youtube.com/watch?v=GfCmiEbGtpE

Here's the gist:

1) make sure you've got Java installed if you use Eclipse (or other Java-based IDEs) http://www.oracle.com/technetwork/java/javase/downloads/index.html

2) download cygwin from www.cygwin.org .  Download the setup.exe file for either 32 or 64 bit systems

3) install cygwin as administrator to the c:\ drive.  The cygwin.mirrors.hoobly.com mirror definitely works.

4) Install these packages in cygwin:
gcc-fortran: GNU Compiler Collection
gdb: The GNU Debugger
make: The GNU version of the 'make' utility

these will get you started.  The g++ compiler is also available and eventually, I (you) might need either OpenMP or OpenMPI.

5) Add path variables:
for 64 bit
;C:\Cygwin64\bin;C:\Cygwin64\usr\bin;C:\Cygwin64\usr\local\bin;C:\Cygwin64\lib;C:\Cygwin64\usr\lib
or for 32 bit
;C:\Cygwin\bin;C:\Cygwin\usr\bin;C:\Cygwin\usr\local\bin;C:\Cygwin\lib;C:\Cygwin\usr\lib

5) Check that gfortran is installed by typing gfortran --version into command prompt

6) Install Eclipse Parallel tools developer kit (containing Photran) http://www.eclipse.org/ptp/