You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
6.7 KiB
221 lines
6.7 KiB
2 years ago
|
\page polyhedra Polyhedral Element Support
|
||
|
\section poly Storage of 3D arbitrary polyhedra elements in Exodus.
|
||
|
|
||
|
The 3D polyhedra elements are represented as elements with a variable
|
||
|
number of faces in their connectivity. The faces can either be
|
||
|
regular faces such as quadrilateral or triangles; or they can be
|
||
|
topologically two-dimensional arbitrary polyhedra themselves.
|
||
|
|
||
|
An arbitrary polyhedra 3D element block will have an element type of
|
||
|
"nfaced" or "NFACED".
|
||
|
|
||
|
The faces that are used in the connectivity of this block should be
|
||
|
defined in one or more face blocks. If the faces are arbitrary
|
||
|
polyhedra, then they will have a face type of "nsided" or "NSIDED".
|
||
|
|
||
|
An annotated example of defining an arbitrary polyhedral element block
|
||
|
consisting of 3 elements is shown below.
|
||
|
|
||
|
The three elements have the following geometry:
|
||
|
|
||
|
* Element 1: 5 faces.
|
||
|
* Face 1: triangle with nodes 5, 6, 8
|
||
|
* Face 2: triangle with nodes 2, 1, 4
|
||
|
* Face 3: quadrilateral with nodes 6, 2, 4, 8
|
||
|
* Face 4: quadrilateral with nodes 8, 4, 1, 5
|
||
|
* Face 5: quadrilateral with nodes 1, 2, 6, 5
|
||
|
* Element 2: 5 faces.
|
||
|
* Face 6: triangle with nodes 5, 8, 7
|
||
|
* Face 7: triangle with nodes 1, 3, 4
|
||
|
* Face 8: quadrilateral with nodes 7, 8, 4, 3
|
||
|
* Face 9: quadrilateral with nodes 7, 3, 1, 5
|
||
|
* Face 4: quadrilateral with nodes 8, 4, 1, 5 (shared with element 1)
|
||
|
* Element 3: 7 faces.
|
||
|
* Face 8: quadrilateral with nodes 7, 8, 4, 3 (shared with element 2)
|
||
|
* Face 10: pentagonal with nodes 8, 4, 14, 10, 12
|
||
|
* Face 11: pentagonal with nodes 7, 11, 9, 13, 3
|
||
|
* Face 12: quadrilateral with nodes 7, 8, 12, 11
|
||
|
* Face 13: quadrilateral with nodes 11, 12, 10, 9
|
||
|
* Face 14: quadrilateral with nodes 9, 10, 14, 13
|
||
|
* Face 15: quadrilateral with nodes 12, 14, 4, 3
|
||
|
|
||
|
The Exodus model is created via the following calls:
|
||
|
|
||
|
* Output the initial information. Since the model contains faces and
|
||
|
a face block, the "extended" version of the `ex_put_init_ext()` call must be used:
|
||
|
~~~~C
|
||
|
ex_init_params par;
|
||
|
ex_copy_string(par.title, "This is the title", MAX_LINE_LENGTH + 1);
|
||
|
par.num_dim = 3;
|
||
|
par.num_nodes = 14;
|
||
|
par.num_edge = 0;
|
||
|
par.num_edge_blk = 0;
|
||
|
par.num_face = 15;
|
||
|
par.num_face_blk = 1;
|
||
|
par.num_elem = 3;
|
||
|
par.num_elem_blk = 1;
|
||
|
par.num_node_sets = 0;
|
||
|
par.num_edge_sets = 0;
|
||
|
par.num_face_sets = 0;
|
||
|
par.num_side_sets = 0;
|
||
|
par.num_elem_sets = 0;
|
||
|
par.num_node_maps = 0;
|
||
|
par.num_edge_maps = 0;
|
||
|
par.num_face_maps = 0;
|
||
|
par.num_elem_maps = 0;
|
||
|
|
||
|
ex_put_init_ext (exoid, &par);
|
||
|
~~~~
|
||
|
|
||
|
* Coordinate output is normal...
|
||
|
* Define the face block.
|
||
|
~~~~C
|
||
|
block_name = "face_block_1";
|
||
|
num_face_in_block[0] = 15;
|
||
|
num_total_nodes_per_blk[0] = 58;
|
||
|
block_id = 10;
|
||
|
|
||
|
ex_put_block (exoid, EX_FACE_BLOCK, block_id, "nsided",
|
||
|
num_face_in_block[0],
|
||
|
num_total_nodes_per_blk[0],
|
||
|
0, 0, 0);
|
||
|
ex_put_name(exoid, EX_FACE_BLOCK, block_id, block_name);
|
||
|
~~~~
|
||
|
|
||
|
* Output the face connectivity for "face_block_1".
|
||
|
The data for the face connectivity is listed above; a portion is shown below...
|
||
|
~~~~C
|
||
|
connect = (int *) calloc(num_total_nodes_per_blk[0], sizeof(int));
|
||
|
i = 0
|
||
|
connect[i++] = 5;
|
||
|
connect[i++] = 6;
|
||
|
connect[i++] = 8; /* connectivity of face 1 of element 1 */
|
||
|
|
||
|
connect[i++] = 2;
|
||
|
connect[i++] = 1;
|
||
|
connect[i++] = 4; /* face 2 of element 1 */
|
||
|
|
||
|
connect[i++] = 6;
|
||
|
connect[i++] = 2;
|
||
|
connect[i++] = 4;
|
||
|
connect[i++] = 8; /* face 3 of element 1 */
|
||
|
|
||
|
connect[i++] = 8;
|
||
|
connect[i++] = 4;
|
||
|
connect[i++] = 1;
|
||
|
connect[i++] = 5; /* face 4 of element 1 */
|
||
|
|
||
|
connect[i++] = 1;
|
||
|
connect[i++] = 2;
|
||
|
connect[i++] = 6;
|
||
|
connect[i++] = 5; /* face 5 of element 1 */
|
||
|
|
||
|
connect[i++] = 5;
|
||
|
connect[i++] = 8;
|
||
|
connect[i++] = 7; /* connectivity of face 1 of element 2 */
|
||
|
|
||
|
... and so on....
|
||
|
assert(i == num_total_nodes_per_blk[0]);
|
||
|
|
||
|
ex_put_conn (exoid, EX_FACE_BLOCK, block_id, connect, NULL, NULL);
|
||
|
~~~~
|
||
|
|
||
|
* Output the number of nodes per face count for "face_block_1":
|
||
|
~~~~C
|
||
|
j = 0;
|
||
|
nnpe[ 1] = 3; /* Face 1 */
|
||
|
nnpe[ 2] = 3;
|
||
|
nnpe[ 3] = 4;
|
||
|
nnpe[ 4] = 4;
|
||
|
nnpe[ 5] = 4;
|
||
|
nnpe[ 6] = 3;
|
||
|
nnpe[ 7] = 3;
|
||
|
nnpe[ 8] = 4;
|
||
|
nnpe[ 9] = 4;
|
||
|
nnpe[10] = 5;
|
||
|
nnpe[11] = 5;
|
||
|
nnpe[12] = 4;
|
||
|
nnpe[13] = 4;
|
||
|
nnpe[14] = 4;
|
||
|
nnpe[15] = 4;
|
||
|
|
||
|
ex_put_entity_count_per_polyhedra(exoid, EX_FACE_BLOCK, block_id, nnpe);
|
||
|
~~~~
|
||
|
|
||
|
* The face block is now fully defined; now define the nfaced element
|
||
|
block which uses these faces.
|
||
|
~~~~C
|
||
|
block_name = "nfaced_1";
|
||
|
|
||
|
num_elem_in_block = 3;
|
||
|
num_total_faces_per_blk = 5 + 5 + 7;
|
||
|
block_id = 10;
|
||
|
|
||
|
ex_put_block (exoid, EX_ELEM_BLOCK, block_id, "nfaced",
|
||
|
num_elem_in_block,
|
||
|
0, /* nodes */
|
||
|
0, /* edges */
|
||
|
num_total_faces_per_blk,
|
||
|
0); /* attribute count */
|
||
|
ex_put_name(exoid, EX_ELEM_BLOCK, block_id, block_name);
|
||
|
~~~~
|
||
|
|
||
|
In the `ex_put_block()` function, the element type is "nfaced". The
|
||
|
connectivity is defined in terms of the faces, so the node and edge
|
||
|
arguments are passed zeros. The nodal connectivity can be defined,
|
||
|
but it isn't required. The face connectivity argument for an
|
||
|
nfaced block is the total number of faces in the connectivity for all
|
||
|
elements in the nfaced block.
|
||
|
|
||
|
* Write the face connectivity:
|
||
|
~~~~C
|
||
|
/* write element-face connectivity */
|
||
|
connect = (int *) calloc(num_total_faces_per_blk, sizeof(int));
|
||
|
|
||
|
i = 0;
|
||
|
connect[i++] = 1;
|
||
|
connect[i++] = 2;
|
||
|
connect[i++] = 3;
|
||
|
connect[i++] = 4;
|
||
|
connect[i++] = 5;
|
||
|
|
||
|
connect[i++] = 4;
|
||
|
connect[i++] = 6;
|
||
|
connect[i++] = 7;
|
||
|
connect[i++] = 8;
|
||
|
connect[i++] = 9;
|
||
|
|
||
|
connect[i++] = 8;
|
||
|
connect[i++] = 10;
|
||
|
connect[i++] = 11;
|
||
|
connect[i++] = 12;
|
||
|
connect[i++] = 13;
|
||
|
connect[i++] = 14;
|
||
|
connect[i++] = 15;
|
||
|
|
||
|
assert(i == num_total_faces_per_blk);
|
||
|
ex_put_conn (exoid, EX_ELEM_BLOCK, block_id, NULL, NULL, connect);
|
||
|
~~~~
|
||
|
|
||
|
* Output the number of faces per element count for "nfaced_1":
|
||
|
~~~~C
|
||
|
nnpe[1] = 5; /* Number of faces per element 1 */
|
||
|
nnpe[2] = 5; /* Number of faces per element 2 */
|
||
|
nnpe[3] = 7; /* Number of faces per element 3 */
|
||
|
|
||
|
ex_put_entity_count_per_polyhedra(exoid, EX_ELEM_BLOCK, block_id, nnpe);
|
||
|
~~~~
|
||
|
|
||
|
* That's all; the rest of the calls are the same as normal Exodus except:
|
||
|
|
||
|
* There is a similar `ex_get_entity_count_per_polyhedra()` function for read.
|
||
|
|
||
|
* The `ex_get_block()` functions return the total number of nodes or
|
||
|
faces for all faces or element for "nfaced" and "nsided" blocks
|
||
|
and not the number per element
|
||
|
|
||
|
* An example read/write usage is shown in the
|
||
|
[testwt-nfaced.c](../test/testwt-nfaced.c) and [testrd-nfaced](../test/testrd-nfaced.c) files.
|
||
|
|
||
|
* These changes are in Exodus version v4.93 and later.
|