-
Notifications
You must be signed in to change notification settings - Fork 4
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
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];
...
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];
...
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 are coded as a particular element which stores a list of element to track.
For efficiency alternative strategies can be applied.
- for each element choose and call _map that loops over the particle.
- for each element
- if global call <elem_map>
- if local for [1] each particle
- load particle constants and coordinate locally
- loop until local elements using _single
- store particle in global array
The strategy 2. is compatible with GPU computation where loop 2.ii. is replace by a GPU kernel.