This section describes structure types intended primarily for time-dependent flows. Data structures are presented for storing time-dependent or iterative data, and for recording rigid and arbitary grid motion. The section concludes with several examples.
In order to keep a record of time dependent or iterative data, the data structures BaseIterativeData_t and ZoneIterativeData_t are used.
The BaseIterativeData_t data structure is located directly under the CGNSBase_t node. It contains information about the number of time steps or iterations being recorded, and the time and/or iteration values at each step. In addition, it may include the list of zones and families for each step of the simulation, if these vary throughout the simulation.
The BaseIterativeData_t data structure is defined as follows:
BaseIterativeData_t := { int NumberOfSteps (r) DataArray_t<real, 1, NumberOfSteps> TimeValues ; (o/r) DataArray_t<int, 1, NumberOfSteps> IterationValues ; (r/o) DataArray_t<int, 1, NumberOfSteps> NumberOfZones ; (o) DataArray_t<int, 1, NumberOfSteps> NumberOfFamilies ; (o) DataArray_t<char, 3, [65, MaxNumberOfZones, NumberOfSteps]> ZonePointers ; (o) DataArray_t<char, 3, [65, MaxNumberOfFamilies, NumberOfSteps]> FamilyPointers ; (o) List( DataArray_t<> DataArray1 ... DataArrayN ) ; (o) List( Descriptor_t Descriptor1 ... DescriptorN ) ; (o) DataClass_t DataClass ; (o) DimensionalUnits_t DimensionalUnits ; (o) List( UserDefinedData_t UserDefinedData1 ... UserDefinedDataN ) ; (o) }Notes
TimeValues and IterationValues are data-name identifiers corresponding to the time and iteration values stored in the file. When IterationValues are used, the iterative data stored in the database correspond to values at the end of the associated iteration.
The data-name identifiers NumberOfZones and ZonePointers are only used if different zone data structures apply to different steps of the simulation. (See the Adapted Unstructured Mesh example.)
Similarly, if the geometry varies with time or iteration, then the data-name identifiers NumberOfFamilies and FamilyPointers are used to record which Family_t data structure(s) correspond(s) to which step.
The DataArray_t nodes for ZonePointers and FamilyPointers are defined as three-dimensional arrays. For each recorded step, the names of all zones and families being used for the step may be recorded. Note that the names are limited to 65 characters; this is the maximum size of a name of a zone from another base: 32 chars + '/' + 32 chars. Only one '/' character is allowed, then the first token before the '/' is the CGNSBase name and the second token is the Zone or Family name. If no '/' is found, the name is a Zone or a Family name of the current CGNS Base. The variables MaxNumberOfZones and MaxNumberOfFamilies represent the maximum number of zones and families that apply to one step. So if NumberOfSteps = 5 and NumberOfZones = {2,2,3,4,3}, then MaxNumberOfZones equals 4.
When NumberOfZones and NumberOfFamilies vary for different stored time steps, the name Null is used in ZonePointers and FamilyPointers as appropriate for steps in which the NumberOfZones or NumberOfFamilies is less than the MaxNumberOfZones or MaxNumberOfFamilies.
Any number of extra DataArray_t nodes are allowed. These should be used to record data not covered by this specification.
The ZoneIterativeData_t data structure is located under the Zone_t node. It may be used to record pointers to zonal data for each recorded step of the simulation, and is defined as follows:
ZoneIterativeData_t< int NumberOfSteps > := { DataArray_t<char, 2, [32, NumberOfSteps]> RigidGridMotionPointers ; (o) DataArray_t<char, 2, [32, NumberOfSteps]> ArbitraryGridMotionPointers ; (o) DataArray_t<char, 2, [32, NumberOfSteps]> GridCoordinatesPointers ; (o) DataArray_t<char, 2, [32, NumberOfSteps]> FlowSolutionPointers ; (o) DataArray_t<char, 2, [32, NumberOfSteps]> ZoneGridConnectivityPointers ; (o) DataArray_t<char, 2, [32, NumberOfSteps]> ZoneSubRegionPointers ; (o) List( DataArray_t<> DataArray1 ... DataArrayN ) ; (o) List( Descriptor_t Descriptor1 ... DescriptorN ) ; (o) DataClass_t DataClass ; (o) DimensionalUnits_t DimensionalUnits ; (o) List( UserDefinedData_t UserDefinedData1 ... UserDefinedDataN ) ; (o) }Notes
The data arrays with data-name identifiers xxxPointers contain lists of associated data structures for each recorded time value or iteration. These data structures contain data at the associated time value, or at the end of the associated iteration. There is an implied one-to-one correspondence between each pointer (from 1, 2, ..., NumberOfSteps) and the associated TimeValues and/or IterationValues under BaseIterativeData_t. They refer by name to data structures within the current zone. The name Null is used when a particular time or iteration does not have a corresponding data structure to point to.
Any number of extra DataArray_t nodes are allowed. These should be used to record data not covered by this specification.
The ZoneIterativeData_t data structure may not exist without the BaseIterativeData_t under the CGNSBase_t node. However BaseIterativeData_t may exist without ZoneIterativeData_t.
Adding rigid grid motion information to the CGNS file enables an application code to determine the mesh location without the need to alter the original mesh definition recorded under GridCoordinates_t. A data structure named RigidGridMotion_t is used to record the necessary data defining a rigid translation and/or rotation of the grid coordinates.
The rigid grid motion is recorded independently for each zone of the CGNS base. Therefore the RigidGridMotion_t data structure is located under the zone data structure (Zone_t). There may be zero to several RigidGridMotion_t nodes under a Zone_t node. The multiple rigid grid motion definitions may be associated with different iterations or time steps in the computation. This association is recorded under the ZoneIterativeData_t data structure.
RigidGridMotion_t := { List( Descriptor_t Descriptor1 ... DescriptorN ) ; (o) RigidGridMotionType_t RigidGridMotionType ; (r) DataArray_t<real, 2, [PhysicalDimension, 2]> OriginLocation ; (r) DataArray_t<real, 1, PhysicalDimension> RigidRotationAngle ; (o/d) DataArray_t<real, 1, PhysicalDimension> RigidVelocity ; (o) DataArray_t<real, 1, PhysicalDimension> RigidRotationRate ; (o) List( DataArray_t DataArray1 ... DataArrayN ) ; (o) DataClass_t DataClass ; (o) DimensionalUnits_t DimensionalUnits ; (o) List( UserDefinedData_t UserDefinedData1 ... UserDefinedDataN ) ; (o) } ;Notes
RigidGridMotionType_t is an enumeration type that describes the type of rigid grid motion.
RigidGridMotionType_t := Enumeration( RigidGridMotionTypeNull, RigidGridMotionTypeUserDefined, ConstantRate, VariableRate ) ;
The characteristics of the grid motion are defined by the following
data-name identifiers:
Data-Name Identifier | Description | Units | ||
---|---|---|---|---|
OriginLocation | Physical coordinates of the origin before and after the rigid grid motion | L | ||
RigidRotationAngle | Rotation angles about each axis of the translated coordinate system. If rotating about more than one axis, the rotation is performed first about the x-axis, then the y-axis, then the z-axis. If not specified, RigidRotationAngle is set to zero. | α | ||
RigidVelocity | Grid velocity vector of the origin translation | L/T | ||
RigidRotationRate | Rotation rate vector about the axis of the translated coordinate system | α/T | ||
Any number of DataArray_t nodes are allowed. These may be used to record data not covered by this specification.
"Rigid grid motion" implies relative motion of grid zones. However, no attempt is made in the RigidGridMotion_t data structure to require that the ZoneGridConnectivity_t information be updated to be consistent with the new grid locations. Whether the ZoneGridConnectivity_t information refers to the original connectivity (of GridCoordinates) or the latest connectivity (of the moved or deformed grid) is currently left up to the user.
When a grid is in motion, it is often necessary to account for the position of each grid point as the grid deforms. When all grid points move at the same velocity, the grid keeps its original shape. This particular case of grid motion may be recorded under the RigidGridMotion_t data structure. On the other hand, if the grid points have different velocity, the grid is deforming. The ArbitraryGridMotion_t data structure allows the CGNS file to contain information about arbitrary grid deformations. If not present, the grid is assumed to be rigid.
Note that multiple GridCoordinates_t nodes may be stored under a Zone_t. This allows the storage of the instantaneous grid locations at different time steps or iterations.
The arbitrary grid motion is recorded independently for each zone of the CGNS base. Therefore the ArbitraryGridMotion_t data structure is located under the zone data structure (Zone_t). There may be zero to several ArbitraryGridMotion_t nodes under a single Zone_t node. The multiple arbitrary grid motion definitions may be associated with different iterations or time steps in the computation. This association is recorded under the ZoneIterativeData_t data structure.
ArbitraryGridMotion_t< int IndexDimension, int VertexSize[IndexDimension], int CellSize[IndexDimension] > := { ArbitraryGridMotionType_t ArbitraryGridMotionType ; (r) List(DataArray_t<real, IndexDimension, DataSize[]> GridVelocityX GridVelocityY ... ) ; (o) List( Descriptor_t Descriptor1 ... DescriptorN ) ; (o) GridLocation_t GridLocation ; (o/d) Rind_t<IndexDimension> Rind ; (o/d) DataClass_t DataClass ; (o) DimensionalUnits_t DimensionalUnits ; (o) List( UserDefinedData_t UserDefinedData1 ... UserDefinedDataN ) ; (o) }Notes
ArbitraryGridMotion_t requires three structure parameters; IndexDimension identifies the dimensionality of the grid-size arrays, and VertexSize and CellSize are the number of core vertices and cells, respectively, in each index direction, excluding rind points. For structured zones, core vertices and cells begin at [1,1,1] (in 3-D) and end at VertexSize and CellSize, respectively. For unstructured zones, IndexDimension is always 1.
ArbitraryGridMotionType_t is an enumeration type that describes the type of arbitrary grid motion.
ArbitraryGridMotionType_t := Enumeration( ArbitraryGridMotionTypeNull, ArbitraryGridMotionTypeUserDefined, NonDeformingGrid, DeformingGrid ) ;
The DataArray_t nodes are used
to store the components of the grid velocity vector.
The table below lists the data-name identifiers used to record these
vectors in Cartesian, cylindrical, and spherical coordinate systems.
Data-Name Identifier | Description | Units | ||
---|---|---|---|---|
GridVelocityX | x-component of grid velocity | L/T | ||
GridVelocityY | y-component of grid velocity | L/T | ||
GridVelocityZ | z-component of grid velocity | L/T | ||
GridVelocityR | r-component of grid velocity | L/T | ||
GridVelocityTheta | θ-component of grid velocity | α/T | ||
GridVelocityPhi | φ-component of grid velocity | α/T | ||
GridVelocityXi | ξ-component of grid velocity | L/T | ||
GridVelocityEta | η-component of grid velocity | L/T | ||
GridVelocityZeta | ζ-component of grid velocity | L/T | ||
The field GridLocation specifies the location of the grid velocities with respect to the grid; if absent, the grid velocities are assumed to coincide with grid vertices (i.e., GridLocation = Vertex). All grid velocities within a given instance of ArbitraryGridMotion_t must reside at the same grid location.
Rind is an optional field that indicates the number of rind planes (for structured grids) or rind points or elements (for unstructured grids) included in the data. Its purpose and function are identical to those described for the GridCoordinates_t structure. Note, however, that the Rind in this structure is independent of the Rind contained in GridCoordinates_t or FlowSolution_t. They are not required to contain the same number of rind planes or elements. Also, the location of any rind points is assumed to be consistent with the location of the core data points (e.g., if GridLocation = CellCenter, rind points are assumed to be located at fictitious cell centers).
DataClass defines the default for the class of data contained in the DataArray_t entities. For dimensional grid velocities, DimensionalUnits may be used to describe the system of dimensional units employed. If present, these two entities take precedence over all corresponding entities at higher levels of the hierarchy, following the standard precedence rules.
The UserDefinedData_t data structure allows arbitrary user-defined data to be stored in Descriptor_t and DataArray_t children without the restrictions or implicit meanings imposed on these node types at other node locations.
Point-by-point grid velocity implies a deformation (or potentially only motion) of the grid points relative to each other. Because the original grid coordinates definition remains unchanged with the name GridCoordinates, any deformed coordinates must be written with a different name (e.g., MovedGrid#1 or another used-defined name) and are pointed to using GridCoordinatesPointers in the data structure ZoneIterativeData_t.
Point-by-point grid velocity may also lead to relative motion of grid zones, or movement of grid along abutting interfaces. However, no attempt is made here to require that the ZoneGridConnectivity_t information be updated to be consistent with the new grid locations. Whether the ZoneGridConnectivity_t information refers to the original connectivity (of GridCoordinates) or the latest connectivity (of the moved or deformed grid) is currently left up to the user.
The function DataSize[] is the size of the DataArrays containing the grid velocity components. It is identical to the function DataSize[] defined for FlowSolution_t.
In this example, the whole mesh moves rigidly, so the only time-dependent data are the grid coordinates and flow solutions. However, since the mesh moves rigidly, the grid coordinates need not be recorded at each time step. Instead, a RigidGridMotion_t data structure is recorded for each step of the computation.
The number of steps and time values for each step are recorded under BaseIterativeData_t.
CGNSBase_t { BaseIterativeData_t { NumberOfSteps = N ; TimeValues = time1, time2, ..., timeN ; } ; } ;
The multiple rigid grid motion and flow solution data structures are recorded under the zone. RigidGridMotionPointers and FlowSolutionPointers keep the lists of which RigidGridMotion_t and FlowSolution_t nodes correspond to each time step.
Zone_t Zone { --- Time independent data GridCoordinates_t GridCoordinates ZoneBC_t ZoneBC ZoneGridConnectivity_t ZoneGridConnectivity --- Time dependent data RigidGridMotion_t RigidGridMotion#1 RigidGridMotion_t RigidGridMotion#2 ... RigidGridMotion_t RigidGridmotion#N FlowSolution_t Solution#0 FlowSolution_t Solution#1 FlowSolution_t Solution#2 ... FlowSolution_t Solution#N ZoneIterativeData_t { RigidGridMotionPointers = {"RigidGridMotion#1", "RigidGridMotion#2", ..., "RigidGridMotion#N"} FlowSolutionPointers = {"Solution#1", "Solution#2, ..., "Solution#N"} } }
Note that there may be more solutions under a zone than those pointed to by FlowSolutionPointers. In this example, Solution#0 could correspond to a restart solution.
In this example, velocity vectors are node dependent allowing for mesh deformation. In such a case, it is difficult or even impossible to recompute the mesh at each time step. Therefore the grid coordinates are recorded for each step.
Multiple GridCoordinates_t and FlowSolution_t data structures are recorded under the zone. In addition, the data structure ArbitraryGridMotion_t is recorded for each step. GridCoordinatesPointers, FlowSolutionPointers, and ArbitraryGridMotionPointers_t keep the list of which grid coordinates definition, flow solution, and arbitrary grid motion definition correspond to each time step.
Zone_t Zone { --- Time independent data ZoneBC_t ZoneBC ZoneGridConnectivity_t ZoneGridConnectivity --- Time dependent data List ( GridCoordinates_t GridCoordinates MovedGrid#1 MovedGrid#2 ... MovedGrid#N ) List ( FlowSolution_t Solution#0 Solution#1 Solution#2 ... Solution#N ) List ( ArbitraryGridMotion_t ArbitraryGridMotion#1 ArbitraryGridMotion#2 ... ArbitraryGridMotion#N ) ZoneIterativeData_t { GridCoordinatesPointers = {"MovedGrid#1", "MovedGrid#2", ..., "MovedGrid#N"} FlowSolutionPointers = {"Solution#1", "Solution#2, ..., "Solution#N"} ArbitraryGridMotionPointers = {"ArbitraryGridMotion#1", "ArbitraryGridMotion#2", ..., "ArbitraryGridMotion#N"} } }
In this example, the mesh size varies at each remeshing, therefore new zones must be created. ZonePointers is used to keep a record of the zone definition corresponding to each recorded step. Let's assume that the solution is recorded every 50 iterations, and the grid is adapted every 100 iterations.
The number of steps, iteration values for each step, number of zones for each step, and name of these zones are recorded under BaseIterativeData_t.
CGNSBase_t { BaseIterativeData_t { NumberOfSteps = 4 IterationValues = {50, 100, 150, 200} NumberOfZones = {1, 1, 1, 1} ZonePointers = {"Zone1", "Zone1", "Zone2", "Zone2"} } }
Each zone holds 2 solutions recorded at 50 iterations apart. Therefore the ZoneIterativeData_t data structure must be included to keep track of the FlowSolutionPointers.
Zone_t Zone1 { --- Constant data GridCoordinates_t GridCoordinates Elements_t Elements ZoneBC_t ZoneBC --- Variable data List ( FlowSolution_t InitialSolution Solution50 Solution100 ) ZoneIterativeData_t { FlowSolutionPointers = {"Solution50", "Solution100", "Null", "Null"} } } Zone_t Zone2 { --- Constant data GridCoordinates_t GridCoordinates Elements_t Elements ZoneBC_t ZoneBC --- Variable data List ( FlowSolution_t RestartSolution Solution150 Solution200 ) ZoneIterativeData_t { FlowSolutionPointers = {"Null", "Null", "Solution150", "Solution200"} } }Notes
The following is an example demonstrating the use of the rigid grid motion, arbitrary grid motion, and time-accurate data nodes in CGNS. The example is a 3-zone case. Zone 1 is rigidly rotating about the x-axis at a constant rate, with no translation. Zone 2 is a deforming zone. Zone 3 is a fixed zone. This is a time-accurate simulation with two solutions saved at times 15.5 and 31.0, corresponding to iteration numbers 1000 and 2000.
No units are given in this example, but a real case would establish them. Also, a real case would include connectivity, boundary conditions, and possibly other information as well. Each indentation represents a level down (a child) from the parent node.
Base (CGNSBase_t) SimulationType (SimulationType_t) Data=TimeAccurate BaseIterativeData (BaseIterativeData_t) Data=NumberOfSteps=2 TimeValues (DataArray_t) Data=(15.5, 31.0) IterationValues (DataArray_t) Data=(1000, 2000) Zone#1 (Zone_t) GridCoordinates (GridCoordinates_t) CoordinateX (DataArray_t) CoordinateY (DataArray_t) RigidGridMotion#1(RigidGridMotion_t) Data=RigidGridMotionType=ConstantRate OriginLocation (DataArray_t) Data=(0,0,0), (0,0,0) RigidRotationAngle (DataArray_t) Data=(5., 0., 0.) RigidGridMotion#2(RigidGridMotion_t) Data=RigidGridMotionType=ConstantRate OriginLocation (DataArray_t) Data=(0,0,0), (0,0,0) RigidRotationAngle (DataArray_t) Data=(10., 0., 0.) ZoneIterativeData (ZoneIterativeData_t) RigidGridMotionPointers (DataArray_t) Data=(RigidGridMotion#1, RigidGridMotion#2) FlowSolutionPointers (DataArray_t) Data=(Soln#1, Soln#2) Soln#1 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t) Soln#2 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t) Zone#2 (Zone_t) GridCoordinates (GridCoordinates_t) CoordinateX (DataArray_t) CoordinateY (DataArray_t) MovedGrid#1 (GridCoordinates_t) CoordinateX (DataArray_t) CoordinateY (DataArray_t) MovedGrid#2 (GridCoordinates_t) CoordinateX (DataArray_t) CoordinateY (DataArray_t) ArbitraryGridMotion#1 (ArbitraryGridMotion_t) Data=ArbitraryGridMotionType=DeformingGrid ArbitraryGridMotion#2 (ArbitraryGridMotion_t) Data=ArbitraryGridMotionType=DeformingGrid GridVelocityX (DataArray_t) GridVelocityY (DataArray_t) ZoneIterativeData (ZoneIterativeData_t) ArbitraryGridMotionPointers (DataArray_t) Data=("ArbitraryGridMotion#1", "ArbitraryGridMotion#2") GridCoordinatesPointers (DataArray_t) Data=("MovedGrid#1", "MovedGrid#2") FlowSolutionPointers (DataArray_t) Data=("Soln#1", "Soln#2") Soln#1 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t) Soln#2 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t) Zone#3 (Zone_t) GridCoordinates (GridCoordinates_t) CoordinateX (DataArray_t) CoordinateY (DataArray_t) ZoneIterativeData (ZoneIterativeData_t) FlowSolutionPointers (DataArray_t) Data=("Soln#1", "Soln#2") Soln#1 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t) Soln#2 (FlowSolution_t) Density (DataArray_t) VelocityX (DataArray_t)Notes
Data = (Null, ArbitraryGridMotion#2)