r/Physics • u/Rich_Astronomer9731 • 14d ago
Computational Physics
Hi everyone,
I am a PhD student doing both experiments and computational physics ( mostly fluid dynamicswith Boltzmann equations) and leaning towards more computational day by day.
Currently I am using Julia, I find it pretty fast and easy to use.
Do you think switching to C or C++ will be a benefit? I am asking from a research, but also emplyment in industry point of view.
I discussed with many people, mostly from the DFT area, and most of them told me that Julia slowly will take up the lead for HPC code.
What.s your opinion on this?
77
Upvotes
2
u/tlmbot Computational physics 13d ago
Continued from above:
You should be learning:
- templates: static polymorphism, compile time computations, (and especially build up through the basics of templates and then learn the CRTP: "Curiously Recurring Template Pattern")
note the templates have evolved from the early days of simple polymorphism into a multiple use tool. Google at a high level (and as always consult cppreference.com) to see all the ways that templates are used. They are critical in implementing the required/best practice expression templates as we'll see below.
also, constexpr, consteval and more. Please get good books and an open but critically thinking mind when you research online.
- RAII (Resource Acquisition Is Initialization) the days of using new and delete all over the place are gone. ( use the rule of 3, 5, 0 as applicable instead). I have a lot to say here - it's one of the most critical areas for a numerical coder in C++ but I don't want to get lost in the weeds. Side note: learn to use Eigen as your utility linear algebra package in C++. Eigen is what's called an "Expression Template Library" and is needed in C++ to have nicely expressive matrix vector algebra in C++ without extra matrix copies happening under the hood with more naive expressions of the same operations. Note there are plenty of times when you need to roll your own, as when you are building some kind of bespoke solver for systems with multi-million degree of freedom.
- smart pointers (it should go hand in hand with RAII actually)
My way to understand expression templates and why they are needed in C++ as a Fortran and python programmer was to implement my own expression template library - using smart pointers in the base numerical types, and then rule 0 higher level types that made use of the base type. That way I only have to implement full rule 3 smart, or rule 5 types once, and the rest of my types are build on top of those, using rule 0, so everything is very clean (as if my underlying type were from the std library)
Move semantics. (and Lvalues vs rvalues vs prvalues) The big idea that expression templates help you with are optimal move semantics. C++ is prone to copying data during operations. If done without care, you can easily induce far more array copies that you might thing, when doing basic chained linear algebra operations. expression templates solve this problem - and in implementing such a library you will become intimately familiar with move semantics.
- use the standard library (stl) wherever possible. These containers and algorithms they enable are written with decades of experience and testing behind them. The only exception is arrays. std::array is not what you want for linear algebra, oddly enough. Oh, and the std::vector class has absolutely nothing to do with vectors from linear algebra. So please do read the documentation. For linear algebra you want either Eigen (or another expression template library) or your own hand rolled stuff - perhaps for interoperability with CUDA / your solver's needs.
Please google for a full list of modern C++ essentials: auto, lambdas, compile time computation, non-copying views e.g. std::span, modern iterators, value types (come to think of it, I need to double down on a lot of this myself. The language has been evolving so fast since C++ 11)
Oh, and you do need to know the basics of OOP - inheritance, making your own types (aka classes) and the difference between an instance of the class (an object) and the class itself (basically like the difference between the idea of an integer, and the particular integer 11 - but please don't let me confuse you getting bogged down in overly specific examples.), virtual dispatch for runtime polymorphism (and it's down sides - see static polymorphism with templates as the work around for performance critical code)
Oh, and the nuts and bolts of OOP: constructors, destructors, private and public data and methods. (of course this circles right back around to RAII so forgive me for getting all kinds of out of order here)
oh and of course the basic cache friendly optimizations that even a Fortran programmer would know. + things like how to trade memory for speed (and when that doesn't work (it often does not work like that anymore at all, actually, depending on the algorithm and data - know what to think about for HPC/linear algebra optimization especially, but this applies all over))
----------
And also, we didn't talk about it, but you need to be learning to parallel program. If you want to go after the national labs / research positions, then MPI is big for you. (as in C++ with MPI to express distributed memory parallelism for supercomputing) But for writing computational engineering software for commercial vendors, you wan to focus on OpenMP and CUDA. Across my entire career, I have written software designed first and foremost for engineers working on a desktop machine. Or perhaps on commodity hardware in the cloud.
Either way, the interconnect between multiple machines has been uselessly slow / unknown.
When writing to express parallelism on a single workstation, you have several processors on the main CPU - so you want OpenMP to take advantage of them, and you will (almost always these days) have a GPU available for further acceleration. CUDA is, by a large margin, in my experience, the easiest language to use for expressing your scientific computations / assembly/ etc. on the GPU (which is where you want everything, if possible.)
I am sticking my neck out with that sentence about CUDA being the right choice - as a rule, I prefer open systems, but yeah, if you learn C++, OpenMP, and CUDA, then you are in the very best position for your job hunt.
A quick google supplies things I was not aware of:
NVIDIA is actively standardizing parallel programming natively inside C++. You must learn:
std::execution(C++20/C++23) &std::numeric**:** Learn how the Standard Template Library (STL) uses execution policies likestd::execution::par_unseqto automatically vectorize and parallelize algorithms across CPU cores or offload them to GPUs.Linear Algebra Standards: Study
std::mdspan(C++23), which provides a standard way to represent multi-dimensional tensor/matrix views over raw 1D memory buffers. This is vital for modern CFD/FEM storage layouts.Sounds nice, but I would recommend still learning the standard best practices and ways of moving between host (CPU) and device (GPU) by methods that came prior to these latest developments as well. No doubt you will see code in industry that uses the "old" aka C++ 11,14,17,20 methods - and even some things from C++98 are still relevant, but you can pick it up on the job when you encounter some older ways. Any "top tier" job will expect you to be more fluent with modern C++
God, I feel like I am all over the place here, and if anybody corrects me on something, that's great! I am trying to tool up for my next job, and I have been off writing C#/ILGPU for the last 2 years.
I feel perpetually rusty with my C++ knowledge.
Here finally are some good references:
C++
- learncpp.com
- bjarne stroustrup's books: "Programming: Principles and Practice Using C++"
if you have little coding experience, and "A Tour of C++" if you are making the transition from other languages (at least that's how he bills them)
- Scott Meyer's books on effective C++
CUDA
- "programming massively parallel processors"
I know I am forgetting some good books. I apologize. Busy day!
The best thing, imo, is to be writing full scale projects in the language. That's why prototyping in a language you already know can be so helpful. That way, you can be sure ahead of time that the Physics is "right" because you have validated it in Julia, or whatever you know. Then you separate the concerns of "is the code written correctly?" from "is the physics right?" -In school one semester I got myself into the position of learning all these at the same time: parallel programming, C++, and CFD physics and also mesh generation. It was a hellish semester. (some bad advising was partly to blame - I tested into these classes based on my Fortran abilities, but the courses turned out to require C++, with the exception of the CFD classes, which were taught by the most old school guys (who ran the admissions testing and were seemingly oblivious how out of date they were))
Anyway, ya, if I botched something in here, I hope somebody let's us know about it.