[Tutorial] GEANT4 Introduction: Linux & C++

Weihe Zeng

Tsinghua University

Nov. 18, 2017


Linux commands and environment variables

  • file permission and directory
  • basic commands: ls, cd, cp, mv, rm, mkdir, pwd, grep, cat, echo, ...
  • redirect in/out and pipe
  • remote control: secure shell
  • environment variables: PATH, LD_LIBRARY_PATH
  • bash and start-up script
  • run as superuser
  • manual page and online help

From Windows to Linux

Obstacles

  • less responsive Graphical User Interface (GUI)
  • poor software support from companies, e.g. MS office, QQ
  • steep command line learning curve

Advantages

  • more control over operating system (OS)
  • large and helpful community support
  • free and open source

Recommendations

  • Ubuntu is an easy starting point
  • Try to do your works without GUI

File Permissions

-rw-r--r-- 1 tom video  29K Nov 10 15:10 importance.png
# change permission: read=4, write=2, excute=1
chmod 755 <path-to-file>  
chmod +x <path-to-file>  
# change owner of file
chown <user>:<group> <path-to-file>  

Frequently used commands

  • Ctrl+c: kill current process
  • Tab: auto-complete
  • up/down: last/next history command

Directory operation

Directory is a tree structure of file position similar to folder in windows.

/softwares/geant4/geant4.10.03-install/share/
  • Linux OS use / as delimeter of different level of directories.
  • / is the root directory, /home/username is the home directory of user (equal to ~).
  • . means current directory, .. represents directory in upper level.

# ls = list files in directory
ls <directory (empty means current dir.)>  
ls -a # list files (hidden files included)  
ls -l # list files with more information

# cd = change directory
cd <path-of-directory>  
cd ~ # go to home directory  
cd .. # go to upper level

# pwd = print (name of) working directory
pwd

# mkdir = make directory
mkdir <name-of-the-new-directory>  

File Modification

Create, copy, move or DELETE file(s) using commands.

touch <name-of-file> # create an empty file

# -R or -r  means recursive
# copy file to a destination
cp <path-to-source-file> <name-of-destination-file>  
# copy whole directory to a destination
cp -R <source-directory> <destination-directory> 

# move file/directory to a new destination
mv <source-file> <destination>  
mv -R <source-directory> <destination-directory>  

Warning: dangerous operation

rm <path-to-file> # remove the file from disk  
rm -rf <directory> # remove the directory  

Read File in terminal

Sometimes (e.g. using SSH to access server) reading files in terminal is a faster way to debug and monitoring.

For other use, I recommend editors with GUI and plugins, e.g. Atom, vs-code.

# concatenate files and print
cat <file-1> [<file-2> ...] 

more <filename> # read file in pages  
less <filename> # less > more

head -10 <filename> # print the first 10 lines  
tail -20 <filename> # print the last 20 lines  

Other commands

(Symbolic) link between files (similar to shortcut in Windows)

ln -s <target> <link-name> # make a link to target  

Compare two files

diff <file1> <file2>  
colordiff <file1> <file2> # a more colorful version  

Search within file (Regular Expression)

# search for <pattern> within <filename>
grep <pattern> <filename>  

Find specific file in directory (recursive)

# find all files ending with '.txt' in '/home/tom'
find /home/tom -name "*.txt"  

I/O Redirect and Pipe

Redirecting standard input(keyboard) and output(screen) to file is useful in many cases.

  • <: redirect file to std. input
  • >: redirect std. output to file
  • >>: redirect std. output to the end of file
# some examples
cat < data.txt

# save diff result in a file
diff file1.c file2.c > compare_ver.txt

# save list result and append to a file
ls -a >> accumulate_list.txt  

Pipe (|) combines two commands by using the output of left command as the input of right command.

Here are some examples.

# get command history and use 'less' to 
# read the history
history | less

# get all processes and search for the line 
# containing keyword 'geant4'
ps aux | grep geant4  

Remote Control

Using Secure Shell (SSH) to get access to servers.

Linux/Mac

# username=tom login to server with IP addr=192.168.1.1
ssh tom@192.168.1.1  
# then follow the instruction in terminal

# the server is running on non-standard port '1234'
ssh -p 1234 tom@192.168.1.1

# copy files between local and server
# copy to remote machine
scp $local_file user@ip:/home/user/[destination]  
# copy from remote machine
scp user@ip:/home/user/[$remote_files ] [local_destination]  

Windows

Recommended applications: PuTTY and WinSCP (included in PuTTY).


Environment Variables

Shell is a program language and has variables. Some of them are special variables and are initialized when shell is started.

  • $PATH: search for excutable files within directories in \$PATH
  • $LD_LIBRARY_PATH: link compiled files to libraries within directories in \$LDLIBRARYPATH
# check current $PATH value
echo $PATH

# add directory to the beginning of $PATH
export PATH=/softwares/geant4/bin:$PATH

# define your own variables
export MY_PATH=/softwares/myapp/bin  

Start-up Script

Variables set in one terminal will be lost when it's closed. We can make use of scripts that are excuted before/when we open a terminal.

  • /etc/profile: variables for all users
  • ~/.bash_profile: excuted when user login
  • ~/.bashrc: excuted when bash is called

Note: files starting with a dot are hidden files

Edit ~/.bashrcand add your own environment variables or modify existing variables, then source ~/.bashrc or restart a terminal.


Run as Superuser/Administrator

drwxr-xr-x  0 root root   512 Nov 19 10:45 etc  
-rwxr-xr-x  1 root root   51K Jan  1  1970 init

If you want to make changes to files that belong to other users, sudo is the command.

sudo apt-get install cmake  

We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things:

  #1) Respect the privacy of others.
  #2) Think before you type.
  #3) With great power comes great responsibility.

More ...

授人以鱼不如授人以渔。

The best instructions of each command / program is in its manual page.

man <command>  

Mastering online search skills are also important. Here are some recommanded resources.

Some very useful commands are not included in this slide: alias, tar, zip, kill, which, whoami, du, top, sed ...

Install packages: apt-get, yum, zypper, pacman, ...


A (Fake) C++ Tutorial

  • Data type

  • Operators

  • Branching statements and loops

  • Functions

  • Class and Object-oriented programming

  • Compile and link C++ code in Linux


Data Type


Operators

| Arithmetic | Relational | Logical | Bitwise | Assign | Misc | | ---------- | ---------- | ------- | ------- | ------ | ---------------------- | | + | == | && | & | = | sizeof | | - | != | \|\| | \| | += | cond. ? X : Y | | * | > | ! | ^ | -= | , | | / | >= | | ~ | *= | . (dot) and -> (arrow) | | % | < | | << | /= | Cast | | ++ | <= | | >> | %= | & | | -- | | | | <<= | * |

Reference: online C++ wiki


Branching and loop statements

// if statements
if (logical expression){  
  /* run these code if logical expression is true */
}else{
  /* run these code if logical expression is false */
}

if (logical expression){...}  
else if (logical expression) {...}  
else {...}

// switch statement
switch (expression or variable){  
  case constant1: expr.1; break;
  case constant2: expr.2; break;
    ...
  default: expr.n;
}

// for loop
for (int i=0; i<n; i++){  
  /* expressions that may use variable i
     note that i is local variable inside this block */
}

// while loop
while (logical expression) {  
  /* code that runs if logical expression remains true */
}

// do while loop
do{  
  /* code runs and then jump out of loop 
     if logical expression is false */
} while (logical expression);

// other loop control
break;  
continue;  

Functions

Reference: cplusplus document

type func_name ( parameter1, parameter2, ...) {  
  [...statements...];
  return value;
}
/* "type" is the data type of return value
   if no return value is provided, type = void */

A simple example:

int addition (int a, int b){  
  int r;
  r=a+b;
  return r;
}
// call this function
int z;  
z = addition(5, 2);  

A more complex example:

$ F0 = 0,, F1 = 1 $

$ F{n} = F{n-1} + F_{n-2} $

long fibonacci (long n){  
  if (n <= 0)
    return 0;
  else if (n == 1)
    return 1;
  else
    return fibonacci(n-1) + fibonacci(n-2);
}

Object and Class

A program is a combination of code that solve problems of real world in machine's language. Object-oriented languages, e.g. C++, Java, etc., make it more natural to express problems in real life.

Q: Some examples of objects in real life

Q: How to describe an object

In C++, Classes are categories of objects that share the same properties and methods, while Objects are instances of various classes.


A simple example

class Rectangle {  
    int width, height;
  public:
    Rectangle(int,int);
    int area() {return width*height;}
};

Rectangle::Rectangle (int x, int y) {  
  width = x;
  height = y;
}

And one can make an instance of "Rectangle".

#include <iostream>
int main () {  
  Rectangle rect (3,4);
  std::cout << "area: " << rect.area() << std::endl;
  return 0;
}

Inheritance

Classes in C++ can be extended, creating new classes which retain characteristics of the base class. This process, known as inheritance, involves a base class and a derived class: The derived class inherits the members of the base class, on top of which it can add its own members. (From Cplusplus Doc)

class derived_class_name: public base_class_name  
{ /*...*/ };

#include <iostream>
using namespace std;

class Polygon {  
  protected:
    int width, height;
  public:
    void set_values (int a, int b) { width=a; height=b;}
};

class Rectangle: public Polygon {  
  public:
    int area () { return width * height; }
};
class Triangle: public Polygon {  
  public:
    int area () { return width * height / 2; }
};

int main () {  
  Rectangle rect;
  Triangle trgl;
  rect.set_values (4,5);
  trgl.set_values (4,5);
  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}

Polymorphism

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.

int main () {  
  Rectangle rect;
  Triangle trgl;
  Polygon * ppoly1 = &rect;
  Polygon * ppoly2 = &trgl;
  ppoly1->set_values (4,5);
  # equivalent to 'rect.set_values (4,5)'
  ppoly2->set_values (4,5);
  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}

Pointers to base class can access members of base class, but NOT members defined in derived class. This is why we need virtual members.


Virtual members

class Polygon {  
  protected:
    int width, height;
  public:
    void set_values (int a, int b){ width=a; height=b; }
    virtual int area () { return 0; }
};

int main () {  
  Rectangle rect;
  Triangle trgl;
  Polygon poly;
  Polygon * ppoly1 = &rect;
  Polygon * ppoly2 = &trgl;
  Polygon * ppoly3 = &poly;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly3->set_values (4,5);
  cout << ppoly1->area() << '\n';
  cout << ppoly2->area() << '\n';
  cout << ppoly3->area() << '\n';
  return 0;
}

Abstract class

Abstract base classes are something very similar to the Polygon class in the previous example. They are classes that can only be used as base classes, and thus are allowed to have virtual member functions without definition (known as pure virtual functions).

  • Abstract base classes cannot be used to instantiate objects.
  • Classes derived from abstract classes must implement its pure virtual functions.
// abstract class CPolygon
class Polygon {  
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area () = 0;
};

Compile, link and run C++ program in Linux

Required softwares: gcc, g++, make, cmake

Hello world in C++ (save as "hello.cpp"):

#include <iostream>
int main(){  
  std::cout << "Hello, World!" << std::endl;
  return 0;
}

Then compile and link with g++ -o hello hello.cpp

It should generate a executable file named "hello" in current directory. Run with ./hello.

g++ -o <name-output> -I<include-path> \  
-L<library-path> -l<library> xxx.cpp

CMake

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)  
project(B1)

# set up GEANT4 variables
find_package(Geant4 REQUIRED)  
include(${Geant4_USE_FILE})  
include_directories(${PROJECT_SOURCE_DIR}/include)

# Locate sources and headers for this project
# NB: headers are included so they will show up in IDEs
#
file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)  
file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)

# Add the executable, and link it to the Geant4 libraries
#
add_executable(exampleB1 exampleB1.cc ${sources} ${headers})  
target_link_libraries(exampleB1 ${Geant4_LIBRARIES})  

Recommended reading: A short tutorial of CMake.


More ...

Some important features of C++ are not included in this slide, e.g. Overload, Friend, Template, STL, IO stream, GDB .... Please refer to the following materials.