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
 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);
 }