# CFD General Notation System (CGNS) Usage for Structured Grids

Bruce Wedan
ANSYS/ICEM CFD

## Presentation Overview

• Compare PLOT3D and CGNS Formats
• Simple cube/cylinder example
• PLOT3D code
• CGNS code
• Timings and file size
• Enhancing the Data with CGNS
• Documentation
• Coordinate systems
• Connectivity
• Boundary Conditions
• Solution Data
• What Else Can You Do?

## Example - Initialization Code

```         include 'cgnslib_f.h'

mach = 0.5
alpha = 0
re = 0
time = 0

C---- zone 1 - cube
do n=1,3
idim1(n,1) = 5
idim1(n,2) = 4
idim1(n,3) = 0
enddo
do i=1,5
do j=1,5
do k=1,5
r1(i,j,k,1) = i - 3
r1(i,j,k,2) = j - 3
r1(i,j,k,3) = k - 5
do n=1,5
q1(i,j,k,n) = n
enddo
enddo
enddo
enddo

C---- zone 2 - cylinder
do n=1,3
idim2(n,1) = 5
idim2(n,2) = 4
idim2(n,3) = 0
enddo
idim2(2,1) = 10
idim2(2,2) = 9
do i=1,5
do j=1,10
do k=1,5
rad = i - 1
ang = 0.6981317*(j - 1)
r2(i,j,k,1) = rad * cos(ang)
r2(i,j,k,2) = rad * sin(ang)
r2(i,j,k,3) = k - 1
do n=1,5
q2(i,j,k,n) = n
enddo
enddo
enddo
enddo
```

## Example - PLOT3D Code

```   c---- write PLOT3D xyz file

iunit = 11
open(iunit,file='example.xyz',form='unformatted')
write(iunit) 2
write(iunit) (idim1(i,1),i=1,3),(idim2(i,1),i=1,3)
write(iunit) ((((r1(i,j,k,n),i=1,5),j=1,5),k=1,5),n=1,3)
write(iunit) ((((r2(i,j,k,n),i=1,5),j=1,10),k=1,5),n=1,3)
close(iunit)

c---- write PLOT3D q file

open(iunit,file='example.q',form='unformatted')
write(iunit) 2
write(iunit) (idim1(i,1),i=1,3),(idim2(i,1),i=1,3)
write(iunit) mach,alpha,re,time
write(iunit) ((((q1(i,j,k,n),i=1,5),j=1,5),k=1,5),n=1,5)
write(iunit) ((((q2(i,j,k,n),i=1,5),j=1,10),k=1,5),n=1,5)
close(iunit)
```

## Example - CGNS Code

```   c---- open file and create base
call cg_open_f('example.cgns',MODE_WRITE,ifile,ierr)
if (ierr .ne. CG_OK) call cg_error_exit_f

call cg_base_write_f(ifile,'Example',3,3,ibase,ierr)

c---- zone 1 - cube

call cg_zone_write_f(ifile,ibase,'Cube',idim1,Structured,izone,ierr)

call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateX',r1(1,1,1,1),
&                      icoord,ierr)
call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateY',r1(1,1,1,2),
&                      icoord,ierr)
call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateZ',r1(1,1,1,3),
&                      icoord,ierr)
```
```         call cg_sol_write_f(ifile,ibase,izone,'Cube Solution',Vertex,isol,ierr)

call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,'Density',
&                      q1(1,1,1,1),ifld,ierr)
call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,'MomentumX',
&                      q1(1,1,1,2),ifld,ierr)
call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,'MomentumY',
&                      q1(1,1,1,3),ifld,ierr)
call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,'MomentumZ',
&                      q1(1,1,1,4),ifld,ierr)
call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,'EnergyStagnationDensity',
&                      q1(1,1,1,5),ifld,ierr)
```
```   c---- zone 2 - cylinder

call cg_zone_write_f(ifile,ibase,'Cylinder',idim2,Structured,izone,ierr)
do n=1,3
call cg_coord_write_f(ifile,ibase,izone,RealSingle,cnames(n),r2(1,1,1,n),
&                        icoord,ierr)
enddo
call cg_sol_write_f(ifile,ibase,izone,'Cylinder Solution',Vertex,isol,ierr)
do n=1,5
call cg_field_write_f(ifile,ibase,izone,isol,RealSingle,snames(n),q2(1,1,1,n),
&                        ifld,ierr)
enddo

c---- close file

call cg_close_f(ifile,ierr)
```

## What Do We Have?

• Mesh Coordinates and Conserved Variables at Vertices
• PLOT3D
• Two files which are non-portable unless ASCII or machines are binary compatible
• Need to know format (i.e. single/double precision, single/multiblock, planar/whole, iblank or none)
• CGNS
• Completely machine independent and portable
• Self-contained, with inquiry functions to determine content
• Utilities available to convert to and from PLOT3D format

## But I Want Separate Files

• Write the Grid File
• Create Base, Zone and Write Coordinates
• Write the Solution File
• Create Base, Zone and Write Solution
• Link to Coordinates in Grid File
```   call cg_zone_write_f(ifile,ibase,'Cube',idim1,Structured,izone,ierr)

call cg_goto_f(ifile,ibase,ierr,'Zone_t',izone,'end')
call cg_link_write_f('GridCoordinates','grid.cgns','/Example/Cube/GridCoordinates',ierr)
```
• No Apparent Difference Between Solution File and Combined File to an Application Reading the Solution

## Timings and File Size

 100×100×100 200×200×200 400×400×400 Mesh Size File Size 30.5 MB 244 MB 1.90 GB PLOT3D 2.32 (3.62) secs 16.0 (45.8) secs 126 (216) secs CGNS (1 file) (+6K bytes) 2.48 (0.63) secs 17.2 (7.9) secs 129 (40) secs CGNS (2 files) (+14K bytes) 2.34 (0.67) secs 17.4 (8.1) secs 164 (41) secs
• You've already benefited from CGNS!

## Enhancing the Data

• Documentation
• Descriptors
• Units
• Data Class
• Reference State
• Simulation Type
• Flow Equations and Models
• Coordinate Systems
• Connectivity
• One to One Matching
• Mismatched Abutting
• Boundary Conditions
• Solution Data
• Cell-Centered
• Ghost Cells (rind)

## Documentation

• Adding a Descriptor Node
```   call cg_goto_f(ifile,ibase,ierr,'end')
text = 'This is a simple example of a cube and cylinder'
call cg_descriptor_write_f('Description',text,ierr)
```
• Defining the Units
```   call cg_units_write_f(Kilogram,Meter,Second,Kelvin,Degree,ierr)

call cg_unitsfull_write_f(Kilogram,Meter,Second,Kelvin,Degree,Ampere,Mole,Candela,ierr)
```
• Defining the Data Class
```   call cg_dataclass_write_f(NormalizedByUnknownDimensional,ierr)
```
• Reference State
```   call cg_state_write_f('Reference Quantities',ierr)

call cg_goto_f(ifile,ibase,ierr,'ReferenceState_t',1,'end')
call cg_array_write_f('Mach',RealSingle,1,1,mach,ierr)

call cg_goto_f(ifile,ibase,ierr,'ReferenceState_t',1,'DataArray_t',1,'end')
call cg_dataclass_write_f(NondimensionalParameter,ierr)

call cg_goto_f(ifile,ibase,ierr,'ReferenceState_t',1,'end')
call cg_array_write_f('LengthReference',RealSingle,1,1,reflen,ierr)
call cg_goto_f(ifile,ibase,ierr,'ReferenceState_t',1,'DataArray_t',3,'end')

call cg_dataclass_write_f(Dimensional,ierr)
call cg_units_write_f(Null,Foot,Null,Null,Null,ierr)
```
• Simulation Type
```   call cg_simulation_type_write_f(ifile,ibase,NonTimeAccurate,ierr)
```
• Equation Set and Numerical Models
```   call cg_goto_f(ifile,ibase,ierr,'end')
call cg_equationset_write_f(5,ierr)

call cg_goto_f(ifile,ibase,ierr,'FlowEquationSet_t',1,'end')
call cg_governing_write_f(Euler,ierr)
call cg_model_write_f('GasModel_t',Ideal,ierr)
```

## Coordinate Systems

• Four Predefined Coordinate Systems
• Cartesian (x,y,z)
• Cylindrical (r,θ,z)
• Spherical (r,θ,φ)
• Auxiliary (ξ,η,ζ)
• Write Cylinder coordinates as Cylindrical
```   call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateR',rc(1,1,1,1),
&                      icoord,ierr)
call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateTheta',rc(1,1,1,2),
&                      icoord,ierr)
call cg_coord_write_f(ifile,ibase,izone,RealSingle,'CoordinateZ',rc(1,1,1,3),
&                      icoord,ierr)
```

## Connectivity

• Cylinder Cut as One to One Connection

```   do n=1,3
transform(n) = n
range(n,1) = 1
range(n,2) = 5
d_range(n,1) = 1
d_range(n,2) = 5
enddo
range(2,2) = 1
d_range(2,1) = 10
d_range(2,2) = 10

call cg_1to1_write_f(ifile,ibase,izone,'Periodic','Cylinder',range,d_range,transform,
&                     iconn,ierr)
```
• Cube to Cylinder Abutting Connection

```      n = 0
do j=1,5
do i=1,5
rad = sqrt(r1(i,j,5,1)**2 + r1(i,j,5,2)**2)
ang = atan2(r1(i,j,5,2), r1(i,j,5,1))
ic = rad
if (ic .ge. 4) ic = 3
if (ang .lt. 0.0) ang = ang + 6.2831853
ang = ang / 0.6981317
jc = ang
if (jc .ge. 9) jc = 8;
pts(n+1) = i;
pts(n+2) = j;
pts(n+3) = 5;
d_cell(n+1) = ic + 1;
d_cell(n+2) = jc + 1;
d_cell(n+3) = 1;
interp(n+1) = rad - ic;
interp(n+2) = ang - jc;
interp(n+3) = 0.0;
n = n + 3
enddo
enddo

call cg_conn_write_f(ifile,ibase,izone,'Cube -> Cylinder',Vertex,Abutting,PointList,
&                     n/3,pts,'Cylinder',Structured,CellListDonor,Integer,n/3,d_cell,
&                     iconn,ierr)

c     write the interpolants

call cg_goto_f(ifile,ibase,ierr,'Zone_t',izone,'ZoneGridConnectivity_t',1,
&               'GridConnectivity_t',iconn,'end')
dims(1) = 3;
dims(2) = n / 3;
call cg_array_write_f('InterpolantsDonor',RealSingle,2,dims,interp,ierr)
```

## Boundary Conditions

• Inlet on Cube Using Point Range

```   do n=1,3
range(n,1) = 1
range(n,2) = 5
enddo
range(3,2) = 1

call cg_boco_write_f(ifile,ibase,izone,'Inlet',BCInflow,PointRange,2,range,ibc,ierr)
```
• Defining the Inlet Boundary Condition
```   call cg_dataset_write_f(ifile,ibase,izone,ibc,'Inflow Conditions',BCInflowSubsonic,
&                        idset,ierr)

call cg_bcdata_write_f(ifile,ibase,izone,ibc,idset,Dirichlet,ierr)

call cg_goto_f(ifile,ibase,ierr,'Zone_t',izone,'ZoneBC_t',1,'BC_t',ibc,'BCDataSet_t',
&               idset,'BCData_t',Dirichlet,'end')

call cg_array_write_f('Density',RealSingle,1,1,0.9,ierr)
call cg_array_write_f('VelocityX',RealSingle,1,1,1.5,ierr)
call cg_array_write_f('VelocityY',RealSingle,1,1,0.0,ierr)
call cg_array_write_f('VelocityZ',RealSingle,1,1,0.0,ierr)
```
• Walls on Cube using Point List

```   n = 0
do k=1,5
do i=1,4
pts(n+1) = i+1
pts(n+2) = 1
pts(n+3) = k
pts(n+4) = i
pts(n+5) = 5
pts(n+6) = k
n = n + 6
enddo
do j=1,4
pts(n+1) = 1
pts(n+2) = j
pts(n+3) = k
pts(n+4) = 5
pts(n+5) = j+1
pts(n+6) = k
n = n + 6
enddo
enddo
call cg_boco_write_f(ifile,ibase,izone,'Walls',BCWall,PointList,n/3,pts,ibc,ierr)
```
• Cylinder Axis as Degenerate Line

```   range(1,1) = 1
range(1,2) = 1
range(2,1) = 1
range(2,2) = 10
range(3,1) = 1
range(3,2) = 5

call cg_boco_write_f(ifile,ibase,izone,'Axis',BCDegenerateLine,PointRange,2,range,
&                     ibc,ierr)
```

## Solution Data

• Cell-Centered Data
• Change Vertex in
```   call cg_sol_write_f(ifile,ibase,izone,'Cylinder Solution',Vertex,isol,ierr)
```
• To CellCenter
```   call cg_sol_write_f(ifile,ibase,izone,'Cylinder Solution',CellCenter,isol,ierr)
```

## Solutions

• Ghost Cells (Rind)

```   rind(1,1) = 0
rind(2,1) = 1
rind(1,2) = 0
rind(2,2) = 0
rind(1,3) = 0
rind(2,3) = 1

call cg_goto_f(ifile,ibase,ierr,'Zone_t',izone,'FlowSolution_t',isol,'end')

call cg_rind_write_f(rind,ierr)
```

## What Else Can You Do?

• Multiple Cases (bases)
• Data Conversions and Dimensional Exponents
• Gravity
• Convergence History
• Moving/Rotating/Axisymmetric Grids
• Time-dependent Solutions
• User-defined Data
• Integral and Discrete Data
• Group by Families
• Geometry References
• Connectivity and Boundary Condition Properties