This was great thank you. Can you now do a purely Windows version? There is a fairly large number of engineers worldwide that are forced by company policy to use pure Windows machines.
Glad you liked it. As far as structure of an fpm project, Windows is no different. I can do a video on how I set up Windows for doing Fortran development, if that would be helpful.
That will be great if you can do that. Working in a “sheltered” environment I had to find out what a toml file is, why one uses git, what a bash shell is etc. For the last 25 years the only Fortran I used is Intel going back to Microsoft Powerstation, then Dec and Compaq and now Intel and Visual Studio.
I have long suspected there are many Fortran programmers working in such “sheltered” environments. My aim (and I believe one of the aims of this community) is to teach new tools and techniques to such people and demonstrate the benefits of their use.
I’m curious to know the statistics on this across Fortran programmers, but in your case, if not git, what do you use for version/source code control? (And yes, copies of the project folder with dates/version #'s in the title, if not optimal, does count)
FYI, I spent the first 5 years of my career working at a company where this was the official procedure for version control, so I fully understand the difficulties of working without a “proper” version control system.
We are engineers not programmers. So we tend to learn enough to get the job done. We also want the equations to look like the equations in the text books and to maintain the connection with physics. Half the time I do not even recognize what FortranFan does when he gives examples.
Version control is just the number we increment with each release.
Welcome to the community @Neels. Thank you @everythingfunctional for the video. Yes, one of our aim is to teach modern tools and development practices.
Yes, making the code look like math and understandable to engineers and physicists is how Fortran was designed. That is one of its strengths.
Can you please show a couple of instances where you don’t recognize what is involved in my examples?
Or, consider the latest one I posted last night involving complex numbers, a basic aspect of math and science: Real and imaginary parts of complex number - #3 by FortranFan
Can you please point out what you think you don’t recognize?
Thanks,
@FortranFan, me not recognizing parts is most definitely not your fault but mine. I have not followed enough of modern Fortran to fully understand it or use it. I am trying to rectify that. That is why I am here. I am not in any way implying a fault on your side. Your posts are one of the highlights of my day, even if I do not fully follow the Fortran I fully understand and support your attitude.
Hopefully my post makes sense, English is my second language.
All good points, and I certainly understand the sentiment.
However, learning some more advanced techniques and newer features of Fortran often makes it possible to write code that “looks like the equations in text books” without lots of obfuscation (i.e. nested loops, complicated branching logic, etc.).
And a good version control system makes collaboration smoother and more efficient, and makes it easier to understand the evolution of the project.
Glad you’re here and willing to learn. I hope we can be of help, so don’t hesitate to ask questions.
My favorite example is on slide 8 of @rouson’s 2014 presentation.
For me personally this particular example from slide 8:
u_t = -(.grad.p)/rho + nu*(.laplacian.u) -(u.dot.(.grad.u))
looks similar to the equation in the text book at the high level, but I have no idea what is going on underneath, because it is hidden underneath the layers of derived types and overloaded operators. To maintain such code, fix bugs, improve performance, etc., one has to understand all the pieces and how they interact with each other. I personally prefer to explicitly expose all arrays and loops, such as here:
where you see all the arrays and all the operations and the loop corresponds directly to the mathematics derived in the corresponding paper, equations (79)-(82).
At first it might seem more complicated, but what you see is all the complexity there is to solving the equation on the grid. Nothing else is happening and it is only using Fortran primitives. So you can easily go in, and refactor it in any way you would like.
For a fair comparison, one should also include all the code needed to make the line u_t = -(.grad.p)/rho + nu*(.laplacian.u) -(u.dot.(.grad.u))
work, so all the derived types and the overloaded operators.
@milancurcic’s book has examples of both approaches.
This is an important topic and I would like to later work on more examples of this and have full working examples, using the OO approach as well as the direct approach.
The OO style is more like using a framework, such as MOOSE, deal.II, libmesh or mfem. If you look at any of their examples, such as here, you have to understand the framework to know what is going on. It takes time. The libmesh’s style example is more readable at the lowest level, so I like that more. It could be that mfem is doing more complicated parallelization and mesh handling under the hood, so they had to do it the way they did. Either way, with these large frameworks it always takes time to get into it and understand what is going on and how to improve things. It’s probably inevitable. But many times it is possible to write code, such as the dftatom
atomic solver above, that is not written as a framework, but rather uses Fortran primitives directly, and if the engineering problem that I am trying to solve allows that approach, I personally always prefer it.
You’ve clearly come to the right place, hope you will continue to engage with the community here. Re: modern Fortran, as you now know, there is a growing list of resources including videos by @everythingfunctional , the book by @milancurcic , and more. Once you are able to spare a bit of your attention toward them, you will pick up most aspects of modern Fortran of relevance to your needs as a practicing engineer in no time.
Also, note for most of the “regulars” here, English is no better than a “second” language, for Fortran comes before that!!
Actually, to realize the kind of blackboard abstraction shown on that slide 8, it takes a tremendous amount of sweat and blood!!
First to develop the language with modular, object-oriented, functional, and parallel programming facilities. It’s mind-boggling effort to work out the syntax and semantics in a manner that fits “natively” and consistently into a language that was the first high-level
enterprise of such kind by the humans in the 1950s! Countless hours by the standard-bearers are involved here.
Then with the compiler implementations to arrive at a level of robustness with the language having to support such multiple programming paradigms. The number of bug reports and bug resolutions and compiler developer and support time that have gone into all this is shocking.
This is followed by the usual scientific/engineering program developer time and all the tooling and all the scaffolding and infrastructure they need to get their code right and to package and distribute it reliably with collaborators and users, a gigantic effort.
Yet after all this, there are some glaring gaps: without bringing in the paradigm of generic metaprogramming into the language and repeating the above cycle all over again, one ends up using object-oriented approach as a clutch with polymorphism and inheritance getting employed when they possibly should not be used and this can then lead of the classic “black hole” illustrated in cartoons around programmer productivity.
Considering all this, it’s better to ensure one has good robust code also in the classical imperative style, a la the example by @certik above, for the scientific / engineering endeavor of interest!
I’m confused. What I posted is an API of a framework. What you posted is an implementation of a library.
The user of the former would build solvers using the custom types and operators. The user of the latter would run only the specific solver that your library implements.
They’re completely different things (framework vs. library, as you acknowledge in your post). It’s not a difference in style. If you do want to know how the operators are implemented, you can. Just look inside–it looks like your code. So you’re comparing two different levels of abstraction, not two different styles. The implementation of parallel functional operators is still good ol’ loops and array arithmetic.
Do you mean to say that you prefer it like this?
call integrate_navier_stokes(u, p, rho, nu, dx, dt, du_dt)
I like that also.
Yes, it is a difference between a framework and a library perhaps. I think it is also a difference in style. It would be hard to put the framework like API on top of the imperative code because the imperative code ties everything together.
Can you post an implementation of the .laplacian.
, .grad.
and .dot.
? I suspect it might be slow — is it a finite difference implementation I assume? It might not be efficient to separate it into subroutines. If you post it, I am happy to reimplement in imperative style and we can discuss pros and cons and benchmark it. In theory compilers might optimize it to be the same fast, but in practice it has been my experience that typically compilers produce faster code when things are more direct.
I don’t have the vector operators from Damian’s example, but here’s the implementation of scalar parallel operators, which is very similar, though somewhat simpler:
1 uses 2 and 2 uses 3.
Perfect, thanks! That’s a great example. Didn’t you have an imperative version in your book also? If not, I’ll implement it for comparisons.
I don’t, because I abstracted away incrementally as each chapter introduced a concept that warranted boilerplate. The chapter 2 version is the only completely imperative one, but it’s a trivial example. It shouldn’t be difficult to refactor the final version into an imperative or procedural style.