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.
Showing posts with label Fortran. Show all posts
Showing posts with label Fortran. Show all posts
Thursday, September 3, 2015
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.
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.
Labels:
Fortran
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.
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.
Labels:
Fortran
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.
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.
Labels:
Fortran,
Programming
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/
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/
Labels:
Fortran,
Programming
Subscribe to:
Posts (Atom)