Legacy Fortran modernization

Initial FEM-1D validation

One of the book's authors, Darrell Pepper, was kind enough to send me some sample files so I could make sure my translation of his work was producing the correct results. I did find a couple of errors, and so I've updated the code and pushed the changes to the GitHub repository. But it does match the test data, so so far so good.

I still have a while to go before the entire translation is complete. There's also a mesh generator that I haven't put together yet, along with the 2D and 3D variants of both the mesh generator and the FEM code. This is on top of all the code streamlining and refactoring I want to do in the future. But ideally by the end there would be only a single program to call that would handle all permutations, along with common modules that would make debugging and maintenance easier. I don't know how much the code will be picked up once I'm done with it, but it has been an interesting exercise so far and I look forward to trying out more advanced features of the language.

David PernerComment
First working version of FEM-1D and basic gfortran usage

Over the past week or so, I've been able to put together a translation of the original FEM-1D.FOR file into Fortran 2008, FEM-1D.f08, along with several modules in the "common modules" folder. The program runs, but I still need to verify that the results are correct. 

The commit containing this first working version can be found here.

The modules do need to be compiled, which can be done with the following command from the terminal (on a Mac or Linux system) using assemb_mod.f08 as an example:

gfortran -c assemb_mod.f08

This particular command uses the GNU Fortran compiler, but there are several out there that would work. However, these will potentially have different compiler flags, so these commands may not work. Also, this command will only work if the current directory for the terminal is the common modules folder.

With all the modules compiled, we then have to compile the main program from the fem-1d folder. This can be done with the following command:

gfortran -I../common\ modules ../common\ modules/assemb_mod.o ../common\ modules/init_mod.o ../common\ modules/gauss_mod.o -o FEM-1D.o FEM-1D.f08 

What this is saying, piece by piece is that:

-I indicates that there are compiled modules to find in the common modules folder. The phrasing here says to go up a directory level, and the common modules will be under that parent folder, a so called relative path.

The list of *.o files after that are the compiled modules, which have to be given with a path since they're not present in the fem-1d folder.

-o specifies the name of the output file, in this case FEM-1D.o

Finally, FEM-1D.f08 is the file containing the main program.

The program can be run from the terminal with a command:


I believe in Windows, the leading "./" is not necessary. The program in its current form will ask for an input and output file name. The input files can be found in the "Original code/fem-1d" folder, as the *.DAT files. The output can be named anything except for an existing file name, and the program will throw an error if such a name is used. Otherwise, let me know if there are any issues, I'd like to make the code as robust, stable, and accurate as possible.

GitHub repository

As is required with any modern software project it seems, I've created a GitHub repository so people can view and contribute to this project if they so choose, as well as making sure I can revert or restore my own local copy if need be. It can be found here:

The Finite Element Method

I've posted both the original code and my revised version. There are perhaps better ways to organize the files, so any suggestions would be greatly appreciated!



In my efforts to learn Fortran, there were two main skill sets I was hoping to develop: using the language to create my own code, and translating legacy code (mainly Fortran 77) into modern Fortran. In looking up different HPC (high performance computing; more or less supercomputers) centers, I came across Dr. Darrell Pepper and Dr. Juan Heinrich's book The Finite Element Method and the code examples written for the book posted on their UNLV website. In reviewing the code, it looks to be mostly in a 77 style, and in talking to Dr. Pepper, it sounds like the code hasn't had major revisions since the 70s. In short, it looked like a good opportunity to work with some legacy Fortran and maybe even learn some finite element analysis along the way.

So what are the major differences in legacy and modern Fortran?

Some of the changes that entered the language after the 77 standard are relatively minor. Some of the ones I'll be changing in my version are:

  1. Defaulting to lowercase for readability. Fortran 77 and older only supported uppercase characters.
  2. Replacing .EQ., .GT., etc. intrinsic functions with their more intuitive ==, >, etc. counterparts.
  3. Using "end do" instead of the do [tag] [iterator] syntax.
  4. Moving from fixed format to free format and using indentation. 
  5. Replacing loops with array operations where possible.

Some of the major changes are:

  1. Eliminating the use of GOTOs. 
  2. Eliminating implicit typing
  3. Replacing COMMON blocks with modules.
  4. Organizing methods into different modules, instead of having a single, monolithic source file.
  5. Making data and methods private where possible to reduce data access.
  6. Having arrays be allocatable where possible instead of having their sizes hard coded.

Also, in general, I tried to maintain some kind of style and best coding practices, although I am learning those as I'm doing this project, so it may be slightly inconsistent.

What about future improvements?

Part of this depends on the needs and interest of the authors. I'm not sure it does me any good to perfect code that won't be used or doesn't meet the needs of the readers of this text. But, left to my devices, I'd like to:

  1. Improve the data management of the code. Right now data flow depends heavily on essentially global variables. I'd like to make the data flow more explicit and traceable. I'd also like to use some object oriented programming in order to make sure the input data can't be altered once read, for instance.
  2. Vectorize computations. The original code does vector and matrix calculations element by element. It's correct, but I'd like to gain a better insight into FEM so that these calculations can use the vectorization features of Fortran and be a bit more compact and intuitive.
  3. Parallelize computations. A lot of work going into the Fortran standard since 2003 or so has been around parallel computation, as you might expect for a language used heavily in HPC. Several features in Fortran can implicitly parallelize, such as forall, do concurrent, and coarrays, and there are also several explicit options such as OpenMP and MPI. There are differences in how each of these work that make them better or worse options depending on the system, but it might allow much larger examples to be given online than were possible with the previous code.
David PernerFortran, FEM