1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
 int
 saf_describe_field(SAF_ParMode pmode,           /* The parallel mode. */
                    SAF_Field *field,            /* The field handle. */
                    SAF_FieldTmpl *ftmpl,        /* [OUT] The returned field template handle. Pass NULL if you do not want this
                                                  * value returned. */
                    char **name,                 /* [OUT] The returned name of the field. Pass NULL if you do not want this
                                                  * value returned. (see Returned Strings). */
                    SAF_Set *base_space,         /* [OUT] The returned base space of the field. Pass NULL if you do not want
                                                  * this value returned. */
                    SAF_Unit *unit,              /* [OUT] The returned unit of measure. */
                    hbool_t *is_coord,           /* [OUT] A returned boolean indicating if the field is a coordinate field. Pass
                                                  * NULL if you do not want this value returned. */
                    SAF_Cat *homog_decomp,       /* NULL: If the field is homogeneous, the value returned here, if requested,
                                                  * is always SAF_SELF(). That is, SAF_EQUIV(SAF_SELF(db), homog_decomp) will
                                                  * return true. Otherwise, it will return false, the field is inhomogeneous
                                                  * and this argument is the decomposition on which the field is presumably
                                                  * piecewise homogeneous. Pass NULL if you do not want this value returned. */
                    SAF_Cat *coeff_assoc,        /* [OUT] The collection with which the field coefficients are associated in an
                                                  * n:1 relationship. Pass NULL if you do not want this value returned. */
                    int *assoc_ratio,            /* [OUT] The `n' in the n:1 relationship described for the COEFF_ASSOC
                                                  * argument. Pass NULL if you do not want this value returned. */
                    SAF_Cat *eval_coll,          /* [OUT] The collection whose sets decompose the base space set and over which
                                                  * the field is actually evaluated. Pass NULL if you do not want this value
                                                  * returned. */
                    SAF_Eval *eval_func,         /* [OUT] The evaluation function. Pass NULL if you do not want this value
                                                  * returned. */
                    hid_t *data_type,            /* [OUT] The file datatype of the field. Pass NULL if you do not want this value
                                                  * returned. The caller is responsible for invoking H5Tclose() when the
                                                  * datatype is no longer needed. A negative returned value indicates no
                                                  * known file datatype. */
                    int *num_comps,              /* [OUT] The number of components in the field. Pass NULL if you do not want
                                                  * this value returned. */
                    SAF_Field **comp_flds,       /* [OUT] The component fields. Pass NULL if you do not want this value returned. */
                    SAF_Interleave *comp_intlv,  /* [OUT] The particular fashion in which components are interleaved.  Currently
                                                  * there are really only two: SAF_INTERLEAVE_VECTOR and SAF_INTERLEAVE_COMPONENT.
                                                  * These represent the XYZXYZ...XYZ and the XXX...XYYY...YZZZ...Z cases.  Note that
                                                  * interleave really only deals within a single blob of storage.  In the case of a
                                                  * composite field whose coefficients are stored independently on the component
                                                  * fields then interleave really has no meaning (use SAF_INTERLEAVE_INDEPENDENT).
                                                  * Interleave only has meaning on fields with storage.  In the case of a scalar
                                                  * field interleave is also meaningless, both cases degenerate to the same layout:
                                                  * XXX...X (use SAF_INTERLEAVE_NONE). */
                    int **comp_order             /* [OUT] The component ordering in the field. Pass NULL if you do not want this
                                                  * value returned. */
                    )
 {
     SAF_ENTER(saf_describe_field, SAF_PRECONDITION_ERROR);
     ss_blob_t           blob=SS_BLOB_NULL;
     ss_fieldtmpl_t      ftmpl_storage=SS_FIELDTMPL_NULL;
     int                 i, ncomps;

     SAF_REQUIRE(_saf_valid_pmode(pmode), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("PMODE must be valid"));
     if (!_saf_is_participating_proc(pmode)) SAF_RETURN(-1);

     SAF_REQUIRE(SS_FIELD(field), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("FIELD must be a valid field handle for all participating processes"));

     /* fill in all the stuff we get from the field record itself */
     if (base_space) *base_space = SS_FIELD(field)->base_space;
     if (!ftmpl) ftmpl = &ftmpl_storage; /*because we need it below*/
     *ftmpl = SS_FIELD(field)->ftmpl;
     if (_saf_setupReturned_string(name, ss_string_ptr(SS_FIELD_P(field,name))))
         SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to return NAME for field"));
     if (unit) *unit = SS_FIELD(field)->units;
     if (is_coord) *is_coord = SS_FIELD(field)->is_coord_field;
     if (homog_decomp) *homog_decomp = SS_FIELD(field)->storage_decomp_cat;
     if (coeff_assoc) *coeff_assoc = SS_FIELD(field)->dof_assoc_cat;
     if (assoc_ratio) *assoc_ratio = SS_FIELD(field)->assoc_ratio;
     if (eval_coll) *eval_coll = SS_FIELD(field)->eval_decomp_cat;
     if (eval_func) *eval_func = SS_FIELD(field)->evaluation;
     ncomps = SS_FIELDTMPL(ftmpl)->num_comps;
     if (num_comps) *num_comps = ncomps;
     if (data_type) {
         blob = SS_FIELD(field)->dof_blob;
         if (SS_PERS_ISNULL(&blob)) {
             *data_type = H5I_INVALID_HID;
         } else if (ss_array_nelmts(SS_FIELD_P(field,indirect_fields))>0) {
             *data_type = H5Tcopy(ss_pers_tm);
         } else {
             if (ss_blob_bound_f(&blob, NULL, NULL, NULL, NULL, data_type)<0)
                 SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("unable to obtain file datatype for field DOFs"));
         }
     }
     if (comp_intlv) *comp_intlv = SS_FIELD(field)->comp_intlv;
     if (ncomps > 1) {
         /*  Ah, we have component fields, did the caller request any component fields? */
         if (comp_flds) {
             /*  Yes, then the caller must pass a pointer to a variable which either already holds or will hold the
              *  number of components. */
             if (num_comps == NULL)
                 SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("you must provide NUM_COMPS if you ask for the"
                                                         " component fields"));
             /*  Is there already a buffer to hold the component field handles? */
             if (*comp_flds != NULL) {
                 /* If the client has allocated storage for the component fields, make sure that there is enough. */
                 if (*num_comps < (int)ncomps)
                     SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("NUM_COMPS is too small for component field handles %i %i",
                                                             *num_comps, ncomps));
             } else {
                 /*  The caller passed a pointer to a nil pointer so we'll allocate the buffer... */
                 *comp_flds = calloc((size_t)ncomps, sizeof(**comp_flds));
                 if (*comp_flds == NULL)
                     SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate space for component field handles COMP_FLDS"));
             }

             if (NULL==ss_array_get(SS_FIELD_P(field,comp_fields), ss_pers_tm, 0, (size_t)ncomps, *comp_flds)) {
                 SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("unable to read component field array"));
             }
         }

         /*  If the client wants the component ordering then return it. */
         if (comp_order) {
             if (num_comps == NULL)
                 SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("you must provide NUM_COMPS if you ask for"
                                                         " the component order"));
             if (*comp_order != NULL) {
                 /* If the client has allocated storage for the component order, make sure that there is enough. */
                 if (*num_comps < (int)ncomps)
                     SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("NUM_COMPS is too small for component order %i %i",
                                                             *num_comps, ncomps));
             } else {
                 /* Attempt to allocate storage if the client hasn't already. */
                 if (NULL==(*comp_order=malloc(ncomps*sizeof(**comp_order))))
                     SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate comp_order array"));
             }

             /* If the component order was stored in a metablob then read it into the comp_order array */
             if (0==ss_array_nelmts(SS_FIELD_P(field,comp_order))) {
                 for (i=0; i<ncomps; i++) (*comp_order)[i] = i;
             } else {
                 if (NULL==ss_array_get(SS_FIELD_P(field,comp_order), H5T_NATIVE_INT, 0, (size_t)ncomps, *comp_order))
                     SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("unable to read component field order"));
             }
         }
     }
     SAF_LEAVE(SAF_SUCCESS);
 }