Parts
A part is what block or cylinder opens: a structured grid of one or more blocks of elements, described by three lists of node indices and three lists of coordinates. This chapter explains the six lists, how blocks are deleted to carve the topology, how partitions are inserted and element counts changed after the fact, and how a part ends.
The chapter assumes you have read the concepts chapter for reduced indices, regions and the three phases.
The six lists
block takes six lists. The first three are index lists, one for i, one for j and one for k. The last three are coordinate lists, one for x, one for y and one for z.
block i_index_list ; j_index_list ; k_index_list ;
x_list [ ; ] y_list [ ; ] z_list [ ; ]
An index list says where the partition lines of a direction lie in node numbering. A coordinate list says where they lie in space. The two lists of a direction have the same length: one coordinate for each index entry.
The script tests/corpus/030-block-ends-open-part/input.tg, which make test runs, opens two parts. The second block closes the first part without an endpart, and that is the point of the case.
block 1 3; 1 3; 1 2; 0 1; 0 1; 0 1;
pb 2 2 1 2 2 1 x 5
block 1 2; 1 2; 1 2; 0 1; 0 1; 0 1;
endpart
Read the first line from left to right.
1 3;is the i index list. It has two entries, so the part has two reduced indices in i. Node 1 and node 3 lie on partition lines, so the region between them holds two elements.1 3;is the j index list, read the same way. It holds two elements.1 2;is the k index list. It holds one element.0 1;is the x list. The partition line at reduced index 1 lies at x = 0 and the one at reduced index 2 lies at x = 1.0 1;and0 1;are the y and z lists.
The first part is a unit cube of 2 x 2 x 1 elements and 3 x 3 x 2 nodes. The pb line on the second line moves the vertex at reduced index (2, 2, 1) to x = 5, and it belongs to this part. The second block then closes the part, as endpart would, and opens a second part of one element.
The rules of the lists are these.
- Each index list starts at
1. A list that starts at another number is E0401. - Each entry exceeds the one before it (E0402).
- A coordinate list has as many numbers as its index list (E0403).
- The
;that ends an index list is required. The;that ends a coordinate list may be left out. James then splits the run of numbers by the lengths of the index lists. - A reduced index is a position in a list, not a node number. The i list
1 3has reduced indices 1 and 2.
A 0 in an index list marks a gap, and James refuses it with E0413. A 0 in a coordinate list is only the number zero. The script tests/corpus/117-block-gap-rejected/input.tg has a gap:
block 1 0 3; 1 3; 1 2;
0 1 2; 0 1; 0 1;
endpart
James prints the message in tests/corpus/117-block-gap-rejected/expected.diag.txt:
input.tg:1:9: error [E0413]: gap in the index list not supported in this version of James
james: 1 error, 0 warnings
A negative entry marks a shell partition and is E0400. James refuses both in this version. The compatibility chapter says when they come.
The command pages for block and cylinder hold the syntax.
Cylinder parts
cylinder takes the same six lists, but its coordinate lists are radius, angle and height. The first direction runs out from the axis, the second runs around it and the third runs along it. The angle is in degrees.
All the work on a cylinder part is done in radius, angle and height. The vertices that pb, mb and mbi move move in those coordinates. When the part ends, James converts every node to Cartesian coordinates:
- x = r cos(theta)
- y = r sin(theta)
- z = z
The merge phase and the output files see Cartesian coordinates only. The script examples/ring.tg, which make test runs, makes a whole turn:
c A ring about the z axis, r 1 to 2, a whole turn in eight intervals. The
c part's faces at 0 and at 360 degrees are one face in space, and stp merges
c them: 81 nodes become 72.
c
c james ring.tg --format exodus -o ring.exo
cylinder 1 3;1 9;1 3;1 2;0 360;0 1;
endpart
merge
stp .0001
write
The part has 3 nodes along the radius, 9 around the turn and 3 up the height, 81 in all. The angles 0 and 360 give the same place in space, so stp merges the nine nodes at 360 degrees into the nine at 0. James writes 72 nodes and 32 elements.
Three rules follow from the conversion.
- A negative radius is refused. A negative entry in the radius list stops the run with exit code 2. So does a node whose radius turns negative when the part ends, for example after an
mbwith a large negative offset in the first direction. Zero is legal, so a solid slice may touch its axis. - Angles interpolate as ordinary numbers. A part that runs from 350 to 10 degrees through 0 writes
350 370, not350 10. - An angle past 360 degrees is neither wrapped nor refused. It passes through unchanged and converts periodically when the part ends, so 390 degrees lands where 30 does.
The script tests/golden/016-cylinder-angle-wrap/input.tg shows the last rule:
c A cylinder part whose j = 2 vertex at r = 1 is pushed by mb 300 degrees past
c its 90: the angle passes through unchanged and converts periodically at
c endpart, so the vertex lands at 30 degrees, below its neighbour at 90,
c and the one element folds (vertex-positioning.md, Decisions, M7).
cylinder 1 2;1 2;1 2;1 2;0 90;0 1;
mb 1 2 1 1 2 1 y 300
merge
neutral
write
The mb pushes the vertex at radius 1 and 90 degrees by 300 degrees, to 390. James writes it at (0.866, 0.5, 0), which is 30 degrees. It now lies before the vertex at 90 degrees and the element folds, so James warns. The warning is in tests/golden/016-cylinder-angle-wrap/input.diag.txt:
input.tg:5:1: warning: part #0 has 1 element with a negative Jacobian
james: 0 errors, 1 warning
Changing what the lists mean
Two commands change how the next part reads its lists. Both are session state: they apply to every later part, and neither is used up by the part that follows.
partmode
After partmode i the index lists hold element counts in place of node indices. Each entry is the number of elements in one region, so an index list has one entry fewer than its coordinate list. partmode s returns to node indices, which is the default. The script tests/corpus/164-partmode-i-element-counts/input.tg, which make test runs:
c partmode i reads element counts, which the IR shows as node indices.
partmode i
block 3 2;4;1 1;0 1 2;0 2;0 1 2;
endpart
The i list 3 2 is two regions of 3 and 2 elements. James converts it when it reads the block, and the IR shows the node indices [1 4 6] with the coordinates [0 1 2]. The j list 4 becomes [1 5] and the k list 1 1 becomes [1 2 3]. See partmode.
meshscal
meshscal n multiplies the element count of every region of every part by the whole number n. The coordinates do not change, so the shape stays and the elements get smaller. It comes before every part. After a part has ended it is E0409. The script tests/corpus/114-meshscal-scales-part/input.tg:
meshscal 2
block 1 2;1 2;1 2;0 1;0 1;0 1;
endpart
The part has one element in each direction as written. The IR shows each index list as [1 3]: two elements in each direction. See meshscal.
Carving a part: de and dei
A part is a box of elements. de deletes the elements inside a region of reduced indices, and dei deletes the elements of an index progression. The i in dei means the command takes a progression. It does not mean inverse.
Deleted elements carry no conditions, appear in no output and take no part in the merge. The nodes stay in the part, and James writes only the nodes that a remaining element uses. Pass --write-unref-nodes to write them all.
The script tests/golden/018-notched-plate/input.tg, which make test runs, cuts two notches from a square plate:
c A notched plate: a 3 by 3 grid of blocks, the top and bottom blocks of
c the middle column deleted by one progression with a union, and the
c outer faces of what remains projected onto a cylinder, so the square
c plate becomes a round one with two rectangular notches cut in from the
c rim.
sd 1 cyli 0 0 0 0 0 1 4
block 1 4 7 10;1 4 7 10;1 3;-3 -1 1 3;-3 -1 1 3;0 1;
dei 2 3;1 2 0 3 4;;
sfi -1 -4;;;sd 1
sfi ;-1 -4;;sd 1
endpart
merge
neutral
write
The block has four reduced indices in i and in j, so three regions in each. The plate runs from -3 to 3 in x and y.
In the progression 2 3;1 2 0 3 4;;, the 2 3 in i is the region between reduced indices 2 and 3, the middle column. In j, the 1 2 is the region between reduced indices 1 and 2, the 3 4 is the region between 3 and 4, and the 0 joins them into a union. The empty k list means the whole range. The progression expands to two regions, the bottom and top blocks of the middle column. James’s IR shows them as [2 1 1 3 2 2] and [2 3 1 3 4 2]. The command deletes them. The part that is left has seven blocks, 264 nodes and 126 elements. The two sfi commands then project the outer faces onto the cylinder, and the plate becomes round with two notches cut in from the rim.
Two rules about what de selects.
- A region that holds no element is not an error. A face, an edge or a vertex holds no element. James warns that the
deselects no element and names the region, and the part is unchanged. - A part whose every element is deleted is kept. James warns, and writes none of its nodes unless you pass
--write-unref-nodes.
The warning for an empty part is in tests/corpus/147-part-all-deleted-warns/expected.diag.txt. A reduced index outside the part is E0404. See de and dei.
Changing the topology: insprt, mseq and lmseq
Three commands change a part after its block line. They work on the part’s lists at once and are not steps of the hierarchy, so every later command sees the new numbering.
insprt
insprt adds one partition to a direction, next to a reduced index. Its four arguments are a sign, a type from 1 to 6, a reduced index and the number of elements of the new region. The type picks the direction and the side: 1 and 2 are i left and right, 3 and 4 are j, 5 and 6 are k. A sign of -1 asks for a shell, which is E0400.
The new partition adds a reduced index to the direction. Every command already given for the part has its regions renumbered, so each still names the partition it named before. A command given after the insprt reads the new numbering. The script tests/corpus/165-insprt-renumbers-later-pb/input.tg:
c The pb names reduced i 2; the insprt that follows renumbers it to i 3.
block 1 3 5;1 3;1 2;0 1 2;0 1;0 1;
pb 2 1 1 2 2 1 z 0.5
insprt 1 1 2 1
endpart
The pb names reduced index 2 in i. The insprt puts one new element to the left of reduced index 2, so the i list becomes [1 2 3 5] with the coordinates [0 0.5 1 2]. The IR shows the pb region as 3 1 1 3 2 1: the same vertices, now at reduced index 3. The renumbering reaches de and dei too.
An insertion that splits a region takes its elements from that region, so the count must be smaller than the region’s (E0405). See insprt.
mseq
mseq adds a signed whole number to the element count of every region of one direction. It takes the direction, then one number for each region. The script tests/corpus/166-mseq-doubles-j/input.tg:
c mseq j adds two elements to each j region, so 1 3 5 becomes 1 5 9.
block 1 3;1 3 5;1 2;0 1;0 1 2;0 1;
mseq j 2 2
endpart
The j list 1 3 5 has two regions of two elements. The 2 2 adds two to each, and the IR shows the j list as [1 5 9]. A count of values that is not the number of regions is E0406. See mseq.
lmseq
lmseq changes one region. It takes the direction, the reduced index on the left of the region and the signed change. The script tests/corpus/115-lmseq-folds-single-region/input.tg:
block
1 3 5 7;1 3;1 6 8 13;
1 3 5 7;1 3;1 3 5 7;
lmseq k 2 4
endpart
lmseq k 2 4 adds 4 elements to the k region that starts at reduced index 2. The k list 1 6 8 13 becomes [1 6 12 17]: the region’s right end and every entry after it grow by 4. A change that would leave a region with fewer than one element is E0407. See lmseq.
update is not supported in this version, and James refuses it with E0100. When it is supported, mseq and lmseq after it will be refused too. The coordinate equations (x=, y=, z=, t1=, t2=, t3=) are reported as not recognized (E0105).
Ending a part
A part ends in one of these ways. End of input is covered below.
endpartends the part and returns to the Control phase. Acylinderpart is converted to Cartesian coordinates now.controldoes the same and names the phase. It is for a script that reads better that way. The scripttests/corpus/167-control-then-second-part/input.tgends one part with it, defines a surface in the Control phase and opens a second part.- A
blockorcylindercloses the open part asendpartwould and opens another part, so the session stays in the Part phase. Amergecloses it and enters the Merge phase.endpartis often unnecessary between parts. abortthrows the part away, with every command given for it, and returns to the Control phase.
Each of endpart, control and abort is legal in the Part phase only. In the Merge phase James refuses them with E0411, and there is no way back from the Merge phase except a new part.
The script tests/corpus/031-abort-discards-part/input.tg:
block 1 3; 1 3; 1 2; 0 1; 0 1; 0 1;
pb 2 2 1 2 2 1 x 5
abort
block 1 2; 1 2; 1 2; 0 1; 0 1; 0 1;
endpart
The first part and its pb are discarded, and the IR holds the second part alone. See endpart, control, abort and merge.
A part that is still open when end is read, or when the input ends, is closed as endpart would close it and kept. James warns so that a forgotten endpart shows. The script tests/corpus/133-part-open-at-end-of-input/input.tg:
block 1 2;1 2;1 2;0 1;0 1;0 1;
pb 1 1 1 1 1 1 x 2
James prints the warnings in tests/corpus/133-part-open-at-end-of-input/expected.diag.txt:
input.tg:2:18: warning [E0416]: part 1 was still open at end of input; closed as if by endpart
input.tg:1:1: warning: part #0 has 1 element with a negative Jacobian
james: 0 errors, 2 warnings
The first line is E0416. The second is about the pb, which moves a vertex to x = 2 and turns the element inside out. The part is kept.
Two things that can surprise you
A part whose lists fail still opens. James reports each bad list, then reads the later commands of the part against lists it has repaired, so one mistake in a block line gives one diagnostic and no cascade. The part adds nothing to the mesh.
A list with one entry makes one node in its direction and no elements. James meshes such a part, warns that it has no element, and writes none of its nodes unless you pass --write-unref-nodes.
What James refuses in this version
- Shell partitions, a negative entry in an index list (E0400).
- Gaps, a
0in an index list (E0413). update(E0100) and the coordinate equations, which James reports as not recognized (E0105).
The compatibility chapter says which milestone lifts each.