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
 SAF_FieldTmpl *
 saf_declare_field_tmpl(SAF_ParMode pmode,       /* The parallel mode. */
                        SAF_Db *db,              /* The database handle in which to create the template. */
                        const char *name,        /* The name of the field template. */
                        SAF_Algebraic *atype,    /* The algebraic type: SAF_ALGTYPE_SCALAR, SAF_ALGTYPE_VECTOR,
                                                  * SAF_ALGTYPE_TENSOR, SAF_ALGTYPE_SYMTENSOR, SAF_ALGTYPE_FIELD.  If
                                                  * the algebraic type is SAF_ALGTYPE_FIELD, then all we know about the
                                                  * field is that it references other fields (i.e., an indirect field).
                                                  * Therefore, the next four arguments are not applicable.  More
                                                  * generalized user defined type definitions will be available in later
                                                  * implementations. */
                        SAF_Basis *basis,        /* The basis. Not implemented yet. Pass null */
                        SAF_Quantity *quantity,  /* The quantity. See saf_declare_quantity() for quantity definitions and how
                                                  * to define new quantities. */
                        int num_comp,            /* Number of components. Although this may often be inferred from ATYPE,
                                                  * SAF currently does no work to infer it. Pass SAF_NOT_APPLICABLE_INT if
                                                  * this template will be used in the declaration of an inhomogeneous field.
                                                  * Otherwise, pass the number of components. For a simple scalar field, the
                                                  * number of components is 1. See Fields for further discussion of
                                                  * inhomogeneous fields. */
                        SAF_FieldTmpl *ctmpl,    /* This is an array of NUM_COMPS field template handles that comprise the
                                                  * composite field template or NULL if there are no component field
                                                  * templates. Pass NULL if this field template will be used in the
                                                  * declaration of an INhomogeneous field. */
                        SAF_FieldTmpl *ftmpl     /* Returned field template handle for composite fields. If the algebraic
                                                  * type (ATYPE) is SAF_ALGTYPE_FIELD, then the returned field template
                                                  * may be used as a state template (see State Templates). */
                        )
 {
     SAF_ENTER(saf_declare_field_tmpl, NULL);
     ss_scope_t          scope=SS_SCOPE_NULL;    /* The scope in which to declare the new field template. */

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

     SAF_REQUIRE(ftmpl, SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("FTMPL must be non-null"));
     SAF_REQUIRE(name, SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("NAME must be non-null"));
     SAF_REQUIRE(num_comp==SAF_NOT_APPLICABLE_INT || num_comp>=1, SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("NUM_COMP >= 1"));
     SAF_REQUIRE(num_comp==SAF_NOT_APPLICABLE_INT || (num_comp>1 && ctmpl) || num_comp==1, SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("CTMPL must be non-NULL if NUM_COMP > 1"));
     SAF_REQUIRE(SS_ALGEBRAIC(atype), SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("ATYPE must be a valid algebraic type handle"));
     SAF_REQUIRE(ctmpl || num_comp==SAF_NOT_APPLICABLE_INT || (!ctmpl && num_comp==1 && !SS_ALGEBRAIC(atype)->indirect),
                 SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("CTMPL may be NULL only if NUM_COMP == 1 and ATYPE must be direct"));
     SAF_REQUIRE(!ctmpl || (ctmpl && num_comp!=SAF_NOT_APPLICABLE_INT), SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("CTMPL must be NULL if components are not appropriate"));
     SAF_REQUIRE(!basis || SS_BASIS(basis), SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("BASIS must be a valid basis handle or NULL"));
     SAF_REQUIRE(!quantity || SS_QUANTITY(quantity), SAF_LOW_CHK_COST, NULL,
                 _saf_errmsg("QUANTITY must be a valid quantity handle if supplied"));

     /* The scope in which to declare the field template. */
     ss_file_topscope(db, &scope);

     /* Allocate and/or initialize the new field template object. */
     ftmpl = (ss_fieldtmpl_t*)ss_pers_new(&scope, SS_MAGIC(ss_fieldtmpl_t), NULL, SAF_ALL==pmode?SS_ALLSAME:0U,
                                          (ss_pers_t*)ftmpl, NULL);
     if (SAF_EACH==pmode) SS_PERS_UNIQUE(ftmpl);

     /* Save the component field templates */
     if (ctmpl) {
         if (ss_array_resize(SS_FIELDTMPL_P(ftmpl,ftmpls), (size_t)num_comp)<0 ||
             ss_array_put(SS_FIELDTMPL_P(ftmpl,ftmpls), ss_pers_tm, (size_t)0, (size_t)num_comp, ctmpl)<0)
             SAF_ERROR(NULL, _saf_errmsg("unable to link to component field templates"));
     }

     /* Initialize the other non-zero parts of the field template */
     ss_string_set(SS_FIELDTMPL_P(ftmpl,name), name);
     SS_FIELDTMPL(ftmpl)->algebraic = *atype;
     if (basis) SS_FIELDTMPL(ftmpl)->basis = *basis;
     if (quantity) SS_FIELDTMPL(ftmpl)->quantity = *quantity;
     SS_FIELDTMPL(ftmpl)->num_comps = num_comp;

     /* return stuff */
     SAF_LEAVE(ftmpl);
 }