POSC Specifications Version 3.0 |
Epicentre Modeling Methodology |
This is the non-normative specification of the Epicentre data type. A normative text version is included. The Epicentre data types are defined as meta types. In order to minimize behavioral differences with standard express, the meta path syntax is not used and is not allowed in a conformant Epicentre model. The meta derived element syntax is not used because derived attributes are not used in a compliant Epicentre model.
The meta type descriptions in the V2.2 DAE Appendix F "Summary of Data Types" document specified a variant of the parameter specification defined here because it allowed optional components to the actual parameter list. For example:
LOCATION `(' [ constraint ] `,' precision_spec `)'
It was inconsistent for MONEY because it allowed the whole parameter list to be optional but did not allow the individual parameter to be optional.
MONEY [`(' currency_type `)' ]
It was also inconsistent for UNSTRUCTURED_3D_TOPOLOGY because it specified an empty parameter list.
UNSTRUCTURED_3D_TOPOLOGY`(' `)'
Fortunately, the epicentre_extensions file specifies an empty string for all optional arguments. For example:
TYPE ndt_location = location('', 10); END_TYPE;
Thus, the only effect this will have on our NDT specifications will be to fix ndt_money and ndt_unstructured_grid_3d (not counting any modifications required by other changes).
The following interface changes have been made with respect to the V2.2 DAE specification. They do not represent a semantic change to the meta type and do not require a change to the DAE.
The following semantic changes have been made with respect to the V2.2 DAE specification. These represent a logical change in capability.
The following capabilities have been added with respect to the V2.2 specification:
This section defines parts of a conformant Epicentre model that are required to exist in order to use all of the Epicentre quantity and geometry data types. The simple pattern types are not dependent on the Epicentre Data Model.
ENTITY COORDINATE_SYSTEM ABSTRACT SUPERTYPE OF ( ONEOF ( simple_coordinate_system, compound_coordinate_system ) ); ref_coordinate_sys_constraint : ref_coordinate_sys_constraint; END_ENTITY; ENTITY ref_coordinate_sys_constraint; identifier : STRING(40); axis_type : SET [0:?] OF coordinate_axis_constraint; END_ENTITY; ENTITY SIMPLE_COORDINATE_SYSTEM SUBTYPE OF ( coordinate_system ); coordinate_system_axis : SET [0:?] OF coordinate_system_axis; END_ENTITY; ENTITY COMPOUND_COORDINATE_SYSTEM SUBTYPE OF ( coordinate_system ); first_system : simple_coordinate_system; second_system : simple_coordinate_system; END_ENTITY; ENTITY coordinate_system_axis; axis_order : INTEGER; constrained_to_unit : OPTIONAL ref_unit_of_measure; property_kind : property_kind; END_ENTITY; ENTITY VERTEX; END_ENTITY; ENTITY coordinate_axis_constraint; END_ENTITY; ENTITY PROPERTY_KIND; quantity_constraint : OPTIONAL ref_quantity_type; END_ENTITY; ENTITY REF_QUANTITY_TYPE; identifier : STRING(40); alternative_unit_of_measure : SET [0:?] OF quantity_type_alternative; END_ENTITY; ENTITY quantity_type_alternative; unit_of_measure : ref_unit_of_measure; END_ENTITY; ENTITY REF_UNIT_OF_MEASURE; acronym : STRING(40); END_ENTITY; ENTITY REF_PROPERTY_SET; identifier : STRING(40); ref_property_set_type : ref_property_set_type; use_limit : OPTIONAL INTEGER; component_kind : SET [0:?] OF property_set_composition; END_ENTITY; ENTITY property_set_composition; property_kind : property_kind; END_ENTITY; ENTITY ref_property_set_type; identifier : STRING(40); END_ENTITY; ENTITY GRID_OR_MESH; END_ENTITY; ENTITY GRID_GEOMETRY_BEHAVIOR; END_ENTITY; ENTITY REF_CURRENCY_UNIT; acronym : STRING(15); smaller_unit : OPTIONAL ref_currency_unit; sub_unit_per_unit : OPTIONAL INTEGER; END_ENTITY; |
The following simple pattern types define the interrelationship of multiple components of what is logically a single value: complex, rational, ratio, date, time, timestamp, yearmonthinterval, daytimeinterval. These types have a single where rule to test the validity of the type. This is intended to facilitate projecting the logical model to an EXPRESS Version 1 syntax using the attribute replication technique. That is, the validity function calling parameters could be adjusted to conform to the projection technique with the function itself being hand modified to conform to the changes.
META_TYPE COMPLEX ( precision : INTEGER ); real_part : REAL (precision); imaginary_part : REAL (precision); WHERE is_valid: complex_valid ( precision, real_part, imaginary_part ); END_META_TYPE; META_TYPE RATIONAL; numerator : INTEGER; denominator : INTEGER; WHERE is_valid: rational_valid ( numerator, denominator ); END_META_TYPE; META_TYPE RATIO ( precision : INTEGER ); numerator : REAL (precision); denominator : REAL (precision); WHERE is_valid: ratio_valid ( precision, numerator, denominator ); END_META_TYPE; META_TYPE DATE (*This is intended to conform to the SQL92 specification for DATE.*); year : INTEGER; month : INTEGER; day : INTEGER; WHERE is_valid: date_valid ( year, month, day ); END_META_TYPE; META_TYPE TIME ( precision : INTEGER ) (*This is intended to conform to the SQL92 specification for TIME. The Offset of the time-zone is from Universal Coordinated Time.*); hour : INTEGER; minute : INTEGER; second : REAL ( precision ); offset_hour : INTEGER; offset_minute : INTEGER; WHERE is_valid: time_valid ( precision, hour, minute, second, offset_hour, offset_minute ); END_META_TYPE; META_TYPE TIMESTAMP ( precision : INTEGER ) (*This is intended to support the reduced precision of the ISO 8601 specification for Dates and Dates with Time-of-Day. In addition, it adds support for quarter and geologic age. Not specifying a full precision timestamp (e.g., a quarter or no hour) indicates an imprecise point-in-time rather than a period-of-time. Information should be specified to the greatest degree of precision that is known. A content_code of "M" with all elements specified is intended to conform to the SQL92 specification for TIMESTAMP. The Offset of the time-zone is from Universal Coordinated Time. The allowed imprecise combinations for each code are: Code Combination G geologic-age C century-only Q year quarter-of-year M year month-of-year [day-of-month [time-of-day]] W year week-of-year [day-of-week [time-of-day]] D year [day-of-year [time-of-day]] where time-of-day = hour [minute [second]] [offset_hour [offset_second]]. *); content_code : emi_timestamp_content (*Indicates the semantic content of elements year, year_part and day. G = Year is geologic age in millions of years ago. No other option is allowed. C = Year is the whole number Gregorian century with no year (e.g., 19 = somewhere in 1900's). No other option is allowed. D = Year is whole number Gregorian year including century. Day is day-of-year. Year_part is not allowed. M = Year is whole number Gregorian year including century. Year_part is month-of-year (1 = January, 12 = December). Day is day-of-month. W = Year is whole number Gregorian year including century. Year_part is week-of-year (1 = first week with a Thursday). Day is day-of-week (1 = Monday, 7 = Sunday). Q = Year is whole number Gregorian year including century. Year_part is quarter-of-year (1 = somewhere in Jan, Feb or Mar). *); year : REAL(6); year_part : OPTIONAL INTEGER; day : OPTIONAL INTEGER; hour : OPTIONAL INTEGER; -- 0 or 24 = midnight minute : OPTIONAL INTEGER; second : OPTIONAL REAL ( precision ); offset_hour : OPTIONAL INTEGER; offset_minute : OPTIONAL INTEGER; WHERE is_valid: timestamp_valid ( precision, content_code, year, year_part, day, hour, minute, second, offset_hour, offset_minute ); END_META_TYPE; TYPE emi_timestamp_content = ENUMERATION OF ( G, C, D, M, W, Q ); END_TYPE; META_TYPE YEARMONTHINTERVAL (*This is intended to conform to the SQL92 specification of year-month intervals.*); years : INTEGER; months : INTEGER; WHERE is_valid: yearmonthinterval_valid ( years, months ); END_META_TYPE; META_TYPE DAYTIMEINTERVAL ( precision : INTEGER ) (*This is intended to conform to the SQL92 specification for day-time intervals.*); day : INTEGER; hour : INTEGER; minute : INTEGER; second : REAL ( precision ); WHERE is_valid: daytimeinterval_valid (precision, day ,hour, minute, second); END_META_TYPE; |
The following measured quantity types also define the interrelationship of multiple components of what is logically a single value: money, location, quantity, anyquantity, angle. They differ from the simple pattern types in that they require unit of measure information in addition to the numerical values. See the Data Type Summary for a summary of the parameters. These types also have a single where rule to test the validity of the type.
META_TYPE MONEY ( money_constraint : STRING(80) ); currency_value : INTEGER; currency_unit : ref_currency_unit; subvalue : OPTIONAL LIST[1:10] OF INTEGER; WHERE is_valid: money_valid ( money_constraint, currency_value, currency_unit, subvalue ); END_META_TYPE; META_TYPE LOCATION ( coordinate_constraint : STRING(80); precision : INTEGER ); system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coords : LIST[1:20] OF emi_ordinal (precision) (*The list refers to the order of the axes on the coordinate system.*); WHERE is_valid: location_valid ( coordinate_constraint, precision, system, origin, coords ); END_META_TYPE; META_TYPE emi_ordinal ( precision : INTEGER ); ordinal_value : REAL (precision); ordinal_unit : ref_unit_of_measure; minute_value : OPTIONAL INTEGER; second_value : OPTIONAL REAL(precision-5); END_META_TYPE; META_TYPE QUANTITY ( quantity_type : STRING(80); precision : INTEGER ); quantity_value : REAL (precision); quantity_unit : ref_unit_of_measure; WHERE is_valid: quantity_valid ( quantity_type, precision, quantity_value, quantity_unit ); END_META_TYPE; META_TYPE ANYQUANTITY ( precision : INTEGER ); quantity_value : REAL ( precision ); quantity_unit : ref_unit_of_measure; quantity_type : ref_quantity_type; WHERE is_valid: anyquantity_valid ( precision, quantity_value, quantity_unit, quantity_type ); END_META_TYPE; META_TYPE ANGLE ( quantity_type : STRING(80); precision : INTEGER ); quantity_value : REAL (precision); quantity_unit : ref_unit_of_measure; minute_value : OPTIONAL INTEGER; second_value : OPTIONAL REAL(precision-5); WHERE is_valid: angle_valid ( quantity_type, precision , quantity_value, quantity_unit, minute_value, second_value ); END_META_TYPE; |
The following geometry types define a somewhat complex interaction of arrays of data that is used to define the geometry and other properties of an object: geometry, point, sample, line, surface, volume, hypercell, . element. The abstract geometry type allows a meta type instance to be any of its subtypes; however, parameters may be used to constrain an instance to be one of a subset of the subtypes. See the Data Type Summary for a summary of the parameters. The following table describes some of the main aggregation concepts used by the geometry types.
Concept | Description |
---|---|
Descriptor | The descriptors provide a mechanism to implicitly describe the grid indexes of the grid nodes where information will be defined. Basically, the descriptors map the N dimensional grid indexes to the one dimensional list index. The first descriptor specifies the grid index that varies the fastest. For a 2x3 grid with INDEX_J being specified by the first descriptor, the list order will correspond to the following grid nodes: (1,1), (1,2), (1,3), (2,1), (2,1), (2,3). If INDEX_I was specified in the first descriptor then the following list ordered grid nodes would be implied: (1,1), (2,1), (1,2), (2,2), (1,3, (2,3). The descriptor mechanism is mutually exclusive with the index leaf mechanism and is generally used for a dense sampling of the grid. |
Index Leaf | The index leaves provide a mechanism to explicitly describe the grid indices of the grid nodes where information will be defined. For each index leaf, there can only one index value at each node. The index leaf mechanism is generally used for a sparse sampling of the grid. |
Geometry Leaf | The geometry leaves define the geometrical coordinates at each specified node of the grid. There will be one leaf for each axis of the coordinate system. The number of axes should normally be greater than or equal to the number of dimensions of the grid. For each geometry leaf, there can only be one ordinate value at each node. |
Property Leaf | The property leaves define the property values at each specified node of the grid. For each property leaf, there can only one property value at each node. |
The unstructured_3d_topology type is a special case that allows an unstructured grid to be defined independent of a volume instance.
META_TYPE GEOMETRY ( representation_constraint : STRING(80); position_constraint : STRING(80); coordinate_constraint : STRING(80); coordinate_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER ) ABSTRACT SUPERTYPE OF ( ONEOF ( point, sample, line, surface, volume, hypercell, element ) ); WHERE coordinate_precision_valid : coordinate_precision > 0; property_precision_valid : (property_constraint='none') OR ((property_constraint<>'none') AND (property_precision>0)); END_META_TYPE; META_TYPE POINT SUBTYPE OF ( geometry ); location_value : location (coordinate_constraint, coordinate_precision); property_value : OPTIONAL SET[1:?] OF emi_point_property (property_precision); WHERE is_valid: point_property_valid ( representation_constraint, position_constraint, property_constraint, property_value ); END_META_TYPE; META_TYPE emi_point_property ( prop_precision : INTEGER ) ABSTRACT SUPERTYPE OF ( ONEOF ( emi_point_integer_value, emi_point_real_value, emi_point_string_value, emi_point_boolean_value, emi_point_logical_value, emi_point_complex_value, emi_point_rational_value, emi_point_ratio_value, emi_point_dms_value, emi_point_quantity_value, emi_point_date_value, emi_point_yearmonthinterval_value, emi_point_daytimeinterval_value ) ); kind : property_kind; UNIQUE pk : kind; END_META_TYPE; META_TYPE emi_point_integer_value SUBTYPE OF ( emi_point_property ); integer_value : INTEGER; END_META_TYPE; META_TYPE emi_point_real_value SUBTYPE OF ( emi_point_property ); real_value : REAL(prop_precision); END_META_TYPE; META_TYPE emi_point_string_value SUBTYPE OF ( emi_point_property ); string_value : STRING(80); END_META_TYPE; META_TYPE emi_point_boolean_value SUBTYPE OF ( emi_point_property ); boolean_value : BOOLEAN; END_META_TYPE; META_TYPE emi_point_logical_value SUBTYPE OF ( emi_point_property ); logical_value : LOGICAL; END_META_TYPE; META_TYPE emi_point_complex_value SUBTYPE OF ( emi_point_property ); complex_value : complex(prop_precision); END_META_TYPE; META_TYPE emi_point_rational_value SUBTYPE OF ( emi_point_property ); rational_value : rational; END_META_TYPE; META_TYPE emi_point_ratio_value SUBTYPE OF ( emi_point_property ); ratio_value : ratio(prop_precision); END_META_TYPE; META_TYPE emi_point_dms_value SUBTYPE OF ( emi_point_property ); angle_value : emi_angle_dms(prop_precision) (*The value is assumed to be defined in units of angular degree.*); END_META_TYPE; META_TYPE emi_point_quantity_value SUBTYPE OF ( emi_point_property ); quantity_value : REAL (prop_precision); quantity_unit : ref_unit_of_measure; WHERE is_valid: quantity_valid ( kind.quantity_constraint.identifier, prop_precision, quantity_value, quantity_unit ); END_META_TYPE; META_TYPE emi_point_date_value SUBTYPE OF ( emi_point_property ); date_value : date; END_META_TYPE; META_TYPE emi_point_yearmonthinterval_value SUBTYPE OF ( emi_point_property ); yearmonthinterval_value : yearmonthinterval; END_META_TYPE; META_TYPE emi_point_daytimeinterval_value SUBTYPE OF ( emi_point_property ); daytimeinterval_value : daytimeinterval(prop_precision); END_META_TYPE; META_TYPE SAMPLE SUBTYPE OF ( geometry ); tuple_count : INTEGER; system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coordinate_leaf : LIST[1:?] OF emi_geometry_leaf (coordinate_precision) (*The list order aligns with the coordinate system axis. The underlying LIST aligns the tuples.*); property_leaf : OPTIONAL SET[1:?] OF emi_property_leaf (property_precision) (*The underlying LIST aligns the tuples.*); WHERE is_valid: sample_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, system, coordinate_leaf, property_leaf ); END_META_TYPE; META_TYPE LINE SUBTYPE OF ( geometry, emi_geometry_grid ); system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coordinate_leaf : LIST[1:?] OF emi_geometry_leaf (coordinate_precision) (*The list order aligns with the coordinate system axis.*); property_leaf : OPTIONAL SET[1:?] OF emi_property_leaf (property_precision) (*The underlying LIST aligns the tuples.*); WHERE is_valid: line_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, grid1, descriptor, index_leaf, system, coordinate_leaf, property_leaf ); END_META_TYPE; META_TYPE SURFACE ABSTRACT SUPERTYPE OF ( ONEOF ( emi_surface_grid, emi_isoline_set ) ) SUBTYPE OF ( geometry ); END_META_TYPE; META_TYPE emi_surface_grid SUBTYPE OF ( surface, emi_geometry_grid ); system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coordinate_leaf : LIST[1:?] OF emi_geometry_leaf (coordinate_precision) (*The list order aligns with the coordinate system axis.*); property_leaf : OPTIONAL SET[1:?] OF emi_property_leaf (property_precision) (*The underlying LIST aligns the tuples.*); WHERE is_valid: surface_grid_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, grid1, descriptor, index_leaf, system, coordinate_leaf, property_leaf ); END_META_TYPE; META_TYPE emi_isoline_set SUBTYPE OF ( surface ); system : coordinate_system (*This is the coordinate system of the coordinates. This must be a compound system with the 1D component applying to the isovalue.*); kind : property_kind; value_unit : ref_unit_of_measure; isoline : SET [1:?] OF emi_isoline (coordinate_precision, property_constraint,property_precision); WHERE is_valid: isoline_set_valid ( representation_constraint, position_constraint, coordinate_constraint, system, kind, value_unit, isoline ); END_META_TYPE; META_TYPE emi_isoline ( coord_precision : INTEGER; prop_constraint : STRING(80); prop_precision : INTEGER ); isovalue : REAL(coord_precision); line_geometry : line('grid1d','node','', coord_precision,prop_constraint, prop_precision); UNIQUE pk : isovalue; END_META_TYPE; META_TYPE VOLUME SUBTYPE OF ( geometry, emi_geometry_grid ); system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coordinate_leaf : LIST[1:?] OF emi_geometry_leaf (coordinate_precision) (*The list order aligns with the coordinate system axis.*); property_leaf : OPTIONAL SET[1:?] OF emi_property_leaf (property_precision) (*The underlying LIST aligns the tuples.*); WHERE is_valid: volume_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, grid1, descriptor, index_leaf, system , coordinate_leaf, property_leaf ); END_META_TYPE; META_TYPE HYPERCELL SUBTYPE OF ( geometry, emi_geometry_grid ); system : coordinate_system (*This is the coordinate system of the coordinates except when Origin is specified. If origin is specified then this is the coordinate system from which the actual coordinate system is created by transformation.*); origin : OPTIONAL vertex (*The origin of the coordinates if different from the origin of the coordinate system. Note that specifying this value is a shortcut to creating a new coordinate system with this origin as a transformation parameter from the existing coordinate system to the new system.*); coordinate_leaf : LIST[1:?] OF emi_geometry_leaf (coordinate_precision) (*The list order aligns with the coordinate system axis.*); property_leaf : OPTIONAL SET[1:?] OF emi_property_leaf (property_precision) (*The underlying LIST aligns the tuples.*); WHERE is_valid: hypercell_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, grid1, descriptor, index_leaf, system , coordinate_leaf, property_leaf ); END_META_TYPE; META_TYPE emi_geometry_leaf ( coord_precision : INTEGER ) ABSTRACT SUPERTYPE OF ( ONEOF ( emi_geometry_leaf_variable, emi_geometry_leaf_equal, emi_geometry_leaf_unequal ) ); ordinal_unit : ref_unit_of_measure; END_META_TYPE; META_TYPE emi_geometry_leaf_variable SUBTYPE OF ( emi_geometry_leaf ); ordinal_values : LIST[1:?] OF REAL(coord_precision) (*One value per tuple. This is used when the geometry is irregular.*); END_META_TYPE; META_TYPE emi_geometry_leaf_unequal SUBTYPE OF ( (emi_geometry_leaf ); ordinal_values : LIST[1:?] OF REAL(coord_precision) (*One value per index value of one dimension.*); unequal_index : emi_index_type (*Specifies the dimension to which these values are held constant. For example, INDEX_J would indicate that ordinal_value(1) is held constant for all nodes with j=1.*); END_META_TYPE; META_TYPE emi_geometry_leaf_equal SUBTYPE OF ( emi_geometry_leaf ) (*Defines a simple formula for calculating the values based on the grid index. The list corresponds to the grid dimension. That is, the ordinal value at a node is "start +step(1)*i +step(2)*j +step(3)*k, etc". Note that specifying a zero step for all but one dimension is a variation of an unequal geometry leaf.*); start : REAL(coord_precision); step : LIST[1:15] OF REAL(coord_precision) (*Missing values are assumed to be zero.*); END_META_TYPE; META_TYPE UNSTRUCTURED_3D_TOPOLOGY (*This is a special type whose only purpose is to allow the grid to be defined independent of an instance of a VOLUME type. The only real use for this is for grid modification which is currently out of scope for a data type.*); u3_topology : emi_grid_unstructured_3d; END_META_TYPE; META_TYPE ELEMENT SUBTYPE OF ( geometry, emi_geometry_grid ); geom1 : emi_geom_relationship (*The instance that contains the geometrical values associated with grid1.*); geom2 : OPTIONAL emi_geom_relationship (*The instance that contains the geometrical values associated with grid2.*); grid2 : OPTIONAL emi_grid; sparse_flag : BOOLEAN; value_connection : emi_index_type (*This is constrained to an element of a grid (e.g., node, edge)*); property_leaf : SET[1:?] OF emi_property_leaf (property_precision); WHERE is_valid: element_valid ( representation_constraint, position_constraint, coordinate_constraint, coordinate_precision, property_constraint, property_precision, tuple_count, grid1, geom1, grid2, geom2, sparse_flag , value_connection, descriptor, index_leaf, property_leaf ); END_META_TYPE; META_TYPE emi_geom_relationship; (*The three geom_xxxx elements represent a direct relationship to the geometry meta type instance that contains the geometrical values associated with the grid in an element meta type instance. Grid_geometry_behavior is intended to be the abstract supertype of all entities that have an attribute of type geometry whose contents may be shared with an attribute of type element.*) geom_instance : grid_geometry_behavior (*The instance that contains the attribute of type geometry.*); geom_subtype : STRING(80) (*The name of the subtype in geom_instance that contains the attribute.*); geom_attribute : STRING(80) (*The name of the geometrical attribute in geom_subtype.*); END_META_TYPE; META_TYPE emi_property_leaf ( prop_precision : INTEGER ) ABSTRACT SUPERTYPE OF ( ONEOF ( emi_leaf_equal_step_values, emi_leaf_integer_values, emi_leaf_real_values, emi_leaf_string_values, emi_leaf_boolean_values, emi_leaf_logical_values, emi_leaf_complex_values, emi_leaf_rational_values, emi_leaf_ratio_values, emi_leaf_dms_values, emi_leaf_date_values, emi_leaf_yearmonthinterval_values, emi_leaf_daytimeinterval_values, emi_leaf_quantity_values ) ); kind : property_kind; UNIQUE pk : kind; END_META_TYPE; META_TYPE emi_leaf_quantity_values SUBTYPE OF ( emi_property_leaf ); property_unit : ref_unit_of_measure; values : LIST[1:?] OF REAL(prop_precision); null_value : OPTIONAL REAL(prop_precision); END_META_TYPE; META_TYPE emi_leaf_equal_step_values SUBTYPE OF ( emi_property_leaf ) (*Defines a simple formula for calculating the values based on the grid index (or list index for SAMPLE). The list corresponds to the grid dimension. That is, the value at a node is "start +step(1)*i +step(2)*j +step(3)*k, etc".*); start : REAL(prop_precision); step : LIST[1:15] OF REAL(prop_precision); END_META_TYPE; META_TYPE emi_leaf_integer_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF INTEGER; null_value : OPTIONAL INTEGER; END_META_TYPE; META_TYPE emi_leaf_real_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF REAL(prop_precision); null_value : OPTIONAL REAL(prop_precision); END_META_TYPE; META_TYPE emi_leaf_string_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF STRING(80); null_value : OPTIONAL STRING(80); END_META_TYPE; META_TYPE emi_leaf_boolean_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF BOOLEAN; END_META_TYPE; META_TYPE emi_leaf_logical_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF LOGICAL; END_META_TYPE; META_TYPE emi_leaf_complex_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF complex(prop_precision); null_value : OPTIONAL complex(prop_precision); END_META_TYPE; META_TYPE emi_leaf_rational_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF rational; null_value : OPTIONAL rational; END_META_TYPE; META_TYPE emi_leaf_ratio_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF ratio(prop_precision); null_value : OPTIONAL ratio(prop_precision); END_META_TYPE; META_TYPE emi_leaf_dms_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF emi_angle_dms(prop_precision); null_value : OPTIONAL emi_angle_dms(prop_precision); END_META_TYPE; META_TYPE emi_angle_dms ( precision : INTEGER ) (*This is a compound-quantity with a fixed unit of measure (i.e., degrees).*); degree_value : INTEGER; minute_value : INTEGER; second_value : REAL(precision-5); WHERE is_valid : dms_valid (degree_value, minute_value, second_value); END_META_TYPE; META_TYPE emi_leaf_date_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF date; null_value : OPTIONAL date; END_META_TYPE; META_TYPE emi_leaf_yearmonthinterval_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF yearmonthinterval; null_value : OPTIONAL yearmonthinterval; END_META_TYPE; META_TYPE emi_leaf_daytimeinterval_values SUBTYPE OF ( emi_property_leaf ); values : LIST[1:?] OF daytimeinterval(prop_precision); null_value : OPTIONAL daytimeinterval(prop_precision); END_META_TYPE; META_TYPE emi_geometry_grid ABSTRACT SUPERTYPE OF ( ONEOF ( line, emi_surface_grid, volume, hypercell, element ) ); grid1 : emi_grid; tuple_count : INTEGER; descriptor : OPTIONAL LIST[1:16] OF UNIQUE emi_descriptor (*This implicitly defines the grid index values of each tuple in the list. The maximum bound must allow for an element index.*); index_leaf : OPTIONAL SET[1:?] OF emi_index_leaf (*This explicitly defines the grid index values of each tuple in the list.*); WHERE mse : EXISTS(descriptor) XOR EXISTS(index_leaf); END_META_TYPE; TYPE emi_index_type = ENUMERATION OF ( -- Axis indices (I = first dimension) INDEX_I, INDEX_J, INDEX_K, INDEX_L, INDEX_M, INDEX_N, INDEX_O, INDEX_P, INDEX_Q, INDEX_R, INDEX_S, INDEX_T, INDEX_U, INDEX_V, INDEX_W, -- Element indices (node = 0 dimensional) INDEX_NODE, INDEX_EDGE, INDEX_FACE, INDEX_CELL, INDEX_4, INDEX_5, INDEX_6, INDEX_7, INDEX_8, INDEX_9, INDEX_10, INDEX_11, INDEX_12, INDEX_13, INDEX_14, INDEX_15 ); END_TYPE; META_TYPE emi_descriptor (*This describes the implicit indexing for one dimension of the grid.*); dimension : emi_index_type; lower_bound : INTEGER (*The beginning index value.*); count : INTEGER; UNIQUE pk : dimension; WHERE lower_bound_valid : lower_bound > 0; count_valid : count > 0; END_META_TYPE; META_TYPE emi_index_leaf (*This provides and explicit grid index value for each tuple.*); index_name : emi_index_type; grid_number : INTEGER; data_values : LIST[1:?] OF INTEGER; UNIQUE pk : index_name, grid_number; WHERE grid_number_valid : (grid_number=1) OR (grid_number=2); END_META_TYPE; TYPE emi_grid_type = ENUMERATION OF ( regular, cornerpoint, trimesh, unstructured_3d); END_TYPE; META_TYPE emi_grid ABSTRACT SUPERTYPE OF ( ONEOF ( emi_grid_regular, emi_grid_trimesh, emi_grid_unstructured_3d ) ); grid_type : emi_grid_type; dimension_count : INTEGER; node_count : INTEGER (*The total number of nodes on the grid.*); grid_modified : OPTIONAL grid_or_mesh (*This refers to an equivalent grid description that "somehow" contains knowledge about how this grid has been refined or coarsened by another grid.*); WHERE dimension_count_valid : dimension_count<=15; END_META_TYPE; META_TYPE emi_grid_regular SUBTYPE OF ( emi_grid ); grid_axis_point_count : LIST[1:15] OF INTEGER (*Specifies the node count on each axis. The list corresponds to the axis order.*); grid_axis_lower_bound : LIST[1:15] OF INTEGER (*Specifies the starting index value on each axis. The list corresponds to the axis order.*); closed_flag : OPTIONAL LIST[1:15] OF BOOLEAN (*TRUE indicates that the last node is topologically connected to the first node. The list corresponds to the axis order.*); WHERE axis_count_valid : SIZEOF(grid_axis_point_count) = dimension_count; axis_bound_valid : SIZEOF(grid_axis_lower_bound) = dimension_count; flag_count_valid : NOT (EXISTS(closed_flag)) OR (SIZEOF(closed_flag) <= dimension_count); regular_type_valid : (grid_type=emi_grid_type.regular) OR (grid_type=emi_grid_type.cornerpoint); END_META_TYPE; META_TYPE emi_grid_trimesh SUBTYPE OF ( emi_grid ); mesh_edge : SET[1:?] OF emi_mesh_edge; mesh_face : SET[1:?] OF emi_mesh_face; WHERE trimesh_count_valid : dimension_count=2; mesh_type_valid : grid_type=emi_grid_type.trimesh; END_META_TYPE; META_TYPE emi_mesh_edge; edge_index : INTEGER; start_node : INTEGER; end_node : INTEGER; UNIQUE pk : edge_index; sk : start_node, end_node; END_META_TYPE; META_TYPE emi_mesh_face; face_index : INTEGER; node1 : INTEGER; node2 : INTEGER; node3 : INTEGER; UNIQUE pk : face_index; END_META_TYPE; META_TYPE emi_grid_unstructured_3d SUBTYPE OF ( emi_grid ); u3_cell : OPTIONAL SET[1:?] OF emi_u3_cell; u3_face : OPTIONAL SET[1:?] OF emi_u3_face; u3_edge : OPTIONAL SET[1:?] OF emi_u3_edge; WHERE unstruct_count_valid : dimension_count=3; unstruct_type_valid : grid_type=emi_grid_type.unstructured_3d; END_META_TYPE; META_TYPE emi_u3_cell; cell_index : INTEGER; bounding_face : OPTIONAL SET[1:?] OF INTEGER (*This specifies the face indices of the faces that bound the cell.*); center_node : OPTIONAL INTEGER (*This specifies the node index of the node at the center of the cell.*); UNIQUE pk : cell_index; END_META_TYPE; META_TYPE emi_u3_face; face_index : INTEGER; bounding_edge : OPTIONAL SET[1:?] OF INTEGER (*This specifies the edge indices of the edges that bound the face.*); adjacent_face : OPTIONAL SET[1:?] OF INTEGER (*This specifies the faces indices of the faces that are adjacent to this face.*); center_node : OPTIONAL INTEGER (*This specifies the node index of the node at the center of the face.*); UNIQUE pk : face_index; END_META_TYPE; META_TYPE emi_u3_edge; edge_index : INTEGER; bounding_node : OPTIONAL LIST[1:?] OF UNIQUE INTEGER (*This specifies the node indices of the nodes that define the edge.*); UNIQUE pk : edge_index; END_META_TYPE; |
These are the functions that are required in order to check the validity of the Epicentre Simple Pattern and Quantity (i.e., non-geometry) types.
FUNCTION complex_valid ( precision : INTEGER; real_part : REAL; imaginary_part : REAL ) : BOOLEAN; -- Return FALSE if the complex data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(real_part) <> EXISTS(imaginary_part) ) THEN RETURN (FALSE); END_IF; *) IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION rational_valid (numerator : INTEGER; denominator : INTEGER ) : BOOLEAN; -- Return FALSE if the rational data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(numerator) <> EXISTS(denominator) ) THEN RETURN (FALSE); END_IF; *) RETURN (TRUE); END_FUNCTION; FUNCTION ratio_valid ( precision : INTEGER; numerator : INTEGER; denominator : INTEGER ) : BOOLEAN; -- Return FALSE if the ratio data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(numerator) <> EXISTS(denominator) ) THEN RETURN (FALSE); END_IF; *) IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION money_valid ( money_constraint : STRING; currency_value : INTEGER; currency_unit : ref_currency_unit; subvalue : LIST OF INTEGER ) : BOOLEAN; -- Return FALSE if the currency data is not valid. LOCAL val : INTEGER; parent_unit : ref_currency_unit; END_LOCAL; (*The following are enforced by the meta type. IF ( EXISTS(currency_value) <> EXISTS(currency_unit) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(subvalue) AND NOT EXISTS(currency_value) ) THEN RETURN (FALSE); END_IF; *) -- Check the unit constraint. IF ( money_constraint<>'' ) THEN IF ( money_constraint<>currency_unit.acronym ) THEN RETURN (FALSE); END_IF; END_IF; -- Check the sign. IF (SIZEOF(subvalue)=0 ) THEN RETURN (TRUE); END_IF; val := 0; IF (currency_value<>0) THEN val := currency_value; ELSE REPEAT i := LOINDEX(subvalue) TO HIINDEX(subvalue); IF (subvalue[i]<>0) THEN val := subvalue[i]; ESCAPE; END_IF; END_REPEAT; END_IF; IF ( val>0 ) THEN -- All values must be positive or zero. IF ( SIZEOF(QUERY( tmp <* subvalue | tmp<0 ))<>0 ) THEN RETURN (FALSE); END_IF; ELSE IF ( val<0 ) THEN -- All values must be negative or zero. IF ( SIZEOF(QUERY( tmp <* subvalue | tmp>0 ))<>0 ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; -- Insure that there are not more subunits than are allowed. IF ( EXISTS(subvalue) ) THEN IF ( SIZEOF(subvalue) > subcurrency_depth(currency_units) ) THEN RETURN (FALSE); END_IF; END_IF; -- Insure that the subvalues are less than the allowed subunit per unit. parent_unit := currency_unit; REPEAT i := LOINDEX(subvalue) TO HIINDEX(subvalue); IF NOT (subvalue[i] < parent_unit.sub_unit_per_unit) THEN RETURN (FALSE); END_IF; parent_unit := parent_unit.smaller_unit; END_REPEAT; RETURN (TRUE); END_FUNCTION; FUNCTION subcurrency_depth ( unit : ref_currency_unit ) : INTEGER; -- Recursive function that returns the count of currency subunits. IF NOT EXISTS(unit.sub_unit_per_unit) THEN RETURN ( 0 ); ELSE RETURN ( 1 + subunit_depth(unit.sub_unit_per_unit) ); END_IF; END_FUNCTION; FUNCTION location_valid ( coord_constraint : STRING; precision : INTEGER; system : coordinate_system; origin : vertex; coords : LIST OF emi_ordinal ) : BOOLEAN; -- Return FALSE if the location values are not valid. LOCAL uom : LIST[0:?] OF ref_unit_of_measure; END_LOCAL; -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( coord_constraint<>'' ) THEN IF ( coord_constraint<>system.ref_coordinate_sys_constraint.identifier ) THEN RETURN (FALSE); END_IF; END_IF; -- Check the coordinate values. REPEAT i := LOINDEX(coords) TO HIINDEX(coords); -- Check any DMS values. IF ( NOT quantity_dms_valid ( coords[i].ordinal_value, coords[i].ordinal_unit, coords[i].minute_value, coords[i].second_value) ) THEN RETURN (FALSE); END_IF; -- Collect the units into a local variable. uom[i] := coords[i].ordinal_unit; END_REPEAT; -- Check the coordinate units against what is allowed by the system. IF ( NOT coordinate_units_valid (system,uom) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION coordinate_units_valid ( system : coordinate_system; uom : LIST OF ref_unit_of_measure ) : BOOLEAN; -- Return FALSE if the units do not match what is allowed by the axes -- of the coordinate system. IF (SIZEOF(uom) <> SIZEOF(system.ref_coordinate_sys_constraint.axis_type)) THEN RETURN (FALSE); END_IF; IF ( SIZEOF(QUERY( typ <* TYPEOF(system) | typ LIKE '*SIMPLE_COORDINATE_SYSTEM*'))>0 ) THEN -- This is not a compound system. IF (NOT(simple_system_unit_valid(system\simple_coordinate_system,uom,0))) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; IF ( SIZEOF(QUERY( typ <* TYPEOF(system) | typ LIKE '*COMPOUND_COORDINATE_SYSTEM*'))>0 ) THEN -- This is a compound system that is composed of two ordered simple -- systems (e.g., a 2d horizontal plus a 1d vertical). ALIAS first FOR system.first_system; -- Check each component system in order. The first N axes belong -- to the first system. IF ( NOT (simple_system_unit_valid (first, uom, 0)) ) THEN RETURN (FALSE); END_IF; -- The next M axes belong to the second system. IF ( NOT (simple_system_unit_valid ( system.second_system, uom, SIZEOF(first.coordinate_system_axis))) ) THEN RETURN (FALSE); END_IF; END_ALIAS; RETURN (TRUE); END_IF; -- bad model. RETURN (FALSE); END_FUNCTION; FUNCTION simple_system_unit_valid ( system : simple_coordinate_system ; uom : LIST OF ref_unit_of_measure; ix : INTEGER ) : BOOLEAN; -- Return FALSE if the units do not match those allowed by the simple system. -- Parameter "ix" specifies the number of axes utilized in a previous -- component of a compound system. ALIAS csa FOR system.coordinate_system_axis; REPEAT i := LOINDEX(csa) TO HIINDEX(csa); IF ( EXISTS(csa[i].constrained_to_unit) ) THEN -- This axis is constrained to use a particular unit of measure. IF (csa[i].constrained_to_unit <> uom[ix+csa[i].axis_order]) THEN RETURN (FALSE); END_IF; ELSE -- Check against the units allowed by the underlying quantity type. IF ( SIZEOF(QUERY( alt <* csa[i].property_kind.quantity_constraint.alternative_unit_of_measure | alt.unit_of_measure = uom[ix+csa[i].axis_order]))=0 ) THEN RETURN (FALSE); END_IF; END_IF; END_REPEAT; END_ALIAS; RETURN (TRUE); END_FUNCTION; FUNCTION whole_number ( real_value : REAL ) : BOOLEAN; -- Return TRUE if the number has no fractional part. LOCAL int : INTEGER; END_LOCAL; int := real_value; IF ( (real_value -int) <> 0 ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION date_valid ( year : INTEGER; month : INTEGER; day : INTEGER ) : BOOLEAN; -- Return FALSE if the date data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(year) <> EXISTS(month) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(year) <> EXISTS(day) ) THEN RETURN (FALSE); END_IF; *) -- Check the year. IF ( ( year<1 ) OR ( year>9999 ) ) THEN RETURN (FALSE); END_IF; -- Check the month. IF ( ( month<1 ) OR ( month>12 ) ) THEN RETURN (FALSE); END_IF; -- Check the day. IF ( NOT( ((month IN [1,3,5,7,8,10,12]) AND { 1 <= day <= 31 }) XOR (((month IN [4,6,9,11]) AND { 1 <= day <= 30 }) XOR ((month = 2) AND ((leap_year(year) AND { 1 <= day <= 29 }) OR { 1 <= day <= 28 }))) ) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION leap_year ( year : INTEGER ) : BOOLEAN; IF ( (((year mod 4) = 0) AND ((year mod 100) <> 0)) OR ((year mod 400) = 0) ) THEN RETURN (TRUE); END_IF; RETURN (FALSE); END_FUNCTION; FUNCTION time_valid ( precision : INTEGER; hour : INTEGER; minute : INTEGER; second : REAL; offset_hour : INTEGER; offset_minute : INTEGER) : BOOLEAN; -- Return FALSE if the time data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(hour) <> EXISTS(minute) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(hour) <> EXISTS(second) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(hour) <> EXISTS(offset_hour) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(hour) <> EXISTS(offset_minute) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the hour. IF ( ( hour<0 ) OR ( hour>23 ) ) THEN RETURN (FALSE); END_IF; -- Check the minute. IF ( ( minute<0 ) OR ( minute>59 ) ) THEN RETURN (FALSE); END_IF; -- Check the second. IF ( ( second<0 ) OR ( second>=62 ) ) THEN RETURN (FALSE); END_IF; IF ( ( second>=60 ) AND (( hour<>23 ) OR ( minute<>59 )) ) THEN -- Bad leap second. RETURN (FALSE); END_IF; -- Check the offset. IF ( ABS(offset_hour) > 13 ) THEN RETURN (FALSE); END_IF; IF ( ( offset_hour=13 ) AND ( offset_minute<>0 ) ) THEN RETURN (FALSE); END_IF; IF ( ABS(offset_minute) >= 60 ) THEN RETURN (FALSE); END_IF; -- Check the SIGN. IF NOT (((offset_hour>=0) AND (offset_minute>=0)) OR ((offset_hour<=0) AND (offset_minute<=0))) THEN -- Everything must be positive or negative. RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION timestamp_valid ( precision : INTEGER; content_code : emi_timestamp_content; year : REAL; year_part : INTEGER; day : INTEGER; hour : INTEGER; minute : INTEGER; second : REAL; offset_hour : INTEGER; offset_minute : INTEGER) : BOOLEAN; -- Return FALSE if the timestamp data is not valid. (*The following is checked by the meta syntax. IF ( NOT EXISTS(year) ) THEN RETURN (FALSE); END_IF; IF ( NOT EXISTS(content_code) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check for geologic age only. IF ( content_code=emi_timestamp_content.G ) THEN -- We are in geologic time. IF ( year<0 ) THEN -- Must be positive. RETURN (FALSE); END_IF; IF ( EXISTS(year_part) OR EXISTS(day) OR EXISTS(hour) OR EXISTS(minute) OR EXISTS(second) OR EXISTS(offset_hour) OR EXISTS(offset_minute) ) THEN -- This is mutually exclusive with the other components. RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; -- We are in modern times. IF ( NOT whole_number(year) ) THEN -- Fractional parts are not allowed. RETURN (FALSE); END_IF; -- Check for century only. IF ( content_code=emi_timestamp_content.C ) THEN -- Only the century is being specified. IF ( abs(year)>99 ) THEN -- Must be maximum of two digits. RETURN (FALSE); END_IF; IF ( EXISTS(year_part) OR EXISTS(day) OR EXISTS(hour) OR EXISTS(minute) OR EXISTS(second) OR EXISTS(offset_hour) OR EXISTS(offset_minute) ) THEN -- This is mutually exclusive with the other components. RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; -- Check the year. IF ( year=0 ) THEN -- Negative values indicate "Before Christian Era". RETURN (FALSE); END_IF; -- Check the quarter of the year. IF ( content_code=emi_timestamp_content.Q ) THEN IF ( (year_part<1) OR (year_part>4) ) THEN RETURN (FALSE); END_IF; -- This is mutually exclusive with the other components. IF ( EXISTS(day) OR EXISTS(hour) OR EXISTS(minute) OR EXISTS(second) OR EXISTS(offset_hour) OR EXISTS(offset_minute) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; -- Check the month of the year. IF ( content_code=emi_timestamp_content.M ) THEN IF ( (year_part<1) OR (year_part>12) ) THEN RETURN (FALSE); END_IF; -- Check the day of the month. IF ( EXISTS(day) ) THEN IF ( year_part=2 ) THEN -- February. IF ( NOT( (leap_year(year) AND { 1 <= day <= 29 }) OR { 1 <= day <= 28 } ) ) THEN RETURN (FALSE); END_IF; ELSE -- Not February. IF ( NOT( ((year_part IN [1,3,5,7,8,10,12]) AND { 1 <= day <= 31 }) XOR ((year_part IN [4,6,9,11]) AND { 1 <= day <= 30 }) ) ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; END_IF; -- Check the week of the year. IF ( content_code=emi_timestamp_content.W ) THEN IF ( (year_part<1) OR (year_part>53) ) THEN RETURN (FALSE); END_IF; -- Check the day of the week. 1=Monday. IF EXISTS(day) THEN IF ( (day<1) OR (day>7) ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; -- Check the day of the year. IF ( content_code=emi_timestamp_content.D ) THEN IF EXISTS(day) THEN IF ( (day>366) OR ((NOT leap_year(year)) AND (day>365)) ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; -- Check the hour of the day. IF ( EXISTS(hour) ) THEN IF ( NOT EXISTS(day) ) THEN RETURN (FALSE); END_IF; IF ( (hour<0) OR (hour>24) ) THEN RETURN (FALSE); END_IF; END_IF; -- Check the minute of the hour. IF ( EXISTS(minute) ) THEN IF ( NOT EXISTS(hour) ) THEN RETURN (FALSE); END_IF; IF ( (minute<0) OR (minute>59) ) THEN RETURN (FALSE); END_IF; IF ( (hour=24) AND (minute>0) ) THEN RETURN (FALSE); END_IF; END_IF; -- Check the second. IF ( EXISTS(second) ) THEN IF ( NOT EXISTS(minute) ) THEN RETURN (FALSE); END_IF; -- Check the low side. IF ( (second<0) ) THEN RETURN (FALSE); END_IF; IF ( (hour=24) AND (second>0) ) THEN RETURN (FALSE); END_IF; -- Check the high side. IF ( content_code=emi_timestamp_content.M ) THEN -- Month given. Check for a bad leap year second. IF ( second>=60 ) THEN IF ( NOT (leap_year(year) AND (year_part=12) AND (day=31) AND (hour=23) AND (minute=59) AND (second<62)) ) THEN RETURN (FALSE); END_IF; END_IF; ELSE -- Month not given. IF ( content_code=emi_timestamp_content.D ) THEN -- Day of year. -- Check for a bad leap year second. IF ( second>=60 ) THEN IF ( NOT (leap_year(year) AND (day=366) AND (hour=23) AND (minute=59) AND (second<62)) ) THEN RETURN (FALSE); END_IF; END_IF; ELSE -- Day of week. -- Too complicated to check for a leap second. IF ( (second>=62) ) THEN -- Allow for leap seconds. RETURN (FALSE); END_IF; END_IF; END_IF; END_IF; -- Check the offset hour. IF ( EXISTS(offset_hour) ) THEN IF ( NOT EXISTS(hour) ) THEN RETURN (FALSE); END_IF; IF ( (offset_hour<-12) OR (offset_hour>13) ) THEN RETURN (FALSE); END_IF; END_IF; -- Check the offset minute. IF ( EXISTS(offset_minute) ) THEN IF ( NOT EXISTS(offset_hour) ) THEN RETURN (FALSE); END_IF; IF ( (offset_hour=13) AND (offset_minute<>0) ) THEN RETURN (FALSE); END_IF; IF ( ABS(offset_minute)>59 ) THEN RETURN (FALSE); END_IF; -- Check the SIGN. IF ( ((offset_hour>0) AND (offset_minute<0)) OR ((offset_hour<0) AND (offset_minute>0)) ) THEN -- Both must be positive or negative. RETURN (FALSE); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION yearmonthinterval_valid ( years : INTEGER; months : INTEGER) : BOOLEAN; -- Return FALSE if the yearmonthinterval data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(years) <> EXISTS(months) ) THEN RETURN (FALSE); END_IF; *) -- Check the years. IF ( ABS(years)>9999 ) THEN RETURN (FALSE); END_IF; -- Check the months. IF ( ABS(months)>12 ) THEN RETURN (FALSE); END_IF; -- Check the sign. IF ( ((years>0) AND (months<0)) OR ((years<0) AND (months>0)) ) THEN -- Both must be positive or negative. RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION daytimeinterval_valid ( precision : INTEGER; day : INTEGER; hour : INTEGER; minute : INTEGER; second : REAL) : BOOLEAN; -- Return FALSE if the daytimeinterval data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(day) <> EXISTS(hour) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(day) <> EXISTS(minute) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(day) <> EXISTS(second) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the day. IF ( ABS(day)>9999 ) THEN RETURN (FALSE); END_IF; -- Check the hour. IF ( ABS(hour)>23 ) THEN RETURN (FALSE); END_IF; -- Check the minute. IF ( ABS(minute)>59 ) THEN RETURN (FALSE); END_IF; -- Check the second. IF ( ABS(second)>=60 ) THEN RETURN (FALSE); END_IF; -- Check the sign. IF ( (NOT ((day>=0) AND (hour>=0) AND (minute>=0) AND (second>=0))) AND (NOT ((day<=0) AND (hour<=0) AND (minute<=0) AND (second<=0))) ) THEN -- All must be positive or negative. RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION quantity_valid ( quantity_type : STRING(80); precision : INTEGER; quantity_value : REAL; quantity_unit : ref_unit_of_measure) : BOOLEAN; -- Return FALSE if the quantity data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(quantity_value) <> EXISTS(quantity_unit) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the constraint. IF ( quantity_type='' ) THEN RETURN (FALSE); END_IF; -- Check the unit of measure against those allowed by the type. IF ( SIZEOF(QUERY( tmp <* USEDIN ( quantity_unit, 'REF_QUANTITY_TYPE.ALTERNATIVE_UNIT_OF_MEASURE.UNIT_OF_MEASURE') | tmp.identifier=quantity_type ))<>1 ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION anyquantity_valid ( precision : INTEGER; quantity_value: REAL; quantity_unit : ref_unit_of_measure; quantity_type : ref_quantity_type) : BOOLEAN; -- Return FALSE if the anyquantity data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(quantity_value) <> EXISTS(quantity_unit) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(quantity_value) <> EXISTS(quantity_type) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the unit of measure against those allowed by the type. IF ( SIZEOF(QUERY( tmp <* quantity_type.alternative_unit_of_measure | tmp.unit_of_measure :=: quantity_unit ))<>1 ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION angle_valid ( quantity_type : STRING(80); precision : INTEGER; quantity_value : REAL; quantity_unit : ref_unit_of_measure; minute_value : INTEGER; second_value : REAL ) : BOOLEAN; -- Return FALSE if the angle data is not valid. (*The following are enforced by the meta type. IF ( EXISTS(quantity_value) <> EXISTS(quantity_unit) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(minute_value) AND NOT EXISTS(minute_value) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS(minute_value) AND NOT EXISTS(second_value) ) THEN RETURN (FALSE); END_IF; *) -- Check the precision. IF ( precision <= 0 ) THEN RETURN (FALSE); END_IF; -- Check the constraint. IF ( quantity_type='' ) THEN RETURN (FALSE); END_IF; -- Check the unit of measure against those allowed by the type. IF ( SIZEOF(QUERY( tmp <* USEDIN ( quantity_unit, 'REF_QUANTITY_TYPE.ALTERNATIVE_UNIT_OF_MEASURE.UNIT_OF_MEASURE') | tmp.identifier=quantity_type ))<>1 ) THEN RETURN (FALSE); END_IF; -- Check the value. IF ( NOT quantity_dms_valid ( quantity_value, quantity_unit, minute_value, second_value ) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION quantity_dms_valid ( quantity_value : REAL; quantity_unit : ref_unit_of_measure; minute_value : INTEGER; second_value : REAL ) : BOOLEAN; -- Return FALSE if the dms data is not valid. -- The minute and second values may be null. IF ( EXISTS(minute_value) OR EXISTS(second_value) ) THEN -- This is a DMS value. IF (EXISTS(minute_value) <> EXISTS(second_value) ) THEN -- If either is given then both must be given. RETURN (FALSE); END_IF; IF ( quantity_unit.acronym<>'dega' ) THEN -- The unit must specify degrees of angle. RETURN (FALSE); END_IF; IF ( NOT whole_number(quantity_value) ) THEN -- The degree component must be a whole number. RETURN (FALSE); END_IF; IF (ABS(minute_value) > 59) THEN RETURN (FALSE); END_IF; IF (ABS(second_value) >= 60) THEN RETURN (FALSE); END_IF; IF ( (NOT ((quantity_value>=0) AND (minute_value >=0) AND (second_value >=0))) AND (NOT ((quantity_value<=0) AND (minute_value <=0) AND (second_value <=0))) ) THEN -- All must be positive or negative. RETURN (FALSE); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; |
These are the functions that are required in order to check the validity of the complex Epicentre Geometry types. Some of the simple pattern validity functions may also be utilized.
FUNCTION point_property_valid ( rep_constraint : STRING; position_constraint : STRING; property_constraint : STRING; property : SET OF emi_point_property ) : BOOLEAN; -- Return FALSE if the point property data is not valid. LOCAL prp : SET[0:?] OF property_kind; END_LOCAL; -- Check the representation constraints. IF ( (rep_constraint<>'') AND (rep_constraint<>'grid0d') ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the property constraint and the properties. IF EXISTS(property) THEN REPEAT i := LOINDEX(property) TO HIINDEX(property); -- Note that the SET constrains the values to be unique. prp[i] := property[i].kind; END_REPEAT; END_IF; IF ( NOT property_set_valid (property_constraint,prp) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION property_set_valid ( property_constraint : STRING ; property : SET OF property_kind ) : BOOLEAN; -- Return FALSE if the properties are not allowed by the constraint. LOCAL type_set : SET[0:?] OF ref_property_set; constraint : ref_property_set; END_LOCAL; IF ( (NOT EXISTS(property)) AND ((property_constraint<>'none') AND (property_constraint<>'')) ) THEN -- A property is required. RETURN (FALSE); END_IF; IF ( NOT EXISTS(property) ) THEN -- Nothing else to check. RETURN (TRUE); END_IF; IF ( property_constraint='none' ) THEN -- Properties are not allowed. RETURN (FALSE); END_IF; IF ( (property_constraint<>'') AND (property_constraint<>'required') ) THEN -- Find all sets that use the first property kind. type_set := USEDIN ( property[1], 'REF_PROPERTY_SET.COMPONENT_KIND.PROPERTY_KIND'); -- Find the kind that matches the constraint. REPEAT i := LOINDEX(type_set) TO HIINDEX(type_set); IF ( type_set[i].identifier = property_constraint ) THEN constraint := type_set[i]; ESCAPE; END_IF; END_REPEAT; IF ( NOT EXISTS(constraint) ) THEN -- The constraint instance was not found. RETURN (FALSE); END_IF; -- Make sure the number of properties is valid. IF ( constraint.use_limit > 0 ) THEN IF ( NOT (((constraint.use_limit=SIZEOF(property)) AND (constraint.ref_property_set_type.identifier='EQ')) OR ((constraint.use_limit>SIZEOF(property)) AND (constraint.ref_property_set_type.identifier='LE'))) ) THEN RETURN (FALSE); END_IF; END_IF; -- Make sure each property is allowed by the constraint. REPEAT i := LOINDEX(property) TO HIINDEX(property); IF ( SIZEOF(QUERY( comp <* constraint.component_kind | property[i] = comp.property_kind ))=0 ) THEN RETURN (FALSE); END_IF; END_REPEAT; END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION sample_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; system : coordinate_system; coordinate_leaf : LIST OF emi_geometry_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the sample values are not valid. -- Check the validity of the property leaf. IF ( NOT leaf_property_valid(1,tuple_count,property_constraint, property_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the units match what is allowed by the CS axes. IF ( NOT geometry_coord_valid( system, coordinate_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'random') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION line_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; grid1 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; system : coordinate_system; coord_leaf : LIST OF emi_geometry_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the line values are not valid. -- Check the validity of the property leaf. IF ( NOT leaf_property_valid(grid1.dimension_count,tuple_count, property_constraint,property_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the descriptor and index_leaf are valid. IF ( NOT geometry_descriptor_valid (tuple_count,grid1,descriptor, index_leaf,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the units match what is allowed by the CS axes. IF ( NOT geometry_coord_valid (system,coordinate_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. IF ( grid1.dimension_count<>1 ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( grid1.grid_type<>emi_grid_type.regular ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'grid1d') AND (rep_constraint<>'grid1to2d') AND (rep_constraint<>'grid') ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION isoline_set_valid ( rep_constraint : STRING; position_constraint : STRING(80); coord_constraint : STRING(80); system : coordinate_system ; prop_kind : property_kind; value_unit : ref_unit_of_measure; isoline : SET OF emi_isoline ) : BOOLEAN; -- Return FALSE if the isoline set is not valid. LOCAL uom : LIST[0:?] OF ref_unit_of_measure; sys_1d : simple_coordinate_system; sys_nd : simple_coordinate_system; first : INTEGER; found : BOOLEAN; END_LOCAL; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'contour')) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; -- The system must be compound. IF ( SIZEOF(QUERY( tmp <* TYPEOF(system) | tmp LIKE '*COMPOUND_COORDINATE_SYSTEM*' ))<>1 ) THEN RETURN (FALSE); END_IF; -- The dimensionality of the compound system must be greater than or equal to 3D. IF ( (SIZEOF(system.first_system.coordinate_system_axis) + SIZEOF(system.second_system.coordinate_system_axis)) < 3 ) THEN RETURN (FALSE); END_IF; -- Find each component system. IF ( SIZEOF(system.second_system.coordinate_system_axis)=1) THEN sys_nd := system.first_system; sys_1d := system.second_system; ELSE IF ( SIZEOF(system.first_system.coordinate_system_axis)=1) THEN sys_1d := system.first_system; sys_nd := system.second_system; ELSE -- At least one component must be 1D. RETURN (FALSE); END_IF; END_IF; -- Each isoline must use the Nd component of the compound system. REPEAT i := LOINDEX(isoline) TO HIINDEX(isoline); IF (isoline[i].line_geometry.system <> sys_nd) THEN RETURN (FALSE); END_IF; END_REPEAT; -- Each isoline must specify the same properties. first := LOINDEX(isoline); REPEAT i := first+1 TO HIINDEX(isoline); -- Iterate over the properties for this isoline. REPEAT j := LOINDEX(isoline[i].property_leaf) TO HIINDEX(isoline[i].property_leaf); -- Compare the property to those for the first isoline. found := FALSE; REPEAT k := LOINDEX(isoline[first].property_leaf) TO HIINDEX(isoline[first].property_leaf); IF ( isoline[i].line_geometry.property_leaf[j].kind = isoline[first].line_geometry.property_leaf[k].kind ) THEN found := TRUE; ESCAPE; END_IF; END_REPEAT; IF (NOT found) THEN RETURN (FALSE); END_IF; END_REPEAT; END_REPEAT; -- The property must match the 1D component of the compound system. IF ( prop_kind <> sys_1d.coordinate_system_axis.property_kind ) THEN RETURN (FALSE); END_IF; -- The unit must conform to the 1D component of the compound system. uom[1] := value_unit; IF ( NOT coordinate_units_valid (sys_1d,uom) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION surface_grid_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; grid1 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; system : coordinate_system; coord_leaf : LIST OF emi_geometry_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the (gridded) surface values are not valid. -- Check the validity of the property leaf. IF ( NOT leaf_property_valid (grid1.dimension_count,tuple_count, property_constraint,property_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the descriptor and index_leaf are valid. IF ( NOT geometry_descriptor_valid (tuple_count,grid1,descriptor, index_leaf,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the units match what is allowed by the CS axes. IF ( NOT geometry_coord_valid (system,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. IF ( (grid1.dimension_count<>2) ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( (grid1.grid_type<>emi_grid_type.regular) AND (grid1.grid_type<>emi_grid_type.trimesh) ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'grid2d') AND (rep_constraint<>'trimesh') AND (rep_constraint<>'grid1to2d') AND (rep_constraint<>'grid') ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( ((rep_constraint='grid2d') AND (grid1.grid_type<>emi_grid_type.regular)) OR ((rep_constraint='trimesh') AND (grid1.grid_type<>emi_grid_type.trimesh)) OR ((rep_constraint='grid1to2d') AND (grid1.grid_type<>emi_grid_type.regular)) OR ((rep_constraint='grid') AND (grid1.grid_type<>emi_grid_type.regular)) ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION volume_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; grid1 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; system : coordinate_system; coord_leaf : LIST OF emi_geometry_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the volume values are not valid. -- Check the validity of the property leaf. IF ( NOT leaf_property_valid (grid1.dimension_count,tuple_count, property_constraint,property_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the descriptor and index_leaf are valid. IF ( NOT geometry_descriptor_valid (tuple_count,grid1,descriptor, index_leaf, coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the units match what is allowed by the CS axes. IF ( NOT geometry_coord_valid (system,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. IF ( (grid1.dimension_count<>3) ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( (grid1.grid_type<>emi_grid_type.regular) AND (grid1.grid_type<>emi_grid_type.unstructured_3d) AND (grid1.grid_type<>emi_grid_type.cornerpoint) ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'grid3d') AND (rep_constraint<>'grid') AND (rep_constraint<>'unstructured_3d') AND (rep_constraint<>'cornerpoint') ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( ((rep_constraint='grid3d') AND (grid1.grid_type<>emi_grid_type.regular)) OR ((rep_constraint='grid') AND (grid1.grid_type<>emi_grid_type.regular)) OR ((rep_constraint='unstructured_3d') AND (grid1.grid_type<>emi_grid_type.unstructured_3d)) OR ((rep_constraint='cornerpoint') AND (grid1.grid_type<>emi_grid_type.cornerpoint)) ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION hypercell_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; grid1 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; system : coordinate_system; coord_leaf : LIST OF emi_geometry_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the hypercell values are not valid. -- Check the validity of the property leaf. IF ( NOT leaf_property_valid (grid1.dimension_count,tuple_count, property_constraint,property_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the descriptor and index_leaf are valid. IF ( NOT geometry_descriptor_valid (tuple_count,grid1, descriptor,index_leaf,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Insure that the units match what is allowed by the CS axes. IF ( NOT geometry_coord_valid (system,coord_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. IF ( grid1.dimension_count>3 ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( grid1.grid_type<>emi_grid_type.regular ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. IF ( (position_constraint<>'') AND (position_constraint<>'node') ) THEN RETURN (FALSE); END_IF; -- Check the coordinate system constraint. IF ( (coord_constraint<>'') AND (coord_constraint<>system.ref_coordinate_sys_constraint.identifier) ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'grid') AND (rep_constraint<>'gridhyper') AND (rep_constraint<>'grid4D') AND (rep_constraint<>'grid5D') AND (rep_constraint<>'grid6D') AND (rep_constraint<>'grid7D') AND (rep_constraint<>'grid8D') AND (rep_constraint<>'grid9D') AND (rep_constraint<>'grid10D') AND (rep_constraint<>'grid11D') AND (rep_constraint<>'grid12D') AND (rep_constraint<>'grid13D') AND (rep_constraint<>'grid14D') AND (rep_constraint<>'grid15D') ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. IF ( ((rep_constraint='grid') AND (grid1.dimension_count<4)) OR ((rep_constraint='gridhyper') AND (grid1.dimension_count<4)) OR ((rep_constraint='grid4D') AND (grid1.dimension_count<>4)) OR ((rep_constraint='grid5D') AND (grid1.dimension_count<>5)) OR ((rep_constraint='grid6D') AND (grid1.dimension_count<>6)) OR ((rep_constraint='grid7D') AND (grid1.dimension_count<>7)) OR ((rep_constraint='grid8D') AND (grid1.dimension_count<>8)) OR ((rep_constraint='grid9D') AND (grid1.dimension_count<>9)) OR ((rep_constraint='grid10D') AND (grid1.dimension_count<>10)) OR ((rep_constraint='grid11D') AND (grid1.dimension_count<>11)) OR ((rep_constraint='grid12D') AND (grid1.dimension_count<>12)) OR ((rep_constraint='grid13D') AND (grid1.dimension_count<>13)) OR ((rep_constraint='grid14D') AND (grid1.dimension_count<>14)) OR ((rep_constraint='grid15D') AND (grid1.dimension_count<>15)) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION element_valid ( rep_constraint : STRING(80); position_constraint : STRING(80); coord_constraint : STRING(80); coord_precision : INTEGER; property_constraint : STRING(80); property_precision : INTEGER; tuple_count : INTEGER; grid1 : emi_grid; geom1 : emi_geom_relationship; grid2 : emi_grid; geom2 : emi_geom_relationship; sparse_flag : BOOLEAN; value_connection : emi_index_type; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return false if the element values are not valid. LOCAL cnt : INTEGER; pos : STRING; END_LOCAL; -- If one is given, then both must be given. IF ( EXISTS(geom2) <> EXISTS(grid2) ) THEN RETURN (FALSE); END_IF; -- Check the property constraint. IF ( property_constraint='none' ) THEN RETURN (FALSE); END_IF; -- Check the validity of the property leaf. IF ( NOT leaf_property_valid (grid1.dimension_count,tuple_count, property_constraint,property_leaf )) THEN RETURN (FALSE); END_IF; -- Check the validity of the descriptor and the index leaf. IF ( NOT element_descriptor_valid (tuple_count,sparse_flag, grid1,grid2,value_connection,descriptor,index_leaf) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. cnt := grid1.dimension_count; IF ( ((cnt=1) AND (grid1.grid_type<>emi_grid_type.regular)) OR ((cnt=2) AND ((grid1.grid_type<>emi_grid_type.regular) AND (grid1.grid_type<>emi_grid_type.trimesh))) OR ((cnt=3) AND ((grid1.grid_type<>emi_grid_type.regular) AND (grid1.grid_type<>emi_grid_type.unstructured_3d) AND (grid1.grid_type<>emi_grid_type.cornerpoint))) OR ((cnt>3) AND (grid1.grid_type<>emi_grid_type.regular)) ) THEN RETURN (FALSE); END_IF; -- Check the position constraint. pos := position_constraint; IF ( (pos<>'') AND (pos<>'node') AND (pos<>'edge') AND (pos<>'face') AND (pos<>'cell') AND (pos<>'hyper4') AND (pos<>'hyper5') AND (pos<>'hyper6') AND (pos<>'hyper7') AND (pos<>'hyper8') AND (pos<>'hyper9') AND (pos<>'hyper10') AND (pos<>'hyper11') AND (pos<>'hyper12') AND (pos<>'hyper13') AND (pos<>'hyper14') AND (pos<>'hyper15') ) THEN RETURN (FALSE); END_IF; IF ( ((pos='node') AND (value_connection<>emi_index_type.INDEX_NODE)) OR ((pos='edge') AND (value_connection<>emi_index_type.INDEX_EDGE)) OR ((pos='face') AND (value_connection<>emi_index_type.INDEX_FACE)) OR ((pos='cell') AND (value_connection<>emi_index_type.INDEX_CELL)) OR ((pos='hyper4') AND (value_connection<>emi_index_type.INDEX_4)) OR ((pos='hyper5') AND (value_connection<>emi_index_type.INDEX_5)) OR ((pos='hyper6') AND (value_connection<>emi_index_type.INDEX_6)) OR ((pos='hyper7') AND (value_connection<>emi_index_type.INDEX_7)) OR ((pos='hyper8') AND (value_connection<>emi_index_type.INDEX_8)) OR ((pos='hyper9') AND (value_connection<>emi_index_type.INDEX_9)) OR ((pos='hyper10') AND (value_connection<>emi_index_type.INDEX_10)) OR ((pos='hyper11') AND (value_connection<>emi_index_type.INDEX_11)) OR ((pos='hyper12') AND (value_connection<>emi_index_type.INDEX_12)) OR ((pos='hyper13') AND (value_connection<>emi_index_type.INDEX_13)) OR ((pos='hyper14') AND (value_connection<>emi_index_type.INDEX_14)) OR ((pos='hyper15') AND (value_connection<>emi_index_type.INDEX_15)) ) THEN RETURN (FALSE); END_IF; -- Check the representation constraint. IF ( (rep_constraint<>'') AND (rep_constraint<>'trimesh') AND (rep_constraint<>'unstructured_3d') AND (rep_constraint<>'cornerpoint') AND (rep_constraint<>'grid1to2d') AND (rep_constraint<>'grid1to2d') AND (rep_constraint<>'grid') AND (rep_constraint<>'gridhyper') AND (rep_constraint<>'grid1d') AND (rep_constraint<>'grid2d') AND (rep_constraint<>'grid3d') AND (rep_constraint<>'grid4d') AND (rep_constraint<>'grid5d') AND (rep_constraint<>'grid6d') AND (rep_constraint<>'grid7d') AND (rep_constraint<>'grid8d') AND (rep_constraint<>'grid9d') AND (rep_constraint<>'grid10d') AND (rep_constraint<>'grid11d') AND (rep_constraint<>'grid12d') AND (rep_constraint<>'grid13d') AND (rep_constraint<>'grid14d') AND (rep_constraint<>'grid15d') ) THEN RETURN (FALSE); END_IF; -- Check the instantiated representation. IF ( ((rep_constraint='trimesh') AND (grid1.grid_type=emi_grid_type.trimesh)) OR ((rep_constraint='unstructured_3d') AND (grid1.grid_type=emi_grid_type.unstructured_3d)) OR ((rep_constraint='cornerpoint') AND (grid1.grid_type=emi_grid_type.cornerpoint)) OR ((rep_constraint LIKE 'grid*') AND (grid1.grid_type=emi_grid_type.regular)) ) THEN RETURN (FALSE); END_IF; -- Check the dimensionality of the grid. cnt := grid1.dimension_count; IF ( (cnt<1) OR ((rep_constraint='trimesh') AND (cnt<>2)) OR ((rep_constraint='unstructured_3d') AND (cnt<>3)) OR ((rep_constraint='cornerpoint') AND (cnt<>3)) OR ((rep_constraint='grid1to2d') AND (cnt>2)) OR ((rep_constraint='grid1to2d') AND (cnt>2)) OR ((rep_constraint='grid') AND (cnt<1)) OR ((rep_constraint='gridhyper') AND (cnt<4)) OR ((rep_constraint='grid1d') AND (cnt<>1)) OR ((rep_constraint='grid2d') AND (cnt<>2)) OR ((rep_constraint='grid3d') AND (cnt<>3)) OR ((rep_constraint='grid4d') AND (cnt<>4)) OR ((rep_constraint='grid5d') AND (cnt<>5)) OR ((rep_constraint='grid6d') AND (cnt<>6)) OR ((rep_constraint='grid7d') AND (cnt<>7)) OR ((rep_constraint='grid8d') AND (cnt<>8)) OR ((rep_constraint='grid9d') AND (cnt<>9)) OR ((rep_constraint='grid10d') AND (cnt<>10)) OR ((rep_constraint='grid11d') AND (cnt<>11)) OR ((rep_constraint='grid12d') AND (cnt<>12)) OR ((rep_constraint='grid13d') AND (cnt<>13)) OR ((rep_constraint='grid14d') AND (cnt<>14)) OR ((rep_constraint='grid15d') AND (cnt<>15)) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION geometry_coord_valid ( system : coordinate_system ; coords : LIST OF emi_geometry_leaf ) : BOOLEAN; -- Return FALSE if the units do not match what is allowed by the axes. LOCAL uom : LIST[0:?] OF ref_unit_of_measure; END_LOCAL; REPEAT i := LOINDEX(coords) TO HIINDEX(coords); uom[i] := coords[i].ordinal_unit; END_REPEAT; IF ( NOT coordinate_units_valid (system,uom) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION geometry_descriptor_valid (tuple_count : INTEGER; grid1 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf; coordinate_leaf : LIST OF emi_geometry_leaf ) : BOOLEAN; -- Return TRUE if the descriptor and index_leaf appear to be valid. LOCAL sparse_flag : boolean := FALSE; partial_allowed : boolean := FALSE; grid2 : emi_grid; -- Always NULL for everything but element. END_LOCAL; -- Check the validity of all non-geometry aspects. IF ( NOT descriptor_valid (tuple_count, emi_index_type.INDEX_NODE, sparse_flag, partial_allowed, grid, grid2, descriptor, index_leaf) ) THEN RETURN (FALSE); END_IF; -- Only one grid is allowed for geometries. REPEAT i := LOINDEX(index_leaf) TO HIINDEX(index_leaf); IF ( index_leaf[i].grid_number<>1 ) THEN RETURN (FALSE); END_IF; END_REPEAT; -- The number of coordinate system axes must be greater than or equal -- to the number of dimensions of the grid. IF ( SIZEOF(coordinate_leaf) < grid1.dimension_count ) THEN RETURN (FALSE); END_IF; -- The number of coordinate values must equal the expected value count. REPEAT i := LOINDEX(coordinate_leaf) TO HIINDEX(coordinate_leaf); IF ( SIZEOF(QUERY( tmp <* TYPEOF(coordinate_leaf[i]) | tmp LIKE '*EMI_GEOMETRY_LEAF_VARIABLE*' ))<>0 ) THEN -- Each node gets a value. IF ( SIZEOF(coordinate_leaf[i].ordinal_values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ELSE IF ( SIZEOF(QUERY( tmp <* TYPEOF(coordinate_leaf[i]) | tmp LIKE '*EMI_GEOMETRY_LEAF_UNEQUAL*' ))<>0 ) THEN -- Unequal step based on grid index. REPEAT j := LOINDEX(descriptor) TO HIINDEX(descriptor); -- Check the value count against the appropriate grid axis. IF ( descriptor[j].dimension=coordinate_leaf[i].unequal_index ) THEN IF ( SIZEOF(coordinate_leaf[i].ordinal_values) <> descriptor[J].count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; END_REPEAT; ELSE -- Equal step based on grid index. IF ( SIZEOF(coordinate_leaf[i].step)>grid1.dimension_count ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; FUNCTION descriptor_valid (tuple_count : INTEGER; connection_type : emi_index_type; sparse_flag : BOOLEAN; partial_allowed : BOOLEAN; grid1 : emi_grid; grid2 : emi_grid; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf ) : BOOLEAN; -- Return TRUE if the descriptor or index leaf is valid. -- Parameter partial_allowed indicates whether the value count must -- match the grid count. TRUE indicates no. LOCAL idx : INTEGER; index_type : SET[1:?] OF emi_index_type; index2_type : SET[1:?] OF emi_index_type; -- Correspondence of index type to axis order. -- That is, the first axis is index "i". axis_index : LIST[1:15] OF UNIQUE emi_index_type := [emi_index_type.INDEX_I, emi_index_type.INDEX_J, emi_index_type.INDEX_K, emi_index_type.INDEX_L, emi_index_type.INDEX_M, emi_index_type.INDEX_N, emi_index_type.INDEX_O, emi_index_type.INDEX_P, emi_index_type.INDEX_Q, emi_index_type.INDEX_R, emi_index_type.INDEX_S, emi_index_type.INDEX_T, emi_index_type.INDEX_U, emi_index_type.INDEX_V, emi_index_type.INDEX_W]; -- Correspondence of index type to element dimensionality. -- That is, the lowest dimensional element is "node". elem_index : LIST[1:16] OF UNIQUE emi_index_type := [emi_index_type.INDEX_NODE, emi_index_type.INDEX_EDGE, emi_index_type.INDEX_FACE, emi_index_type.INDEX_CELL, emi_index_type.INDEX_4, emi_index_type.INDEX_5, emi_index_type.INDEX_6, emi_index_type.INDEX_7, emi_index_type.INDEX_8, emi_index_type.INDEX_9, emi_index_type.INDEX_10, emi_index_type.INDEX_11, emi_index_type.INDEX_12, emi_index_type.INDEX_13, emi_index_type.INDEX_14, emi_index_type.INDEX_15]; END_LOCAL; IF ( (NOT sparse_flag) AND EXISTS(grid2) ) THEN -- A second grid requires a sparse representation. RETURN (FALSE); END_IF; -- Compare the tuple count against the number of values allowed by the grid. IF ( NOT tuple_count_valid (tuple_count,connection_type, partial_allowed,grid,grid2,elem_index) ) THEN RETURN (FALSE); END_IF; -- Distinguish between the two different scenarios. IF ( EXISTS(descriptor) ) THEN -- Dense population in one regular grid. IF ( sparse_flag OR ((grid1.grid_type<>emi_grid_type.regular) AND (grid1.grid_type<>emi_grid_type.cornerpoint)) ) THEN RETURN (FALSE); END_IF; REPEAT i := LOINDEX(descriptor) TO LOINDEX(descriptor); -- Needed for next function call. index_type[i] := descriptor[i].dimension; END_REPEAT; IF ( NOT index_type_valid (grid1.grid_type, connection_type, grid1.dimension_count, index_type, axis_index, elem_index) ) THEN RETURN (FALSE); END_IF; -- Compare the number of tuples specified by the descriptor against -- the number of tuples allowed by the grid and the connection element. REPEAT i := LOINDEX(descriptor) TO HIINDEX(descriptor); -- The index count cannot be greater than the number of points on the -- corresponding grid axis. -- This check excludes the grid-element indices. REPEAT j := LOINDEX(axis_index) TO (LOINDEX(axis_index)+grid1.dimension_count-1); IF ( descriptor[i].dimension=axis_index[j] ) THEN -- Found the corresponding axis. IF ( partial_allowed ) THEN IF ( descriptor[i].count > grid1.grid_axis_point_count[j] ) THEN RETURN (FALSE); END_IF; IF ( descriptor[i].lower_bound < grid1.grid_axis_lower_bound[j] ) THEN RETURN (FALSE); END_IF; ELSE IF ( descriptor[i].count <> grid1.grid_axis_point_count[j] ) THEN RETURN (FALSE); END_IF; IF ( descriptor[i].lower_bound <> grid1.grid_axis_lower_bound[j] ) THEN RETURN (FALSE); END_IF; END_IF; ESCAPE; END_IF; END_REPEAT; -- The number of values cannot be greater than the maximum count -- of any "grid element" for this dimension. REPEAT j := LOINDEX(elem_index) TO (LOINDEX(elem_index)+grid1.dimension_count); IF ( descriptor[i].dimension=elem_index[j] ) THEN -- Found a connection grid-element. IF ( partial_allowed ) THEN IF ( descriptor[i].count > max_count(grid1.grid_type,descriptor[i].dimension, grid1.dimension_count, elem_index) ) THEN RETURN (FALSE); END_IF; ELSE IF ( descriptor[i].count <> max_count(grid1.grid_type,descriptor[i].dimension, grid1.dimension_count, elem_index) ) THEN RETURN (FALSE); END_IF; END_IF; ESCAPE; END_IF; END_REPEAT; END_REPEAT; ELSE -- Irregular grid or sparse population of regular grid. IF ( NOT EXISTS(index_leaf) ) THEN RETURN (FALSE); END_IF; idx := 0; REPEAT i := LOINDEX(index_leaf) TO HIINDEX(index_leaf); -- The number of index values must equal the expected value count. IF ( SIZEOF(index_leaf[i].data_values) <> tuple_count ) THEN RETURN (FALSE); END_IF; -- Specific to first grid. IF ( index_leaf[i].grid_number=1 ) THEN -- Check the leaf index values against what is allowed by the regular grid. IF ( NOT index_leaf_valid(grid1,index_leaf[i], axis_index,elem_index) ) THEN RETURN (FALSE); END_IF; -- Needed for next function call. idx := idx +1; index_type[idx] := index_leaf[i].index_name; END_IF; END_REPEAT; -- Insure that the index types are valid for the first grid. IF ( NOT index_type_valid (grid1.grid_type, connection_type, grid1.dimension_count, index_type, axis_index, elem_index) ) THEN RETURN (FALSE); END_IF; IF ( EXISTS (grid2) ) THEN idx := 0; REPEAT i := LOINDEX(index_leaf) TO HIINDEX(index_leaf); IF ( index_leaf[i].grid_number=2 ) THEN -- Check the index values against what is allowed by the grid. IF ( NOT index_leaf_valid(grid2,index_leaf[i], axis_index,elem_index) ) THEN RETURN (FALSE); END_IF; -- Needed for next function call. idx := idx +1; index2_type[idx] := index_leaf[i].index_name; END_IF; END_REPEAT; -- Insure that the index types are valid for the second grid. IF ( NOT index_type_valid (grid2.grid_type, connection_type, grid2.dimension_count, index2_type, axis_index, elem_index) ) THEN RETURN (FALSE); END_IF; END_IF; -- Insure that the index tuples are all unique. -- Note that this check also works for the combination of grid1 and grid2. -- That is, either the grid1 tuple is unique or the combination of -- grid1 and grid2 tuples are unique. IF ( NOT index_tuples_valid (index_leaf) ) THEN RETURN (FALSE); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION index_leaf_valid (grid : emi_grid; index_leaf : emi_index_leaf; axis_index : LIST OF emi_index_type; elem_index : LIST OF emi_index_type ) : BOOLEAN; -- Return TRUE if the index leaf "index values" are valid. -- axis_index is the correspondence of index type to axis order. -- That is, the first axis is index "i". -- elem_index is the correspondence of index type to element dimensionality. -- That is, the lowest dimensional element is "node". LOCAL max : INTEGER; END_LOCAL; IF ( (grid.grid_type<>emi_grid_type.regular) AND (grid.grid_type<>emi_grid_type.cornerpoint) ) THEN; -- Not a regular grid. RETURN(TRUE); END_IF; -- Check against grid axis first. REPEAT i := LOINDEX(axis_index) TO LOINDEX(axis_index)+grid.dimension_count-1; IF ( index_leaf.index_name=axis_index[i] ) THEN -- Found the corresponding axis. max := grid.grid_axis_lower_bound[i] +grid_axis_point_count[i] -1; REPEAT j := LOINDEX(index_leaf.data_values) TO HIINDEX(index_leaf.data_values); IF ( index_leaf.data_values[j] > max ) THEN RETURN(FALSE); END_IF; END_REPEAT; RETURN(TRUE); END_IF; END_REPEAT; -- Does not represent a grid axis. -- Check against the possible grid elements. REPEAT i := LOINDEX(elem_index) TO LOINDEX(elem_index)+grid.dimension_count; IF ( index_leaf.index_name=elem_index[i] ) THEN -- This is a valid grid element. max := max_count(grid.grid_type,index_leaf.index_name, grid.dimension_count, elem_index); REPEAT j := LOINDEX(index_leaf.data_values) TO HIINDEX(index_leaf.data_values); IF ( index_leaf.data_values[j] > max ) THEN RETURN(FALSE); END_IF; END_REPEAT; RETURN(TRUE); END_IF; END_REPEAT; -- Neither a valid grid axis index nor a valid grid element index. RETURN (FALSE); END_FUNCTION; FUNCTION index_tuples_valid (index_leaf : SET OF emi_index_leaf ) : BOOLEAN; -- Return TRUE if the index tuples are unique. -- This assumes that the bounds of index aggregates are the same. LOCAL tuple : LIST OF INTEGER; start : INTEGER; stop : INTEGER; END_LOCAL; start := LOINDEX(index_leaf[LOINDEX(index_leaf)].data_values); stop := LOINDEX(index_leaf[LOINDEX(index_leaf)].data_values); REPEAT i := start TO stop; tuple := next_tuple(i,index_leaf); REPEAT j := start TO stop; IF ( j<>i ) THEN IF ( tuple = next_tuple(j,index_leaf) ) THEN RETURN(FALSE); END_IF; END_IF; END_REPEAT; END_REPEAT; RETURN (TRUE); END_FUNCTION; FUNCTION next_tuple (ix : INTEGER; index_leaf : SET OF emi_index_leaf ) : LIST of INTEGER; -- Returns ix'th tuple from the set of demultiplexed leaf values. -- This assumes that all aggregates have the same lower index. LOCAL tuple : LIST OF INTEGER; END_LOCAL; REPEAT i := LOINDEX(index_leaf) TO HIINDEX(index_leaf); tuple[i] := index_leaf[i].data_values[ix]; END_REPEAT; RETURN (tuple); END_FUNCTION; FUNCTION tuple_count_valid (tuple_count : INTEGER; connection_type : emi_index_type; partial_allowed : BOOLEAN; grid1 : emi_grid; grid2 : emi_grid; elem_index : LIST OF emi_index_type ) : BOOLEAN; -- Return TRUE if the tuple count is valid when compared against the grid. -- Parameter partial_allowed indicates whether the value count must -- match the grid count. TRUE indicates no. -- elem_index is the correspondence of index type to element dimensionality. -- That is, the lowest dimensional element is "node". LOCAL grid_cnt : INTEGER; grid2_cnt : INTEGER; END_LOCAL; -- Determine the maximum number of tuples allowed by the grid -- and the grid connection. IF ( (grid1.grid_type=emi_grid_type.regular) OR (grid1.grid_type=emi_grid_type.cornerpoint) ) THEN -- regular grid. -- First check the grid. grid_cnt := 1; REPEAT i := LOINDEX(grid1.grid_axis_point_count) TO HIINDEX(grid1.grid_axis_point_count); grid_cnt := grid_cnt * grid1.grid_axis_point_count[i]; END_REPEAT; IF ( grid_cnt<>grid1.node_count ) THEN RETURN (FALSE); END_IF; -- Add any space for grid elements. IF ( ((grid1.grid_type=emi_grid_type.cornerpoint) AND (connection_type=elem_index[1])) OR ((grid1.grid_type<>emi_grid_type.cornerpoint) AND ((connection_type<>elem_index[1]) AND (connection_type<>elem_index[grid1.dimension_count+1]))) ) THEN -- Need space for the grid-element index. grid_cnt := grid_cnt * max_count(grid1.grid_type,connection_type, grid1.dimension_count, elem_index); END_IF; ELSE -- Irregular grid. grid_cnt := grid1.node_count; END_IF; IF ( EXISTS (grid2) ) THEN -- Determine the total number of points on the second grid. IF ( grid2.grid_type=emi_grid_type.regular ) THEN -- regular grid. -- First check the grid. grid2_cnt := 1; REPEAT i := LOINDEX(grid2.grid_axis_point_count) TO HIINDEX(grid2.grid_axis_point_count); grid2_cnt := grid2_cnt * grid2.grid_axis_point_count[i]; END_REPEAT; IF ( grid2_cnt<>grid2.node_count ) THEN RETURN (FALSE); END_IF; -- Add any space for grid elements. IF ( ((grid2.grid_type=emi_grid_type.cornerpoint) AND (connection_type=elem_index[1])) OR ((grid2.grid_type<>emi_grid_type.cornerpoint) AND ((connection_type<>elem_index[1]) AND (connection_type<>elem_index[grid1.dimension_count+1]))) ) THEN -- Need space for the grid-element index. grid2_cnt := grid2_cnt * max_count(grid2.grid_type,connection_type, grid2.dimension_count, elem_index); END_IF; ELSE -- Irregular grid. grid2_cnt := grid1.node_count; END_IF; IF ( grid2_cnt < grid_count) THEN -- We need the minimum size of a grid. grid_cnt := grid2_count; END_IF; END_IF; IF ( partial_allowed ) THEN -- The number of values cannot be greater than the number of points on the grid. IF ( tuple_count > grid_cnt ) THEN RETURN (FALSE); END_IF; ELSE -- The number of values must equal the number of points on the grid. IF ( tuple_count <> grid_cnt ) THEN RETURN (FALSE); END_IF; END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION index_type_valid (grid_type : emi_grid_type; connection_type : emi_index_type; dimension_count : INTEGER; index_type : SET OF emi_index_type; axis_index : LIST OF emi_index_type; elem_index : LIST OF emi_index_type ) : BOOLEAN; -- Return TRUE if the index type is valid. -- It is assumed that the parameters all apply to one grid. -- axis_index = Correspondence of index type to regular grid axis order. -- For example, the first axis is INDEX_I. -- elem_index = Correspondence of index type to element dimensionality. -- For example, the lowest dimensional element is INDEX_NODE. LOCAL found : BOOLEAN; idx : INTEGER; index_type : SET[1:?] OF emi_index_type; END_LOCAL; -- Check the number of index types and the allowed types. -- This combination inherently results in a failure for types -- which are not allowed. -- Make sure the connection type is valid for this dimension. REPEAT i := LOINDEX(elem_index) TO LOINDEX(elem_index)+dimension_count; IF ( connection_type=elem_index[i] ) THEN found := TRUE; ESCAPE; END_IF; END_REPEAT; IF ( NOT found ) THEN RETURN (FALSE); END_IF; -- Check for the irregular grids. IF ( (grid_type = emi_grid_type.trimesh) OR (grid_type = emi_grid_type.unstructured_3d) ) THEN -- These irregular grids only utilize one index. IF ( SIZEOF(index_type)<>1 ) THEN RETURN (FALSE); END_IF; IF ( connection_type<>index_type[LOINDEX(index_type)] ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_IF; -- Regular grid. In general, the node and the highest dimensional element is -- referenced by the i,j,k indexes with an additional index if connecting to -- the other "elements" (e.g., edge or face). IF ( grid_type=emi_grid_type.cornerpoint ) THEN -- Corner point is different because the node element is required -- when the connection type is node. IF (connection_type=emi_index_type.INDEX_FACE) THEN IF ( SIZEOF(index_type)<>dimension_count ) THEN RETURN (FALSE); END_IF; ELSE IF ( SIZEOF(index_type)<>(dimension_count+1) ) THEN RETURN (FALSE); END_IF; IF ( (SIZEOF(QUERY ( tmp <* index_type | tmp=connection_type ))<>1) ) THEN RETURN (FALSE); END_IF; END_IF; ELSE -- Not cornerpoint. IF ( (connection_type=emi_index_type.INDEX_NODE) or (connection_type=elem_index[LOINDEX(elem_index)+dimension_count]) ) THEN IF ( SIZEOF(index_type)<>(dimension_count) ) THEN RETURN (FALSE); END_IF; ELSE IF ( SIZEOF(index_type)<>dimension_count+1 ) THEN -- Need an index for the "other" element. RETURN (FALSE); END_IF; IF ( (SIZEOF(QUERY ( tmp <* index_type | tmp=connection_type ))<>1) ) THEN RETURN (FALSE); END_IF; END_IF; END_IF; -- For a regular grid, there must be one and only one unique index -- type for each axis. REPEAT i := LOINDEX(axis_index) TO (LOINDEX(axis_index)+dimension_count-1); IF ( (SIZEOF(QUERY ( tmp <* index_type | tmp=axis_index[i] ))<>1) ) THEN RETURN (FALSE); END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; FUNCTION dms_valid (degree_value : INTEGER; minute_value : INTEGER; second_value : REAL ) : BOOLEAN; -- Return false if the dms values are not valid. (*The following are enforced by the meta type. IF ( EXISTS(degree_value)<>EXISTS(minute_value) THEN RETURN(FALSE); END_IF; IF ( EXISTS(degree_value)<>EXISTS(second_value) THEN RETURN(FALSE); END_IF; *) IF NOT( ((degree_value <= 0) AND (minute_value <= 0) AND (second_value <= 0)) OR ((degree_value >= 0) AND (minute_value >= 0) AND (second_value >= 0)) ) THEN -- Must be same sign. RETURN(FALSE); END_IF; IF ( ABS(minute_value) > 59 ) THEN RETURN(FALSE); END_IF; IF ( ABS(second_value) >= 60 ) THEN RETURN(FALSE); END_IF; RETURN(TRUE); END_FUNCTION; FUNCTION max_count (grid_type : emi_grid_type; index_type : emi_index_type; dimension_count : INTEGER; elem_index : LIST OF emi_index_type ) : INTEGER; -- Return the upper bound for indices specified for the index type and dimension. -- The upper bound will always be 1 for node and for the highest dimensional -- element. The exception is that corner point node will be 8. -- elem_index = Correspondence of index type to element dimensionality. -- For example, the lowest dimensional element is INDEX_NODE. LOCAL ele_dim : INTEGER; -- The dimensionality of the element (index_type). count : INTEGER; END_LOCAL; IF ( grid_type=emi_grid_type.cornerpoint ) THEN IF ( index_type=emi_index_type.INDEX_NODE ) THEN RETURN (8); END_IF; IF ( index_type=emi_index_type.INDEX_EDGE ) THEN RETURN (12); END_IF; IF ( index_type=emi_index_type.INDEX_FACE ) THEN RETURN (6); END_IF; IF ( index_type=emi_index_type.INDEX_CELL ) THEN RETURN (1); END_IF; RETURN (0); END_IF; REPEAT i := LOINDEX(elem_index) TO (LOINDEX(elem_index)+dimension_count); IF ( index_type=elem_index[i] ) THEN -- The first element in the array has dimensionality of zero. ele_dim := i -LOINDEX(elem_index); count := (factorial(dimension_count)) / (factorial(dimension_count-ele_dim) * factorial(ele_dim)); RETURN (count); END_IF; END_REPEAT; RETURN (0); END_FUNCTION; FUNCTION factorial (int_value : INTEGER ) : INTEGER; -- Return the factorial of the specified positive integer. LOCAL i_fact : INTEGER; END_LOCAL; i_fact := 1; REPEAT i :=2 TO int_value BY 1; i_fact := i_fact * i; END_REPEAT; RETURN (i_fact); END_FUNCTION; FUNCTION element_descriptor_valid (tuple_count : INTEGER; sparse_flag : BOOLEAN; grid1 : emi_grid; grid2 : emi_grid; value_connection : emi_index_type; descriptor : LIST OF emi_descriptor; index_leaf : SET OF emi_index_leaf ) : BOOLEAN; -- Return TRUE if the descriptor and index_leaf appear to be valid. LOCAL partial_allowed : BOOLEAN := TRUE; END_LOCAL; -- Check the validity of all non-element aspects. IF ( NOT descriptor_valid (tuple_count, value_connection, sparse_flag, partial_allowed, grid, grid2, descriptor, index_leaf) ) THEN RETURN (FALSE); END_IF; RETURN (TRUE); END_FUNCTION; FUNCTION leaf_property_valid ( dimension_count : INTEGER; tuple_count : INTEGER; property_constraint : STRING ; property_leaf : SET OF emi_property_leaf ) : BOOLEAN; -- Return FALSE if the properties are not allowed by the constraint -- or the value count is not valid. LOCAL prp : SET[0:?] OF property_kind; value_type : SET[0:?] OF STRING; END_LOCAL; IF ( EXISTS(property_leaf) ) THEN REPEAT i := LOINDEX(property_leaf) TO HIINDEX(property_leaf); prp[i] := property_leaf[i].kind; END_REPEAT; END_IF; IF ( NOT property_set_valid (property_constraint,prp) ) THEN RETURN (FALSE); END_IF; IF ( SIZEOF(property_leaf)=0 ) THEN -- Nothing to check. RETURN (TRUE); END_IF; -- The number of property values must equal the expected value count. REPEAT i := LOINDEX(property_leaf) TO HIINDEX(property_leaf); value_type := TYPEOF(property_leaf[i]); IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_QUANTITY_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_quantity_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; -- Check the unit of measure against those allowed by the property kind. IF ( SIZEOF(QUERY( tmp <* kind.quantity_constraint.alternative_unit_of_measure | tmp.unit_of_measure = property_unit ))<>1 ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_REAL_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_real_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_INTEGER_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_integer_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_EQUAL_STEP_VALUES*' ))>0 ) THEN -- Equal step based on grid/list index. IF ( SIZEOF(coordinate_leaf.step)>dimension_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_STRING_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_string_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_BOOLEAN_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_boolean_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_LOGICAL_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_logical_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_COMPLEX_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_complex_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_RATIONAL_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_rational_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_RATIO_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_ratio_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_DMS_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_dms_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_DATE_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_date_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_YEARMONTHINTERVAL_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_yearmonthinterval_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; IF ( SIZEOF(QUERY( tmp <* value_type | tmp LIKE '*EMI_LEAF_DAYTIMEINTERVAL_VALUES*' ))>0 ) THEN IF ( SIZEOF(property_leaf[i]\emi_leaf_yearmonthinterval_values.values) <> tuple_count ) THEN RETURN (FALSE); END_IF; ESCAPE; END_IF; END_REPEAT; RETURN (TRUE); END_FUNCTION; |