 Okay, so quickly just some basic stuff to help you find your way around the programming interface. As you know, foam is open source, so not only do you get all the executables and the binary files, you also get the full source, and you also get the development environment. Okay, the development environment is slightly old-fashioned, because I personally use a shell, Emacs, GDB, and Intel or GCC compilers. But there are people out there who use unified development environment, and it will pop straight into that. The things that you need to know is how to organize your work, how to create your own application, and some bits about the WMake build system. I will jump over those two fairly quickly and tell you a little bit about programming guidelines and enforcing a consistent style, because this is something that impacts me personally quite often. Okay, so the first thing is that open foam is set up so that you can live in a certain way. Okay, when you type foam, it will take you to the main foam installation. Inside there you have SRC for the source file, applications for the top-level solvers in utilities, and there is quite a deep tree up to all the systems. The idea is that we group things together that belong together. So for example, under solvers we have incompressible solvers, and then a set of solvers that live there. Under tutorials we have the same thing, tutorials, incompressible, simple foam, and then you have a bunch of tutorials that belong there. The second thing is that you have this run directory. The idea of the run directory is that you keep your cases in one place. If you work with a team, it is not only enough for you to know where your cases are, you also need to be able to look at your colleagues' cases when they are on the trip or on the phone. Pick out some files and send them to you. My students in Zagreb have got this fashion of keeping their simulation cases on the desktop. I have no idea why. In which case, if you really like it, link your foam run to the location of the desktop rather than some arbitrary place. So when I type run, it will take me to foam run, and that will be whatever place you need to have to keep your data. In terms of HPC, you will typically have three locations of storage. The main backed up storage of your home directory. This is where you keep the important stuff. If you have your own version of the file, there is common storage, which is not backed up, but it is persistent. And there is, of course, scratch storage. I do all my runs in scratch space, play with them there, hoping that they will not kill them within two or three days while the run is running. When the run is finished, tie the app up to yourself, see how much of the data you need, and move it over there. Students who use a terabyte of memory to do their diploma thesis usually get shouted at. Apart from the local workspace, there is a set of environment variables that need to be set up for foam to work properly. So in the foam installation directory, there is an ETC sub directory with bashrc, cshrc files, with what we would consider sensible defaults. Now, if you're on your grandmas desktop computer, it really doesn't matter what you do. But on an HPC cluster, they have a preferred version of MPI compiler, et cetera, that you're using. And you should override the settings to make sure that, for example, you're not using MPI out of third-party, but use the one that came with the cluster, because there are usually good reasons why you should be using that one. When you source the ETC bashrc or cshrc variables, there will be lots of things set up for you that will allow you to do the compilation. The build system that we use is called wmake, and it is basically a nice wrapper around make. It will allow you to build multiple platforms. So we have various forms of Linux. I think some of the older Solaris platforms are live, IBM, and if I'm not mistaken, Apple Mac, but also nowadays Windows. Windows is a little bit special because we need to import a shell, and we use something called the MinGW, which is the minimum bash-like development infrastructure. From Windows, you can build everything in the usual way with the additional benefit that you can zip up all of the executables and libraries and move from one machine to another if the person on the other machine just wants to run the code rather than do development. The wmake system, there are several things that you need to know. The commands are wclean, meaning clean everything that remains from a previous build. wmake for build application, and wmake libsoft for building an SO or a shared object library. If you keep developing the same thing over and over again, there is no need for you to type wclean all the time because the system will figure out what you're doing and it will recompile only the files that it needs to. Anyone working with multiple versions of OpenFoam? So for maniacs like me, we also use something called Ccash, which will cache parts of the compilation and when you're switching with different git repositories and branches, it can prick them up and run them pretty quickly so I can get a quasi compilation done in about 15 minutes. Okay, so how do we actually work with the code in terms of development? There are two things that you do. The first one is starting from the beginning, something that no one has ever done before or nothing quite similar to that has been done before. This is quite a wrap. In many more cases, you will start from some existing functionality and then you will want to add things for it, okay? A good example for this afternoon will be take icophone and add a temperature equation to it, okay? In that case, you will find the executable or a function or a boundary condition, which is most similar to what you want to do. You will copy it into your own workspace, you will rename it, okay, and then start making changes to it, okay? I usually recompile it after renaming it and make it run with a little message inside saying hello girls so that I know that I'm actually running my code, okay? To make sure that the starting point of the code that I'm running is actually valid, okay? Typical things that you will do is either create your own application, okay? So I told you, take icophone, rename it icotemperature form, or implement some of the parts of the system which are made through runtime selection mechanism. Okay, now, if you run fluent or commercial code or similar commercial code, you will have some options which refer to user coding, okay? Do you remember the first day when we spoke about procedural programming in fluent? Okay, so I said the top level code is a big if-then-else statement, which says you will start this, is this laminar or turbulent, is it single phase or multi-phase, is it compressible or incompressible, is there an energy equation on or off, etc., okay? So when you have a choice of turbulence model, it will say, is it K epsilon, RNG, K epsilon, realizable K epsilon, K omega ssd, spalartal, maras, and one of the else is user coding, okay? And the idea is that they will open a way for you to interact with the closed source code in order to do what you need to do, which is within the realms of turbulence modeling. But this is not how they do it themselves, okay? In open form, at every location where we have multiple choices, we use something called the runtime selection mechanism. Where are we? Runtime selection, okay? The idea is that all the turbulence model which are written will interface with the rest of the code in the same way which in C++ language is done through a virtual base class, okay? So there is a set of functions that you have to do like please provide me turbulent viscosity or please update yourself or provide me the matrix contribution to the momentum equation and then all of the existing turbulence models including the ones in the library as well as the new ones answered to the same interface. Why is it done like that? Because now, as a developer of open form, you will be able to implement your new functionality and add it to the runtime selection table without interfering with any of the existing code. Why is it so important? Because if you haven't touched it, you haven't broken it. Which means that you're capable of doing new developments without breaking any of the existing functionality, okay? So this afternoon, apart from the people who will be changing the top-level code, I will ask the groups to implement a new boundary condition or something called a function object, okay? So the idea of a boundary condition is clear. You will know how a value at the boundary changes. You want to change it in your own way and you can write a little piece of code that will do that. For a function object, I already told you that there are ways of including little bits of code to the main executable using that function's entry in the control dictionary which will give you access to the basic things in the code so that you can do some post-processing or similar level applications. Okay? Just to conclude, the build system that we use is called WMake and it is controlled by two files, okay? Make files and make options, okay? I guess we will have to do that one also hands-on because when we start changing the name of the existing capability we will play around with make files and make options, okay? To finish this off, a few things about programming guidelines. Okay, so number one, open phone is object-oriented, okay? Please try and live within the concept of object orientation which means when you have to implement something new it will typically not be a function, it will be a class, okay? Maybe to your level of thinking it is easier to think about it as a function but stick a function in a class and do it like that for a little bit and also take a look at the existing code as an example of doing things well. Some typical errors. Number one, writing C in C++. How many C experts do we have? Wow, I win, okay? So the thing that these people will do is they will print things out of the code using printf. Yeah, okay, it's very easy but C++ has got a stream structure. Printf is not object-oriented. They will write function pointers and void star pointers, okay? That's on C++ because it breaks strong type checking and you should be able to get into the idea of writing object orientation. When you're writing the code try and think about why C++ forces you to do things because that will make you a better program, okay? So one of the typical things that I have is playing games, okay? So when you look at the code and the scalar transport equation doesn't work anymore you do not go and say, well, that means somebody has broken upwind although I didn't touch it because if upwind differencing was broken lots of other functionality of the code would be broken as well so you can go to one of those pieces and find out what's going on. The second thing is try and adhere to the style even if you don't understand why, okay? Because these guidelines are done for special reasons, okay? The things that I complain about most is number one, trailing blank spaces and tabs makes my code look ugly and then when I start looking at the contributions for the next release first I have to put on rubber gloves and clean it up, okay? It doesn't make you popular and you should be able to do that yourself. And number two, you have to put comments in the code. I know you're a genius, okay? There is no doubt about that but if I show you your own code five years from now I bet you won't remember, okay? So you're not writing this code just for yourself or you're writing this code for your stupid self in ten years time who needs to fix something in ten minutes while the phone is ringing, okay? So do put as many comments as you like and also we have something called deoxygen, okay? So deoxygen is an automatic documentation generator which relies on the comments for your code, okay? So typically I will have something like a filename N where I read the surface normals of whatever, okay? Well, please write a one line comment, read surface normals, okay? Or this is surface normals. Or return access to mesh. Yeah, I know it is obvious now but this code gets worse and worse and worse and bigger and bigger and bigger, which is the same thing and we need to be able to keep it alive, okay? So one of the other things is enforcing the consistent style, okay? So the code will be separated into the files, header files, C files, C++ templates, definition files, there will be include protection, et cetera, okay? One way of getting that is to start from the code that has already been written like that and then try not to butcher it completely. If you're writing something completely new, we have a way to generate a blank file for my example class by using the phone new script, okay? What that one will do is it will give you the standard layout from the file from the top header to the bottom header with the bits that you may wish to have, okay? Some of the things that are in the stub are incompatible with each other so you have to delete the ones that are extra for you. That's okay, okay? And of course, please work on your programming quality and programming skill as much as you can because good C++ is really worth not only your current problem solution but it's a programming skill that's worth carrying with you. Okay, so if you want to jump into doing some programming, let us start by having a look at the SRC part of the training path that I have given, okay? So in the run, there is a set of examples. In SRC, I have a little selection of source code. The first thing that I have here is magu, which is a top-level utility, and in make slash files, I will say what I want to compile. What did you say? Control F? Control K. Control F, awesome. Sorry, pound it. For my make files, it says you will compile magu and you will put it into the location called phone underscore user underscore upwind. Okay? If you're copying out of the main installation, that used to say phone underscore upwind. But your installation will be typically shared by many other people. You probably don't have right to right there. So phone user upwind together with phone user livewind is a part of your working space. Into user upwind, go executables. Into user livewind, go your shared object libraries. What's the difference? Do we know? What's the difference between an executable and a library? An executable has main in it, so you can run it. And the library has functionality, which is basically the dot c part that belongs with the c++ class objects, but you can't run it. Okay? So an executable will use libraries to do its job. Apart from the make file, I also have, apart from make files, I also have make options. Okay? And that one has got two parts. The first part is exe ink and the second part is exe lips. In exe ink here, I have finite volume. In exe lips, I have minus l finite volume. What's going on here? Do you remember yesterday we looked at scalar transport foam and I was showing you lots of class headers. Okay? A class header for a class called fvmesh tells you what the mesh is and what functions are available. Okay? So magu will use the functions out of fvmesh.h but to actually execute what is necessary, it needs to link the object code that does the job and that lives in the library that I link with my executable. Do you know what this ln include part is? Well, I already told you. So in the finite volume library, I will have a hierarchy of classes and the directories will be deeper and deeper and deeper and deeper. So to avoid this business of having an endless include line, per library all the files are linked into the ln include directory. Let me show you how bad this is. So foam takes me to my foam installation. It's probably not working. And inside here I have SRC for the sources, applications, tutorials and various other things. Under SRC, I have a whole set of libraries and one of those libraries is called finite volume. Look how many files. Okay? So to avoid the business of going through the files one at a time, they are all linked in that ln include directory whereas individual files actually live in something like fvmesh, fvpatches, constraint patches and down here I have a veg patch for example. How do you find that? Well I know it by heart so it's unfair to ask but you will use find and grep which are the standard tools for that or you use the oxygen documentation keep clicking on the files and that will give you links to make your way around the library. Okay. Going back to my system, if I want to build this executable I will type wmic. Next to that I also have a library called postlib and in this library I have all kinds of arbitrary garbage. Okay? I have something called an animation dump. I have a surface graph, the form surface and linear wave which happens to be a boundary condition. Okay? What's common for all these libraries? Well I give them to you. Okay? In principle you should group your functionality library per library or add the object files to the executable unless you have to use them and then move them around later on. Okay? One of the big things that I get asked for people who start programming is well how do I design my perfect class structure so that the rest of my life can fit in here? No, you don't. Okay? You want to know how to write a good code? Write it once then throw it away do it again and again and again and again and after three or four times it will be good. Okay? I have personally thrown away the mesh classes in open form five times and now they're okay. So there is no message of start it again from the beginning. Okay? So here I have a library and again I have similar functionality in Make Files I have a list of files that I want to compile. Okay? And in Make Options I have a list of libraries that I want to work with and notice under Exe Inc I have sampling under Lib Libs I have sampling. Okay? So when I pick up the headers from the library I probably want the other files as well. How do I build that? What happens if I do W Make? I get a nasty error saying well there are missing symbols that because this thing doesn't have the main and of course it needs to links additional libraries so the compilation is not complete. For the libraries I will compile them with W Make Lipso. Okay? So this is what I would like you to do now. Okay? People with least experience hands up. Okay? So for everybody, huh? For you I want you to make a copy of the Scalar Transport Phone executable and call it My Scalar Transport Phone. More advanced people. Okay? I want you to go into Postlib pick up one of the function objects and make a new function object which just says hello. Okay? Then take the swirl test that we played around with yesterday and make your function object work with the swirl test and then we'll figure out some capability for it. Okay? Please start. I will try and do both of those jobs simultaneously. In the executable and in the source code of the executable I will compile the My Scalar Transport Phone which will be on the screen in the library. There in the executable is the name of the executable and then I will type it out and as a My Scalar Transport Phone I will type it out. That's all that needs to be done. Okay, that's all that needs to be done. Okay? Thank you very much. And then I don't know what you're talking about but now you're making it. It doesn't matter because it doesn't have an executable. It doesn't have an executable. It doesn't make clips. It makes a mic. Still working? I have something else to do. I will type new source code. Okay. Are you ready? Shall we play games? Okay, so the first thing is for those people who are booking in a function object I had to introduce this part here into the control dictionary file. So a new function object is an arbitrary name. Type is hers function object which is the new function object I wrote and the library in which it lives is called libpost.so. Okay, remember. The function objects like turbulence models, etc. are all loaded from the libraries and this mechanism with function object lips basically does the equivalent of DLL open on Windows both for Windows and Unix. Okay, so that means that if you introduce one of those while the code is running at that point it will load the library. The new function object will become available and then it will create a function object from your library. If the function object is not available the whole thing may fail because the libraries may require other libraries so please be a little bit careful when you're playing with this. Okay. For my ScalaTransport phone all I did so far was to change the names and introduce one print statement which says here hello from her. Okay, so now if I run the executable I will get hello from her from the top level code and in the function object I have hello from function object which is this thing here. Okay, do you remember what we said about the code knowing only the classes that have been created before? And yesterday when we were going through ScalaTransport I said well first we create the argument list then we create the time then we create the mesh then we create the velocity field then we create the temperature field etc. So at the point of discretization for example I created the fluxes which needed the mesh for mesh.sf and you in order to interpolate the velocity. So when you're in the top level code you are hacking because you made a special version of executable just for yourself. But you have access to data that already exists in the code. So for example can you please write a little piece of code which will pick up the value of temperature in the cell number 164. So where I said hello from her please write out the temperature in the cell number 164. So it's really easy. How about doing it from a function object? Can you do it from there? In the top level code it was all nice and easy. So I said info t in cell 164 t is available for me I asked for the internal field square brackets 164 write it out on the screen. Dangerous. What if my mesh has got 50 cells? The second thing is do you have any idea where cell 164 is? No. So why don't you try and write me the value of the field t in the cell that is nearest to the x, y, z point location that we are going to agree on in a minute. Don't jump straight into it. I want to take a look at how much harder function object people have to work. Okay. So here when I'm in a function object I have the private data which is the function object name time and the region name and now suddenly in this function execute I have to access the field t. How am I going to do that? It is not declared here. So for that reason you remember yesterday when we went to scale a transport phone we said that the old fields will register with the mesh to make sure that all the checking can be done. My mesh in fact time is a hierarchical database which takes care of all the objects that exist on the input output level. How do you know that? Here I did run time dot write then the database went through the hierarchies of objects decided whether it is time to write and based on that the field t wrote itself out and the transport property dictionary did not. Okay. So for that reason all of the objects at the field level are available okay. In the function object the only thing that we have is the database itself so rather than just accessing the code from the top level I have to dig out this object from the database. This is how I do it. I say constant finite volume mesh reference time dot lookup object of the type of value mesh region name. Why is that? Because if I'm doing a single region calculation like in scalar transport form I'm going to have default region 0 and if I'm doing fluid structure interaction I may have a fluid region and a solid region or which one do you want? So the region name will allow you to choose whether this is a fluid or a solid. Once I have the mesh I can ask if it can find the object of the type volume scalar field called t. If it can find me then I will tell you please look up this object and return me a reference to the field f which is a field called t okay. And then I'm going to write f dot internal field 164 and everybody's happy. Okay. So have you seen what I did? Okay. Into the function object I passed time which is my top level database it knows delta t start time and time right time, output time whatever you like okay. Based on that it will dig out the field based on the name that I gave it and then I'm going to have full access to that field even though it has not been exposed to me in top level. Okay. So while we're here next to my new function object you have one called animation dot. So the idea for that function object is that you do something like a free surface flow calculation and you don't want to have 100 fields written out but you want to have the volume of fluid field written out every time step so that you can have a really pretty looking one. Okay. So shall I set the right frequency to one? No, that's overkill because if I do that then all of the fields will be written out. So what I need to have is a little function object which says Dear function object every n time steps print out the field called a. Okay shall we take a look at the code together? So the first new thing that I have is the list of functions and the dump interval. Where will that get read from? Well, in system control dictionary I have a set of function objects. This one is called Herve's function object. I could make another one called animation dump. Okay. So here is that enough? No, not really. Let's see what happens. The code says fatal error keyword objects is undefined in dictionary dump t line 58 to 58 so it didn't tell me completely nicely but I know that what I'm missing is a keyword objects. Now it says oh I can find the objects but I can't find the interval. Object banana not found. Why? Well I asked the database there is no object called banana so I can't write it out and now it is my decision whether that's a fatal error or I should ignore it but in any case I can fix it by pulling the banana out of the tailpipe output in 5 I have t, t, o, t, o, o, u, n, p but in 4.95 I only have t which is done out of the animation dump. So what does this thing actually do for me? It said if time index percent integral is not equal to 0 look up the mesh look up the object and if you have found it then write it otherwise say that you cannot find the object. So what I would like you to do now is to go to my new function object and rather than printing out the name of the field t or cell 164 read in the name of the field and the cell index from the input file and then dig out the value of t in cell 164 as per user input. For the top level people I want you to do the same but you need to figure out where to read the name of the field and the cell index in the top level code. Okay, hint. Take a look at the transport properties. Have you done it? Enjoy? Okay, so if I want to be really, really rude I'm going to do something like this word field name transport properties dot lookup field cell index read label dot lookup index okay, and now in my scalar transport phone at least I can do something like index. I messed up because here is called cell index and in the other one I just called it index. Now if I try and run my scalar transport form it says keyword field cannot be found in constant transport properties constant transport properties index 164 and suddenly it is working again but I'm not too happy about it because in constant transport properties I have put things that definitely don't belong there okay, so let's just copy constant transport properties into something like system sampling properties or sampling okay, sampling properties okay, vi, that one change this to sampling properties it will only have the field and the index vi constant transport properties delete the additional stuff now I want to take create fields I want to make a new thing which will only do these things so vi read sampling clean up create fields okay, that and that doesn't belong there and now in read sampling I need to make some changes so first sampling properties IO dictionary sampling properties sampling properties did we say constant or system system runtime system must read reading diffusivity, I don't need that bit recompile so index vi my scale of transport fold and somewhere in here I have to include my new file, say here read sampling should say delete from sampling properties and the thing works beautifully so what's the message well message number one as you can see this is a game right I just went and played with it changing the code is really really easy bringing new parameters is really really easy if you need to do something quickly or you want to play around or you're not sure what you're doing make a copy of existing capability and change it and change it until it can do what it needs to do once you have working code then we can tidy up and move things from the code into the function objects etc there in the back row I think they're still struggling with the function object because it is a little bit more complicated to access the data that is not readily available in your part of the code what do you do in such cases panic? yeah good start right then start looking through the code because somebody must have already done something similar to what you're doing and this is why I showed you for example the animation dump which shows you how to pull in parameters from the dictionary in order to find out what's going on two more messages number one did I type everything perfectly the first time? no I've been working with this code for 24 25 years now I still make mistakes message number two the error message never says go to hell the code is trying to tell you something so I know that it is very frustrating but it is a game please read the message try and figure out what happened and your life will get much easier okay I think this is enough for the programming part of the course you have managed to compile and executable you have managed to compile a library we played around with the function object I gave you a set of easy function object examples to start with we played around with the top level code and we did a bunch of basic things I didn't do the C things or writing things into a file etc but that's because you're all experienced C++ programmers and I don't have to worry about this I propose 15 minutes break for coffee and then we'll set up an open table for discussions if you have questions, problems etc now is your time coffee