int
saf_declare_collection(SAF_ParMode pmode, /* The parallel mode. */
SAF_Set *containing_set, /* The containing set of the collection. In SAF_ONE() parallel mode, all
* processes except the process identified by the rank argument of the SAF_ONE()
* macro are free to pass SAF_NULL_SET with the set's database handle. */
SAF_Cat *cat, /* The collection category. */
SAF_CellType ctype, /* The cell type of the members of the collection. If this is a non-primitive
* collection, pass SAF_CELLTYPE_SET. If this is a primitive collection of
* mixed cell type, pass SAF_CELLTYPE_MIXED. If this is a primitive collection
* of arbitrarily connected cells, pass SAF_CELLTYPE_ARB. Otherwise, it must
* be a primitive collection of homogeneous type and the caller should pass
* one of the cell types specified by SAF_CellType. */
int count, /* The number of members of the collection. If the containing set is an
* extendible set, the count can be changed by a call to
* saf_extend_collection(). */
SAF_IndexSpec ispec, /* The indexing scheme of the collection (e.g., how are members of the collection
* identified within the collection). We have predefined some macros for common
* cases: SAF_1DC(), SAF_2DC(), and SAF_3DC() for C-ordered and indexed arrays and
* likewise for Fortran-ordered and indexed arrays (replace the "C" with
* an "F" in the macro name). */
SAF_DecompMode is_decomp /* Indicates if the specified collection is a decomposition of its containing set.
* That is, if we take the union of all the members of the collection do we form
* a set that is equal to the containing set? */
)
{
SAF_ENTER(saf_declare_collection, SAF_PRECONDITION_ERROR);
ss_scope_t scope=SS_SCOPE_NULL; /* Scope to own the new collection */
ss_indexspec_t idx=SS_INDEXSPEC_NULL; /* The default index spec */
ss_collection_t coll=SS_COLLECTION_NULL; /* The new collection */
int i, n;
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_SET(containing_set), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("CONTAINING_SET must be a valid set handle for participating processes"));
SAF_REQUIRE(SS_CAT(cat), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("CAT must be a valid category handle for participating processes"));
SAF_REQUIRE(is_decomp != SAF_DECOMP_TORF, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("IS_DECOMP must be either SAF_DECOMP_TRUE or SAF_DECOMP_FALSE for participating processes"));
SAF_REQUIRE(_saf_valid_indexspec(ispec, count), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("ISPEC rank and sizes must be valid for participating processes"));
/* The scope that owns CONTAINING_SET will also be the owner of the new collection. */
if (NULL==ss_pers_scope((ss_pers_t*)containing_set, &scope))
SAF_RETURN(SAF_SSLIB_ERROR);
/* Initialize an index record */
if (NULL==ss_pers_new(&scope, SS_MAGIC(ss_indexspec_t), NULL, SAF_ALL==pmode?SS_ALLSAME:0U, (ss_pers_t*)&idx, NULL))
SAF_RETURN(SAF_SSLIB_ERROR);
if (SAF_EACH==pmode) SS_PERS_UNIQUE(&idx);
SS_INDEXSPEC(&idx)->ndims = ispec.ndims;
for (i=0, n=1; i<ispec.ndims; i++) {
n *= ispec.sizes[i];
SS_INDEXSPEC(&idx)->sizes[i] = ispec.sizes[i];
SS_INDEXSPEC(&idx)->origins[i] = ispec.origins[i];
SS_INDEXSPEC(&idx)->order[i] = ispec.order[i];
}
/* Initialize the collection record */
if (NULL==ss_pers_new(&scope, SS_MAGIC(ss_collection_t), NULL, SAF_ALL==pmode?SS_ALLSAME:0U, (ss_pers_t*)&coll, NULL))
SAF_RETURN(SAF_SSLIB_ERROR);
/* Fill in the record */
if (SAF_EACH==pmode) SS_PERS_UNIQUE(&coll);
SS_COLLECTION(&coll)->containing_set = *containing_set;
SS_COLLECTION(&coll)->cat = *cat;
SS_COLLECTION(&coll)->cell_type = ctype;
SS_COLLECTION(&coll)->count = n;
ss_array_resize(SS_COLLECTION_P(&coll,indexing), 1);
ss_array_put(SS_COLLECTION_P(&coll,indexing), ss_pers_tm, (size_t)0, (size_t)1, &idx);
SS_COLLECTION(&coll)->is_decomp = is_decomp?TRUE:FALSE;
/* If this is a non-primitive collection then extend the variable length array of Set links. We extend the array here
* because we don't actually store the COUNT value anywhere in the collection. The initial values of the array are all
* null Set pointers. */
if (SAF_CELLTYPE_SET==ctype) {
if (ss_array_resize(SS_COLLECTION_P(&coll,members), (size_t)count)<0)
SAF_RETURN(SAF_SSLIB_ERROR);
}
/* update the set record */
_saf_putCollection_set(pmode, containing_set, cat, &coll);
SAF_LEAVE(SAF_SUCCESS);
}