Set Particles Information
Table of contents
yt_get_ParticlesPtr
int yt_get_ParticlesPtr( yt_particle **particle_list );
- Usage: Get the 
yt_particlearray pointer wherelibytaccess particles information from. Each MPI rank should call this function and fill them in. If you don’t have any particles, then skip this. - Return: 
YT_SUCCESSorYT_FAIL 
Every MPI rank must call this API and fill in the particle information in the same order. We do not broadcast and sync information here.
yt_particle
- 
const char* par_type(set bylibyt)- Usage: Name of the particle type. 
libytonly copies the pointer frompar_type_list’s data memberpar_typeto this variable and does not make a hard copy. You don’t need to assign it again. Refer to Naming and Field Information for how particle/attribute names and yt fields are linked and reused.
 The lifetime of par_typeshould cover in situ analysis process.libytonly borrows this pointer and does not make a hard copy. 
 - Usage: Name of the particle type. 
 - 
int num_attr(set bylibyt)- Usage: Number of attributes does this particle type has. 
libytwill assign your inputpar_type_list’s data membernum_attrto this variable. You may skip this. 
 - Usage: Number of attributes does this particle type has. 
 - 
yt_attribute* attr_list(initialized bylibyt)- Usage: Attribute list of this particle. This is a 
yt_attributearray with lengthnum_attr. - Data member in 
yt_attribute:- 
const char* attr_name(Default=NULL)- Usage: Attribute name. Refer to Naming and Field Information for how particle/attribute names and yt fields are linked and reused. 
 The lifetime of attr_nameshould cover in situ analysis process.libytonly borrows this variable and does not make a copy. 
 - Usage: Attribute name. Refer to Naming and Field Information for how particle/attribute names and yt fields are linked and reused. 
 - 
yt_dtype attr_dtype(Default=YT_DOUBLE)- Usage: Attribute’s data type.
 - Valid Value: 
yt_dtype 
 - 
const char* attr_unit(Default="")- Usage: Unit of the attribute, using 
ytunit system.
 The lifetime of attr_unitshould coveryt_commit. 
 - Usage: Unit of the attribute, using 
 - 
int num_attr_name_alias(Default=0)- Usage: Number of name aliases.
 
 - 
const char **attr_name_alias(Default=NULL)- Usage: A list of name aliases. 
 The lifetime of attr_name_aliasshould coveryt_commit. 
 - Usage: A list of name aliases. 
 - 
const char *attr_display_name(Default=NULL)- Usage: Display name on the output figure. If it is not set, then it will use 
attr_nameinstead.
 The lifetime of attr_display_nameshould coveryt_commit. 
 - Usage: Display name on the output figure. If it is not set, then it will use 
 
 - 
 
 - Usage: Attribute list of this particle. This is a 
 - 
const char *coor_x, *coor_y, *coor_z(Default=NULL)- Usage: Attribute name representing coordinate or position x, y, and z. 
 The lifetime of coor_x,coor_y,coor_zshould cover the in situ analysis process.libytonly borrows these names and does not make a copy. 
 - Usage: Attribute name representing coordinate or position x, y, and z. 
 - 
void (*get_par_attr) (const int, const long*, const char*, const char*, yt_array*)(Default=NULL)- Usage: Function pointer to get particle’s attribute.
 
 
![]()
libytborrows the full field and particle information class (class XXXFieldInfo) fromfrontend. It is OK not to set a particle’sattr_unit,num_attr_name_alias,attr_name_alias,attr_display_name, if thisattr_nameis already inside your frontend. If you are adding a totally new particle attribute, please add them.libytwill add these new attributes information alongside with your original one.
Get Particle Attribute Function
For each particle type, there should be one get particle attribute function get_par_attr. This function is able to write particle attribute to an array, just through knowing the grid id, particle type, and attribute name.
Get particle attribute function must have a prototype like this:
void GetAttr(const int list_len, const long *list_gid, const char *par_type, const char *attr_name, yt_array *data_array);
- 
get_par_attr(const int, const long*, const char*, const char*, yt_array*): generate particle attribute in that grid when input grid id, particle type, and particle attribute name.- 
const int list_len: number of grid id inlist_gid. - 
const long *list_gid: prepare particle data inside the grid id in this list. - 
const char *par_type: target particle type to prepare. - 
const char *attr_name: target attribute to prepare. - 
yt_array *data_array: write generated particle data to the pointer in this array correspondingly. Fill in particle attribute insideyt_arrayarray using the same order as inlist_gid. 
 - 
 
yt_array
- Usage: a struct used in derived function and get particle attribute function.
 - Data Member: 
- 
long gid: grid id. - 
long data_length: length ofdata_ptr. - 
void *data_ptr: data pointer where you should write in particle data of this grid. 
 - 
 
We should always write our particle attribute data in the same order, since we get attributes separately.
Example
par_io_get_par_attr function gets particle type io attributes. This particle type has position at the center of the grid it belongs to with value grid level (int).
int main(){
    ...
    /* libyt API. */
    yt_particle *particle_list;  
    yt_get_ParticlesPtr( &particle_list );
    
    /* This particle "io" has 4 attributes (position X/Y/Z and level). */
    const char *attr_name[]  = {"ParPosX", "ParPosY", "ParPosZ", "Level"};
    const char *attr_name_alias[] = {"grid_level"};
    for ( int v=0; v < 4; v++ ){
        particle_list[0].attr_list[v].attr_name  = attr_name[v];
        if ( v == 3 ){  
            particle_list[0].attr_list[v].attr_dtype = YT_INT;
            particle_list[0].attr_list[v].attr_unit  = "";
            particle_list[0].attr_list[v].num_attr_name_alias = 1;
            particle_list[0].attr_list[v].attr_name_alias     = attr_name_alias;  
            particle_list[0].attr_list[v].attr_display_name   = "Level of the Grid";
        }     
        else{   
            particle_list[0].attr_list[v].attr_dtype = ( typeid(real) == typeid(float) ) ? YT_FLOAT : YT_DOUBLE;
        }
    }
    
    /* Fill in positions attribute name. */
    particle_list[0].coor_x = attr_name[0];
    particle_list[0].coor_y = attr_name[1];  
    particle_list[0].coor_z = attr_name[2];
    
    /* Fill in get attribute function pointer. */
    particle_list[0].get_par_attr = par_io_get_par_attr;
}
void par_io_get_par_attr(const int list_len, const long *gid_list, const char *par_type, const char *attribute, yt_array *data_array) {
    // loop over gid_list, and fill in particle attribute data inside data_array.
    for (int lid = 0; lid < list_len; lid++) {
        // =============================================================
        // libyt: [Optional] Use libyt look up grid info API
        // =============================================================
        int Level;
        double RightEdge[3], LeftEdge[3];
        yt_getGridInfo_Level(gid_list[lid], &Level);
        yt_getGridInfo_RightEdge(gid_list[lid], &RightEdge);
        yt_getGridInfo_LeftEdge(gid_list[lid], &LeftEdge);
        // fill in particle data.
        // we can get the length of the array to fill in like this, though this example only has one particle in each grid.
        for (int i = 0; i < data_array[lid].data_length; i++) {
            // fill in particle data according to the attribute.
            if (strcmp(attribute, "ParPosX") == 0) {
                ((real *) data_array[lid].data_ptr)[0] = 0.5 * (RightEdge[0] + LeftEdge[0]);
            } else if (strcmp(attribute, "ParPosY") == 0) {
                ((real *) data_array[lid].data_ptr)[0] = 0.5 * (RightEdge[1] + LeftEdge[1]);
            } else if (strcmp(attribute, "ParPosZ") == 0) {
                ((real *) data_array[lid].data_ptr)[0] = 0.5 * (RightEdge[2] + LeftEdge[2]);
            } else if (strcmp(attribute, "Level") == 0) {
                ((int *) data_array[lid].data_ptr)[0] = Level;
            }
        }
    }
}