Skip to content

C coding conventions

Riccardo De Maria edited this page Jul 17, 2015 · 11 revisions

C coding conventions

The maps are written in a portable C. The data types of integers and real number are specified through macro to allow flexibility:

#ifndef FLOAT
#define FLOAT double
#endif

#ifndef INT
#define INT int
#endif

Elements

Element parameters are extracted starting from elemid:

     INT etype=elemi[elemid];
     INT fattr=elemi[elemid+1];
     INT <first int parameter>= elemf[elemid+2];
     INT <second int parameter>= elemf[elemid+3];
     ....
     FLOAT <first float parameter>= elemf[fattr+0];
     FLOAT <second float parameter>= elemf[fattr+1];
     ...

Particles

Particle parameters are extracted starting from partid:

INT npart=parti[0]; //number of particles
INT ndf=parti[1];   //float coordinate dimension
INT ndi=parti[2];   //int coordinate dimension
INT stf=parti[3];   //offset for float coordinates
INT sti=parti[4];   //offset for int coordinates

Particle constants are at the beginning of the array:

FLOAT <first float constant> = partf[0];
...
FLOAT <last float constant> = partf[stf-1];
INT <first int constant> = parti[4+0];
...
INT <last int constant> = parti[stf-1];

Particle coordinates are at the end of the array

INT foff=stf+ndf*partid; //flaot offset particle `partid`
INT ioff=sti+ndi*partid; //int offset particle `partid`
FLOAT <first coordinate particle partid >  = partf[foff+0];
FLOAT <second coordinate parcticle partid> = partf[foff+1];
...
FLOAT <icoord0> = parti[ioff+0];
FLOAT <icoord1> = parti[ioff+1];
...

Maps

Each map is defined in a .c file that defines a set of functions. There two class of elements: single particle elements and global elements.

Calculation for tracking a particle:

INT <elemtype>_track(<arguments>, FLOAT coordf[], FLOAT coordi[]) 
  <map and save results in coordf, coordi>

Track a single particle:

INT <elemtype>_single(INT elemi[], FLOAT elemf[], INT elemid,
                      INT parti[], FLOAT partf[], INT partid)
  <extract argumemts for elem and part>
  <extract `coordf`,`coordi` from `partid`>
  <elemtype>_track(<arguments>, &coordf, &coordi);

Track a set of particles in particle arrays:

INT <elemtype>_map(INT elemi[], FLOAT elemf[], INT elemid,
                   INT parti[], FLOAT partf[], INT partid, INT partn)
  <extract argumemts for elem and part>
  <loop `partid` to `partid+partn`>
     <extract `coordf`,`coordi` from `partid`>
     <INT <elemtype>_track(<specific arguments>, &coordf, &coordi)>

Track a particle in a context of GPU kernel:

INT <elemtype>_map_kernel(INT elemi[], FLOAT elemf[], INT elemid,
                          INT parti[], FLOAT partf[])
  <get `partid` from process>
  <elemtype>_single(elemi, elemf, elemid, parti, partf, partid);

Update element attributes:

INT <elemtype>_update(INT elemi[], FLOAT elemf[], INT elemid)
  <update dependent attritubes upon changes>

Init element attributes:

INT <elemtype>_init(INT elemi[], FLOAT elemf[], INT elemid)
  <update dependent attritubes upon changes>

Loops

Loops are coded as a particular element which stores a list of element to track.

For efficiency alternative strategies can be applied.

  1. for each element choose and call _map that loops over the particle.
  2. for each element
    1. if global call <elem_map>
    2. if local for [1] each particle
      1. load particle constants and coordinate locally
      2. loop until local elements using _single
      3. store particle in global array

The strategy 2. is compatible with GPU computation where loop 2.ii. is replace by a GPU kernel.

Clone this wiki locally