Derived Field
Table of contents
Definition of Derived Field
When the field is not part of the iterative process or, we want to provide a specific C function to generate data during in situ Python analysis, we should set field_type
to "derived_func"
. Derived field data will be generated by our input C function, derived_func
, whenever yt
or Python needs them.
Derived Field Function
Derived functions must have prototype:
void DerivedFunc(const int list_len, const long *list_gid, const char *field_name, yt_array *data_array);
derived_func(const int, const long*, const char*, yt_array*)
: generate field data of that grid when input a list grid id.const int list_len
: number of gid inlist_gid
.const long *list_gid
: a list of grid id that this function needs to prepare.const char *field_name
: target field data name to prepare.yt_array *data_array
: write generated data to the pointer in this array in the same order inlist_gid
without ghost cell.
Derived function derived_func
generates data and stores in yt_array
array data member data_ptr
without ghost cell. Make sure your function writes the data in x-address alters first orientation (which is [z][y][x]), if contiguous_in_x
is set to true
. Write the data in z-address alters first orientation (which is [x][y][z]), if contiguous_in_x
is set to false
.
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 field data of this grid.
Example
Field InvDens
is a derived field and is reciprocal of density field Dens
. derived_func_InvDens
first gets level, grid dimensions and density data of the grid, and it generates data and stores them in data_array
.
// get pointer of the array where we should put data to
yt_field *field_list;
yt_get_FieldsPtr(&field_list);
// Reciprocal of density field "InvDens"
field_list[1].field_name = "InvDens";
field_list[1].field_type = "derived_func";
field_list[1].contiguous_in_x = true;
field_list[1].field_dtype = (typeid(real) == typeid(float)) ? YT_FLOAT : YT_DOUBLE;
field_list[1].derived_func = derived_func_InvDens;
void derived_func_InvDens(const int list_len, const long *gid_list, const char *field_name, yt_array *data_array) {
// loop over gid_list, and fill in grid data inside data_array.
for (int lid = 0; lid < list_len; lid++) {
// =================================================
// libyt: [Optional] Use libyt look up grid info API
// =================================================
int level, dim[3];
yt_getGridInfo_Level(gid_list[lid], &level);
yt_getGridInfo_Dimensions(gid_list[lid], &dim);
// =============================================================
// libyt: [Optional] Use libyt API to get data pointer passed in
// =============================================================
// the label "Dens" we used here should be same as yt_get_FieldsPtr (libyt step 4)
yt_data dens_data;
yt_getGridInfo_FieldData(gid_list[lid], "Dens", &dens_data);
// generate and fill in data in [z][y][x] order, since we set this field contiguous_in_x = true
int index, index_with_ghost_cell;
for (int k = 0; k < dim[2]; k++) {
for (int j = 0; j < dim[1]; j++) {
for (int i = 0; i < dim[0]; i++) {
index = k * dim[1] * dim[0] + j * dim[0] + i;
index_with_ghost_cell = (k + GHOST_CELL) * (dim[1] + GHOST_CELL * 2) * (dim[0] + GHOST_CELL * 2)
+ (j + GHOST_CELL) * (dim[0] + GHOST_CELL * 2)
+ (i + GHOST_CELL);
// write generated data in data_array allocated by libyt.
((real *) data_array[lid].data_ptr)[index] = 1.0 / ((real *) dens_data.data_ptr)[index_with_ghost_cell];
}
}
}
}
}