tag:blogger.com,1999:blog-48554851430375098102018-03-04T08:04:26.087-08:00Fortran in a C WorldUsing Fortran (90+) in a world where everyone hates itKyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-4855485143037509810.post-6416518941437990322013-10-03T07:47:00.000-07:002013-10-03T07:47:43.396-07:00on Project Euler & BigIntsAbout a year ago, I discovered <a href="http://www.projecteuler.net">Project Euler</a> and started blowing through problems. The first two dozen or so are actually pretty simple and shouldn't take much more than 50 lines of code to do (most require less). I even wrote a <code>MODULE</code> that contained a fair number of repeated functions (like a prime finder and a digit sum) to make life more simple. <br><br>But some of the posted solutions for <a href="http://projecteuler.net/problem=16">Problem 16</a> bother me. The question asks, <blockquote><i>2<sup>15</sup> = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. What is the sum of the digits of the number 2<sup>1000</sup>?</i></blockquote><br>The digit sum is a fairly simple thing to do:<br><blockquote><code> digit = 0 <br>do while(n /= 0) <br> digit = digit + mod(n,10)<br> n = n/10<br>enddo </code></blockquote><br>But the way I solved this, this part isn't even necessary (though it's still useful to know).<br>The problem you'll run into is that 2<sup>1000</sup> contains 302 digits and even using quadruple precision (via the <code>ISO_FORTRAN_ENV</code> module and assuming you have the library for it) the maximum value is a mere 19 digit number: 9223372036854775807. Obviously way too small. <br>So some people, namely C/C++ and Java programmers, utilized the BigInt package that extends integers to arbitrary positions. <br><br>I personally think this is cheating. I think this problem is to be solved <i>without</i> resorting to external libraries that extend precision to arbitrary limits. And this problem can be done in any language without doing so too. <br><br>All you have to remember is this: arrays. If you think of any <i>n</i>-digit number as an <i>n</i>-celled array, then a 302-digit number is a 302-celled array.<br><blockquote><code>2 → (2)<br>22 → (2,2)<br>222 → (2,2,2)<br></code></blockquote>and so on. If you add 22+222, you get 244: <blockquote><code>222+22 → (2,2,2) + (2,2) = (2,4,4)<br></code></blockquote>Adding 66, you have to carry your 10 over: <blockquote><code>244+66 → (2,4,4) + (6,6) = (2,10,10) = (3,0,10) = (3,1,0)<br></code></blockquote>With multiplication, you need to multiply each cell by the value & carry the tens <i>multiple</i> times: <blockquote><code>222*22 → (2,2,2) * 22 = (2*22,2*22,2*22) = (44,44,44) = (4,8,8,4)<br></code></blockquote>If you understand this, then 2<sup>1000</sup> is painlessly easy. <br><br>I clocked this method with the Fortran intrinsic subroutine <code>cpu_time</code>, which is accurate to the microsecond, and kept getting zero's across the board (i.e., 0.000000E+00). Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com1tag:blogger.com,1999:blog-4855485143037509810.post-19747551089633429622013-09-24T08:20:00.001-07:002013-09-24T08:21:18.997-07:00on TrafficSo I have apparently completely forgotten about this blog. Between research and teaching (Intro to Computing in the Spring), posting kept getting further and further back until it was just completely lost on me. <br /><br />Then this morning, I got an email letting me know that I had <a href="http://fortraninacworld.blogspot.com/2012/12/but-isnt-fortran-dead.html?showComment=1380007376406#c5296756607388195714">a comment</a>! I then checked this and saw that I've had quite a number of visitors over the last several weeks. <br /><br />It took me a while, but I think that I figured out why people were visiting this site: <a href="http://stackoverflow.com/users/1276356/kyle-kanos">my stackoverflow account</a>. I guess this makes sense, since I have been pretty active on SO lately. <br /><br />Given the increase of traffic here, I suppose I can try blogging again. Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com1tag:blogger.com,1999:blog-4855485143037509810.post-37217593171196930742012-12-24T11:59:00.001-08:002012-12-24T11:59:50.097-08:00On Floors and IntegersA couple projects I have worked on in the past have involved <a href="http://en.wikipedia.org/wiki/Monte_Carlo_method">Monte Carlo</a> techniques for placing point particles (representing stars in a galaxy) in such a way that we have a constant surface density. In order to test that we do indeed have a constant surface density, we simply count the number of points from <code>r=0</code> to <code>r=rMax</code> in steps of <code>dr</code> and display the total number per bin over the total radius. <br /><br />Conceptually, this is fairly simple. Fortunately, this is also a fairly easy program too. If we have a radius of 15 units (for the galaxy I was modeling, this would be 15 <a href="http://en.wikipedia.org/wiki/Parsec">kiloparsecs</a>), the easiest thing to do would make an integer array with 15 cells so that the bin size is 1 unit. Then you could just take the <a href="http://en.wikipedia.org/wiki/Floor_and_ceiling_functions">floor</a> of the radial position and get the distribution quickly:<br /><blockquote><code>do i=1,iMax<br /> b=floor(radius(i))<br /> hist(b)=hist(b)+1<br />enddo </blockquote></code>where <code>b</code> and <code>hist</code> are appropriately defined as integers. <br /><br />Alternatively, since Fortran returns integer values for integer math, dividing by 1 can accomplish the same thing:<br /><blockquote><code>do i=1,iMax<br /> b=radius(i)/1<br /> hist(b)=hist(b)+1<br />enddo </blockquote></code>Upon testing these methods on a the same set of 10 million real values, <code>floor</code> takes about 3.9 seconds compared to 3.8 for dividing by 1. Similar results are found for using <code>ceiling</code> and dividing by 1 and adding 1. <br /><br />If we want smaller bins, say <code>dr=0.5</code>, we might think we would run into the problem of determining which half-unit this point belongs to in order to add it to the correct bin--this would basically involve something like finding the remainder of <code>real(floor(radius(i)))-radius(i)</code> and seeing if it is greater or lesser than <code>0.5</code> and then putting it into the appropriate bin. <br /><br />However, there is far more simple method of doing this that requires us to first do two things:<br /> (1) Set the histogram lower index to 0 and the upper index to number of bins - 1 (i.e., <code>allocate(hist(0:31))</code><br /> (2) Multiply the radius by 2: <blockquote><code>allocate(hist(0:31)) do i=1,iMax<br /> b=2*radius(i)<br /> hist(b)=hist(b)+1<br />enddo </blockquote></code>If <code>radius(i)=0.75</code>, multiplying this by 2 gives 1, which is the correct bin. If <code>radius(i)=4.25</code>, then multiplying by 2 gives 8, which is also the correct bin. Note that we could have left the indices as they were and just add 1 to the multiplication of 2, but this method adds a needless (and potentially costly) extra mathematical operation. <br /><br />So, the next time you have to create a histogram of your data, recall this easy-binning method, which can easily be extended to larger or smaller bin sizes. <br /><br />Comments always welcome! Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com0tag:blogger.com,1999:blog-4855485143037509810.post-54897417476775971542012-12-14T09:04:00.000-08:002012-12-14T09:04:42.412-08:00On Shaping ArraysThe best thing about Fortran is its handling of arrays, in particular the multi-dimensional ones. As someone who models astrophysical fluid flows for a living, I tend use 4-dimensional arrays (3 for space and 1 for variables) in most of my relevant codes. <br /><br />In defining arrays, there are three methods by which we can use to define them:<br> (1) nested do loops<br /> (2) forall assignment<br /> (3) nested implied-do loops <br /><br />I presume every Fortran user knows of the first of these methods very well, as it is the most used and most versatile method of defining an array. I think most people have heard of the forall assignment, which was once part of the now-defunct <a href="http://en.wikipedia.org/wiki/High_Performance_Fortran">High Performance Fortran</a> but added to Fortran 95 update. It is used as follows, <blockquote><code>forall(i=1:iMax, j=1:jMax, k=1:kMax) A(i,j,k)=i*k+j/jMax </blockquote></code>I can pass the <code>i,j,k</code> indices to a function that returns a value, so it can work much like the nested do loop. The original point of the <code>forall</code> assigment was for optimization in defining arrays, but since most compilers are pretty good at optimizing loops for memory purposes, the use of this command is declining. For an array of size (750,750,750), it takes about half a second to define the array with the above definition using either of the two methods. <br /><br />The last method, the nested implied do loop, is probably about as useful as the <code>forall</code> assignment, but it introduces the command <code>reshape</code>, which has some useful applications for clusters and file I/O. Suppose we have a 2D array defined in the nested do loop, <blockquote><code>do j=1,jMax<br /> do i=1,iMax<br /> B(i,j) = i*j<br /> enddo<br />enddo</blockquote></code>we can collapse the inner loop as, <blockquote><code>do j=1,jMax<br /> B(1:iMax,j) = (/ (i*j, i=1,iMax) /)<br />enddo</blockquote></code>But in collapsing this other <code>do</code> loop, <blockquote><code>B =(/ ((/ (i*j, i=1,iMax) /), j=1,jMax) /) </blockquote></code>we would get an "incompatible ranks" error. This is because B is defined as a 2-dimensional array, <code>B(iMax,jMax)</code>, and the above doubly-collapsed loop is a 1-dimensional array with dimensions of <code>(iMax*jMax)</code>. To get into the 2D array from the 1D array, we can use the <code>reshape</code> command. For ease, I have written the (iMax*jMax) array as a separate line: <blockquote><code>tempArray=(/ ((/ (i*j, i=1,iMax) /), j=1,jMax) /)<br />B =reshape( tempArray, (/iMax,jMax/) ) </blockquote></code>Extending this to a 3D array should be straight-forward. <br /><br />Nested do loops should be the primary method for defining your arrays as it is the most clear method (you just have to remember that Fortran is <a href="http://en.wikipedia.org/wiki/Row-major_order#Column-major_order">column-major</a>). The <code>forall</code> assignment, while sometimes convenient, just is not as useful as it was thought to be, probably should be dropped from codes that currently employ it, a should be marked as <a href="http://pic.dhe.ibm.com/infocenter/compbg/v121v141/index.jsp?topic=%2Fcom.ibm.xlf141.bg.doc%2Flanguage_ref%2Fobsoletefeat.html">obsolescent</a> in future updates to Fortran. The nested implied do loops probably should not be used for defining arrays, but it is useful for understanding how <code>reshape</code> works for use in other areas of codes. <br /><br />Comments are always welcome! Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com0tag:blogger.com,1999:blog-4855485143037509810.post-41272186649537566332012-12-12T09:20:00.003-08:002012-12-12T09:25:27.870-08:00On Numerical RecipesWhile doing some investigating on employing <a href="http://phase.hpcc.jp/mirrors/netlib/lapack90/index.html">LAPACK routines</a> for a computational course I am teaching next semester, I found an article written by Dr Benjamin Weiner titled, <a href="http://mingus.as.arizona.edu/~bjw/software/boycottnr.html">Boycott Numerical Recipes</a>. Given that I am an avid user and advocator of NR, I opted to take a look. <br /><br />Dr Weiner has two arguments on that page:<br /> (1) the routines in NR are old and outdated (I imagine most people have the 1992/1996 versions, though the books were updated in 2007)<br /> (2) the NR routines given in the book are copyrighted which means you cannot distribute the source of a code that has NR routines in them to people who do not have the NR license (though you can distribute the <i>binary</i> of the code) <br /><br />I have never really paid attention to the content copyright pages, so I took a look of my copy of Numerical Recipes to find the following: <blockquote>...These [diskettes] provide demonstration programs that illustrate the use of each subroutine and procedure in this book. They too can be ordered in the above manner. <br />Unlicensed transfer of Numerical Recipes programs from the abovementioned IBM PC or Apple Macintosh diskettes to any other format, or to any computer except a single IBM PC or Apple Macintosh or compatible for each diskette purchased, is strictly prohibited.</blockquote>Now, I am no copyright law professional, but it seems like I can write a code with some functions/subroutines <i>based</i> on NR without trouble. <br /><br />In any event, there are alternatives to Numerical Recipes codes that are more up to date and free. I already mentioned LAPACK at the top of the page, but there is also:<br /> <a href="http://www.netlib.org/slatec/index.html">SLATEC</a> -- a large collection of routines such as ODE solvers, numerical integrators, and so on (it was partially re-written in F90 by John Burkardt, <a href="http://people.sc.fsu.edu/~jburkardt/f_src/slatec/slatec.html">see here</a>)<br /> <a href="http://www.netlib.org/blas/">BLAS</a> -- Basic Linear Algebra Subprograms, this is included in the SLATEC package, but is available separately<br /> <a href="http://www.lrz.de/services/software/mathematik/gsl/fortran/">FGSL</a> -- Fortran interface to the GNU Scientific Library (GSL)<br /> <a href="http://www.netlib.org/minpack/">MINPACK</a> -- collection of non-linear equation solvers<br /><br />I know that some of my colleagues use external libraries (GSL in particular), but I have yet to use any of them. I am somewhat curious about using LAPACK and SLATEC, but I will have to see if I can employ it beyond teaching a lecture or two on it for my class. <br /><br />I can understand Dr Weiner's argument: why use routines that you have to pay for and are very restrictive in sharing when you can get it free from someone else without any restrictions? And I completely agree, however, I will not be boycotting Numerical Recipes because it is still a fantastic source of information for beginning programmers. <br /> <br />Comments are welcome! Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com0tag:blogger.com,1999:blog-4855485143037509810.post-9625772561787182912012-12-06T09:03:00.000-08:002012-12-06T09:08:16.120-08:00On FunctionsLike every other programming languages, Fortran allows you to write your own functions to be evaluated in your codes. There are two types of functions in Fortran: <b>statement functions</b> (also called <b>inline functions</b>) and <b>subprogram function</b> (also called <b>external functions</b>). In this post, we will be discussing the use and possible advantages of these different types of functions, starting with the statement function. <br /><br />In order to use the statement function, you must <br /> (1) declare the function name and its argument in the variable declarations at the beginning of the program<br /> (2) define the function before any other variables are defined, even if it depends on other variables not yet defined<br />A simple example is given below <br /><blockquote><code>program fcnTest<br /> implicit none <br /> real::f,a,pi,x,dx<br /> integer::i<br /><br /> f(a)=a**5<br/ ><br /> pi=acos(-1.0);dx=0.0000012;x=1.0<br /> do i=1,1000000<br /> print *,x,(4.5**x)*sin(pi*f(x))<br /> x=x+dx<br /> enddo<br />end program</code></blockquote><br />Note also that multiple statement functions can be employed in Fortran. We could have chosen to define <code>g</code> such that <code>g(a)=4.5**a</code> and used this in the above code (which, though I do not get into it here, does not change the results at the bottom of the page).<br /><br />The function <code>f</code> is actually from a <a href="http://www.gnuplot.info/">gnuplot</a> tutorial I have seen online and looks like, using <a href="http://soft.proindependent.com/qtiplot.html">QtiPlot</a>, a free-ware plotting program that I have grown to like.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/--kVqJY8DDO4/UMCtI8LKICI/AAAAAAAAAYY/luN-X4Qhzxk/s1600/fcnTest.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="186" width="320" src="http://4.bp.blogspot.com/--kVqJY8DDO4/UMCtI8LKICI/AAAAAAAAAYY/luN-X4Qhzxk/s320/fcnTest.png" /></a></div><br />I also chose to iterate the loop 1,000,000 times because it will give a long enough runtime to make a difference. If I used 1,000 iterations, the millisecond runtimes would not be enough to show a difference between one or the other.<br /><br />I compiled the code without any optimization flags (i.e., just <code>ifort -o fcnTest fcnTest.f90</code>) and ran it twice, getting 60.013 s and 59.901 s, which is pretty slow to do 5 operations a million times. If I changed the code to output the data to a formatted file,<br /><blockquote><code>program fcnTest<br /> implicit none <br /> real::f,a,pi,x,dx<br /> integer::i<br /><br /> f(a)=a**5<br/ ><br /> open(unit=10,file='fcnTest.txt',status='unknown')<br /><br /> pi=acos(-1.0);dx=0.0000012;x=1.0<br /> do i=1,1000000<br /> write(10,*),x,(4.5**x)*sin(pi*f(x))<br /> x=x+dx<br /> enddo<br />end program</code></blockquote><br />which dropped the runtime to a fairly consistent 3.95 s with deviations of about 0.04 s (I ran it 5 times). Fortran also enables putting data in binary files simply by adding the option <code>form='unformatted'</code> in the <code>open</code> command and replacing <code>write(10,*)</code> with <code>write(10)</code>. Doing so, the runtime drops to a slightly-less-fairly consistent 2.78 s with deviations of about 0.09 s (also ran 5 times).<br /><br />The reason for the significant difference is, hopefully, obvious: Fortran was not designed for putting a large amount of data to the screen, it was designed for dumping it to data files for analyzing later. <br /> <br />A problem that exists with the binary output (<code>form='unformatted'</code>) is that the binary output is machine-dependent, so dumping data in that format and then transferring it to another machine <i>can</i> cause issues with reading the file on the second machine. I have my own desktop (running <a href="http://www.ubuntu.com/">Ubuntu Linux</a> with an AMD Phenom X4 processor), my own laptop (running <a href="https://www.archlinux.org/">Arch Linux</a> with an Intel i5 processor), and access to a super computer cluster (running <a href="https://www.scientificlinux.org/">Scientific Linux</a> with Intel Xeon and Itanium processors) and I can tell you now that I have not experienced any file-reading issues between the three of them, but that is not to say this problem does not exist. <br /><br />If you are a one-computer type of person, this problem should not be an issue. If you are working with multiple computers and are dumping data into binary format, it might be worth your time to write a second program to read in the binary code and output it as a formatted file to prevent these issues. Or, if you are working with multiple computers and large data sets, you might just want to use something like <a href="http://www.hdfgroup.org/HDF5/">HDF5</a>. <br /><br />Anyway, now that we have some data on the inline function statement, how does it compare to the external function statement? This requires a significant change to the code, but it is not difficult:<br /><blockquote><code>program fcnTest<br /> implicit none<br /> real::pi,x,dx<br /> real,external::f<br /> integer::i<br /><br /> pi=acos(-1.0); dx=0.0000012; x=1.0<br /> do i=1,1000000<br /> print *,x,4.5**x*sin(pi*f(x))<br /> x=x+dx<br /> enddo<br />end program fcnTest<br /><br />real function f(x) result(a)<br /> implicit none<br /> real::x<br /><br /> a = x**5<br />end function f<br /></code></blockquote><br />Compiling and running this in the same manner, it took 59.985 s and 60.010 s to run the display to screen. The formatted output took an average of 4.03 s with a deviation of 0.07 s; the unformatted output took an average of 2.84 s with a small deviation of about 0.06 s. <br /><br />As a scientist, I like pretty pictures and tables of the data. Taking the data from above:<br /><br /><center><table border="1"><tr><td><b>output</b></td> <td><b>inline runtime</b></td> <td><b>external runtime</b></td><tr><td>screen</td> <td>59.96±0.08</td> <td>60.00±0.18</td><tr><td>formatted file</td> <td>3.95±0.04</td> <td>4.03±0.07</td><tr><td>unformatted file</td> <td>2.78±0.09</td> <td>2.84±0.06</td></tr></table></center><br />The data indicates the following:<br /><blockquote> (1) There is no advantage between inline and external functions <i>at least for simple functions</i><br /> (2) Unformatted output is faster than formatted output<br /> (3) You should never put 1,000,000 data points on the screen (probably any output more than 10 lines long should go to a file)<br /></blockquote>If multiple subroutines require the use of the same function, then clearly the choice should be to use the external function. If the function is rather complex, the external function should also be the clear choice. <br />Still, it is good to know that, for simple functions in a simple program, writing it once at the beginning of your code can make it more tidy without sacrificing any performance. <br /><br />Comments always welcome. Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com0tag:blogger.com,1999:blog-4855485143037509810.post-51844690356788100772012-12-03T07:13:00.000-08:002015-04-14T06:34:44.352-07:00Ternary Operator ?Suppose you had a variable <code>x</code> that has a value depends on the variables <code>a</code> and <code>b</code>. The most obvious choice is to write an <code>if-else</code> statement to determine what <code>x</code> is: <br /><blockquote><code>if(a > b) then <br /> x = a<br />else<br /> x = b<br />endif</blockquote></code><br />But this seems a bit cumbersome, particularly when you look at a more compressed form using the ternary operator <span style="font-family: Times, "Times New Roman", serif;">?</span> as in C (among other languages): <br /><blockquote><code> x = a > b ? a : b;</blockquote></code><br />I used to be jealous of C because they had the inline-if and I believed that Fortran did not. Fortunately for us, Fortran added this inline-if into the 1995 standard. Unfortunately, they chose the most random of intrinsic function names I have ever heard of: <code>merge</code>. It is used quite like the above: <br /><blockquote><code>x = merge(a,b,a>b)</code></blockquote><br />More explicitly, <br /><blockquote><code>variable = merge(value if true, value if false, condition)</code></blockquote><br />The following is a snippet from a simulation I wrote that involved a Monte Carlo sampling of positions in cylindrical coordinates. R,P,Z are the rho-phi-zed coordinate-arrays. <br /><blockquote><code>do i=1,numPoints <br /> call random_number(rTemp)<br /> call random_number(pTemp)<br /> call random_number(zTemp)<br /> call random_number(cTemp) <br /> R(i) = sqrt(rTemp)*rScale <br /> P(i) = 2.*pi*pTemp <br /> Z(i) = merge(zTemp*zScale,-zTemp*zScale, cTemp > 0.5) <br />enddo</blockquote></code><br />A couple notes on the above:<br />(1) Fortran uses 1-index, rather than C's 0-index--which leads me to the aside: quickly count to 10. Did you start at 0? Fortran can actually start at 0, if you want. You would have to define the array to start there by using <br /><blockquote><code> real,dimension(0:numPoints)::myArray</code></blockquote><br /> (2) Fortran uses curved braces for the array index, whereas C uses the square braces for the same thing.<br />(3) The variable <code>pi</code> is not an intrinsic (why not!?) and needs to be declared beforehand; I find the easiest option is using <code>pi=acos(-1.0)</code>, though others may suggest <code>pi=4*atan(1.0)</code> (which is fine, but it seems to me that one operation is better/faster than two).<br />(4) The intrinsic subroutine <code>random_number(variable)</code> was used because it is superior to the intrinsic function <code>rand()</code>. The former has a period of 2<sup>123</sup> (~10<sup>37</sup>) while the latter has a period of (I think) 2<sup>32</sup> (~10<sup>9</sup>). <br /><br /><br /> Comments always welcome.Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com6tag:blogger.com,1999:blog-4855485143037509810.post-6135429582314793732012-12-03T06:38:00.005-08:002012-12-03T15:52:08.620-08:00But isn't Fortran dead?Despite what many programmers in Comp Sci would tell you, no Fortran is not dead. And it likely will never be dead, even when the "next generation" of compilers (Cray Chapel, IBM X10) start being used outside of Cray & IBM.<br /><br />MPI support for Fortran still exists with updates coinciding with the C/C++ updates. Intel recently released version 13 of their compiler, adding more compatibility with the Fortran 2003 and 2008 standards. The Portland Group brand of Fortran compilers are working hand-in-hand with nVidia to allow Fortran the use of the graphics cards for faster, cheaper computations.<br /><br />I know several hydrodynamic codes that utilize Fortran: Athena (the original code was in C, but it was ported to F90), VH-1, Ramses, CLAWPACK (and all its derivatives, sparing only pyCLAW), VAC (And its derivatives), Pencil, Piernik and several others. Some of these have been released within the last 5 years, others a decade or so. There are many other codes written for research purposes using Fortran. <br /><br />So no, Fortran is definitely not dead.<br /><br />I started using Fortran 90 in 2007 as part of my Master's degree (in physics) research in the optical properties of superlattice- and Gallium-based semiconductors. Most of what I did there was translate my advisors Fortran 77 code into a more-up-to-date standardized form (i.e., eliminating <code>do-continue</code> and replacing it with <code>do-enddo</code>). I moved on to my PhD program in 2009 where I started research on numerically modeling supernova remnants using the F90/95 standard for the hydrodynamic simulations. I use the Intel compiler on the cluster we have on campus.<br /><br /><br />This blog will be about the things I have discovered about Fortran 90/95/03 through discussions with my C/C++ using colleagues and tips & tricks for those budding physicists who want a modern, fast, number-crunching language without the use of any ugly curly braces. You will not find any <code>goto</code> here, unless it is my complaining about seeing it elsewhere. <br /><br /><br />Comments are always welcome!Kyle Kanoshttp://www.blogger.com/profile/05322908974312681257noreply@blogger.com2