(CGNS Documentation Home Page)
(Steering Committee Charter)
(Overview and Entry-Level Document)
(A User's Guide to CGNS)
(Mid-Level Library)
(Standard Interface Data Structures)
(SIDS File Mapping Manual)
(CGIO User's Guide)
(Parallel CGNS User's Guide)
(ADF Implementation)
(HDF5 Implementation)
(Python Implementation)
(CGNS Tools and Utilities)
(General Remarks)
(The PCGNS Software Library)
(Example Programs)
Examples
The following examples create a 4x4x4 cube of hexahedral elements
using parallel data output. A cell-centered solution field and a
data array under a user-defined node are also created. Each process
writes a subset of the total data based on it's rank and the number
of processes.
Fortran Example
program fexample
#ifdef WINNT
include 'cgnswin_f.h'
#endif
include 'cgnslib_f.h'
include 'mpif.h'
integer nperside, totnodes, totelems
parameter (nperside = 5)
parameter (totnodes=nperside*nperside*nperside)
parameter (totelems=(nperside-1)*(nperside-1)*(nperside-1))
integer commsize, commrank, ierr
integer i, j, k, n, nn, ne
integer F, B, Z, E, S, Fs, Cx, Cy, Cz, A
integer nnodes, nelems
integer sizes(3), start, end
real*4 fx(totnodes), fy(totnodes), fz(totnodes), fd(totelems)
integer ie(8*totelems)
c---- initialize MPI
call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, commsize, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, commrank, ierr)
c---- open file and create base and zone
sizes(1) = totnodes
sizes(2) = totelems
sizes(3) = 0
c---- default is MPI_COMM_WORLD, but can set another
c communicator with this
c call cgp_mpi_comm_f(MPI_COMM_WORLD,ierr)
call cgp_open_f('fexample.cgns', CG_MODE_WRITE, F, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cg_base_write_f(F, 'Base', 3, 3, B, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cg_zone_write_f(F, B, 'Zone', sizes, Unstructured, Z, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- print info
if (commrank .eq. 0) then
print *, 'writing',totnodes,' coordinates and', totelems,
& ' hex elements to fexample.cgns'
endif
c---- create data nodes for coordinates
call cgp_coord_write_f(F, B, Z, RealSingle, 'CoordinateX',
& Cx, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_coord_write_f(F, B, Z, RealSingle, 'CoordinateY',
& Cy, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_coord_write_f(F, B, Z, RealSingle, 'CoordinateZ',
& Cz, ierr)
c---- number of nodes and range this process will write
nnodes = (totnodes + commsize - 1) / commsize
start = nnodes * commrank + 1
end = nnodes * (commrank + 1)
if (end .gt. totnodes) end = totnodes
c---- create the coordinate data for this process
nn = 1
n = 1
do k=1,nperside
do j=1,nperside
do i=1,nperside
if (n .ge. start .and. n .le. end) then
fx(nn) = i
fy(nn) = j
fz(nn) = k
nn = nn + 1
endif
n = n + 1
enddo
enddo
enddo
c---- write the coordinate data in parallel
call cgp_coord_write_data_f(F, B, Z, Cx, start, end, fx, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_coord_write_data_f(F, B, Z, Cy, start, end, fy, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_coord_write_data_f(F, B, Z, Cz, start, end, fz, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- create data node for elements
call cgp_section_write_f(F, B, Z, 'Hex', HEXA_8, 1, totelems,
& 0, E, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- number of elements and range this process will write
nelems = (totelems + commsize - 1) / commsize
start = nelems * commrank + 1
end = nelems * (commrank + 1)
if (end .gt. totelems) end = totelems
c---- create the hex element data for this process
nn = 0
n = 1
do k=1,nperside-1
do j=1,nperside-1
do i=1,nperside-1
if (n .ge. start .and. n .le. end) then
ne = i + nperside*((j-1)+nperside*(k-1))
ie(nn+1) = ne
ie(nn+2) = ne + 1
ie(nn+3) = ne + 1 + nperside
ie(nn+4) = ne + nperside
ne = ne + nperside*nperside
ie(nn+5) = ne
ie(nn+6) = ne + 1
ie(nn+7) = ne + 1 + nperside
ie(nn+8) = ne + nperside
nn = nn + 8
endif
n = n + 1
enddo
enddo
enddo
c---- write the element connectivity in parallel
call cgp_elements_write_data_f(F, B, Z, E, start, end, ie, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- create a centered solution
call cg_sol_write_f(F, B, Z, 'Solution', CellCenter, S, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_field_write_f(F, B, Z, S, RealSingle, 'CellIndex',
& Fs, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- create the field data for this process
nn = 1
do n=1, totelems
if (n .ge. start .and. n .le. end) then
fd(nn) = n
nn = nn + 1
endif
enddo
c---- write the solution field data in parallel
call cgp_field_write_data_f(F, B, Z, S, Fs, start, end, fd, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- create user data under the zone and duplicate solution data
call cg_goto_f(F, B, ierr, 'Zone_t', 1, 'end')
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cg_user_data_write_f('User Data', ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cg_gorel_f(F, ierr, 'User Data', 0, 'end')
if (ierr .ne. CG_OK) call cgp_error_exit_f
call cgp_array_write_f('CellIndex', RealSingle, 1, totelems,
& A, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- write the array data in parallel
call cgp_array_write_data_f(A, start, end, fd, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
c---- close the file and terminate MPI
call cgp_close_f(F, ierr)
if (ierr .ne. CG_OK) call cgp_error_exit_f
call MPI_FINALIZE(ierr)
end
C Example
#include <stdio.h>
#include <stdlib.h>
#include "pcgnslib.h"
#include "mpi.h"
#define NODES_PER_SIDE 5
int main(int argc, char *argv[])
{
int comm_size, comm_rank;
int tot_nnodes, tot_nelems, nnodes, nelems;
int F, B, Z, E, S, Fs, A, Cx, Cy, Cz;
int i, j, k, n, nn, ne;
float *x, *y, *z, *d;
cgsize_t sizes[3], *e, start, end, ncells;
static char *outfile = "cexample.cgns";
/* initialize MPI */
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
/* total number of nodes and hex elements */
tot_nnodes = NODES_PER_SIDE * NODES_PER_SIDE * NODES_PER_SIDE;
tot_nelems = (NODES_PER_SIDE-1) * (NODES_PER_SIDE-1) * (NODES_PER_SIDE-1);
/* open the file and create base and zone */
sizes[0] = tot_nnodes;
sizes[1] = tot_nelems;
sizes[2] = 0;
/* the default here is to use MPI_COMM_WORLD,
but this allows assigning of another communicator
cgp_mpi_comm(MPI_COMM_WORLD); */
if (cgp_open(outfile, CG_MODE_WRITE, &F) ||
cg_base_write(F, "Base", 3, 3, &B) ||
cg_zone_write(F, B, "Zone", sizes, Unstructured, &Z))
cgp_error_exit();
/* print info */
if (comm_rank == 0) {
printf("writing %d coordinates and %d hex elements to %s\n",
tot_nnodes, tot_nelems, outfile);
}
/* create data nodes for coordinates */
if (cgp_coord_write(F, B, Z, RealSingle, "CoordinateX", &Cx) ||
cgp_coord_write(F, B, Z, RealSingle, "CoordinateY", &Cy) ||
cgp_coord_write(F, B, Z, RealSingle, "CoordinateZ", &Cz))
cgp_error_exit();
/* number of nodes and range this process will write */
nnodes = (tot_nnodes + comm_size - 1) / comm_size;
start = nnodes * comm_rank + 1;
end = nnodes * (comm_rank + 1);
if (end > tot_nnodes) end = tot_nnodes;
/* create the coordinate data for this process */
x = (float *)malloc(nnodes * sizeof(float));
y = (float *)malloc(nnodes * sizeof(float));
z = (float *)malloc(nnodes * sizeof(float));
nn = 0;
for (n = 1, k = 0; k < NODES_PER_SIDE; k++) {
for (j = 0; j < NODES_PER_SIDE; j++) {
for (i = 0; i < NODES_PER_SIDE; i++, n++) {
if (n >= start && n <= end) {
x[nn] = (float)i;
y[nn] = (float)j;
z[nn] = (float)k;
nn++;
}
}
}
}
/* write the coordinate data in parallel */
if (cgp_coord_write_data(F, B, Z, Cx, &start, &end, x) ||
cgp_coord_write_data(F, B, Z, Cy, &start, &end, y) ||
cgp_coord_write_data(F, B, Z, Cz, &start, &end, z))
cgp_error_exit();
/* create data node for elements */
if (cgp_section_write(F, B, Z, "Hex", HEXA_8, 1, tot_nelems, 0, &E))
cgp_error_exit();
/* number of elements and range this process will write */
nelems = (tot_nelems + comm_size - 1) / comm_size;
start = nelems * comm_rank + 1;
end = nelems * (comm_rank + 1);
if (end > tot_nelems) end = tot_nelems;
/* create the hex element data for this process */
e = (cgsize_t *)malloc(8 * nelems * sizeof(cgsize_t));
nn = 0;
for (n = 1, k = 1; k < NODES_PER_SIDE; k++) {
for (j = 1; j < NODES_PER_SIDE; j++) {
for (i = 1; i < NODES_PER_SIDE; i++, n++) {
if (n >= start && n <= end) {
ne = i + NODES_PER_SIDE*((j-1)+NODES_PER_SIDE*(k-1));
e[nn++] = ne;
e[nn++] = ne + 1;
e[nn++] = ne + 1 + NODES_PER_SIDE;
e[nn++] = ne + NODES_PER_SIDE;
ne += NODES_PER_SIDE * NODES_PER_SIDE;
e[nn++] = ne;
e[nn++] = ne + 1;
e[nn++] = ne + 1 + NODES_PER_SIDE;
e[nn++] = ne + NODES_PER_SIDE;
}
}
}
}
/* write the element connectivity in parallel */
if (cgp_elements_write_data(F, B, Z, E, start, end, e))
cgp_error_exit();
/* create a centered solution */
if (cg_sol_write(F, B, Z, "Solution", CellCenter, &S) ||
cgp_field_write(F, B, Z, S, RealSingle, "CellIndex", &Fs))
cgp_error_exit();
/* create the field data for this process */
d = (float *)malloc(nelems * sizeof(float));
nn = 0;
for (n = 1; n <= tot_nelems; n++) {
if (n >= start && n <= end) {
d[nn] = (float)n;
nn++;
}
}
/* write the solution field data in parallel */
if (cgp_field_write_data(F, B, Z, S, Fs, &start, &end, d))
cgp_error_exit();
/* create user data under the zone and duplicate solution data */
ncells = tot_nelems;
if (cg_goto(F, B, "Zone_t", 1, NULL) ||
cg_user_data_write("User Data") ||
cg_gorel(F, "User Data", 0, NULL) ||
cgp_array_write("CellIndex", RealSingle, 1, &ncells, &A))
cgp_error_exit();
/* write the array data in parallel */
if (cgp_array_write_data(A, &start, &end, d))
cgp_error_exit();
/* close the file and terminate MPI */
cgp_close(F);
MPI_Finalize();
return 0;
}