diff --git a/cmake/common/set/sparta_cmake_defaults.cmake b/cmake/common/set/sparta_cmake_defaults.cmake index 59afc947f..b95fbe5af 100644 --- a/cmake/common/set/sparta_cmake_defaults.cmake +++ b/cmake/common/set/sparta_cmake_defaults.cmake @@ -56,6 +56,7 @@ if(SPARTA_ENABLE_TESTING) "explicit2implicit" "mfp_mct" "optmove" + "region_mesh" "torque") set(SPARTA_DISABLED_TESTS diff --git a/data/README b/data/README index 8c432a681..635b45637 100644 --- a/data/README +++ b/data/README @@ -19,11 +19,15 @@ Files that end in ".tce" list reactions gas-phase chemistry for the Total Collision Energy (TCE) model and are read by the react command. Files that start with "sdata." contain lists of surface elements and -are read by the read_surf command. +are read by the read_surf command. They can also be read by the region +command with its mesh style, which defines the region as the volume +enclosed by the surface. Files that end in ".stl" are STL-formatted surface files which can be converted to SPARTA formatted surface files via the stl2surf.py tool -in the tools directory. +in the tools directory. They can also be read directly by the region +command with its mesh style, which defines the region as the volume +enclosed by the surface. Files that end in ".surf" list reactions for surface chemistry and are read by the surf_react command. @@ -35,6 +39,6 @@ species = doc/species.html species.vib = doc/species.html vss/vhs/hs = doc/collide.html tce = doc/react.html -sdata = doc/read_surf.html -stl = doc/Section_tools.html#stl2surf +sdata = doc/read_surf.html and doc/region.html +stl = doc/Section_tools.html#stl2surf and doc/region.html surf = doc/surf_react.html diff --git a/doc/region.html b/doc/region.html index ea522a005..466f5dcc3 100644 --- a/doc/region.html +++ b/doc/region.html @@ -17,7 +17,7 @@

region command @@ -54,7 +66,10 @@

region command
region 1 block -3.0 5.0 INF 10.0 INF INF
 region 2 sphere 0.0 0.0 0.0 5 side out
 region void cylinder y 2 3 5 -5.0 INF
-region outside union 4 side1 side2 side3 side4 
+region outside union 4 side1 side2 side3 side4
+region flask mesh flask.stl
+region duct mesh duct.stl scale 0.001 0.001 0.001 side out
+region shell mesh data.circle side out 
 

Description:

@@ -82,6 +97,53 @@

region command y-direction located at x = 2.0 and z = 3.0, with a radius of 5.0, and extending in the y-direction from -5.0 to infinity.

+

The mesh style defines the region as the volume enclosed by a closed +surface which is read from a file. Two file formats are supported and +SPARTA detects which one a file is from its contents, not from its name: +

+

STL (stereolithography) files, in either of the two variants of that +format, plain text ("ASCII") or binary. An STL file always stores a 3d +triangulated surface. +

+

Surface files in the format the read_surf command +reads, which store a 3d surface as triangles or a 2d surface as line +segments. As for read_surf, a Points section is optional, and a +per-surface type column is skipped if it is present. Per-surface custom +attributes are not supported. +

+

Only the geometry in the file is used. Surface types, surface IDs, and +the direction of the normals are all ignored. Every processor reads and +stores the entire mesh, so this style is best suited to small and medium +sized meshes. +

+

A point is tested against a 3d mesh by casting a ray from the point in +the +x direction and counting how many triangles it crosses. An odd +count means the point is inside the surface. A 2d mesh is a closed +curve in the x-y plane, so the ray is cast in that plane and crossings +of the line segments are counted instead. The z coordinate of the point +does not matter for a 2d mesh, which means the region it defines is the +curve extruded to infinity in both z directions. A 2d mesh can thus be +used in a 3d simulation as well, where it defines a prism. +

+

Either way this requires the surface to be closed, and SPARTA prints a +warning if the elements in the file do not enclose a volume (or an area +in 2d), in which case the inside/outside test gives arbitrary answers. +As for the other styles, a point that lies exactly on the surface is +considered to be inside it, and the side keyword selects whether the +region is the volume inside or outside the mesh. +

+

The origin, trans, scale, and rotate keywords can only be used +with the mesh style. They transform the mesh after it is read, which +is useful when the file uses different units or is positioned +differently than the simulation box. They are applied in the order they +appear in the command, and follow the same conventions as the +read_surf keywords of the same name. Trans +translates the mesh by the specified distance. Scale multiplies the +distance of every vertex from the origin point by the specified +factors. Rotate rotates the mesh by theta degrees around the axis +Rx,Ry,Rz which passes through the origin point. The origin point is +0,0,0 by default and is moved along by any preceding trans. +

The union style creates a region consisting of the volume of all the listed regions combined. The intersect style creates a region consisting of the volume that is common to all the listed regions. @@ -127,11 +189,28 @@

region command


-

Restrictions: none +

Restrictions: +

+

An STL file always describes a 3d surface, so a 2d region can only be +defined with a read_surf format file containing lines. +Unlike read_surf, the mesh style does not require the dimensionality +of the file to match the dimension of the simulation, +since as noted above regions in SPARTA are 3d objects in either case. +

+

There is no mesh/kk style. The +create_particles command tests points against a +region on the host, so a mesh region can be used with +create_particles/kk, either on its own or as one of the regions listed +by a union or intersect region. Commands that test regions on the +device, such as fix emit/face and fix ave/histo, +will generate an error if they are given a mesh region when running +with the KOKKOS package, whether it is given to them directly or nested +inside a union or intersect region.

Related commands:

-

dump_modify +

create_particles, read_surf, +dump_modify

Default:

diff --git a/doc/region.txt b/doc/region.txt index a7cbbe022..e4b40014b 100644 --- a/doc/region.txt +++ b/doc/region.txt @@ -13,7 +13,7 @@ region command :h3 region ID style args keyword value ... :pre ID = user-assigned name for the region :ulb,l -style = {block} or {cylinder} or {plane} or {sphere} or {union} or {intersect} or {block/kk} or {cylinder/kk} or {plane/kk} or {sphere/kk} or {union/kk} or {intersect/kk} :l +style = {block} or {cylinder} or {mesh} or {plane} or {sphere} or {union} or {intersect} or {block/kk} or {cylinder/kk} or {plane/kk} or {sphere/kk} or {union/kk} or {intersect/kk} :l {block} or {block/kk} args = xlo xhi ylo yhi zlo zhi xlo,xhi,ylo,yhi,zlo,zhi = bounds of block in all dimensions (distance units) {cylinder} or {cylinder/kk} args = dim c1 c2 radius lo hi @@ -21,6 +21,9 @@ style = {block} or {cylinder} or {plane} or {sphere} or {union} or {intersect} o c1,c2 = coords of cylinder axis in other 2 dimensions (distance units) radius = cylinder radius (distance units) lo,hi = bounds of cylinder in dim (distance units) + {mesh} args = file + file = name of file with a closed surface, in STL format or in the + format the "read_surf"_read_surf.html command reads {plane} or {plane/kk} args = px py pz nx ny nz px,py,pz = point on the plane (distance units) nx,ny,nz = direction normal to plane (distance units) @@ -34,10 +37,19 @@ style = {block} or {cylinder} or {plane} or {sphere} or {union} or {intersect} o N = # of regions to follow, must be 2 or greater reg-ID1,reg-ID2, ... = IDs of regions to intersect :pre zero or more keyword/value pairs may be appended :l -keyword = {side} :l +keyword = {side} or {origin} or {trans} or {scale} or {rotate} :l {side} value = {in} or {out} {in} = the region is inside the specified geometry - {out} = the region is outside the specified geometry :pre + {out} = the region is outside the specified geometry + {origin} values = Ox Oy Oz (only for style {mesh}) + Ox,Oy,Oz = point that {scale} and {rotate} operate around (distance units) + {trans} values = Dx Dy Dz (only for style {mesh}) + Dx,Dy,Dz = distance to translate the mesh by (distance units) + {scale} values = Sx Sy Sz (only for style {mesh}) + Sx,Sy,Sz = scale factor to apply to the mesh in each dimension + {rotate} values = theta Rx Ry Rz (only for style {mesh}) + theta = angle to rotate the mesh by (degrees) + Rx,Ry,Rz = axis of rotation :pre :ule [Examples:] @@ -45,7 +57,10 @@ keyword = {side} :l region 1 block -3.0 5.0 INF 10.0 INF INF region 2 sphere 0.0 0.0 0.0 5 side out region void cylinder y 2 3 5 -5.0 INF -region outside union 4 side1 side2 side3 side4 :pre +region outside union 4 side1 side2 side3 side4 +region flask mesh flask.stl +region duct mesh duct.stl scale 0.001 0.001 0.001 side out +region shell mesh data.circle side out :pre [Description:] @@ -73,6 +88,53 @@ third example above specifies a cylinder with its axis in the y-direction located at x = 2.0 and z = 3.0, with a radius of 5.0, and extending in the y-direction from -5.0 to infinity. +The {mesh} style defines the region as the volume enclosed by a closed +surface which is read from a file. Two file formats are supported and +SPARTA detects which one a file is from its contents, not from its name: + +STL (stereolithography) files, in either of the two variants of that +format, plain text ("ASCII") or binary. An STL file always stores a 3d +triangulated surface. + +Surface files in the format the "read_surf"_read_surf.html command +reads, which store a 3d surface as triangles or a 2d surface as line +segments. As for read_surf, a {Points} section is optional, and a +per-surface type column is skipped if it is present. Per-surface custom +attributes are not supported. + +Only the geometry in the file is used. Surface types, surface IDs, and +the direction of the normals are all ignored. Every processor reads and +stores the entire mesh, so this style is best suited to small and medium +sized meshes. + +A point is tested against a 3d mesh by casting a ray from the point in +the +x direction and counting how many triangles it crosses. An odd +count means the point is inside the surface. A 2d mesh is a closed +curve in the x-y plane, so the ray is cast in that plane and crossings +of the line segments are counted instead. The z coordinate of the point +does not matter for a 2d mesh, which means the region it defines is the +curve extruded to infinity in both z directions. A 2d mesh can thus be +used in a 3d simulation as well, where it defines a prism. + +Either way this requires the surface to be closed, and SPARTA prints a +warning if the elements in the file do not enclose a volume (or an area +in 2d), in which case the inside/outside test gives arbitrary answers. +As for the other styles, a point that lies exactly on the surface is +considered to be inside it, and the {side} keyword selects whether the +region is the volume inside or outside the mesh. + +The {origin}, {trans}, {scale}, and {rotate} keywords can only be used +with the {mesh} style. They transform the mesh after it is read, which +is useful when the file uses different units or is positioned +differently than the simulation box. They are applied in the order they +appear in the command, and follow the same conventions as the +"read_surf"_read_surf.html keywords of the same name. {Trans} +translates the mesh by the specified distance. {Scale} multiplies the +distance of every vertex from the {origin} point by the specified +factors. {Rotate} rotates the mesh by theta degrees around the axis +Rx,Ry,Rz which passes through the {origin} point. The {origin} point is +0,0,0 by default and is moved along by any preceding {trans}. + The {union} style creates a region consisting of the volume of all the listed regions combined. The {intersect} style creates a region consisting of the volume that is common to all the listed regions. @@ -118,10 +180,28 @@ effectively. :line -[Restrictions:] none +[Restrictions:] + +An STL file always describes a 3d surface, so a 2d region can only be +defined with a "read_surf"_read_surf.html format file containing lines. +Unlike read_surf, the {mesh} style does not require the dimensionality +of the file to match the "dimension"_dimension.html of the simulation, +since as noted above regions in SPARTA are 3d objects in either case. + +There is no {mesh/kk} style. The +"create_particles"_create_particles.html command tests points against a +region on the host, so a {mesh} region can be used with +create_particles/kk, either on its own or as one of the regions listed +by a {union} or {intersect} region. Commands that test regions on the +device, such as "fix emit/face"_fix_emit_face.html and "fix +ave/histo"_fix_ave_histo.html, will generate an error if they are given +a {mesh} region when running with the KOKKOS package, whether it is +given to them directly or nested inside a {union} or {intersect} +region. [Related commands:] +"create_particles"_create_particles.html, "read_surf"_read_surf.html, "dump_modify"_dump_modify.html [Default:] diff --git a/examples/region_mesh/air.species b/examples/region_mesh/air.species new file mode 100644 index 000000000..d102d9070 --- /dev/null +++ b/examples/region_mesh/air.species @@ -0,0 +1,24 @@ +# Species data + +# ID +# Molwt (amu) +# Molmass (kg) +# Rotational dof +# RotRel +# Vibrational dof +# VibRel +# VibTemp (K) +# species wt +# charge + +O2 32.00 5.31E-26 2 0.2 2 5.58659E-5 2256.0 1.0 0.0 +N2 28.016 4.65E-26 2 0.2 2 1.90114E-5 3371.0 1.0 0.0 +O 16.00 2.65E-26 0 0.0 0 0.0 0.0 1.0 0.0 +N 14.008 2.325E-26 0 0.0 0 0.0 0.0 1.0 0.0 +NO 30.008 4.98E-26 2 0.2 2 7.14285E-4 2719.0 1.0 0.0 +O2+ 32.00 5.31E-26 2 0.2 2 5.58659E-5 2256.0 1.0 1.0 +N2+ 28.016 4.65E-26 2 0.2 2 1.90114E-5 3371.0 1.0 1.0 +O+ 16.00 2.65E-26 0 0.0 0 0.0 0.0 1.0 1.0 +N+ 14.008 2.325E-26 0 0.0 0 0.0 0.0 1.0 1.0 +NO+ 30.008 4.98E-26 2 0.2 2 7.14285E-4 2719.0 1.0 1.0 +e 0.001 9.10938188E-31 0 0.0 0 0.0 0.0 1.0 -1.0 diff --git a/examples/region_mesh/air.vss b/examples/region_mesh/air.vss new file mode 100644 index 000000000..9c7ecbe5d --- /dev/null +++ b/examples/region_mesh/air.vss @@ -0,0 +1,22 @@ +# VSS collision model parameters for each species + +# diameter (mass) +# omega (unitless) +# tref (temperature) +# alpha (unitless) +# Zrotinf (unitless) +# T* (temperature) +# C1 (temperature) +# C2 (temperature^(1/3)) + +O2 3.96E-10 0.77 273.15 1.4 16.5 113.5 56.5 153.5 +N2 4.07E-10 0.74 273.15 1.6 18.1 91.5 9.1 220.0 +O 3.0E-10 0.80 273.15 1.0 0.0 0.0 0.0 0.0 +N 3.0E-10 0.80 273.15 1.0 0.0 0.0 0.0 0.0 +NO 4.0E-10 0.80 273.15 1.0 7.5 119.0 9.10 220.00 +O2+ 3.96E-10 0.77 273.15 1.4 16.5 113.5 56.5 153.5 +N2+ 4.07E-10 0.74 273.15 1.6 18.1 91.5 9.1 220.0 +O+ 3.0E-10 0.80 273.15 1.0 0.0 0.0 0.0 0.0 +N+ 3.0E-10 0.80 273.15 1.0 0.0 0.0 0.0 0.0 +NO+ 4.0E-10 0.80 273.15 1.0 7.5 119.0 9.10 220.00 +e 7.0E-13 0.50 273.15 1.0 0.0 0.0 0.0 0.0 diff --git a/examples/region_mesh/data.annulus b/examples/region_mesh/data.annulus new file mode 100644 index 000000000..c6b6eadc9 --- /dev/null +++ b/examples/region_mesh/data.annulus @@ -0,0 +1,202 @@ +surf file for an annulus, outer radius 4, inner radius 2 + +96 points +96 lines + +Points + +1 4 0 +2 3.980738907 0.3920685613 +3 3.923141122 0.7803612881 +4 3.827761343 1.161138709 +5 3.69551813 1.530733729 +6 3.527685057 1.885586947 +7 3.325878449 2.222280932 +8 3.092041813 2.537573137 +9 2.828427125 2.828427125 +10 2.537573137 3.092041813 +11 2.222280932 3.325878449 +12 1.885586947 3.527685057 +13 1.530733729 3.69551813 +14 1.161138709 3.827761343 +15 0.7803612881 3.923141122 +16 0.3920685613 3.980738907 +17 2.449293598e-16 4 +18 -0.3920685613 3.980738907 +19 -0.7803612881 3.923141122 +20 -1.161138709 3.827761343 +21 -1.530733729 3.69551813 +22 -1.885586947 3.527685057 +23 -2.222280932 3.325878449 +24 -2.537573137 3.092041813 +25 -2.828427125 2.828427125 +26 -3.092041813 2.537573137 +27 -3.325878449 2.222280932 +28 -3.527685057 1.885586947 +29 -3.69551813 1.530733729 +30 -3.827761343 1.161138709 +31 -3.923141122 0.7803612881 +32 -3.980738907 0.3920685613 +33 -4 4.898587197e-16 +34 -3.980738907 -0.3920685613 +35 -3.923141122 -0.7803612881 +36 -3.827761343 -1.161138709 +37 -3.69551813 -1.530733729 +38 -3.527685057 -1.885586947 +39 -3.325878449 -2.222280932 +40 -3.092041813 -2.537573137 +41 -2.828427125 -2.828427125 +42 -2.537573137 -3.092041813 +43 -2.222280932 -3.325878449 +44 -1.885586947 -3.527685057 +45 -1.530733729 -3.69551813 +46 -1.161138709 -3.827761343 +47 -0.7803612881 -3.923141122 +48 -0.3920685613 -3.980738907 +49 -7.347880795e-16 -4 +50 0.3920685613 -3.980738907 +51 0.7803612881 -3.923141122 +52 1.161138709 -3.827761343 +53 1.530733729 -3.69551813 +54 1.885586947 -3.527685057 +55 2.222280932 -3.325878449 +56 2.537573137 -3.092041813 +57 2.828427125 -2.828427125 +58 3.092041813 -2.537573137 +59 3.325878449 -2.222280932 +60 3.527685057 -1.885586947 +61 3.69551813 -1.530733729 +62 3.827761343 -1.161138709 +63 3.923141122 -0.7803612881 +64 3.980738907 -0.3920685613 +65 1.961570561 -0.390180644 +66 1.847759065 -0.7653668647 +67 1.662939225 -1.111140466 +68 1.414213562 -1.414213562 +69 1.111140466 -1.662939225 +70 0.7653668647 -1.847759065 +71 0.390180644 -1.961570561 +72 -3.673940397e-16 -2 +73 -0.390180644 -1.961570561 +74 -0.7653668647 -1.847759065 +75 -1.111140466 -1.662939225 +76 -1.414213562 -1.414213562 +77 -1.662939225 -1.111140466 +78 -1.847759065 -0.7653668647 +79 -1.961570561 -0.390180644 +80 -2 2.449293598e-16 +81 -1.961570561 0.390180644 +82 -1.847759065 0.7653668647 +83 -1.662939225 1.111140466 +84 -1.414213562 1.414213562 +85 -1.111140466 1.662939225 +86 -0.7653668647 1.847759065 +87 -0.390180644 1.961570561 +88 1.224646799e-16 2 +89 0.390180644 1.961570561 +90 0.7653668647 1.847759065 +91 1.111140466 1.662939225 +92 1.414213562 1.414213562 +93 1.662939225 1.111140466 +94 1.847759065 0.7653668647 +95 1.961570561 0.390180644 +96 2 0 + +Lines + +1 1 2 +2 2 3 +3 3 4 +4 4 5 +5 5 6 +6 6 7 +7 7 8 +8 8 9 +9 9 10 +10 10 11 +11 11 12 +12 12 13 +13 13 14 +14 14 15 +15 15 16 +16 16 17 +17 17 18 +18 18 19 +19 19 20 +20 20 21 +21 21 22 +22 22 23 +23 23 24 +24 24 25 +25 25 26 +26 26 27 +27 27 28 +28 28 29 +29 29 30 +30 30 31 +31 31 32 +32 32 33 +33 33 34 +34 34 35 +35 35 36 +36 36 37 +37 37 38 +38 38 39 +39 39 40 +40 40 41 +41 41 42 +42 42 43 +43 43 44 +44 44 45 +45 45 46 +46 46 47 +47 47 48 +48 48 49 +49 49 50 +50 50 51 +51 51 52 +52 52 53 +53 53 54 +54 54 55 +55 55 56 +56 56 57 +57 57 58 +58 58 59 +59 59 60 +60 60 61 +61 61 62 +62 62 63 +63 63 64 +64 64 1 +65 65 66 +66 66 67 +67 67 68 +68 68 69 +69 69 70 +70 70 71 +71 71 72 +72 72 73 +73 73 74 +74 74 75 +75 75 76 +76 76 77 +77 77 78 +78 78 79 +79 79 80 +80 80 81 +81 81 82 +82 82 83 +83 83 84 +84 84 85 +85 85 86 +86 86 87 +87 87 88 +88 88 89 +89 89 90 +90 90 91 +91 91 92 +92 92 93 +93 93 94 +94 94 95 +95 95 96 +96 96 65 diff --git a/examples/region_mesh/data.torus.stl b/examples/region_mesh/data.torus.stl new file mode 100644 index 000000000..5266fd9b9 --- /dev/null +++ b/examples/region_mesh/data.torus.stl @@ -0,0 +1,4034 @@ +solid torus + facet normal 0.958209 0.126151 0.256751 + outer loop + vertex 4 0 0 + vertex 3.8637 1.03528 0 + vertex 3.73429 1.0006 0.5 + endloop + endfacet + facet normal 0.958209 0.126151 0.256751 + outer loop + vertex 4 0 0 + vertex 3.73429 1.0006 0.5 + vertex 3.86603 0 0.5 + endloop + endfacet + facet normal 0.704063 0.0926916 0.704063 + outer loop + vertex 3.86603 0 0.5 + vertex 3.73429 1.0006 0.5 + vertex 3.38074 0.905867 0.866025 + endloop + endfacet + facet normal 0.704063 0.0926916 0.704063 + outer loop + vertex 3.86603 0 0.5 + vertex 3.38074 0.905867 0.866025 + vertex 3.5 0 0.866025 + endloop + endfacet + facet normal 0.258669 0.0340544 0.965366 + outer loop + vertex 3.5 0 0.866025 + vertex 3.38074 0.905867 0.866025 + vertex 2.89778 0.776457 1 + endloop + endfacet + facet normal 0.258669 0.0340544 0.965366 + outer loop + vertex 3.5 0 0.866025 + vertex 2.89778 0.776457 1 + vertex 3 0 1 + endloop + endfacet + facet normal -0.258669 -0.0340544 0.965366 + outer loop + vertex 3 0 1 + vertex 2.89778 0.776457 1 + vertex 2.41481 0.647048 0.866025 + endloop + endfacet + facet normal -0.258669 -0.0340544 0.965366 + outer loop + vertex 3 0 1 + vertex 2.41481 0.647048 0.866025 + vertex 2.5 0 0.866025 + endloop + endfacet + facet normal -0.704063 -0.0926916 0.704063 + outer loop + vertex 2.5 0 0.866025 + vertex 2.41481 0.647048 0.866025 + vertex 2.06126 0.552313 0.5 + endloop + endfacet + facet normal -0.704063 -0.0926916 0.704063 + outer loop + vertex 2.5 0 0.866025 + vertex 2.06126 0.552313 0.5 + vertex 2.13397 0 0.5 + endloop + endfacet + facet normal -0.958209 -0.126151 0.256751 + outer loop + vertex 2.13397 0 0.5 + vertex 2.06126 0.552313 0.5 + vertex 1.93185 0.517638 1.22465e-16 + endloop + endfacet + facet normal -0.958209 -0.126151 0.256751 + outer loop + vertex 2.13397 0 0.5 + vertex 1.93185 0.517638 1.22465e-16 + vertex 2 0 1.22465e-16 + endloop + endfacet + facet normal -0.958209 -0.126151 -0.256751 + outer loop + vertex 2 0 1.22465e-16 + vertex 1.93185 0.517638 1.22465e-16 + vertex 2.06126 0.552313 -0.5 + endloop + endfacet + facet normal -0.958209 -0.126151 -0.256751 + outer loop + vertex 2 0 1.22465e-16 + vertex 2.06126 0.552313 -0.5 + vertex 2.13397 0 -0.5 + endloop + endfacet + facet normal -0.704063 -0.0926916 -0.704063 + outer loop + vertex 2.13397 0 -0.5 + vertex 2.06126 0.552313 -0.5 + vertex 2.41481 0.647048 -0.866025 + endloop + endfacet + facet normal -0.704063 -0.0926916 -0.704063 + outer loop + vertex 2.13397 0 -0.5 + vertex 2.41481 0.647048 -0.866025 + vertex 2.5 0 -0.866025 + endloop + endfacet + facet normal -0.258669 -0.0340544 -0.965366 + outer loop + vertex 2.5 0 -0.866025 + vertex 2.41481 0.647048 -0.866025 + vertex 2.89778 0.776457 -1 + endloop + endfacet + facet normal -0.258669 -0.0340544 -0.965366 + outer loop + vertex 2.5 0 -0.866025 + vertex 2.89778 0.776457 -1 + vertex 3 0 -1 + endloop + endfacet + facet normal 0.258669 0.0340544 -0.965366 + outer loop + vertex 3 0 -1 + vertex 2.89778 0.776457 -1 + vertex 3.38074 0.905867 -0.866025 + endloop + endfacet + facet normal 0.258669 0.0340544 -0.965366 + outer loop + vertex 3 0 -1 + vertex 3.38074 0.905867 -0.866025 + vertex 3.5 0 -0.866025 + endloop + endfacet + facet normal 0.704063 0.0926916 -0.704063 + outer loop + vertex 3.5 0 -0.866025 + vertex 3.38074 0.905867 -0.866025 + vertex 3.73429 1.0006 -0.5 + endloop + endfacet + facet normal 0.704063 0.0926916 -0.704063 + outer loop + vertex 3.5 0 -0.866025 + vertex 3.73429 1.0006 -0.5 + vertex 3.86603 0 -0.5 + endloop + endfacet + facet normal 0.958209 0.126151 -0.256751 + outer loop + vertex 3.86603 0 -0.5 + vertex 3.73429 1.0006 -0.5 + vertex 3.8637 1.03528 -2.44929e-16 + endloop + endfacet + facet normal 0.958209 0.126151 -0.256751 + outer loop + vertex 3.86603 0 -0.5 + vertex 3.8637 1.03528 -2.44929e-16 + vertex 4 0 -2.44929e-16 + endloop + endfacet + facet normal 0.892909 0.369855 0.256751 + outer loop + vertex 3.8637 1.03528 0 + vertex 3.4641 2 0 + vertex 3.34808 1.93301 0.5 + endloop + endfacet + facet normal 0.892909 0.369855 0.256751 + outer loop + vertex 3.8637 1.03528 0 + vertex 3.34808 1.93301 0.5 + vertex 3.73429 1.0006 0.5 + endloop + endfacet + facet normal 0.656082 0.271758 0.704063 + outer loop + vertex 3.73429 1.0006 0.5 + vertex 3.34808 1.93301 0.5 + vertex 3.03109 1.75 0.866025 + endloop + endfacet + facet normal 0.656082 0.271758 0.704063 + outer loop + vertex 3.73429 1.0006 0.5 + vertex 3.03109 1.75 0.866025 + vertex 3.38074 0.905867 0.866025 + endloop + endfacet + facet normal 0.241041 0.0998425 0.965366 + outer loop + vertex 3.38074 0.905867 0.866025 + vertex 3.03109 1.75 0.866025 + vertex 2.59808 1.5 1 + endloop + endfacet + facet normal 0.241041 0.0998425 0.965366 + outer loop + vertex 3.38074 0.905867 0.866025 + vertex 2.59808 1.5 1 + vertex 2.89778 0.776457 1 + endloop + endfacet + facet normal -0.241041 -0.0998425 0.965366 + outer loop + vertex 2.89778 0.776457 1 + vertex 2.59808 1.5 1 + vertex 2.16506 1.25 0.866025 + endloop + endfacet + facet normal -0.241041 -0.0998425 0.965366 + outer loop + vertex 2.89778 0.776457 1 + vertex 2.16506 1.25 0.866025 + vertex 2.41481 0.647048 0.866025 + endloop + endfacet + facet normal -0.656082 -0.271758 0.704063 + outer loop + vertex 2.41481 0.647048 0.866025 + vertex 2.16506 1.25 0.866025 + vertex 1.84808 1.06699 0.5 + endloop + endfacet + facet normal -0.656082 -0.271758 0.704063 + outer loop + vertex 2.41481 0.647048 0.866025 + vertex 1.84808 1.06699 0.5 + vertex 2.06126 0.552313 0.5 + endloop + endfacet + facet normal -0.892909 -0.369855 0.256751 + outer loop + vertex 2.06126 0.552313 0.5 + vertex 1.84808 1.06699 0.5 + vertex 1.73205 1 1.22465e-16 + endloop + endfacet + facet normal -0.892909 -0.369855 0.256751 + outer loop + vertex 2.06126 0.552313 0.5 + vertex 1.73205 1 1.22465e-16 + vertex 1.93185 0.517638 1.22465e-16 + endloop + endfacet + facet normal -0.892909 -0.369855 -0.256751 + outer loop + vertex 1.93185 0.517638 1.22465e-16 + vertex 1.73205 1 1.22465e-16 + vertex 1.84808 1.06699 -0.5 + endloop + endfacet + facet normal -0.892909 -0.369855 -0.256751 + outer loop + vertex 1.93185 0.517638 1.22465e-16 + vertex 1.84808 1.06699 -0.5 + vertex 2.06126 0.552313 -0.5 + endloop + endfacet + facet normal -0.656082 -0.271758 -0.704063 + outer loop + vertex 2.06126 0.552313 -0.5 + vertex 1.84808 1.06699 -0.5 + vertex 2.16506 1.25 -0.866025 + endloop + endfacet + facet normal -0.656082 -0.271758 -0.704063 + outer loop + vertex 2.06126 0.552313 -0.5 + vertex 2.16506 1.25 -0.866025 + vertex 2.41481 0.647048 -0.866025 + endloop + endfacet + facet normal -0.241041 -0.0998425 -0.965366 + outer loop + vertex 2.41481 0.647048 -0.866025 + vertex 2.16506 1.25 -0.866025 + vertex 2.59808 1.5 -1 + endloop + endfacet + facet normal -0.241041 -0.0998425 -0.965366 + outer loop + vertex 2.41481 0.647048 -0.866025 + vertex 2.59808 1.5 -1 + vertex 2.89778 0.776457 -1 + endloop + endfacet + facet normal 0.241041 0.0998425 -0.965366 + outer loop + vertex 2.89778 0.776457 -1 + vertex 2.59808 1.5 -1 + vertex 3.03109 1.75 -0.866025 + endloop + endfacet + facet normal 0.241041 0.0998425 -0.965366 + outer loop + vertex 2.89778 0.776457 -1 + vertex 3.03109 1.75 -0.866025 + vertex 3.38074 0.905867 -0.866025 + endloop + endfacet + facet normal 0.656082 0.271758 -0.704063 + outer loop + vertex 3.38074 0.905867 -0.866025 + vertex 3.03109 1.75 -0.866025 + vertex 3.34808 1.93301 -0.5 + endloop + endfacet + facet normal 0.656082 0.271758 -0.704063 + outer loop + vertex 3.38074 0.905867 -0.866025 + vertex 3.34808 1.93301 -0.5 + vertex 3.73429 1.0006 -0.5 + endloop + endfacet + facet normal 0.892909 0.369855 -0.256751 + outer loop + vertex 3.73429 1.0006 -0.5 + vertex 3.34808 1.93301 -0.5 + vertex 3.4641 2 -2.44929e-16 + endloop + endfacet + facet normal 0.892909 0.369855 -0.256751 + outer loop + vertex 3.73429 1.0006 -0.5 + vertex 3.4641 2 -2.44929e-16 + vertex 3.8637 1.03528 -2.44929e-16 + endloop + endfacet + facet normal 0.766758 0.588354 0.256751 + outer loop + vertex 3.4641 2 0 + vertex 2.82843 2.82843 0 + vertex 2.73369 2.73369 0.5 + endloop + endfacet + facet normal 0.766758 0.588354 0.256751 + outer loop + vertex 3.4641 2 0 + vertex 2.73369 2.73369 0.5 + vertex 3.34808 1.93301 0.5 + endloop + endfacet + facet normal 0.56339 0.432305 0.704063 + outer loop + vertex 3.34808 1.93301 0.5 + vertex 2.73369 2.73369 0.5 + vertex 2.47487 2.47487 0.866025 + endloop + endfacet + facet normal 0.56339 0.432305 0.704063 + outer loop + vertex 3.34808 1.93301 0.5 + vertex 2.47487 2.47487 0.866025 + vertex 3.03109 1.75 0.866025 + endloop + endfacet + facet normal 0.206987 0.158826 0.965366 + outer loop + vertex 3.03109 1.75 0.866025 + vertex 2.47487 2.47487 0.866025 + vertex 2.12132 2.12132 1 + endloop + endfacet + facet normal 0.206987 0.158826 0.965366 + outer loop + vertex 3.03109 1.75 0.866025 + vertex 2.12132 2.12132 1 + vertex 2.59808 1.5 1 + endloop + endfacet + facet normal -0.206987 -0.158826 0.965366 + outer loop + vertex 2.59808 1.5 1 + vertex 2.12132 2.12132 1 + vertex 1.76777 1.76777 0.866025 + endloop + endfacet + facet normal -0.206987 -0.158826 0.965366 + outer loop + vertex 2.59808 1.5 1 + vertex 1.76777 1.76777 0.866025 + vertex 2.16506 1.25 0.866025 + endloop + endfacet + facet normal -0.56339 -0.432305 0.704063 + outer loop + vertex 2.16506 1.25 0.866025 + vertex 1.76777 1.76777 0.866025 + vertex 1.50895 1.50895 0.5 + endloop + endfacet + facet normal -0.56339 -0.432305 0.704063 + outer loop + vertex 2.16506 1.25 0.866025 + vertex 1.50895 1.50895 0.5 + vertex 1.84808 1.06699 0.5 + endloop + endfacet + facet normal -0.766758 -0.588354 0.256751 + outer loop + vertex 1.84808 1.06699 0.5 + vertex 1.50895 1.50895 0.5 + vertex 1.41421 1.41421 1.22465e-16 + endloop + endfacet + facet normal -0.766758 -0.588354 0.256751 + outer loop + vertex 1.84808 1.06699 0.5 + vertex 1.41421 1.41421 1.22465e-16 + vertex 1.73205 1 1.22465e-16 + endloop + endfacet + facet normal -0.766758 -0.588354 -0.256751 + outer loop + vertex 1.73205 1 1.22465e-16 + vertex 1.41421 1.41421 1.22465e-16 + vertex 1.50895 1.50895 -0.5 + endloop + endfacet + facet normal -0.766758 -0.588354 -0.256751 + outer loop + vertex 1.73205 1 1.22465e-16 + vertex 1.50895 1.50895 -0.5 + vertex 1.84808 1.06699 -0.5 + endloop + endfacet + facet normal -0.56339 -0.432305 -0.704063 + outer loop + vertex 1.84808 1.06699 -0.5 + vertex 1.50895 1.50895 -0.5 + vertex 1.76777 1.76777 -0.866025 + endloop + endfacet + facet normal -0.56339 -0.432305 -0.704063 + outer loop + vertex 1.84808 1.06699 -0.5 + vertex 1.76777 1.76777 -0.866025 + vertex 2.16506 1.25 -0.866025 + endloop + endfacet + facet normal -0.206987 -0.158826 -0.965366 + outer loop + vertex 2.16506 1.25 -0.866025 + vertex 1.76777 1.76777 -0.866025 + vertex 2.12132 2.12132 -1 + endloop + endfacet + facet normal -0.206987 -0.158826 -0.965366 + outer loop + vertex 2.16506 1.25 -0.866025 + vertex 2.12132 2.12132 -1 + vertex 2.59808 1.5 -1 + endloop + endfacet + facet normal 0.206987 0.158826 -0.965366 + outer loop + vertex 2.59808 1.5 -1 + vertex 2.12132 2.12132 -1 + vertex 2.47487 2.47487 -0.866025 + endloop + endfacet + facet normal 0.206987 0.158826 -0.965366 + outer loop + vertex 2.59808 1.5 -1 + vertex 2.47487 2.47487 -0.866025 + vertex 3.03109 1.75 -0.866025 + endloop + endfacet + facet normal 0.56339 0.432305 -0.704063 + outer loop + vertex 3.03109 1.75 -0.866025 + vertex 2.47487 2.47487 -0.866025 + vertex 2.73369 2.73369 -0.5 + endloop + endfacet + facet normal 0.56339 0.432305 -0.704063 + outer loop + vertex 3.03109 1.75 -0.866025 + vertex 2.73369 2.73369 -0.5 + vertex 3.34808 1.93301 -0.5 + endloop + endfacet + facet normal 0.766758 0.588354 -0.256751 + outer loop + vertex 3.34808 1.93301 -0.5 + vertex 2.73369 2.73369 -0.5 + vertex 2.82843 2.82843 -2.44929e-16 + endloop + endfacet + facet normal 0.766758 0.588354 -0.256751 + outer loop + vertex 3.34808 1.93301 -0.5 + vertex 2.82843 2.82843 -2.44929e-16 + vertex 3.4641 2 -2.44929e-16 + endloop + endfacet + facet normal 0.588354 0.766758 0.256751 + outer loop + vertex 2.82843 2.82843 0 + vertex 2 3.4641 0 + vertex 1.93301 3.34808 0.5 + endloop + endfacet + facet normal 0.588354 0.766758 0.256751 + outer loop + vertex 2.82843 2.82843 0 + vertex 1.93301 3.34808 0.5 + vertex 2.73369 2.73369 0.5 + endloop + endfacet + facet normal 0.432305 0.56339 0.704063 + outer loop + vertex 2.73369 2.73369 0.5 + vertex 1.93301 3.34808 0.5 + vertex 1.75 3.03109 0.866025 + endloop + endfacet + facet normal 0.432305 0.56339 0.704063 + outer loop + vertex 2.73369 2.73369 0.5 + vertex 1.75 3.03109 0.866025 + vertex 2.47487 2.47487 0.866025 + endloop + endfacet + facet normal 0.158826 0.206987 0.965366 + outer loop + vertex 2.47487 2.47487 0.866025 + vertex 1.75 3.03109 0.866025 + vertex 1.5 2.59808 1 + endloop + endfacet + facet normal 0.158826 0.206987 0.965366 + outer loop + vertex 2.47487 2.47487 0.866025 + vertex 1.5 2.59808 1 + vertex 2.12132 2.12132 1 + endloop + endfacet + facet normal -0.158826 -0.206987 0.965366 + outer loop + vertex 2.12132 2.12132 1 + vertex 1.5 2.59808 1 + vertex 1.25 2.16506 0.866025 + endloop + endfacet + facet normal -0.158826 -0.206987 0.965366 + outer loop + vertex 2.12132 2.12132 1 + vertex 1.25 2.16506 0.866025 + vertex 1.76777 1.76777 0.866025 + endloop + endfacet + facet normal -0.432305 -0.56339 0.704063 + outer loop + vertex 1.76777 1.76777 0.866025 + vertex 1.25 2.16506 0.866025 + vertex 1.06699 1.84808 0.5 + endloop + endfacet + facet normal -0.432305 -0.56339 0.704063 + outer loop + vertex 1.76777 1.76777 0.866025 + vertex 1.06699 1.84808 0.5 + vertex 1.50895 1.50895 0.5 + endloop + endfacet + facet normal -0.588354 -0.766758 0.256751 + outer loop + vertex 1.50895 1.50895 0.5 + vertex 1.06699 1.84808 0.5 + vertex 1 1.73205 1.22465e-16 + endloop + endfacet + facet normal -0.588354 -0.766758 0.256751 + outer loop + vertex 1.50895 1.50895 0.5 + vertex 1 1.73205 1.22465e-16 + vertex 1.41421 1.41421 1.22465e-16 + endloop + endfacet + facet normal -0.588354 -0.766758 -0.256751 + outer loop + vertex 1.41421 1.41421 1.22465e-16 + vertex 1 1.73205 1.22465e-16 + vertex 1.06699 1.84808 -0.5 + endloop + endfacet + facet normal -0.588354 -0.766758 -0.256751 + outer loop + vertex 1.41421 1.41421 1.22465e-16 + vertex 1.06699 1.84808 -0.5 + vertex 1.50895 1.50895 -0.5 + endloop + endfacet + facet normal -0.432305 -0.56339 -0.704063 + outer loop + vertex 1.50895 1.50895 -0.5 + vertex 1.06699 1.84808 -0.5 + vertex 1.25 2.16506 -0.866025 + endloop + endfacet + facet normal -0.432305 -0.56339 -0.704063 + outer loop + vertex 1.50895 1.50895 -0.5 + vertex 1.25 2.16506 -0.866025 + vertex 1.76777 1.76777 -0.866025 + endloop + endfacet + facet normal -0.158826 -0.206987 -0.965366 + outer loop + vertex 1.76777 1.76777 -0.866025 + vertex 1.25 2.16506 -0.866025 + vertex 1.5 2.59808 -1 + endloop + endfacet + facet normal -0.158826 -0.206987 -0.965366 + outer loop + vertex 1.76777 1.76777 -0.866025 + vertex 1.5 2.59808 -1 + vertex 2.12132 2.12132 -1 + endloop + endfacet + facet normal 0.158826 0.206987 -0.965366 + outer loop + vertex 2.12132 2.12132 -1 + vertex 1.5 2.59808 -1 + vertex 1.75 3.03109 -0.866025 + endloop + endfacet + facet normal 0.158826 0.206987 -0.965366 + outer loop + vertex 2.12132 2.12132 -1 + vertex 1.75 3.03109 -0.866025 + vertex 2.47487 2.47487 -0.866025 + endloop + endfacet + facet normal 0.432305 0.56339 -0.704063 + outer loop + vertex 2.47487 2.47487 -0.866025 + vertex 1.75 3.03109 -0.866025 + vertex 1.93301 3.34808 -0.5 + endloop + endfacet + facet normal 0.432305 0.56339 -0.704063 + outer loop + vertex 2.47487 2.47487 -0.866025 + vertex 1.93301 3.34808 -0.5 + vertex 2.73369 2.73369 -0.5 + endloop + endfacet + facet normal 0.588354 0.766758 -0.256751 + outer loop + vertex 2.73369 2.73369 -0.5 + vertex 1.93301 3.34808 -0.5 + vertex 2 3.4641 -2.44929e-16 + endloop + endfacet + facet normal 0.588354 0.766758 -0.256751 + outer loop + vertex 2.73369 2.73369 -0.5 + vertex 2 3.4641 -2.44929e-16 + vertex 2.82843 2.82843 -2.44929e-16 + endloop + endfacet + facet normal 0.369855 0.892909 0.256751 + outer loop + vertex 2 3.4641 0 + vertex 1.03528 3.8637 0 + vertex 1.0006 3.73429 0.5 + endloop + endfacet + facet normal 0.369855 0.892909 0.256751 + outer loop + vertex 2 3.4641 0 + vertex 1.0006 3.73429 0.5 + vertex 1.93301 3.34808 0.5 + endloop + endfacet + facet normal 0.271758 0.656082 0.704063 + outer loop + vertex 1.93301 3.34808 0.5 + vertex 1.0006 3.73429 0.5 + vertex 0.905867 3.38074 0.866025 + endloop + endfacet + facet normal 0.271758 0.656082 0.704063 + outer loop + vertex 1.93301 3.34808 0.5 + vertex 0.905867 3.38074 0.866025 + vertex 1.75 3.03109 0.866025 + endloop + endfacet + facet normal 0.0998425 0.241041 0.965366 + outer loop + vertex 1.75 3.03109 0.866025 + vertex 0.905867 3.38074 0.866025 + vertex 0.776457 2.89778 1 + endloop + endfacet + facet normal 0.0998425 0.241041 0.965366 + outer loop + vertex 1.75 3.03109 0.866025 + vertex 0.776457 2.89778 1 + vertex 1.5 2.59808 1 + endloop + endfacet + facet normal -0.0998425 -0.241041 0.965366 + outer loop + vertex 1.5 2.59808 1 + vertex 0.776457 2.89778 1 + vertex 0.647048 2.41481 0.866025 + endloop + endfacet + facet normal -0.0998425 -0.241041 0.965366 + outer loop + vertex 1.5 2.59808 1 + vertex 0.647048 2.41481 0.866025 + vertex 1.25 2.16506 0.866025 + endloop + endfacet + facet normal -0.271758 -0.656082 0.704063 + outer loop + vertex 1.25 2.16506 0.866025 + vertex 0.647048 2.41481 0.866025 + vertex 0.552313 2.06126 0.5 + endloop + endfacet + facet normal -0.271758 -0.656082 0.704063 + outer loop + vertex 1.25 2.16506 0.866025 + vertex 0.552313 2.06126 0.5 + vertex 1.06699 1.84808 0.5 + endloop + endfacet + facet normal -0.369855 -0.892909 0.256751 + outer loop + vertex 1.06699 1.84808 0.5 + vertex 0.552313 2.06126 0.5 + vertex 0.517638 1.93185 1.22465e-16 + endloop + endfacet + facet normal -0.369855 -0.892909 0.256751 + outer loop + vertex 1.06699 1.84808 0.5 + vertex 0.517638 1.93185 1.22465e-16 + vertex 1 1.73205 1.22465e-16 + endloop + endfacet + facet normal -0.369855 -0.892909 -0.256751 + outer loop + vertex 1 1.73205 1.22465e-16 + vertex 0.517638 1.93185 1.22465e-16 + vertex 0.552313 2.06126 -0.5 + endloop + endfacet + facet normal -0.369855 -0.892909 -0.256751 + outer loop + vertex 1 1.73205 1.22465e-16 + vertex 0.552313 2.06126 -0.5 + vertex 1.06699 1.84808 -0.5 + endloop + endfacet + facet normal -0.271758 -0.656082 -0.704063 + outer loop + vertex 1.06699 1.84808 -0.5 + vertex 0.552313 2.06126 -0.5 + vertex 0.647048 2.41481 -0.866025 + endloop + endfacet + facet normal -0.271758 -0.656082 -0.704063 + outer loop + vertex 1.06699 1.84808 -0.5 + vertex 0.647048 2.41481 -0.866025 + vertex 1.25 2.16506 -0.866025 + endloop + endfacet + facet normal -0.0998425 -0.241041 -0.965366 + outer loop + vertex 1.25 2.16506 -0.866025 + vertex 0.647048 2.41481 -0.866025 + vertex 0.776457 2.89778 -1 + endloop + endfacet + facet normal -0.0998425 -0.241041 -0.965366 + outer loop + vertex 1.25 2.16506 -0.866025 + vertex 0.776457 2.89778 -1 + vertex 1.5 2.59808 -1 + endloop + endfacet + facet normal 0.0998425 0.241041 -0.965366 + outer loop + vertex 1.5 2.59808 -1 + vertex 0.776457 2.89778 -1 + vertex 0.905867 3.38074 -0.866025 + endloop + endfacet + facet normal 0.0998425 0.241041 -0.965366 + outer loop + vertex 1.5 2.59808 -1 + vertex 0.905867 3.38074 -0.866025 + vertex 1.75 3.03109 -0.866025 + endloop + endfacet + facet normal 0.271758 0.656082 -0.704063 + outer loop + vertex 1.75 3.03109 -0.866025 + vertex 0.905867 3.38074 -0.866025 + vertex 1.0006 3.73429 -0.5 + endloop + endfacet + facet normal 0.271758 0.656082 -0.704063 + outer loop + vertex 1.75 3.03109 -0.866025 + vertex 1.0006 3.73429 -0.5 + vertex 1.93301 3.34808 -0.5 + endloop + endfacet + facet normal 0.369855 0.892909 -0.256751 + outer loop + vertex 1.93301 3.34808 -0.5 + vertex 1.0006 3.73429 -0.5 + vertex 1.03528 3.8637 -2.44929e-16 + endloop + endfacet + facet normal 0.369855 0.892909 -0.256751 + outer loop + vertex 1.93301 3.34808 -0.5 + vertex 1.03528 3.8637 -2.44929e-16 + vertex 2 3.4641 -2.44929e-16 + endloop + endfacet + facet normal 0.126151 0.958209 0.256751 + outer loop + vertex 1.03528 3.8637 0 + vertex 2.44929e-16 4 0 + vertex 2.36726e-16 3.86603 0.5 + endloop + endfacet + facet normal 0.126151 0.958209 0.256751 + outer loop + vertex 1.03528 3.8637 0 + vertex 2.36726e-16 3.86603 0.5 + vertex 1.0006 3.73429 0.5 + endloop + endfacet + facet normal 0.0926916 0.704063 0.704063 + outer loop + vertex 1.0006 3.73429 0.5 + vertex 2.36726e-16 3.86603 0.5 + vertex 2.14313e-16 3.5 0.866025 + endloop + endfacet + facet normal 0.0926916 0.704063 0.704063 + outer loop + vertex 1.0006 3.73429 0.5 + vertex 2.14313e-16 3.5 0.866025 + vertex 0.905867 3.38074 0.866025 + endloop + endfacet + facet normal 0.0340544 0.258669 0.965366 + outer loop + vertex 0.905867 3.38074 0.866025 + vertex 2.14313e-16 3.5 0.866025 + vertex 1.83697e-16 3 1 + endloop + endfacet + facet normal 0.0340544 0.258669 0.965366 + outer loop + vertex 0.905867 3.38074 0.866025 + vertex 1.83697e-16 3 1 + vertex 0.776457 2.89778 1 + endloop + endfacet + facet normal -0.0340544 -0.258669 0.965366 + outer loop + vertex 0.776457 2.89778 1 + vertex 1.83697e-16 3 1 + vertex 1.53081e-16 2.5 0.866025 + endloop + endfacet + facet normal -0.0340544 -0.258669 0.965366 + outer loop + vertex 0.776457 2.89778 1 + vertex 1.53081e-16 2.5 0.866025 + vertex 0.647048 2.41481 0.866025 + endloop + endfacet + facet normal -0.0926916 -0.704063 0.704063 + outer loop + vertex 0.647048 2.41481 0.866025 + vertex 1.53081e-16 2.5 0.866025 + vertex 1.30668e-16 2.13397 0.5 + endloop + endfacet + facet normal -0.0926916 -0.704063 0.704063 + outer loop + vertex 0.647048 2.41481 0.866025 + vertex 1.30668e-16 2.13397 0.5 + vertex 0.552313 2.06126 0.5 + endloop + endfacet + facet normal -0.126151 -0.958209 0.256751 + outer loop + vertex 0.552313 2.06126 0.5 + vertex 1.30668e-16 2.13397 0.5 + vertex 1.22465e-16 2 1.22465e-16 + endloop + endfacet + facet normal -0.126151 -0.958209 0.256751 + outer loop + vertex 0.552313 2.06126 0.5 + vertex 1.22465e-16 2 1.22465e-16 + vertex 0.517638 1.93185 1.22465e-16 + endloop + endfacet + facet normal -0.126151 -0.958209 -0.256751 + outer loop + vertex 0.517638 1.93185 1.22465e-16 + vertex 1.22465e-16 2 1.22465e-16 + vertex 1.30668e-16 2.13397 -0.5 + endloop + endfacet + facet normal -0.126151 -0.958209 -0.256751 + outer loop + vertex 0.517638 1.93185 1.22465e-16 + vertex 1.30668e-16 2.13397 -0.5 + vertex 0.552313 2.06126 -0.5 + endloop + endfacet + facet normal -0.0926916 -0.704063 -0.704063 + outer loop + vertex 0.552313 2.06126 -0.5 + vertex 1.30668e-16 2.13397 -0.5 + vertex 1.53081e-16 2.5 -0.866025 + endloop + endfacet + facet normal -0.0926916 -0.704063 -0.704063 + outer loop + vertex 0.552313 2.06126 -0.5 + vertex 1.53081e-16 2.5 -0.866025 + vertex 0.647048 2.41481 -0.866025 + endloop + endfacet + facet normal -0.0340544 -0.258669 -0.965366 + outer loop + vertex 0.647048 2.41481 -0.866025 + vertex 1.53081e-16 2.5 -0.866025 + vertex 1.83697e-16 3 -1 + endloop + endfacet + facet normal -0.0340544 -0.258669 -0.965366 + outer loop + vertex 0.647048 2.41481 -0.866025 + vertex 1.83697e-16 3 -1 + vertex 0.776457 2.89778 -1 + endloop + endfacet + facet normal 0.0340544 0.258669 -0.965366 + outer loop + vertex 0.776457 2.89778 -1 + vertex 1.83697e-16 3 -1 + vertex 2.14313e-16 3.5 -0.866025 + endloop + endfacet + facet normal 0.0340544 0.258669 -0.965366 + outer loop + vertex 0.776457 2.89778 -1 + vertex 2.14313e-16 3.5 -0.866025 + vertex 0.905867 3.38074 -0.866025 + endloop + endfacet + facet normal 0.0926916 0.704063 -0.704063 + outer loop + vertex 0.905867 3.38074 -0.866025 + vertex 2.14313e-16 3.5 -0.866025 + vertex 2.36726e-16 3.86603 -0.5 + endloop + endfacet + facet normal 0.0926916 0.704063 -0.704063 + outer loop + vertex 0.905867 3.38074 -0.866025 + vertex 2.36726e-16 3.86603 -0.5 + vertex 1.0006 3.73429 -0.5 + endloop + endfacet + facet normal 0.126151 0.958209 -0.256751 + outer loop + vertex 1.0006 3.73429 -0.5 + vertex 2.36726e-16 3.86603 -0.5 + vertex 2.44929e-16 4 -2.44929e-16 + endloop + endfacet + facet normal 0.126151 0.958209 -0.256751 + outer loop + vertex 1.0006 3.73429 -0.5 + vertex 2.44929e-16 4 -2.44929e-16 + vertex 1.03528 3.8637 -2.44929e-16 + endloop + endfacet + facet normal -0.126151 0.958209 0.256751 + outer loop + vertex 2.44929e-16 4 0 + vertex -1.03528 3.8637 0 + vertex -1.0006 3.73429 0.5 + endloop + endfacet + facet normal -0.126151 0.958209 0.256751 + outer loop + vertex 2.44929e-16 4 0 + vertex -1.0006 3.73429 0.5 + vertex 2.36726e-16 3.86603 0.5 + endloop + endfacet + facet normal -0.0926916 0.704063 0.704063 + outer loop + vertex 2.36726e-16 3.86603 0.5 + vertex -1.0006 3.73429 0.5 + vertex -0.905867 3.38074 0.866025 + endloop + endfacet + facet normal -0.0926916 0.704063 0.704063 + outer loop + vertex 2.36726e-16 3.86603 0.5 + vertex -0.905867 3.38074 0.866025 + vertex 2.14313e-16 3.5 0.866025 + endloop + endfacet + facet normal -0.0340544 0.258669 0.965366 + outer loop + vertex 2.14313e-16 3.5 0.866025 + vertex -0.905867 3.38074 0.866025 + vertex -0.776457 2.89778 1 + endloop + endfacet + facet normal -0.0340544 0.258669 0.965366 + outer loop + vertex 2.14313e-16 3.5 0.866025 + vertex -0.776457 2.89778 1 + vertex 1.83697e-16 3 1 + endloop + endfacet + facet normal 0.0340544 -0.258669 0.965366 + outer loop + vertex 1.83697e-16 3 1 + vertex -0.776457 2.89778 1 + vertex -0.647048 2.41481 0.866025 + endloop + endfacet + facet normal 0.0340544 -0.258669 0.965366 + outer loop + vertex 1.83697e-16 3 1 + vertex -0.647048 2.41481 0.866025 + vertex 1.53081e-16 2.5 0.866025 + endloop + endfacet + facet normal 0.0926916 -0.704063 0.704063 + outer loop + vertex 1.53081e-16 2.5 0.866025 + vertex -0.647048 2.41481 0.866025 + vertex -0.552313 2.06126 0.5 + endloop + endfacet + facet normal 0.0926916 -0.704063 0.704063 + outer loop + vertex 1.53081e-16 2.5 0.866025 + vertex -0.552313 2.06126 0.5 + vertex 1.30668e-16 2.13397 0.5 + endloop + endfacet + facet normal 0.126151 -0.958209 0.256751 + outer loop + vertex 1.30668e-16 2.13397 0.5 + vertex -0.552313 2.06126 0.5 + vertex -0.517638 1.93185 1.22465e-16 + endloop + endfacet + facet normal 0.126151 -0.958209 0.256751 + outer loop + vertex 1.30668e-16 2.13397 0.5 + vertex -0.517638 1.93185 1.22465e-16 + vertex 1.22465e-16 2 1.22465e-16 + endloop + endfacet + facet normal 0.126151 -0.958209 -0.256751 + outer loop + vertex 1.22465e-16 2 1.22465e-16 + vertex -0.517638 1.93185 1.22465e-16 + vertex -0.552313 2.06126 -0.5 + endloop + endfacet + facet normal 0.126151 -0.958209 -0.256751 + outer loop + vertex 1.22465e-16 2 1.22465e-16 + vertex -0.552313 2.06126 -0.5 + vertex 1.30668e-16 2.13397 -0.5 + endloop + endfacet + facet normal 0.0926916 -0.704063 -0.704063 + outer loop + vertex 1.30668e-16 2.13397 -0.5 + vertex -0.552313 2.06126 -0.5 + vertex -0.647048 2.41481 -0.866025 + endloop + endfacet + facet normal 0.0926916 -0.704063 -0.704063 + outer loop + vertex 1.30668e-16 2.13397 -0.5 + vertex -0.647048 2.41481 -0.866025 + vertex 1.53081e-16 2.5 -0.866025 + endloop + endfacet + facet normal 0.0340544 -0.258669 -0.965366 + outer loop + vertex 1.53081e-16 2.5 -0.866025 + vertex -0.647048 2.41481 -0.866025 + vertex -0.776457 2.89778 -1 + endloop + endfacet + facet normal 0.0340544 -0.258669 -0.965366 + outer loop + vertex 1.53081e-16 2.5 -0.866025 + vertex -0.776457 2.89778 -1 + vertex 1.83697e-16 3 -1 + endloop + endfacet + facet normal -0.0340544 0.258669 -0.965366 + outer loop + vertex 1.83697e-16 3 -1 + vertex -0.776457 2.89778 -1 + vertex -0.905867 3.38074 -0.866025 + endloop + endfacet + facet normal -0.0340544 0.258669 -0.965366 + outer loop + vertex 1.83697e-16 3 -1 + vertex -0.905867 3.38074 -0.866025 + vertex 2.14313e-16 3.5 -0.866025 + endloop + endfacet + facet normal -0.0926916 0.704063 -0.704063 + outer loop + vertex 2.14313e-16 3.5 -0.866025 + vertex -0.905867 3.38074 -0.866025 + vertex -1.0006 3.73429 -0.5 + endloop + endfacet + facet normal -0.0926916 0.704063 -0.704063 + outer loop + vertex 2.14313e-16 3.5 -0.866025 + vertex -1.0006 3.73429 -0.5 + vertex 2.36726e-16 3.86603 -0.5 + endloop + endfacet + facet normal -0.126151 0.958209 -0.256751 + outer loop + vertex 2.36726e-16 3.86603 -0.5 + vertex -1.0006 3.73429 -0.5 + vertex -1.03528 3.8637 -2.44929e-16 + endloop + endfacet + facet normal -0.126151 0.958209 -0.256751 + outer loop + vertex 2.36726e-16 3.86603 -0.5 + vertex -1.03528 3.8637 -2.44929e-16 + vertex 2.44929e-16 4 -2.44929e-16 + endloop + endfacet + facet normal -0.369855 0.892909 0.256751 + outer loop + vertex -1.03528 3.8637 0 + vertex -2 3.4641 0 + vertex -1.93301 3.34808 0.5 + endloop + endfacet + facet normal -0.369855 0.892909 0.256751 + outer loop + vertex -1.03528 3.8637 0 + vertex -1.93301 3.34808 0.5 + vertex -1.0006 3.73429 0.5 + endloop + endfacet + facet normal -0.271758 0.656082 0.704063 + outer loop + vertex -1.0006 3.73429 0.5 + vertex -1.93301 3.34808 0.5 + vertex -1.75 3.03109 0.866025 + endloop + endfacet + facet normal -0.271758 0.656082 0.704063 + outer loop + vertex -1.0006 3.73429 0.5 + vertex -1.75 3.03109 0.866025 + vertex -0.905867 3.38074 0.866025 + endloop + endfacet + facet normal -0.0998425 0.241041 0.965366 + outer loop + vertex -0.905867 3.38074 0.866025 + vertex -1.75 3.03109 0.866025 + vertex -1.5 2.59808 1 + endloop + endfacet + facet normal -0.0998425 0.241041 0.965366 + outer loop + vertex -0.905867 3.38074 0.866025 + vertex -1.5 2.59808 1 + vertex -0.776457 2.89778 1 + endloop + endfacet + facet normal 0.0998425 -0.241041 0.965366 + outer loop + vertex -0.776457 2.89778 1 + vertex -1.5 2.59808 1 + vertex -1.25 2.16506 0.866025 + endloop + endfacet + facet normal 0.0998425 -0.241041 0.965366 + outer loop + vertex -0.776457 2.89778 1 + vertex -1.25 2.16506 0.866025 + vertex -0.647048 2.41481 0.866025 + endloop + endfacet + facet normal 0.271758 -0.656082 0.704063 + outer loop + vertex -0.647048 2.41481 0.866025 + vertex -1.25 2.16506 0.866025 + vertex -1.06699 1.84808 0.5 + endloop + endfacet + facet normal 0.271758 -0.656082 0.704063 + outer loop + vertex -0.647048 2.41481 0.866025 + vertex -1.06699 1.84808 0.5 + vertex -0.552313 2.06126 0.5 + endloop + endfacet + facet normal 0.369855 -0.892909 0.256751 + outer loop + vertex -0.552313 2.06126 0.5 + vertex -1.06699 1.84808 0.5 + vertex -1 1.73205 1.22465e-16 + endloop + endfacet + facet normal 0.369855 -0.892909 0.256751 + outer loop + vertex -0.552313 2.06126 0.5 + vertex -1 1.73205 1.22465e-16 + vertex -0.517638 1.93185 1.22465e-16 + endloop + endfacet + facet normal 0.369855 -0.892909 -0.256751 + outer loop + vertex -0.517638 1.93185 1.22465e-16 + vertex -1 1.73205 1.22465e-16 + vertex -1.06699 1.84808 -0.5 + endloop + endfacet + facet normal 0.369855 -0.892909 -0.256751 + outer loop + vertex -0.517638 1.93185 1.22465e-16 + vertex -1.06699 1.84808 -0.5 + vertex -0.552313 2.06126 -0.5 + endloop + endfacet + facet normal 0.271758 -0.656082 -0.704063 + outer loop + vertex -0.552313 2.06126 -0.5 + vertex -1.06699 1.84808 -0.5 + vertex -1.25 2.16506 -0.866025 + endloop + endfacet + facet normal 0.271758 -0.656082 -0.704063 + outer loop + vertex -0.552313 2.06126 -0.5 + vertex -1.25 2.16506 -0.866025 + vertex -0.647048 2.41481 -0.866025 + endloop + endfacet + facet normal 0.0998425 -0.241041 -0.965366 + outer loop + vertex -0.647048 2.41481 -0.866025 + vertex -1.25 2.16506 -0.866025 + vertex -1.5 2.59808 -1 + endloop + endfacet + facet normal 0.0998425 -0.241041 -0.965366 + outer loop + vertex -0.647048 2.41481 -0.866025 + vertex -1.5 2.59808 -1 + vertex -0.776457 2.89778 -1 + endloop + endfacet + facet normal -0.0998425 0.241041 -0.965366 + outer loop + vertex -0.776457 2.89778 -1 + vertex -1.5 2.59808 -1 + vertex -1.75 3.03109 -0.866025 + endloop + endfacet + facet normal -0.0998425 0.241041 -0.965366 + outer loop + vertex -0.776457 2.89778 -1 + vertex -1.75 3.03109 -0.866025 + vertex -0.905867 3.38074 -0.866025 + endloop + endfacet + facet normal -0.271758 0.656082 -0.704063 + outer loop + vertex -0.905867 3.38074 -0.866025 + vertex -1.75 3.03109 -0.866025 + vertex -1.93301 3.34808 -0.5 + endloop + endfacet + facet normal -0.271758 0.656082 -0.704063 + outer loop + vertex -0.905867 3.38074 -0.866025 + vertex -1.93301 3.34808 -0.5 + vertex -1.0006 3.73429 -0.5 + endloop + endfacet + facet normal -0.369855 0.892909 -0.256751 + outer loop + vertex -1.0006 3.73429 -0.5 + vertex -1.93301 3.34808 -0.5 + vertex -2 3.4641 -2.44929e-16 + endloop + endfacet + facet normal -0.369855 0.892909 -0.256751 + outer loop + vertex -1.0006 3.73429 -0.5 + vertex -2 3.4641 -2.44929e-16 + vertex -1.03528 3.8637 -2.44929e-16 + endloop + endfacet + facet normal -0.588354 0.766758 0.256751 + outer loop + vertex -2 3.4641 0 + vertex -2.82843 2.82843 0 + vertex -2.73369 2.73369 0.5 + endloop + endfacet + facet normal -0.588354 0.766758 0.256751 + outer loop + vertex -2 3.4641 0 + vertex -2.73369 2.73369 0.5 + vertex -1.93301 3.34808 0.5 + endloop + endfacet + facet normal -0.432305 0.56339 0.704063 + outer loop + vertex -1.93301 3.34808 0.5 + vertex -2.73369 2.73369 0.5 + vertex -2.47487 2.47487 0.866025 + endloop + endfacet + facet normal -0.432305 0.56339 0.704063 + outer loop + vertex -1.93301 3.34808 0.5 + vertex -2.47487 2.47487 0.866025 + vertex -1.75 3.03109 0.866025 + endloop + endfacet + facet normal -0.158826 0.206987 0.965366 + outer loop + vertex -1.75 3.03109 0.866025 + vertex -2.47487 2.47487 0.866025 + vertex -2.12132 2.12132 1 + endloop + endfacet + facet normal -0.158826 0.206987 0.965366 + outer loop + vertex -1.75 3.03109 0.866025 + vertex -2.12132 2.12132 1 + vertex -1.5 2.59808 1 + endloop + endfacet + facet normal 0.158826 -0.206987 0.965366 + outer loop + vertex -1.5 2.59808 1 + vertex -2.12132 2.12132 1 + vertex -1.76777 1.76777 0.866025 + endloop + endfacet + facet normal 0.158826 -0.206987 0.965366 + outer loop + vertex -1.5 2.59808 1 + vertex -1.76777 1.76777 0.866025 + vertex -1.25 2.16506 0.866025 + endloop + endfacet + facet normal 0.432305 -0.56339 0.704063 + outer loop + vertex -1.25 2.16506 0.866025 + vertex -1.76777 1.76777 0.866025 + vertex -1.50895 1.50895 0.5 + endloop + endfacet + facet normal 0.432305 -0.56339 0.704063 + outer loop + vertex -1.25 2.16506 0.866025 + vertex -1.50895 1.50895 0.5 + vertex -1.06699 1.84808 0.5 + endloop + endfacet + facet normal 0.588354 -0.766758 0.256751 + outer loop + vertex -1.06699 1.84808 0.5 + vertex -1.50895 1.50895 0.5 + vertex -1.41421 1.41421 1.22465e-16 + endloop + endfacet + facet normal 0.588354 -0.766758 0.256751 + outer loop + vertex -1.06699 1.84808 0.5 + vertex -1.41421 1.41421 1.22465e-16 + vertex -1 1.73205 1.22465e-16 + endloop + endfacet + facet normal 0.588354 -0.766758 -0.256751 + outer loop + vertex -1 1.73205 1.22465e-16 + vertex -1.41421 1.41421 1.22465e-16 + vertex -1.50895 1.50895 -0.5 + endloop + endfacet + facet normal 0.588354 -0.766758 -0.256751 + outer loop + vertex -1 1.73205 1.22465e-16 + vertex -1.50895 1.50895 -0.5 + vertex -1.06699 1.84808 -0.5 + endloop + endfacet + facet normal 0.432305 -0.56339 -0.704063 + outer loop + vertex -1.06699 1.84808 -0.5 + vertex -1.50895 1.50895 -0.5 + vertex -1.76777 1.76777 -0.866025 + endloop + endfacet + facet normal 0.432305 -0.56339 -0.704063 + outer loop + vertex -1.06699 1.84808 -0.5 + vertex -1.76777 1.76777 -0.866025 + vertex -1.25 2.16506 -0.866025 + endloop + endfacet + facet normal 0.158826 -0.206987 -0.965366 + outer loop + vertex -1.25 2.16506 -0.866025 + vertex -1.76777 1.76777 -0.866025 + vertex -2.12132 2.12132 -1 + endloop + endfacet + facet normal 0.158826 -0.206987 -0.965366 + outer loop + vertex -1.25 2.16506 -0.866025 + vertex -2.12132 2.12132 -1 + vertex -1.5 2.59808 -1 + endloop + endfacet + facet normal -0.158826 0.206987 -0.965366 + outer loop + vertex -1.5 2.59808 -1 + vertex -2.12132 2.12132 -1 + vertex -2.47487 2.47487 -0.866025 + endloop + endfacet + facet normal -0.158826 0.206987 -0.965366 + outer loop + vertex -1.5 2.59808 -1 + vertex -2.47487 2.47487 -0.866025 + vertex -1.75 3.03109 -0.866025 + endloop + endfacet + facet normal -0.432305 0.56339 -0.704063 + outer loop + vertex -1.75 3.03109 -0.866025 + vertex -2.47487 2.47487 -0.866025 + vertex -2.73369 2.73369 -0.5 + endloop + endfacet + facet normal -0.432305 0.56339 -0.704063 + outer loop + vertex -1.75 3.03109 -0.866025 + vertex -2.73369 2.73369 -0.5 + vertex -1.93301 3.34808 -0.5 + endloop + endfacet + facet normal -0.588354 0.766758 -0.256751 + outer loop + vertex -1.93301 3.34808 -0.5 + vertex -2.73369 2.73369 -0.5 + vertex -2.82843 2.82843 -2.44929e-16 + endloop + endfacet + facet normal -0.588354 0.766758 -0.256751 + outer loop + vertex -1.93301 3.34808 -0.5 + vertex -2.82843 2.82843 -2.44929e-16 + vertex -2 3.4641 -2.44929e-16 + endloop + endfacet + facet normal -0.766758 0.588354 0.256751 + outer loop + vertex -2.82843 2.82843 0 + vertex -3.4641 2 0 + vertex -3.34808 1.93301 0.5 + endloop + endfacet + facet normal -0.766758 0.588354 0.256751 + outer loop + vertex -2.82843 2.82843 0 + vertex -3.34808 1.93301 0.5 + vertex -2.73369 2.73369 0.5 + endloop + endfacet + facet normal -0.56339 0.432305 0.704063 + outer loop + vertex -2.73369 2.73369 0.5 + vertex -3.34808 1.93301 0.5 + vertex -3.03109 1.75 0.866025 + endloop + endfacet + facet normal -0.56339 0.432305 0.704063 + outer loop + vertex -2.73369 2.73369 0.5 + vertex -3.03109 1.75 0.866025 + vertex -2.47487 2.47487 0.866025 + endloop + endfacet + facet normal -0.206987 0.158826 0.965366 + outer loop + vertex -2.47487 2.47487 0.866025 + vertex -3.03109 1.75 0.866025 + vertex -2.59808 1.5 1 + endloop + endfacet + facet normal -0.206987 0.158826 0.965366 + outer loop + vertex -2.47487 2.47487 0.866025 + vertex -2.59808 1.5 1 + vertex -2.12132 2.12132 1 + endloop + endfacet + facet normal 0.206987 -0.158826 0.965366 + outer loop + vertex -2.12132 2.12132 1 + vertex -2.59808 1.5 1 + vertex -2.16506 1.25 0.866025 + endloop + endfacet + facet normal 0.206987 -0.158826 0.965366 + outer loop + vertex -2.12132 2.12132 1 + vertex -2.16506 1.25 0.866025 + vertex -1.76777 1.76777 0.866025 + endloop + endfacet + facet normal 0.56339 -0.432305 0.704063 + outer loop + vertex -1.76777 1.76777 0.866025 + vertex -2.16506 1.25 0.866025 + vertex -1.84808 1.06699 0.5 + endloop + endfacet + facet normal 0.56339 -0.432305 0.704063 + outer loop + vertex -1.76777 1.76777 0.866025 + vertex -1.84808 1.06699 0.5 + vertex -1.50895 1.50895 0.5 + endloop + endfacet + facet normal 0.766758 -0.588354 0.256751 + outer loop + vertex -1.50895 1.50895 0.5 + vertex -1.84808 1.06699 0.5 + vertex -1.73205 1 1.22465e-16 + endloop + endfacet + facet normal 0.766758 -0.588354 0.256751 + outer loop + vertex -1.50895 1.50895 0.5 + vertex -1.73205 1 1.22465e-16 + vertex -1.41421 1.41421 1.22465e-16 + endloop + endfacet + facet normal 0.766758 -0.588354 -0.256751 + outer loop + vertex -1.41421 1.41421 1.22465e-16 + vertex -1.73205 1 1.22465e-16 + vertex -1.84808 1.06699 -0.5 + endloop + endfacet + facet normal 0.766758 -0.588354 -0.256751 + outer loop + vertex -1.41421 1.41421 1.22465e-16 + vertex -1.84808 1.06699 -0.5 + vertex -1.50895 1.50895 -0.5 + endloop + endfacet + facet normal 0.56339 -0.432305 -0.704063 + outer loop + vertex -1.50895 1.50895 -0.5 + vertex -1.84808 1.06699 -0.5 + vertex -2.16506 1.25 -0.866025 + endloop + endfacet + facet normal 0.56339 -0.432305 -0.704063 + outer loop + vertex -1.50895 1.50895 -0.5 + vertex -2.16506 1.25 -0.866025 + vertex -1.76777 1.76777 -0.866025 + endloop + endfacet + facet normal 0.206987 -0.158826 -0.965366 + outer loop + vertex -1.76777 1.76777 -0.866025 + vertex -2.16506 1.25 -0.866025 + vertex -2.59808 1.5 -1 + endloop + endfacet + facet normal 0.206987 -0.158826 -0.965366 + outer loop + vertex -1.76777 1.76777 -0.866025 + vertex -2.59808 1.5 -1 + vertex -2.12132 2.12132 -1 + endloop + endfacet + facet normal -0.206987 0.158826 -0.965366 + outer loop + vertex -2.12132 2.12132 -1 + vertex -2.59808 1.5 -1 + vertex -3.03109 1.75 -0.866025 + endloop + endfacet + facet normal -0.206987 0.158826 -0.965366 + outer loop + vertex -2.12132 2.12132 -1 + vertex -3.03109 1.75 -0.866025 + vertex -2.47487 2.47487 -0.866025 + endloop + endfacet + facet normal -0.56339 0.432305 -0.704063 + outer loop + vertex -2.47487 2.47487 -0.866025 + vertex -3.03109 1.75 -0.866025 + vertex -3.34808 1.93301 -0.5 + endloop + endfacet + facet normal -0.56339 0.432305 -0.704063 + outer loop + vertex -2.47487 2.47487 -0.866025 + vertex -3.34808 1.93301 -0.5 + vertex -2.73369 2.73369 -0.5 + endloop + endfacet + facet normal -0.766758 0.588354 -0.256751 + outer loop + vertex -2.73369 2.73369 -0.5 + vertex -3.34808 1.93301 -0.5 + vertex -3.4641 2 -2.44929e-16 + endloop + endfacet + facet normal -0.766758 0.588354 -0.256751 + outer loop + vertex -2.73369 2.73369 -0.5 + vertex -3.4641 2 -2.44929e-16 + vertex -2.82843 2.82843 -2.44929e-16 + endloop + endfacet + facet normal -0.892909 0.369855 0.256751 + outer loop + vertex -3.4641 2 0 + vertex -3.8637 1.03528 0 + vertex -3.73429 1.0006 0.5 + endloop + endfacet + facet normal -0.892909 0.369855 0.256751 + outer loop + vertex -3.4641 2 0 + vertex -3.73429 1.0006 0.5 + vertex -3.34808 1.93301 0.5 + endloop + endfacet + facet normal -0.656082 0.271758 0.704063 + outer loop + vertex -3.34808 1.93301 0.5 + vertex -3.73429 1.0006 0.5 + vertex -3.38074 0.905867 0.866025 + endloop + endfacet + facet normal -0.656082 0.271758 0.704063 + outer loop + vertex -3.34808 1.93301 0.5 + vertex -3.38074 0.905867 0.866025 + vertex -3.03109 1.75 0.866025 + endloop + endfacet + facet normal -0.241041 0.0998425 0.965366 + outer loop + vertex -3.03109 1.75 0.866025 + vertex -3.38074 0.905867 0.866025 + vertex -2.89778 0.776457 1 + endloop + endfacet + facet normal -0.241041 0.0998425 0.965366 + outer loop + vertex -3.03109 1.75 0.866025 + vertex -2.89778 0.776457 1 + vertex -2.59808 1.5 1 + endloop + endfacet + facet normal 0.241041 -0.0998425 0.965366 + outer loop + vertex -2.59808 1.5 1 + vertex -2.89778 0.776457 1 + vertex -2.41481 0.647048 0.866025 + endloop + endfacet + facet normal 0.241041 -0.0998425 0.965366 + outer loop + vertex -2.59808 1.5 1 + vertex -2.41481 0.647048 0.866025 + vertex -2.16506 1.25 0.866025 + endloop + endfacet + facet normal 0.656082 -0.271758 0.704063 + outer loop + vertex -2.16506 1.25 0.866025 + vertex -2.41481 0.647048 0.866025 + vertex -2.06126 0.552313 0.5 + endloop + endfacet + facet normal 0.656082 -0.271758 0.704063 + outer loop + vertex -2.16506 1.25 0.866025 + vertex -2.06126 0.552313 0.5 + vertex -1.84808 1.06699 0.5 + endloop + endfacet + facet normal 0.892909 -0.369855 0.256751 + outer loop + vertex -1.84808 1.06699 0.5 + vertex -2.06126 0.552313 0.5 + vertex -1.93185 0.517638 1.22465e-16 + endloop + endfacet + facet normal 0.892909 -0.369855 0.256751 + outer loop + vertex -1.84808 1.06699 0.5 + vertex -1.93185 0.517638 1.22465e-16 + vertex -1.73205 1 1.22465e-16 + endloop + endfacet + facet normal 0.892909 -0.369855 -0.256751 + outer loop + vertex -1.73205 1 1.22465e-16 + vertex -1.93185 0.517638 1.22465e-16 + vertex -2.06126 0.552313 -0.5 + endloop + endfacet + facet normal 0.892909 -0.369855 -0.256751 + outer loop + vertex -1.73205 1 1.22465e-16 + vertex -2.06126 0.552313 -0.5 + vertex -1.84808 1.06699 -0.5 + endloop + endfacet + facet normal 0.656082 -0.271758 -0.704063 + outer loop + vertex -1.84808 1.06699 -0.5 + vertex -2.06126 0.552313 -0.5 + vertex -2.41481 0.647048 -0.866025 + endloop + endfacet + facet normal 0.656082 -0.271758 -0.704063 + outer loop + vertex -1.84808 1.06699 -0.5 + vertex -2.41481 0.647048 -0.866025 + vertex -2.16506 1.25 -0.866025 + endloop + endfacet + facet normal 0.241041 -0.0998425 -0.965366 + outer loop + vertex -2.16506 1.25 -0.866025 + vertex -2.41481 0.647048 -0.866025 + vertex -2.89778 0.776457 -1 + endloop + endfacet + facet normal 0.241041 -0.0998425 -0.965366 + outer loop + vertex -2.16506 1.25 -0.866025 + vertex -2.89778 0.776457 -1 + vertex -2.59808 1.5 -1 + endloop + endfacet + facet normal -0.241041 0.0998425 -0.965366 + outer loop + vertex -2.59808 1.5 -1 + vertex -2.89778 0.776457 -1 + vertex -3.38074 0.905867 -0.866025 + endloop + endfacet + facet normal -0.241041 0.0998425 -0.965366 + outer loop + vertex -2.59808 1.5 -1 + vertex -3.38074 0.905867 -0.866025 + vertex -3.03109 1.75 -0.866025 + endloop + endfacet + facet normal -0.656082 0.271758 -0.704063 + outer loop + vertex -3.03109 1.75 -0.866025 + vertex -3.38074 0.905867 -0.866025 + vertex -3.73429 1.0006 -0.5 + endloop + endfacet + facet normal -0.656082 0.271758 -0.704063 + outer loop + vertex -3.03109 1.75 -0.866025 + vertex -3.73429 1.0006 -0.5 + vertex -3.34808 1.93301 -0.5 + endloop + endfacet + facet normal -0.892909 0.369855 -0.256751 + outer loop + vertex -3.34808 1.93301 -0.5 + vertex -3.73429 1.0006 -0.5 + vertex -3.8637 1.03528 -2.44929e-16 + endloop + endfacet + facet normal -0.892909 0.369855 -0.256751 + outer loop + vertex -3.34808 1.93301 -0.5 + vertex -3.8637 1.03528 -2.44929e-16 + vertex -3.4641 2 -2.44929e-16 + endloop + endfacet + facet normal -0.958209 0.126151 0.256751 + outer loop + vertex -3.8637 1.03528 0 + vertex -4 4.89859e-16 0 + vertex -3.86603 4.73452e-16 0.5 + endloop + endfacet + facet normal -0.958209 0.126151 0.256751 + outer loop + vertex -3.8637 1.03528 0 + vertex -3.86603 4.73452e-16 0.5 + vertex -3.73429 1.0006 0.5 + endloop + endfacet + facet normal -0.704063 0.0926916 0.704063 + outer loop + vertex -3.73429 1.0006 0.5 + vertex -3.86603 4.73452e-16 0.5 + vertex -3.5 4.28626e-16 0.866025 + endloop + endfacet + facet normal -0.704063 0.0926916 0.704063 + outer loop + vertex -3.73429 1.0006 0.5 + vertex -3.5 4.28626e-16 0.866025 + vertex -3.38074 0.905867 0.866025 + endloop + endfacet + facet normal -0.258669 0.0340544 0.965366 + outer loop + vertex -3.38074 0.905867 0.866025 + vertex -3.5 4.28626e-16 0.866025 + vertex -3 3.67394e-16 1 + endloop + endfacet + facet normal -0.258669 0.0340544 0.965366 + outer loop + vertex -3.38074 0.905867 0.866025 + vertex -3 3.67394e-16 1 + vertex -2.89778 0.776457 1 + endloop + endfacet + facet normal 0.258669 -0.0340544 0.965366 + outer loop + vertex -2.89778 0.776457 1 + vertex -3 3.67394e-16 1 + vertex -2.5 3.06162e-16 0.866025 + endloop + endfacet + facet normal 0.258669 -0.0340544 0.965366 + outer loop + vertex -2.89778 0.776457 1 + vertex -2.5 3.06162e-16 0.866025 + vertex -2.41481 0.647048 0.866025 + endloop + endfacet + facet normal 0.704063 -0.0926916 0.704063 + outer loop + vertex -2.41481 0.647048 0.866025 + vertex -2.5 3.06162e-16 0.866025 + vertex -2.13397 2.61337e-16 0.5 + endloop + endfacet + facet normal 0.704063 -0.0926916 0.704063 + outer loop + vertex -2.41481 0.647048 0.866025 + vertex -2.13397 2.61337e-16 0.5 + vertex -2.06126 0.552313 0.5 + endloop + endfacet + facet normal 0.958209 -0.126151 0.256751 + outer loop + vertex -2.06126 0.552313 0.5 + vertex -2.13397 2.61337e-16 0.5 + vertex -2 2.44929e-16 1.22465e-16 + endloop + endfacet + facet normal 0.958209 -0.126151 0.256751 + outer loop + vertex -2.06126 0.552313 0.5 + vertex -2 2.44929e-16 1.22465e-16 + vertex -1.93185 0.517638 1.22465e-16 + endloop + endfacet + facet normal 0.958209 -0.126151 -0.256751 + outer loop + vertex -1.93185 0.517638 1.22465e-16 + vertex -2 2.44929e-16 1.22465e-16 + vertex -2.13397 2.61337e-16 -0.5 + endloop + endfacet + facet normal 0.958209 -0.126151 -0.256751 + outer loop + vertex -1.93185 0.517638 1.22465e-16 + vertex -2.13397 2.61337e-16 -0.5 + vertex -2.06126 0.552313 -0.5 + endloop + endfacet + facet normal 0.704063 -0.0926916 -0.704063 + outer loop + vertex -2.06126 0.552313 -0.5 + vertex -2.13397 2.61337e-16 -0.5 + vertex -2.5 3.06162e-16 -0.866025 + endloop + endfacet + facet normal 0.704063 -0.0926916 -0.704063 + outer loop + vertex -2.06126 0.552313 -0.5 + vertex -2.5 3.06162e-16 -0.866025 + vertex -2.41481 0.647048 -0.866025 + endloop + endfacet + facet normal 0.258669 -0.0340544 -0.965366 + outer loop + vertex -2.41481 0.647048 -0.866025 + vertex -2.5 3.06162e-16 -0.866025 + vertex -3 3.67394e-16 -1 + endloop + endfacet + facet normal 0.258669 -0.0340544 -0.965366 + outer loop + vertex -2.41481 0.647048 -0.866025 + vertex -3 3.67394e-16 -1 + vertex -2.89778 0.776457 -1 + endloop + endfacet + facet normal -0.258669 0.0340544 -0.965366 + outer loop + vertex -2.89778 0.776457 -1 + vertex -3 3.67394e-16 -1 + vertex -3.5 4.28626e-16 -0.866025 + endloop + endfacet + facet normal -0.258669 0.0340544 -0.965366 + outer loop + vertex -2.89778 0.776457 -1 + vertex -3.5 4.28626e-16 -0.866025 + vertex -3.38074 0.905867 -0.866025 + endloop + endfacet + facet normal -0.704063 0.0926916 -0.704063 + outer loop + vertex -3.38074 0.905867 -0.866025 + vertex -3.5 4.28626e-16 -0.866025 + vertex -3.86603 4.73452e-16 -0.5 + endloop + endfacet + facet normal -0.704063 0.0926916 -0.704063 + outer loop + vertex -3.38074 0.905867 -0.866025 + vertex -3.86603 4.73452e-16 -0.5 + vertex -3.73429 1.0006 -0.5 + endloop + endfacet + facet normal -0.958209 0.126151 -0.256751 + outer loop + vertex -3.73429 1.0006 -0.5 + vertex -3.86603 4.73452e-16 -0.5 + vertex -4 4.89859e-16 -2.44929e-16 + endloop + endfacet + facet normal -0.958209 0.126151 -0.256751 + outer loop + vertex -3.73429 1.0006 -0.5 + vertex -4 4.89859e-16 -2.44929e-16 + vertex -3.8637 1.03528 -2.44929e-16 + endloop + endfacet + facet normal -0.958209 -0.126151 0.256751 + outer loop + vertex -4 4.89859e-16 0 + vertex -3.8637 -1.03528 0 + vertex -3.73429 -1.0006 0.5 + endloop + endfacet + facet normal -0.958209 -0.126151 0.256751 + outer loop + vertex -4 4.89859e-16 0 + vertex -3.73429 -1.0006 0.5 + vertex -3.86603 4.73452e-16 0.5 + endloop + endfacet + facet normal -0.704063 -0.0926916 0.704063 + outer loop + vertex -3.86603 4.73452e-16 0.5 + vertex -3.73429 -1.0006 0.5 + vertex -3.38074 -0.905867 0.866025 + endloop + endfacet + facet normal -0.704063 -0.0926916 0.704063 + outer loop + vertex -3.86603 4.73452e-16 0.5 + vertex -3.38074 -0.905867 0.866025 + vertex -3.5 4.28626e-16 0.866025 + endloop + endfacet + facet normal -0.258669 -0.0340544 0.965366 + outer loop + vertex -3.5 4.28626e-16 0.866025 + vertex -3.38074 -0.905867 0.866025 + vertex -2.89778 -0.776457 1 + endloop + endfacet + facet normal -0.258669 -0.0340544 0.965366 + outer loop + vertex -3.5 4.28626e-16 0.866025 + vertex -2.89778 -0.776457 1 + vertex -3 3.67394e-16 1 + endloop + endfacet + facet normal 0.258669 0.0340544 0.965366 + outer loop + vertex -3 3.67394e-16 1 + vertex -2.89778 -0.776457 1 + vertex -2.41481 -0.647048 0.866025 + endloop + endfacet + facet normal 0.258669 0.0340544 0.965366 + outer loop + vertex -3 3.67394e-16 1 + vertex -2.41481 -0.647048 0.866025 + vertex -2.5 3.06162e-16 0.866025 + endloop + endfacet + facet normal 0.704063 0.0926916 0.704063 + outer loop + vertex -2.5 3.06162e-16 0.866025 + vertex -2.41481 -0.647048 0.866025 + vertex -2.06126 -0.552313 0.5 + endloop + endfacet + facet normal 0.704063 0.0926916 0.704063 + outer loop + vertex -2.5 3.06162e-16 0.866025 + vertex -2.06126 -0.552313 0.5 + vertex -2.13397 2.61337e-16 0.5 + endloop + endfacet + facet normal 0.958209 0.126151 0.256751 + outer loop + vertex -2.13397 2.61337e-16 0.5 + vertex -2.06126 -0.552313 0.5 + vertex -1.93185 -0.517638 1.22465e-16 + endloop + endfacet + facet normal 0.958209 0.126151 0.256751 + outer loop + vertex -2.13397 2.61337e-16 0.5 + vertex -1.93185 -0.517638 1.22465e-16 + vertex -2 2.44929e-16 1.22465e-16 + endloop + endfacet + facet normal 0.958209 0.126151 -0.256751 + outer loop + vertex -2 2.44929e-16 1.22465e-16 + vertex -1.93185 -0.517638 1.22465e-16 + vertex -2.06126 -0.552313 -0.5 + endloop + endfacet + facet normal 0.958209 0.126151 -0.256751 + outer loop + vertex -2 2.44929e-16 1.22465e-16 + vertex -2.06126 -0.552313 -0.5 + vertex -2.13397 2.61337e-16 -0.5 + endloop + endfacet + facet normal 0.704063 0.0926916 -0.704063 + outer loop + vertex -2.13397 2.61337e-16 -0.5 + vertex -2.06126 -0.552313 -0.5 + vertex -2.41481 -0.647048 -0.866025 + endloop + endfacet + facet normal 0.704063 0.0926916 -0.704063 + outer loop + vertex -2.13397 2.61337e-16 -0.5 + vertex -2.41481 -0.647048 -0.866025 + vertex -2.5 3.06162e-16 -0.866025 + endloop + endfacet + facet normal 0.258669 0.0340544 -0.965366 + outer loop + vertex -2.5 3.06162e-16 -0.866025 + vertex -2.41481 -0.647048 -0.866025 + vertex -2.89778 -0.776457 -1 + endloop + endfacet + facet normal 0.258669 0.0340544 -0.965366 + outer loop + vertex -2.5 3.06162e-16 -0.866025 + vertex -2.89778 -0.776457 -1 + vertex -3 3.67394e-16 -1 + endloop + endfacet + facet normal -0.258669 -0.0340544 -0.965366 + outer loop + vertex -3 3.67394e-16 -1 + vertex -2.89778 -0.776457 -1 + vertex -3.38074 -0.905867 -0.866025 + endloop + endfacet + facet normal -0.258669 -0.0340544 -0.965366 + outer loop + vertex -3 3.67394e-16 -1 + vertex -3.38074 -0.905867 -0.866025 + vertex -3.5 4.28626e-16 -0.866025 + endloop + endfacet + facet normal -0.704063 -0.0926916 -0.704063 + outer loop + vertex -3.5 4.28626e-16 -0.866025 + vertex -3.38074 -0.905867 -0.866025 + vertex -3.73429 -1.0006 -0.5 + endloop + endfacet + facet normal -0.704063 -0.0926916 -0.704063 + outer loop + vertex -3.5 4.28626e-16 -0.866025 + vertex -3.73429 -1.0006 -0.5 + vertex -3.86603 4.73452e-16 -0.5 + endloop + endfacet + facet normal -0.958209 -0.126151 -0.256751 + outer loop + vertex -3.86603 4.73452e-16 -0.5 + vertex -3.73429 -1.0006 -0.5 + vertex -3.8637 -1.03528 -2.44929e-16 + endloop + endfacet + facet normal -0.958209 -0.126151 -0.256751 + outer loop + vertex -3.86603 4.73452e-16 -0.5 + vertex -3.8637 -1.03528 -2.44929e-16 + vertex -4 4.89859e-16 -2.44929e-16 + endloop + endfacet + facet normal -0.892909 -0.369855 0.256751 + outer loop + vertex -3.8637 -1.03528 0 + vertex -3.4641 -2 0 + vertex -3.34808 -1.93301 0.5 + endloop + endfacet + facet normal -0.892909 -0.369855 0.256751 + outer loop + vertex -3.8637 -1.03528 0 + vertex -3.34808 -1.93301 0.5 + vertex -3.73429 -1.0006 0.5 + endloop + endfacet + facet normal -0.656082 -0.271758 0.704063 + outer loop + vertex -3.73429 -1.0006 0.5 + vertex -3.34808 -1.93301 0.5 + vertex -3.03109 -1.75 0.866025 + endloop + endfacet + facet normal -0.656082 -0.271758 0.704063 + outer loop + vertex -3.73429 -1.0006 0.5 + vertex -3.03109 -1.75 0.866025 + vertex -3.38074 -0.905867 0.866025 + endloop + endfacet + facet normal -0.241041 -0.0998425 0.965366 + outer loop + vertex -3.38074 -0.905867 0.866025 + vertex -3.03109 -1.75 0.866025 + vertex -2.59808 -1.5 1 + endloop + endfacet + facet normal -0.241041 -0.0998425 0.965366 + outer loop + vertex -3.38074 -0.905867 0.866025 + vertex -2.59808 -1.5 1 + vertex -2.89778 -0.776457 1 + endloop + endfacet + facet normal 0.241041 0.0998425 0.965366 + outer loop + vertex -2.89778 -0.776457 1 + vertex -2.59808 -1.5 1 + vertex -2.16506 -1.25 0.866025 + endloop + endfacet + facet normal 0.241041 0.0998425 0.965366 + outer loop + vertex -2.89778 -0.776457 1 + vertex -2.16506 -1.25 0.866025 + vertex -2.41481 -0.647048 0.866025 + endloop + endfacet + facet normal 0.656082 0.271758 0.704063 + outer loop + vertex -2.41481 -0.647048 0.866025 + vertex -2.16506 -1.25 0.866025 + vertex -1.84808 -1.06699 0.5 + endloop + endfacet + facet normal 0.656082 0.271758 0.704063 + outer loop + vertex -2.41481 -0.647048 0.866025 + vertex -1.84808 -1.06699 0.5 + vertex -2.06126 -0.552313 0.5 + endloop + endfacet + facet normal 0.892909 0.369855 0.256751 + outer loop + vertex -2.06126 -0.552313 0.5 + vertex -1.84808 -1.06699 0.5 + vertex -1.73205 -1 1.22465e-16 + endloop + endfacet + facet normal 0.892909 0.369855 0.256751 + outer loop + vertex -2.06126 -0.552313 0.5 + vertex -1.73205 -1 1.22465e-16 + vertex -1.93185 -0.517638 1.22465e-16 + endloop + endfacet + facet normal 0.892909 0.369855 -0.256751 + outer loop + vertex -1.93185 -0.517638 1.22465e-16 + vertex -1.73205 -1 1.22465e-16 + vertex -1.84808 -1.06699 -0.5 + endloop + endfacet + facet normal 0.892909 0.369855 -0.256751 + outer loop + vertex -1.93185 -0.517638 1.22465e-16 + vertex -1.84808 -1.06699 -0.5 + vertex -2.06126 -0.552313 -0.5 + endloop + endfacet + facet normal 0.656082 0.271758 -0.704063 + outer loop + vertex -2.06126 -0.552313 -0.5 + vertex -1.84808 -1.06699 -0.5 + vertex -2.16506 -1.25 -0.866025 + endloop + endfacet + facet normal 0.656082 0.271758 -0.704063 + outer loop + vertex -2.06126 -0.552313 -0.5 + vertex -2.16506 -1.25 -0.866025 + vertex -2.41481 -0.647048 -0.866025 + endloop + endfacet + facet normal 0.241041 0.0998425 -0.965366 + outer loop + vertex -2.41481 -0.647048 -0.866025 + vertex -2.16506 -1.25 -0.866025 + vertex -2.59808 -1.5 -1 + endloop + endfacet + facet normal 0.241041 0.0998425 -0.965366 + outer loop + vertex -2.41481 -0.647048 -0.866025 + vertex -2.59808 -1.5 -1 + vertex -2.89778 -0.776457 -1 + endloop + endfacet + facet normal -0.241041 -0.0998425 -0.965366 + outer loop + vertex -2.89778 -0.776457 -1 + vertex -2.59808 -1.5 -1 + vertex -3.03109 -1.75 -0.866025 + endloop + endfacet + facet normal -0.241041 -0.0998425 -0.965366 + outer loop + vertex -2.89778 -0.776457 -1 + vertex -3.03109 -1.75 -0.866025 + vertex -3.38074 -0.905867 -0.866025 + endloop + endfacet + facet normal -0.656082 -0.271758 -0.704063 + outer loop + vertex -3.38074 -0.905867 -0.866025 + vertex -3.03109 -1.75 -0.866025 + vertex -3.34808 -1.93301 -0.5 + endloop + endfacet + facet normal -0.656082 -0.271758 -0.704063 + outer loop + vertex -3.38074 -0.905867 -0.866025 + vertex -3.34808 -1.93301 -0.5 + vertex -3.73429 -1.0006 -0.5 + endloop + endfacet + facet normal -0.892909 -0.369855 -0.256751 + outer loop + vertex -3.73429 -1.0006 -0.5 + vertex -3.34808 -1.93301 -0.5 + vertex -3.4641 -2 -2.44929e-16 + endloop + endfacet + facet normal -0.892909 -0.369855 -0.256751 + outer loop + vertex -3.73429 -1.0006 -0.5 + vertex -3.4641 -2 -2.44929e-16 + vertex -3.8637 -1.03528 -2.44929e-16 + endloop + endfacet + facet normal -0.766758 -0.588354 0.256751 + outer loop + vertex -3.4641 -2 0 + vertex -2.82843 -2.82843 0 + vertex -2.73369 -2.73369 0.5 + endloop + endfacet + facet normal -0.766758 -0.588354 0.256751 + outer loop + vertex -3.4641 -2 0 + vertex -2.73369 -2.73369 0.5 + vertex -3.34808 -1.93301 0.5 + endloop + endfacet + facet normal -0.56339 -0.432305 0.704063 + outer loop + vertex -3.34808 -1.93301 0.5 + vertex -2.73369 -2.73369 0.5 + vertex -2.47487 -2.47487 0.866025 + endloop + endfacet + facet normal -0.56339 -0.432305 0.704063 + outer loop + vertex -3.34808 -1.93301 0.5 + vertex -2.47487 -2.47487 0.866025 + vertex -3.03109 -1.75 0.866025 + endloop + endfacet + facet normal -0.206987 -0.158826 0.965366 + outer loop + vertex -3.03109 -1.75 0.866025 + vertex -2.47487 -2.47487 0.866025 + vertex -2.12132 -2.12132 1 + endloop + endfacet + facet normal -0.206987 -0.158826 0.965366 + outer loop + vertex -3.03109 -1.75 0.866025 + vertex -2.12132 -2.12132 1 + vertex -2.59808 -1.5 1 + endloop + endfacet + facet normal 0.206987 0.158826 0.965366 + outer loop + vertex -2.59808 -1.5 1 + vertex -2.12132 -2.12132 1 + vertex -1.76777 -1.76777 0.866025 + endloop + endfacet + facet normal 0.206987 0.158826 0.965366 + outer loop + vertex -2.59808 -1.5 1 + vertex -1.76777 -1.76777 0.866025 + vertex -2.16506 -1.25 0.866025 + endloop + endfacet + facet normal 0.56339 0.432305 0.704063 + outer loop + vertex -2.16506 -1.25 0.866025 + vertex -1.76777 -1.76777 0.866025 + vertex -1.50895 -1.50895 0.5 + endloop + endfacet + facet normal 0.56339 0.432305 0.704063 + outer loop + vertex -2.16506 -1.25 0.866025 + vertex -1.50895 -1.50895 0.5 + vertex -1.84808 -1.06699 0.5 + endloop + endfacet + facet normal 0.766758 0.588354 0.256751 + outer loop + vertex -1.84808 -1.06699 0.5 + vertex -1.50895 -1.50895 0.5 + vertex -1.41421 -1.41421 1.22465e-16 + endloop + endfacet + facet normal 0.766758 0.588354 0.256751 + outer loop + vertex -1.84808 -1.06699 0.5 + vertex -1.41421 -1.41421 1.22465e-16 + vertex -1.73205 -1 1.22465e-16 + endloop + endfacet + facet normal 0.766758 0.588354 -0.256751 + outer loop + vertex -1.73205 -1 1.22465e-16 + vertex -1.41421 -1.41421 1.22465e-16 + vertex -1.50895 -1.50895 -0.5 + endloop + endfacet + facet normal 0.766758 0.588354 -0.256751 + outer loop + vertex -1.73205 -1 1.22465e-16 + vertex -1.50895 -1.50895 -0.5 + vertex -1.84808 -1.06699 -0.5 + endloop + endfacet + facet normal 0.56339 0.432305 -0.704063 + outer loop + vertex -1.84808 -1.06699 -0.5 + vertex -1.50895 -1.50895 -0.5 + vertex -1.76777 -1.76777 -0.866025 + endloop + endfacet + facet normal 0.56339 0.432305 -0.704063 + outer loop + vertex -1.84808 -1.06699 -0.5 + vertex -1.76777 -1.76777 -0.866025 + vertex -2.16506 -1.25 -0.866025 + endloop + endfacet + facet normal 0.206987 0.158826 -0.965366 + outer loop + vertex -2.16506 -1.25 -0.866025 + vertex -1.76777 -1.76777 -0.866025 + vertex -2.12132 -2.12132 -1 + endloop + endfacet + facet normal 0.206987 0.158826 -0.965366 + outer loop + vertex -2.16506 -1.25 -0.866025 + vertex -2.12132 -2.12132 -1 + vertex -2.59808 -1.5 -1 + endloop + endfacet + facet normal -0.206987 -0.158826 -0.965366 + outer loop + vertex -2.59808 -1.5 -1 + vertex -2.12132 -2.12132 -1 + vertex -2.47487 -2.47487 -0.866025 + endloop + endfacet + facet normal -0.206987 -0.158826 -0.965366 + outer loop + vertex -2.59808 -1.5 -1 + vertex -2.47487 -2.47487 -0.866025 + vertex -3.03109 -1.75 -0.866025 + endloop + endfacet + facet normal -0.56339 -0.432305 -0.704063 + outer loop + vertex -3.03109 -1.75 -0.866025 + vertex -2.47487 -2.47487 -0.866025 + vertex -2.73369 -2.73369 -0.5 + endloop + endfacet + facet normal -0.56339 -0.432305 -0.704063 + outer loop + vertex -3.03109 -1.75 -0.866025 + vertex -2.73369 -2.73369 -0.5 + vertex -3.34808 -1.93301 -0.5 + endloop + endfacet + facet normal -0.766758 -0.588354 -0.256751 + outer loop + vertex -3.34808 -1.93301 -0.5 + vertex -2.73369 -2.73369 -0.5 + vertex -2.82843 -2.82843 -2.44929e-16 + endloop + endfacet + facet normal -0.766758 -0.588354 -0.256751 + outer loop + vertex -3.34808 -1.93301 -0.5 + vertex -2.82843 -2.82843 -2.44929e-16 + vertex -3.4641 -2 -2.44929e-16 + endloop + endfacet + facet normal -0.588354 -0.766758 0.256751 + outer loop + vertex -2.82843 -2.82843 0 + vertex -2 -3.4641 0 + vertex -1.93301 -3.34808 0.5 + endloop + endfacet + facet normal -0.588354 -0.766758 0.256751 + outer loop + vertex -2.82843 -2.82843 0 + vertex -1.93301 -3.34808 0.5 + vertex -2.73369 -2.73369 0.5 + endloop + endfacet + facet normal -0.432305 -0.56339 0.704063 + outer loop + vertex -2.73369 -2.73369 0.5 + vertex -1.93301 -3.34808 0.5 + vertex -1.75 -3.03109 0.866025 + endloop + endfacet + facet normal -0.432305 -0.56339 0.704063 + outer loop + vertex -2.73369 -2.73369 0.5 + vertex -1.75 -3.03109 0.866025 + vertex -2.47487 -2.47487 0.866025 + endloop + endfacet + facet normal -0.158826 -0.206987 0.965366 + outer loop + vertex -2.47487 -2.47487 0.866025 + vertex -1.75 -3.03109 0.866025 + vertex -1.5 -2.59808 1 + endloop + endfacet + facet normal -0.158826 -0.206987 0.965366 + outer loop + vertex -2.47487 -2.47487 0.866025 + vertex -1.5 -2.59808 1 + vertex -2.12132 -2.12132 1 + endloop + endfacet + facet normal 0.158826 0.206987 0.965366 + outer loop + vertex -2.12132 -2.12132 1 + vertex -1.5 -2.59808 1 + vertex -1.25 -2.16506 0.866025 + endloop + endfacet + facet normal 0.158826 0.206987 0.965366 + outer loop + vertex -2.12132 -2.12132 1 + vertex -1.25 -2.16506 0.866025 + vertex -1.76777 -1.76777 0.866025 + endloop + endfacet + facet normal 0.432305 0.56339 0.704063 + outer loop + vertex -1.76777 -1.76777 0.866025 + vertex -1.25 -2.16506 0.866025 + vertex -1.06699 -1.84808 0.5 + endloop + endfacet + facet normal 0.432305 0.56339 0.704063 + outer loop + vertex -1.76777 -1.76777 0.866025 + vertex -1.06699 -1.84808 0.5 + vertex -1.50895 -1.50895 0.5 + endloop + endfacet + facet normal 0.588354 0.766758 0.256751 + outer loop + vertex -1.50895 -1.50895 0.5 + vertex -1.06699 -1.84808 0.5 + vertex -1 -1.73205 1.22465e-16 + endloop + endfacet + facet normal 0.588354 0.766758 0.256751 + outer loop + vertex -1.50895 -1.50895 0.5 + vertex -1 -1.73205 1.22465e-16 + vertex -1.41421 -1.41421 1.22465e-16 + endloop + endfacet + facet normal 0.588354 0.766758 -0.256751 + outer loop + vertex -1.41421 -1.41421 1.22465e-16 + vertex -1 -1.73205 1.22465e-16 + vertex -1.06699 -1.84808 -0.5 + endloop + endfacet + facet normal 0.588354 0.766758 -0.256751 + outer loop + vertex -1.41421 -1.41421 1.22465e-16 + vertex -1.06699 -1.84808 -0.5 + vertex -1.50895 -1.50895 -0.5 + endloop + endfacet + facet normal 0.432305 0.56339 -0.704063 + outer loop + vertex -1.50895 -1.50895 -0.5 + vertex -1.06699 -1.84808 -0.5 + vertex -1.25 -2.16506 -0.866025 + endloop + endfacet + facet normal 0.432305 0.56339 -0.704063 + outer loop + vertex -1.50895 -1.50895 -0.5 + vertex -1.25 -2.16506 -0.866025 + vertex -1.76777 -1.76777 -0.866025 + endloop + endfacet + facet normal 0.158826 0.206987 -0.965366 + outer loop + vertex -1.76777 -1.76777 -0.866025 + vertex -1.25 -2.16506 -0.866025 + vertex -1.5 -2.59808 -1 + endloop + endfacet + facet normal 0.158826 0.206987 -0.965366 + outer loop + vertex -1.76777 -1.76777 -0.866025 + vertex -1.5 -2.59808 -1 + vertex -2.12132 -2.12132 -1 + endloop + endfacet + facet normal -0.158826 -0.206987 -0.965366 + outer loop + vertex -2.12132 -2.12132 -1 + vertex -1.5 -2.59808 -1 + vertex -1.75 -3.03109 -0.866025 + endloop + endfacet + facet normal -0.158826 -0.206987 -0.965366 + outer loop + vertex -2.12132 -2.12132 -1 + vertex -1.75 -3.03109 -0.866025 + vertex -2.47487 -2.47487 -0.866025 + endloop + endfacet + facet normal -0.432305 -0.56339 -0.704063 + outer loop + vertex -2.47487 -2.47487 -0.866025 + vertex -1.75 -3.03109 -0.866025 + vertex -1.93301 -3.34808 -0.5 + endloop + endfacet + facet normal -0.432305 -0.56339 -0.704063 + outer loop + vertex -2.47487 -2.47487 -0.866025 + vertex -1.93301 -3.34808 -0.5 + vertex -2.73369 -2.73369 -0.5 + endloop + endfacet + facet normal -0.588354 -0.766758 -0.256751 + outer loop + vertex -2.73369 -2.73369 -0.5 + vertex -1.93301 -3.34808 -0.5 + vertex -2 -3.4641 -2.44929e-16 + endloop + endfacet + facet normal -0.588354 -0.766758 -0.256751 + outer loop + vertex -2.73369 -2.73369 -0.5 + vertex -2 -3.4641 -2.44929e-16 + vertex -2.82843 -2.82843 -2.44929e-16 + endloop + endfacet + facet normal -0.369855 -0.892909 0.256751 + outer loop + vertex -2 -3.4641 0 + vertex -1.03528 -3.8637 0 + vertex -1.0006 -3.73429 0.5 + endloop + endfacet + facet normal -0.369855 -0.892909 0.256751 + outer loop + vertex -2 -3.4641 0 + vertex -1.0006 -3.73429 0.5 + vertex -1.93301 -3.34808 0.5 + endloop + endfacet + facet normal -0.271758 -0.656082 0.704063 + outer loop + vertex -1.93301 -3.34808 0.5 + vertex -1.0006 -3.73429 0.5 + vertex -0.905867 -3.38074 0.866025 + endloop + endfacet + facet normal -0.271758 -0.656082 0.704063 + outer loop + vertex -1.93301 -3.34808 0.5 + vertex -0.905867 -3.38074 0.866025 + vertex -1.75 -3.03109 0.866025 + endloop + endfacet + facet normal -0.0998425 -0.241041 0.965366 + outer loop + vertex -1.75 -3.03109 0.866025 + vertex -0.905867 -3.38074 0.866025 + vertex -0.776457 -2.89778 1 + endloop + endfacet + facet normal -0.0998425 -0.241041 0.965366 + outer loop + vertex -1.75 -3.03109 0.866025 + vertex -0.776457 -2.89778 1 + vertex -1.5 -2.59808 1 + endloop + endfacet + facet normal 0.0998425 0.241041 0.965366 + outer loop + vertex -1.5 -2.59808 1 + vertex -0.776457 -2.89778 1 + vertex -0.647048 -2.41481 0.866025 + endloop + endfacet + facet normal 0.0998425 0.241041 0.965366 + outer loop + vertex -1.5 -2.59808 1 + vertex -0.647048 -2.41481 0.866025 + vertex -1.25 -2.16506 0.866025 + endloop + endfacet + facet normal 0.271758 0.656082 0.704063 + outer loop + vertex -1.25 -2.16506 0.866025 + vertex -0.647048 -2.41481 0.866025 + vertex -0.552313 -2.06126 0.5 + endloop + endfacet + facet normal 0.271758 0.656082 0.704063 + outer loop + vertex -1.25 -2.16506 0.866025 + vertex -0.552313 -2.06126 0.5 + vertex -1.06699 -1.84808 0.5 + endloop + endfacet + facet normal 0.369855 0.892909 0.256751 + outer loop + vertex -1.06699 -1.84808 0.5 + vertex -0.552313 -2.06126 0.5 + vertex -0.517638 -1.93185 1.22465e-16 + endloop + endfacet + facet normal 0.369855 0.892909 0.256751 + outer loop + vertex -1.06699 -1.84808 0.5 + vertex -0.517638 -1.93185 1.22465e-16 + vertex -1 -1.73205 1.22465e-16 + endloop + endfacet + facet normal 0.369855 0.892909 -0.256751 + outer loop + vertex -1 -1.73205 1.22465e-16 + vertex -0.517638 -1.93185 1.22465e-16 + vertex -0.552313 -2.06126 -0.5 + endloop + endfacet + facet normal 0.369855 0.892909 -0.256751 + outer loop + vertex -1 -1.73205 1.22465e-16 + vertex -0.552313 -2.06126 -0.5 + vertex -1.06699 -1.84808 -0.5 + endloop + endfacet + facet normal 0.271758 0.656082 -0.704063 + outer loop + vertex -1.06699 -1.84808 -0.5 + vertex -0.552313 -2.06126 -0.5 + vertex -0.647048 -2.41481 -0.866025 + endloop + endfacet + facet normal 0.271758 0.656082 -0.704063 + outer loop + vertex -1.06699 -1.84808 -0.5 + vertex -0.647048 -2.41481 -0.866025 + vertex -1.25 -2.16506 -0.866025 + endloop + endfacet + facet normal 0.0998425 0.241041 -0.965366 + outer loop + vertex -1.25 -2.16506 -0.866025 + vertex -0.647048 -2.41481 -0.866025 + vertex -0.776457 -2.89778 -1 + endloop + endfacet + facet normal 0.0998425 0.241041 -0.965366 + outer loop + vertex -1.25 -2.16506 -0.866025 + vertex -0.776457 -2.89778 -1 + vertex -1.5 -2.59808 -1 + endloop + endfacet + facet normal -0.0998425 -0.241041 -0.965366 + outer loop + vertex -1.5 -2.59808 -1 + vertex -0.776457 -2.89778 -1 + vertex -0.905867 -3.38074 -0.866025 + endloop + endfacet + facet normal -0.0998425 -0.241041 -0.965366 + outer loop + vertex -1.5 -2.59808 -1 + vertex -0.905867 -3.38074 -0.866025 + vertex -1.75 -3.03109 -0.866025 + endloop + endfacet + facet normal -0.271758 -0.656082 -0.704063 + outer loop + vertex -1.75 -3.03109 -0.866025 + vertex -0.905867 -3.38074 -0.866025 + vertex -1.0006 -3.73429 -0.5 + endloop + endfacet + facet normal -0.271758 -0.656082 -0.704063 + outer loop + vertex -1.75 -3.03109 -0.866025 + vertex -1.0006 -3.73429 -0.5 + vertex -1.93301 -3.34808 -0.5 + endloop + endfacet + facet normal -0.369855 -0.892909 -0.256751 + outer loop + vertex -1.93301 -3.34808 -0.5 + vertex -1.0006 -3.73429 -0.5 + vertex -1.03528 -3.8637 -2.44929e-16 + endloop + endfacet + facet normal -0.369855 -0.892909 -0.256751 + outer loop + vertex -1.93301 -3.34808 -0.5 + vertex -1.03528 -3.8637 -2.44929e-16 + vertex -2 -3.4641 -2.44929e-16 + endloop + endfacet + facet normal -0.126151 -0.958209 0.256751 + outer loop + vertex -1.03528 -3.8637 0 + vertex -7.34788e-16 -4 0 + vertex -7.10177e-16 -3.86603 0.5 + endloop + endfacet + facet normal -0.126151 -0.958209 0.256751 + outer loop + vertex -1.03528 -3.8637 0 + vertex -7.10177e-16 -3.86603 0.5 + vertex -1.0006 -3.73429 0.5 + endloop + endfacet + facet normal -0.0926916 -0.704063 0.704063 + outer loop + vertex -1.0006 -3.73429 0.5 + vertex -7.10177e-16 -3.86603 0.5 + vertex -6.4294e-16 -3.5 0.866025 + endloop + endfacet + facet normal -0.0926916 -0.704063 0.704063 + outer loop + vertex -1.0006 -3.73429 0.5 + vertex -6.4294e-16 -3.5 0.866025 + vertex -0.905867 -3.38074 0.866025 + endloop + endfacet + facet normal -0.0340544 -0.258669 0.965366 + outer loop + vertex -0.905867 -3.38074 0.866025 + vertex -6.4294e-16 -3.5 0.866025 + vertex -5.51091e-16 -3 1 + endloop + endfacet + facet normal -0.0340544 -0.258669 0.965366 + outer loop + vertex -0.905867 -3.38074 0.866025 + vertex -5.51091e-16 -3 1 + vertex -0.776457 -2.89778 1 + endloop + endfacet + facet normal 0.0340544 0.258669 0.965366 + outer loop + vertex -0.776457 -2.89778 1 + vertex -5.51091e-16 -3 1 + vertex -4.59243e-16 -2.5 0.866025 + endloop + endfacet + facet normal 0.0340544 0.258669 0.965366 + outer loop + vertex -0.776457 -2.89778 1 + vertex -4.59243e-16 -2.5 0.866025 + vertex -0.647048 -2.41481 0.866025 + endloop + endfacet + facet normal 0.0926916 0.704063 0.704063 + outer loop + vertex -0.647048 -2.41481 0.866025 + vertex -4.59243e-16 -2.5 0.866025 + vertex -3.92005e-16 -2.13397 0.5 + endloop + endfacet + facet normal 0.0926916 0.704063 0.704063 + outer loop + vertex -0.647048 -2.41481 0.866025 + vertex -3.92005e-16 -2.13397 0.5 + vertex -0.552313 -2.06126 0.5 + endloop + endfacet + facet normal 0.126151 0.958209 0.256751 + outer loop + vertex -0.552313 -2.06126 0.5 + vertex -3.92005e-16 -2.13397 0.5 + vertex -3.67394e-16 -2 1.22465e-16 + endloop + endfacet + facet normal 0.126151 0.958209 0.256751 + outer loop + vertex -0.552313 -2.06126 0.5 + vertex -3.67394e-16 -2 1.22465e-16 + vertex -0.517638 -1.93185 1.22465e-16 + endloop + endfacet + facet normal 0.126151 0.958209 -0.256751 + outer loop + vertex -0.517638 -1.93185 1.22465e-16 + vertex -3.67394e-16 -2 1.22465e-16 + vertex -3.92005e-16 -2.13397 -0.5 + endloop + endfacet + facet normal 0.126151 0.958209 -0.256751 + outer loop + vertex -0.517638 -1.93185 1.22465e-16 + vertex -3.92005e-16 -2.13397 -0.5 + vertex -0.552313 -2.06126 -0.5 + endloop + endfacet + facet normal 0.0926916 0.704063 -0.704063 + outer loop + vertex -0.552313 -2.06126 -0.5 + vertex -3.92005e-16 -2.13397 -0.5 + vertex -4.59243e-16 -2.5 -0.866025 + endloop + endfacet + facet normal 0.0926916 0.704063 -0.704063 + outer loop + vertex -0.552313 -2.06126 -0.5 + vertex -4.59243e-16 -2.5 -0.866025 + vertex -0.647048 -2.41481 -0.866025 + endloop + endfacet + facet normal 0.0340544 0.258669 -0.965366 + outer loop + vertex -0.647048 -2.41481 -0.866025 + vertex -4.59243e-16 -2.5 -0.866025 + vertex -5.51091e-16 -3 -1 + endloop + endfacet + facet normal 0.0340544 0.258669 -0.965366 + outer loop + vertex -0.647048 -2.41481 -0.866025 + vertex -5.51091e-16 -3 -1 + vertex -0.776457 -2.89778 -1 + endloop + endfacet + facet normal -0.0340544 -0.258669 -0.965366 + outer loop + vertex -0.776457 -2.89778 -1 + vertex -5.51091e-16 -3 -1 + vertex -6.4294e-16 -3.5 -0.866025 + endloop + endfacet + facet normal -0.0340544 -0.258669 -0.965366 + outer loop + vertex -0.776457 -2.89778 -1 + vertex -6.4294e-16 -3.5 -0.866025 + vertex -0.905867 -3.38074 -0.866025 + endloop + endfacet + facet normal -0.0926916 -0.704063 -0.704063 + outer loop + vertex -0.905867 -3.38074 -0.866025 + vertex -6.4294e-16 -3.5 -0.866025 + vertex -7.10177e-16 -3.86603 -0.5 + endloop + endfacet + facet normal -0.0926916 -0.704063 -0.704063 + outer loop + vertex -0.905867 -3.38074 -0.866025 + vertex -7.10177e-16 -3.86603 -0.5 + vertex -1.0006 -3.73429 -0.5 + endloop + endfacet + facet normal -0.126151 -0.958209 -0.256751 + outer loop + vertex -1.0006 -3.73429 -0.5 + vertex -7.10177e-16 -3.86603 -0.5 + vertex -7.34788e-16 -4 -2.44929e-16 + endloop + endfacet + facet normal -0.126151 -0.958209 -0.256751 + outer loop + vertex -1.0006 -3.73429 -0.5 + vertex -7.34788e-16 -4 -2.44929e-16 + vertex -1.03528 -3.8637 -2.44929e-16 + endloop + endfacet + facet normal 0.126151 -0.958209 0.256751 + outer loop + vertex -7.34788e-16 -4 0 + vertex 1.03528 -3.8637 0 + vertex 1.0006 -3.73429 0.5 + endloop + endfacet + facet normal 0.126151 -0.958209 0.256751 + outer loop + vertex -7.34788e-16 -4 0 + vertex 1.0006 -3.73429 0.5 + vertex -7.10177e-16 -3.86603 0.5 + endloop + endfacet + facet normal 0.0926916 -0.704063 0.704063 + outer loop + vertex -7.10177e-16 -3.86603 0.5 + vertex 1.0006 -3.73429 0.5 + vertex 0.905867 -3.38074 0.866025 + endloop + endfacet + facet normal 0.0926916 -0.704063 0.704063 + outer loop + vertex -7.10177e-16 -3.86603 0.5 + vertex 0.905867 -3.38074 0.866025 + vertex -6.4294e-16 -3.5 0.866025 + endloop + endfacet + facet normal 0.0340544 -0.258669 0.965366 + outer loop + vertex -6.4294e-16 -3.5 0.866025 + vertex 0.905867 -3.38074 0.866025 + vertex 0.776457 -2.89778 1 + endloop + endfacet + facet normal 0.0340544 -0.258669 0.965366 + outer loop + vertex -6.4294e-16 -3.5 0.866025 + vertex 0.776457 -2.89778 1 + vertex -5.51091e-16 -3 1 + endloop + endfacet + facet normal -0.0340544 0.258669 0.965366 + outer loop + vertex -5.51091e-16 -3 1 + vertex 0.776457 -2.89778 1 + vertex 0.647048 -2.41481 0.866025 + endloop + endfacet + facet normal -0.0340544 0.258669 0.965366 + outer loop + vertex -5.51091e-16 -3 1 + vertex 0.647048 -2.41481 0.866025 + vertex -4.59243e-16 -2.5 0.866025 + endloop + endfacet + facet normal -0.0926916 0.704063 0.704063 + outer loop + vertex -4.59243e-16 -2.5 0.866025 + vertex 0.647048 -2.41481 0.866025 + vertex 0.552313 -2.06126 0.5 + endloop + endfacet + facet normal -0.0926916 0.704063 0.704063 + outer loop + vertex -4.59243e-16 -2.5 0.866025 + vertex 0.552313 -2.06126 0.5 + vertex -3.92005e-16 -2.13397 0.5 + endloop + endfacet + facet normal -0.126151 0.958209 0.256751 + outer loop + vertex -3.92005e-16 -2.13397 0.5 + vertex 0.552313 -2.06126 0.5 + vertex 0.517638 -1.93185 1.22465e-16 + endloop + endfacet + facet normal -0.126151 0.958209 0.256751 + outer loop + vertex -3.92005e-16 -2.13397 0.5 + vertex 0.517638 -1.93185 1.22465e-16 + vertex -3.67394e-16 -2 1.22465e-16 + endloop + endfacet + facet normal -0.126151 0.958209 -0.256751 + outer loop + vertex -3.67394e-16 -2 1.22465e-16 + vertex 0.517638 -1.93185 1.22465e-16 + vertex 0.552313 -2.06126 -0.5 + endloop + endfacet + facet normal -0.126151 0.958209 -0.256751 + outer loop + vertex -3.67394e-16 -2 1.22465e-16 + vertex 0.552313 -2.06126 -0.5 + vertex -3.92005e-16 -2.13397 -0.5 + endloop + endfacet + facet normal -0.0926916 0.704063 -0.704063 + outer loop + vertex -3.92005e-16 -2.13397 -0.5 + vertex 0.552313 -2.06126 -0.5 + vertex 0.647048 -2.41481 -0.866025 + endloop + endfacet + facet normal -0.0926916 0.704063 -0.704063 + outer loop + vertex -3.92005e-16 -2.13397 -0.5 + vertex 0.647048 -2.41481 -0.866025 + vertex -4.59243e-16 -2.5 -0.866025 + endloop + endfacet + facet normal -0.0340544 0.258669 -0.965366 + outer loop + vertex -4.59243e-16 -2.5 -0.866025 + vertex 0.647048 -2.41481 -0.866025 + vertex 0.776457 -2.89778 -1 + endloop + endfacet + facet normal -0.0340544 0.258669 -0.965366 + outer loop + vertex -4.59243e-16 -2.5 -0.866025 + vertex 0.776457 -2.89778 -1 + vertex -5.51091e-16 -3 -1 + endloop + endfacet + facet normal 0.0340544 -0.258669 -0.965366 + outer loop + vertex -5.51091e-16 -3 -1 + vertex 0.776457 -2.89778 -1 + vertex 0.905867 -3.38074 -0.866025 + endloop + endfacet + facet normal 0.0340544 -0.258669 -0.965366 + outer loop + vertex -5.51091e-16 -3 -1 + vertex 0.905867 -3.38074 -0.866025 + vertex -6.4294e-16 -3.5 -0.866025 + endloop + endfacet + facet normal 0.0926916 -0.704063 -0.704063 + outer loop + vertex -6.4294e-16 -3.5 -0.866025 + vertex 0.905867 -3.38074 -0.866025 + vertex 1.0006 -3.73429 -0.5 + endloop + endfacet + facet normal 0.0926916 -0.704063 -0.704063 + outer loop + vertex -6.4294e-16 -3.5 -0.866025 + vertex 1.0006 -3.73429 -0.5 + vertex -7.10177e-16 -3.86603 -0.5 + endloop + endfacet + facet normal 0.126151 -0.958209 -0.256751 + outer loop + vertex -7.10177e-16 -3.86603 -0.5 + vertex 1.0006 -3.73429 -0.5 + vertex 1.03528 -3.8637 -2.44929e-16 + endloop + endfacet + facet normal 0.126151 -0.958209 -0.256751 + outer loop + vertex -7.10177e-16 -3.86603 -0.5 + vertex 1.03528 -3.8637 -2.44929e-16 + vertex -7.34788e-16 -4 -2.44929e-16 + endloop + endfacet + facet normal 0.369855 -0.892909 0.256751 + outer loop + vertex 1.03528 -3.8637 0 + vertex 2 -3.4641 0 + vertex 1.93301 -3.34808 0.5 + endloop + endfacet + facet normal 0.369855 -0.892909 0.256751 + outer loop + vertex 1.03528 -3.8637 0 + vertex 1.93301 -3.34808 0.5 + vertex 1.0006 -3.73429 0.5 + endloop + endfacet + facet normal 0.271758 -0.656082 0.704063 + outer loop + vertex 1.0006 -3.73429 0.5 + vertex 1.93301 -3.34808 0.5 + vertex 1.75 -3.03109 0.866025 + endloop + endfacet + facet normal 0.271758 -0.656082 0.704063 + outer loop + vertex 1.0006 -3.73429 0.5 + vertex 1.75 -3.03109 0.866025 + vertex 0.905867 -3.38074 0.866025 + endloop + endfacet + facet normal 0.0998425 -0.241041 0.965366 + outer loop + vertex 0.905867 -3.38074 0.866025 + vertex 1.75 -3.03109 0.866025 + vertex 1.5 -2.59808 1 + endloop + endfacet + facet normal 0.0998425 -0.241041 0.965366 + outer loop + vertex 0.905867 -3.38074 0.866025 + vertex 1.5 -2.59808 1 + vertex 0.776457 -2.89778 1 + endloop + endfacet + facet normal -0.0998425 0.241041 0.965366 + outer loop + vertex 0.776457 -2.89778 1 + vertex 1.5 -2.59808 1 + vertex 1.25 -2.16506 0.866025 + endloop + endfacet + facet normal -0.0998425 0.241041 0.965366 + outer loop + vertex 0.776457 -2.89778 1 + vertex 1.25 -2.16506 0.866025 + vertex 0.647048 -2.41481 0.866025 + endloop + endfacet + facet normal -0.271758 0.656082 0.704063 + outer loop + vertex 0.647048 -2.41481 0.866025 + vertex 1.25 -2.16506 0.866025 + vertex 1.06699 -1.84808 0.5 + endloop + endfacet + facet normal -0.271758 0.656082 0.704063 + outer loop + vertex 0.647048 -2.41481 0.866025 + vertex 1.06699 -1.84808 0.5 + vertex 0.552313 -2.06126 0.5 + endloop + endfacet + facet normal -0.369855 0.892909 0.256751 + outer loop + vertex 0.552313 -2.06126 0.5 + vertex 1.06699 -1.84808 0.5 + vertex 1 -1.73205 1.22465e-16 + endloop + endfacet + facet normal -0.369855 0.892909 0.256751 + outer loop + vertex 0.552313 -2.06126 0.5 + vertex 1 -1.73205 1.22465e-16 + vertex 0.517638 -1.93185 1.22465e-16 + endloop + endfacet + facet normal -0.369855 0.892909 -0.256751 + outer loop + vertex 0.517638 -1.93185 1.22465e-16 + vertex 1 -1.73205 1.22465e-16 + vertex 1.06699 -1.84808 -0.5 + endloop + endfacet + facet normal -0.369855 0.892909 -0.256751 + outer loop + vertex 0.517638 -1.93185 1.22465e-16 + vertex 1.06699 -1.84808 -0.5 + vertex 0.552313 -2.06126 -0.5 + endloop + endfacet + facet normal -0.271758 0.656082 -0.704063 + outer loop + vertex 0.552313 -2.06126 -0.5 + vertex 1.06699 -1.84808 -0.5 + vertex 1.25 -2.16506 -0.866025 + endloop + endfacet + facet normal -0.271758 0.656082 -0.704063 + outer loop + vertex 0.552313 -2.06126 -0.5 + vertex 1.25 -2.16506 -0.866025 + vertex 0.647048 -2.41481 -0.866025 + endloop + endfacet + facet normal -0.0998425 0.241041 -0.965366 + outer loop + vertex 0.647048 -2.41481 -0.866025 + vertex 1.25 -2.16506 -0.866025 + vertex 1.5 -2.59808 -1 + endloop + endfacet + facet normal -0.0998425 0.241041 -0.965366 + outer loop + vertex 0.647048 -2.41481 -0.866025 + vertex 1.5 -2.59808 -1 + vertex 0.776457 -2.89778 -1 + endloop + endfacet + facet normal 0.0998425 -0.241041 -0.965366 + outer loop + vertex 0.776457 -2.89778 -1 + vertex 1.5 -2.59808 -1 + vertex 1.75 -3.03109 -0.866025 + endloop + endfacet + facet normal 0.0998425 -0.241041 -0.965366 + outer loop + vertex 0.776457 -2.89778 -1 + vertex 1.75 -3.03109 -0.866025 + vertex 0.905867 -3.38074 -0.866025 + endloop + endfacet + facet normal 0.271758 -0.656082 -0.704063 + outer loop + vertex 0.905867 -3.38074 -0.866025 + vertex 1.75 -3.03109 -0.866025 + vertex 1.93301 -3.34808 -0.5 + endloop + endfacet + facet normal 0.271758 -0.656082 -0.704063 + outer loop + vertex 0.905867 -3.38074 -0.866025 + vertex 1.93301 -3.34808 -0.5 + vertex 1.0006 -3.73429 -0.5 + endloop + endfacet + facet normal 0.369855 -0.892909 -0.256751 + outer loop + vertex 1.0006 -3.73429 -0.5 + vertex 1.93301 -3.34808 -0.5 + vertex 2 -3.4641 -2.44929e-16 + endloop + endfacet + facet normal 0.369855 -0.892909 -0.256751 + outer loop + vertex 1.0006 -3.73429 -0.5 + vertex 2 -3.4641 -2.44929e-16 + vertex 1.03528 -3.8637 -2.44929e-16 + endloop + endfacet + facet normal 0.588354 -0.766758 0.256751 + outer loop + vertex 2 -3.4641 0 + vertex 2.82843 -2.82843 0 + vertex 2.73369 -2.73369 0.5 + endloop + endfacet + facet normal 0.588354 -0.766758 0.256751 + outer loop + vertex 2 -3.4641 0 + vertex 2.73369 -2.73369 0.5 + vertex 1.93301 -3.34808 0.5 + endloop + endfacet + facet normal 0.432305 -0.56339 0.704063 + outer loop + vertex 1.93301 -3.34808 0.5 + vertex 2.73369 -2.73369 0.5 + vertex 2.47487 -2.47487 0.866025 + endloop + endfacet + facet normal 0.432305 -0.56339 0.704063 + outer loop + vertex 1.93301 -3.34808 0.5 + vertex 2.47487 -2.47487 0.866025 + vertex 1.75 -3.03109 0.866025 + endloop + endfacet + facet normal 0.158826 -0.206987 0.965366 + outer loop + vertex 1.75 -3.03109 0.866025 + vertex 2.47487 -2.47487 0.866025 + vertex 2.12132 -2.12132 1 + endloop + endfacet + facet normal 0.158826 -0.206987 0.965366 + outer loop + vertex 1.75 -3.03109 0.866025 + vertex 2.12132 -2.12132 1 + vertex 1.5 -2.59808 1 + endloop + endfacet + facet normal -0.158826 0.206987 0.965366 + outer loop + vertex 1.5 -2.59808 1 + vertex 2.12132 -2.12132 1 + vertex 1.76777 -1.76777 0.866025 + endloop + endfacet + facet normal -0.158826 0.206987 0.965366 + outer loop + vertex 1.5 -2.59808 1 + vertex 1.76777 -1.76777 0.866025 + vertex 1.25 -2.16506 0.866025 + endloop + endfacet + facet normal -0.432305 0.56339 0.704063 + outer loop + vertex 1.25 -2.16506 0.866025 + vertex 1.76777 -1.76777 0.866025 + vertex 1.50895 -1.50895 0.5 + endloop + endfacet + facet normal -0.432305 0.56339 0.704063 + outer loop + vertex 1.25 -2.16506 0.866025 + vertex 1.50895 -1.50895 0.5 + vertex 1.06699 -1.84808 0.5 + endloop + endfacet + facet normal -0.588354 0.766758 0.256751 + outer loop + vertex 1.06699 -1.84808 0.5 + vertex 1.50895 -1.50895 0.5 + vertex 1.41421 -1.41421 1.22465e-16 + endloop + endfacet + facet normal -0.588354 0.766758 0.256751 + outer loop + vertex 1.06699 -1.84808 0.5 + vertex 1.41421 -1.41421 1.22465e-16 + vertex 1 -1.73205 1.22465e-16 + endloop + endfacet + facet normal -0.588354 0.766758 -0.256751 + outer loop + vertex 1 -1.73205 1.22465e-16 + vertex 1.41421 -1.41421 1.22465e-16 + vertex 1.50895 -1.50895 -0.5 + endloop + endfacet + facet normal -0.588354 0.766758 -0.256751 + outer loop + vertex 1 -1.73205 1.22465e-16 + vertex 1.50895 -1.50895 -0.5 + vertex 1.06699 -1.84808 -0.5 + endloop + endfacet + facet normal -0.432305 0.56339 -0.704063 + outer loop + vertex 1.06699 -1.84808 -0.5 + vertex 1.50895 -1.50895 -0.5 + vertex 1.76777 -1.76777 -0.866025 + endloop + endfacet + facet normal -0.432305 0.56339 -0.704063 + outer loop + vertex 1.06699 -1.84808 -0.5 + vertex 1.76777 -1.76777 -0.866025 + vertex 1.25 -2.16506 -0.866025 + endloop + endfacet + facet normal -0.158826 0.206987 -0.965366 + outer loop + vertex 1.25 -2.16506 -0.866025 + vertex 1.76777 -1.76777 -0.866025 + vertex 2.12132 -2.12132 -1 + endloop + endfacet + facet normal -0.158826 0.206987 -0.965366 + outer loop + vertex 1.25 -2.16506 -0.866025 + vertex 2.12132 -2.12132 -1 + vertex 1.5 -2.59808 -1 + endloop + endfacet + facet normal 0.158826 -0.206987 -0.965366 + outer loop + vertex 1.5 -2.59808 -1 + vertex 2.12132 -2.12132 -1 + vertex 2.47487 -2.47487 -0.866025 + endloop + endfacet + facet normal 0.158826 -0.206987 -0.965366 + outer loop + vertex 1.5 -2.59808 -1 + vertex 2.47487 -2.47487 -0.866025 + vertex 1.75 -3.03109 -0.866025 + endloop + endfacet + facet normal 0.432305 -0.56339 -0.704063 + outer loop + vertex 1.75 -3.03109 -0.866025 + vertex 2.47487 -2.47487 -0.866025 + vertex 2.73369 -2.73369 -0.5 + endloop + endfacet + facet normal 0.432305 -0.56339 -0.704063 + outer loop + vertex 1.75 -3.03109 -0.866025 + vertex 2.73369 -2.73369 -0.5 + vertex 1.93301 -3.34808 -0.5 + endloop + endfacet + facet normal 0.588354 -0.766758 -0.256751 + outer loop + vertex 1.93301 -3.34808 -0.5 + vertex 2.73369 -2.73369 -0.5 + vertex 2.82843 -2.82843 -2.44929e-16 + endloop + endfacet + facet normal 0.588354 -0.766758 -0.256751 + outer loop + vertex 1.93301 -3.34808 -0.5 + vertex 2.82843 -2.82843 -2.44929e-16 + vertex 2 -3.4641 -2.44929e-16 + endloop + endfacet + facet normal 0.766758 -0.588354 0.256751 + outer loop + vertex 2.82843 -2.82843 0 + vertex 3.4641 -2 0 + vertex 3.34808 -1.93301 0.5 + endloop + endfacet + facet normal 0.766758 -0.588354 0.256751 + outer loop + vertex 2.82843 -2.82843 0 + vertex 3.34808 -1.93301 0.5 + vertex 2.73369 -2.73369 0.5 + endloop + endfacet + facet normal 0.56339 -0.432305 0.704063 + outer loop + vertex 2.73369 -2.73369 0.5 + vertex 3.34808 -1.93301 0.5 + vertex 3.03109 -1.75 0.866025 + endloop + endfacet + facet normal 0.56339 -0.432305 0.704063 + outer loop + vertex 2.73369 -2.73369 0.5 + vertex 3.03109 -1.75 0.866025 + vertex 2.47487 -2.47487 0.866025 + endloop + endfacet + facet normal 0.206987 -0.158826 0.965366 + outer loop + vertex 2.47487 -2.47487 0.866025 + vertex 3.03109 -1.75 0.866025 + vertex 2.59808 -1.5 1 + endloop + endfacet + facet normal 0.206987 -0.158826 0.965366 + outer loop + vertex 2.47487 -2.47487 0.866025 + vertex 2.59808 -1.5 1 + vertex 2.12132 -2.12132 1 + endloop + endfacet + facet normal -0.206987 0.158826 0.965366 + outer loop + vertex 2.12132 -2.12132 1 + vertex 2.59808 -1.5 1 + vertex 2.16506 -1.25 0.866025 + endloop + endfacet + facet normal -0.206987 0.158826 0.965366 + outer loop + vertex 2.12132 -2.12132 1 + vertex 2.16506 -1.25 0.866025 + vertex 1.76777 -1.76777 0.866025 + endloop + endfacet + facet normal -0.56339 0.432305 0.704063 + outer loop + vertex 1.76777 -1.76777 0.866025 + vertex 2.16506 -1.25 0.866025 + vertex 1.84808 -1.06699 0.5 + endloop + endfacet + facet normal -0.56339 0.432305 0.704063 + outer loop + vertex 1.76777 -1.76777 0.866025 + vertex 1.84808 -1.06699 0.5 + vertex 1.50895 -1.50895 0.5 + endloop + endfacet + facet normal -0.766758 0.588354 0.256751 + outer loop + vertex 1.50895 -1.50895 0.5 + vertex 1.84808 -1.06699 0.5 + vertex 1.73205 -1 1.22465e-16 + endloop + endfacet + facet normal -0.766758 0.588354 0.256751 + outer loop + vertex 1.50895 -1.50895 0.5 + vertex 1.73205 -1 1.22465e-16 + vertex 1.41421 -1.41421 1.22465e-16 + endloop + endfacet + facet normal -0.766758 0.588354 -0.256751 + outer loop + vertex 1.41421 -1.41421 1.22465e-16 + vertex 1.73205 -1 1.22465e-16 + vertex 1.84808 -1.06699 -0.5 + endloop + endfacet + facet normal -0.766758 0.588354 -0.256751 + outer loop + vertex 1.41421 -1.41421 1.22465e-16 + vertex 1.84808 -1.06699 -0.5 + vertex 1.50895 -1.50895 -0.5 + endloop + endfacet + facet normal -0.56339 0.432305 -0.704063 + outer loop + vertex 1.50895 -1.50895 -0.5 + vertex 1.84808 -1.06699 -0.5 + vertex 2.16506 -1.25 -0.866025 + endloop + endfacet + facet normal -0.56339 0.432305 -0.704063 + outer loop + vertex 1.50895 -1.50895 -0.5 + vertex 2.16506 -1.25 -0.866025 + vertex 1.76777 -1.76777 -0.866025 + endloop + endfacet + facet normal -0.206987 0.158826 -0.965366 + outer loop + vertex 1.76777 -1.76777 -0.866025 + vertex 2.16506 -1.25 -0.866025 + vertex 2.59808 -1.5 -1 + endloop + endfacet + facet normal -0.206987 0.158826 -0.965366 + outer loop + vertex 1.76777 -1.76777 -0.866025 + vertex 2.59808 -1.5 -1 + vertex 2.12132 -2.12132 -1 + endloop + endfacet + facet normal 0.206987 -0.158826 -0.965366 + outer loop + vertex 2.12132 -2.12132 -1 + vertex 2.59808 -1.5 -1 + vertex 3.03109 -1.75 -0.866025 + endloop + endfacet + facet normal 0.206987 -0.158826 -0.965366 + outer loop + vertex 2.12132 -2.12132 -1 + vertex 3.03109 -1.75 -0.866025 + vertex 2.47487 -2.47487 -0.866025 + endloop + endfacet + facet normal 0.56339 -0.432305 -0.704063 + outer loop + vertex 2.47487 -2.47487 -0.866025 + vertex 3.03109 -1.75 -0.866025 + vertex 3.34808 -1.93301 -0.5 + endloop + endfacet + facet normal 0.56339 -0.432305 -0.704063 + outer loop + vertex 2.47487 -2.47487 -0.866025 + vertex 3.34808 -1.93301 -0.5 + vertex 2.73369 -2.73369 -0.5 + endloop + endfacet + facet normal 0.766758 -0.588354 -0.256751 + outer loop + vertex 2.73369 -2.73369 -0.5 + vertex 3.34808 -1.93301 -0.5 + vertex 3.4641 -2 -2.44929e-16 + endloop + endfacet + facet normal 0.766758 -0.588354 -0.256751 + outer loop + vertex 2.73369 -2.73369 -0.5 + vertex 3.4641 -2 -2.44929e-16 + vertex 2.82843 -2.82843 -2.44929e-16 + endloop + endfacet + facet normal 0.892909 -0.369855 0.256751 + outer loop + vertex 3.4641 -2 0 + vertex 3.8637 -1.03528 0 + vertex 3.73429 -1.0006 0.5 + endloop + endfacet + facet normal 0.892909 -0.369855 0.256751 + outer loop + vertex 3.4641 -2 0 + vertex 3.73429 -1.0006 0.5 + vertex 3.34808 -1.93301 0.5 + endloop + endfacet + facet normal 0.656082 -0.271758 0.704063 + outer loop + vertex 3.34808 -1.93301 0.5 + vertex 3.73429 -1.0006 0.5 + vertex 3.38074 -0.905867 0.866025 + endloop + endfacet + facet normal 0.656082 -0.271758 0.704063 + outer loop + vertex 3.34808 -1.93301 0.5 + vertex 3.38074 -0.905867 0.866025 + vertex 3.03109 -1.75 0.866025 + endloop + endfacet + facet normal 0.241041 -0.0998425 0.965366 + outer loop + vertex 3.03109 -1.75 0.866025 + vertex 3.38074 -0.905867 0.866025 + vertex 2.89778 -0.776457 1 + endloop + endfacet + facet normal 0.241041 -0.0998425 0.965366 + outer loop + vertex 3.03109 -1.75 0.866025 + vertex 2.89778 -0.776457 1 + vertex 2.59808 -1.5 1 + endloop + endfacet + facet normal -0.241041 0.0998425 0.965366 + outer loop + vertex 2.59808 -1.5 1 + vertex 2.89778 -0.776457 1 + vertex 2.41481 -0.647048 0.866025 + endloop + endfacet + facet normal -0.241041 0.0998425 0.965366 + outer loop + vertex 2.59808 -1.5 1 + vertex 2.41481 -0.647048 0.866025 + vertex 2.16506 -1.25 0.866025 + endloop + endfacet + facet normal -0.656082 0.271758 0.704063 + outer loop + vertex 2.16506 -1.25 0.866025 + vertex 2.41481 -0.647048 0.866025 + vertex 2.06126 -0.552313 0.5 + endloop + endfacet + facet normal -0.656082 0.271758 0.704063 + outer loop + vertex 2.16506 -1.25 0.866025 + vertex 2.06126 -0.552313 0.5 + vertex 1.84808 -1.06699 0.5 + endloop + endfacet + facet normal -0.892909 0.369855 0.256751 + outer loop + vertex 1.84808 -1.06699 0.5 + vertex 2.06126 -0.552313 0.5 + vertex 1.93185 -0.517638 1.22465e-16 + endloop + endfacet + facet normal -0.892909 0.369855 0.256751 + outer loop + vertex 1.84808 -1.06699 0.5 + vertex 1.93185 -0.517638 1.22465e-16 + vertex 1.73205 -1 1.22465e-16 + endloop + endfacet + facet normal -0.892909 0.369855 -0.256751 + outer loop + vertex 1.73205 -1 1.22465e-16 + vertex 1.93185 -0.517638 1.22465e-16 + vertex 2.06126 -0.552313 -0.5 + endloop + endfacet + facet normal -0.892909 0.369855 -0.256751 + outer loop + vertex 1.73205 -1 1.22465e-16 + vertex 2.06126 -0.552313 -0.5 + vertex 1.84808 -1.06699 -0.5 + endloop + endfacet + facet normal -0.656082 0.271758 -0.704063 + outer loop + vertex 1.84808 -1.06699 -0.5 + vertex 2.06126 -0.552313 -0.5 + vertex 2.41481 -0.647048 -0.866025 + endloop + endfacet + facet normal -0.656082 0.271758 -0.704063 + outer loop + vertex 1.84808 -1.06699 -0.5 + vertex 2.41481 -0.647048 -0.866025 + vertex 2.16506 -1.25 -0.866025 + endloop + endfacet + facet normal -0.241041 0.0998425 -0.965366 + outer loop + vertex 2.16506 -1.25 -0.866025 + vertex 2.41481 -0.647048 -0.866025 + vertex 2.89778 -0.776457 -1 + endloop + endfacet + facet normal -0.241041 0.0998425 -0.965366 + outer loop + vertex 2.16506 -1.25 -0.866025 + vertex 2.89778 -0.776457 -1 + vertex 2.59808 -1.5 -1 + endloop + endfacet + facet normal 0.241041 -0.0998425 -0.965366 + outer loop + vertex 2.59808 -1.5 -1 + vertex 2.89778 -0.776457 -1 + vertex 3.38074 -0.905867 -0.866025 + endloop + endfacet + facet normal 0.241041 -0.0998425 -0.965366 + outer loop + vertex 2.59808 -1.5 -1 + vertex 3.38074 -0.905867 -0.866025 + vertex 3.03109 -1.75 -0.866025 + endloop + endfacet + facet normal 0.656082 -0.271758 -0.704063 + outer loop + vertex 3.03109 -1.75 -0.866025 + vertex 3.38074 -0.905867 -0.866025 + vertex 3.73429 -1.0006 -0.5 + endloop + endfacet + facet normal 0.656082 -0.271758 -0.704063 + outer loop + vertex 3.03109 -1.75 -0.866025 + vertex 3.73429 -1.0006 -0.5 + vertex 3.34808 -1.93301 -0.5 + endloop + endfacet + facet normal 0.892909 -0.369855 -0.256751 + outer loop + vertex 3.34808 -1.93301 -0.5 + vertex 3.73429 -1.0006 -0.5 + vertex 3.8637 -1.03528 -2.44929e-16 + endloop + endfacet + facet normal 0.892909 -0.369855 -0.256751 + outer loop + vertex 3.34808 -1.93301 -0.5 + vertex 3.8637 -1.03528 -2.44929e-16 + vertex 3.4641 -2 -2.44929e-16 + endloop + endfacet + facet normal 0.958209 -0.126151 0.256751 + outer loop + vertex 3.8637 -1.03528 0 + vertex 4 -9.79717e-16 0 + vertex 3.86603 -9.46903e-16 0.5 + endloop + endfacet + facet normal 0.958209 -0.126151 0.256751 + outer loop + vertex 3.8637 -1.03528 0 + vertex 3.86603 -9.46903e-16 0.5 + vertex 3.73429 -1.0006 0.5 + endloop + endfacet + facet normal 0.704063 -0.0926916 0.704063 + outer loop + vertex 3.73429 -1.0006 0.5 + vertex 3.86603 -9.46903e-16 0.5 + vertex 3.5 -8.57253e-16 0.866025 + endloop + endfacet + facet normal 0.704063 -0.0926916 0.704063 + outer loop + vertex 3.73429 -1.0006 0.5 + vertex 3.5 -8.57253e-16 0.866025 + vertex 3.38074 -0.905867 0.866025 + endloop + endfacet + facet normal 0.258669 -0.0340544 0.965366 + outer loop + vertex 3.38074 -0.905867 0.866025 + vertex 3.5 -8.57253e-16 0.866025 + vertex 3 -7.34788e-16 1 + endloop + endfacet + facet normal 0.258669 -0.0340544 0.965366 + outer loop + vertex 3.38074 -0.905867 0.866025 + vertex 3 -7.34788e-16 1 + vertex 2.89778 -0.776457 1 + endloop + endfacet + facet normal -0.258669 0.0340544 0.965366 + outer loop + vertex 2.89778 -0.776457 1 + vertex 3 -7.34788e-16 1 + vertex 2.5 -6.12323e-16 0.866025 + endloop + endfacet + facet normal -0.258669 0.0340544 0.965366 + outer loop + vertex 2.89778 -0.776457 1 + vertex 2.5 -6.12323e-16 0.866025 + vertex 2.41481 -0.647048 0.866025 + endloop + endfacet + facet normal -0.704063 0.0926916 0.704063 + outer loop + vertex 2.41481 -0.647048 0.866025 + vertex 2.5 -6.12323e-16 0.866025 + vertex 2.13397 -5.22673e-16 0.5 + endloop + endfacet + facet normal -0.704063 0.0926916 0.704063 + outer loop + vertex 2.41481 -0.647048 0.866025 + vertex 2.13397 -5.22673e-16 0.5 + vertex 2.06126 -0.552313 0.5 + endloop + endfacet + facet normal -0.958209 0.126151 0.256751 + outer loop + vertex 2.06126 -0.552313 0.5 + vertex 2.13397 -5.22673e-16 0.5 + vertex 2 -4.89859e-16 1.22465e-16 + endloop + endfacet + facet normal -0.958209 0.126151 0.256751 + outer loop + vertex 2.06126 -0.552313 0.5 + vertex 2 -4.89859e-16 1.22465e-16 + vertex 1.93185 -0.517638 1.22465e-16 + endloop + endfacet + facet normal -0.958209 0.126151 -0.256751 + outer loop + vertex 1.93185 -0.517638 1.22465e-16 + vertex 2 -4.89859e-16 1.22465e-16 + vertex 2.13397 -5.22673e-16 -0.5 + endloop + endfacet + facet normal -0.958209 0.126151 -0.256751 + outer loop + vertex 1.93185 -0.517638 1.22465e-16 + vertex 2.13397 -5.22673e-16 -0.5 + vertex 2.06126 -0.552313 -0.5 + endloop + endfacet + facet normal -0.704063 0.0926916 -0.704063 + outer loop + vertex 2.06126 -0.552313 -0.5 + vertex 2.13397 -5.22673e-16 -0.5 + vertex 2.5 -6.12323e-16 -0.866025 + endloop + endfacet + facet normal -0.704063 0.0926916 -0.704063 + outer loop + vertex 2.06126 -0.552313 -0.5 + vertex 2.5 -6.12323e-16 -0.866025 + vertex 2.41481 -0.647048 -0.866025 + endloop + endfacet + facet normal -0.258669 0.0340544 -0.965366 + outer loop + vertex 2.41481 -0.647048 -0.866025 + vertex 2.5 -6.12323e-16 -0.866025 + vertex 3 -7.34788e-16 -1 + endloop + endfacet + facet normal -0.258669 0.0340544 -0.965366 + outer loop + vertex 2.41481 -0.647048 -0.866025 + vertex 3 -7.34788e-16 -1 + vertex 2.89778 -0.776457 -1 + endloop + endfacet + facet normal 0.258669 -0.0340544 -0.965366 + outer loop + vertex 2.89778 -0.776457 -1 + vertex 3 -7.34788e-16 -1 + vertex 3.5 -8.57253e-16 -0.866025 + endloop + endfacet + facet normal 0.258669 -0.0340544 -0.965366 + outer loop + vertex 2.89778 -0.776457 -1 + vertex 3.5 -8.57253e-16 -0.866025 + vertex 3.38074 -0.905867 -0.866025 + endloop + endfacet + facet normal 0.704063 -0.0926916 -0.704063 + outer loop + vertex 3.38074 -0.905867 -0.866025 + vertex 3.5 -8.57253e-16 -0.866025 + vertex 3.86603 -9.46903e-16 -0.5 + endloop + endfacet + facet normal 0.704063 -0.0926916 -0.704063 + outer loop + vertex 3.38074 -0.905867 -0.866025 + vertex 3.86603 -9.46903e-16 -0.5 + vertex 3.73429 -1.0006 -0.5 + endloop + endfacet + facet normal 0.958209 -0.126151 -0.256751 + outer loop + vertex 3.73429 -1.0006 -0.5 + vertex 3.86603 -9.46903e-16 -0.5 + vertex 4 -9.79717e-16 -2.44929e-16 + endloop + endfacet + facet normal 0.958209 -0.126151 -0.256751 + outer loop + vertex 3.73429 -1.0006 -0.5 + vertex 4 -9.79717e-16 -2.44929e-16 + vertex 3.8637 -1.03528 -2.44929e-16 + endloop + endfacet +endsolid torus diff --git a/examples/region_mesh/in.region_mesh b/examples/region_mesh/in.region_mesh new file mode 100644 index 000000000..89bae0d60 --- /dev/null +++ b/examples/region_mesh/in.region_mesh @@ -0,0 +1,44 @@ +################################################################################ +# thermal gas filling the volume enclosed by a triangulated surface mesh +# +# the mesh is a torus, read from an STL file by the region mesh style, +# which is a shape none of the analytic region styles can describe +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 3 +global gridcut 0.0 comm/sort yes + +boundary rr rr rr + +create_box -5 5 -5 5 -5 5 +create_grid 20 20 20 + +balance_grid rcb cell + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the torus in the file has a major radius of 3 and a minor radius of 1 +# and is centered on the origin with its axis along z + +region tor mesh data.torus.stl + +create_particles air n 0 region tor twopass + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 diff --git a/examples/region_mesh/in.region_mesh.2d b/examples/region_mesh/in.region_mesh.2d new file mode 100644 index 000000000..1cf80f947 --- /dev/null +++ b/examples/region_mesh/in.region_mesh.2d @@ -0,0 +1,44 @@ +################################################################################ +# thermal gas filling the area enclosed by a 2d surface mesh +# +# the mesh is an annulus, read from a file in the same format read_surf +# reads, so a ray cast from a point in the gas crosses both of its loops +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 2 +global gridcut 0.0 comm/sort yes + +boundary rr rr p + +create_box -5 5 -5 5 -0.5 0.5 +create_grid 40 40 1 + +balance_grid rcb cell + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the annulus in the file has an outer radius of 4 and an inner radius of 2 +# and is centered on the origin + +region ann mesh data.annulus + +create_particles air n 0 region ann twopass + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 diff --git a/examples/region_mesh/log.27Aug26.mpi_1.region_mesh b/examples/region_mesh/log.27Aug26.mpi_1.region_mesh new file mode 100644 index 000000000..246328170 --- /dev/null +++ b/examples/region_mesh/log.27Aug26.mpi_1.region_mesh @@ -0,0 +1,122 @@ +SPARTA (24 Sep 2025) +Running on 1 MPI task(s) +################################################################################ +# thermal gas filling the volume enclosed by a triangulated surface mesh +# +# the mesh is a torus, read from an STL file by the region mesh style, +# which is a shape none of the analytic region styles can describe +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 3 +global gridcut 0.0 comm/sort yes + +boundary rr rr rr + +create_box -5 5 -5 5 -5 5 +Created orthogonal box = (-5 -5 -5) to (5 5 5) +create_grid 20 20 20 +Created 8000 child grid cells + CPU time = 0.00188663 secs + create/ghost percent = 44.943 55.057 + +balance_grid rcb cell +Balance grid migrated 0 cells + CPU time = 0.00122457 secs + reassign/sort/migrate/ghost percent = 41.7409 3.72498 9.41123 45.1229 + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the torus in the file has a major radius of 3 and a minor radius of 1 +# and is centered on the origin with its axis along z + +region tor mesh data.torus.stl +Reading STL object torus with 576 triangles from file data.torus.stl + -4 -4 -1 to 4 4 1 mesh bounding box + 55.9049 enclosed mesh volume + +create_particles air n 0 region tor twopass +Created 55854 particles + CPU time = 0.0395966 secs + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 +Memory usage per proc in Mbytes: + particles (ave,min,max) = 6.25 6.25 6.25 + grid (ave,min,max) = 1.51379 1.51379 1.51379 + surf (ave,min,max) = 0 0 0 + modify (ave,min,max) = 0 0 0 + total (ave,min,max) = 7.76379 7.76379 7.76379 +Step CPU Np Natt Ncoll c_temp + 0 0 55854 0 0 299.39732 + 20 0.0523511 55854 8447 5725 299.39732 + 40 0.098892916 55854 8101 5481 299.39732 + 60 0.13834398 55854 7469 4918 299.39732 + 80 0.17101096 55854 6738 4337 299.39732 + 100 0.20099609 55854 5985 3839 299.39732 +Loop time of 0.201027 on 1 procs for 100 steps with 55854 particles +Performance: 497.445 timesteps/s, 27.784 Mparticle-step/s + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Move | 0.044279 | 0.044279 | 0.044279 | 0.0 | 22.03 +Coll | 0.13465 | 0.13465 | 0.13465 | 0.0 | 66.98 +Sort | 0.02067 | 0.02067 | 0.02067 | 0.0 | 10.28 +Comm | 9.7879e-05 | 9.7879e-05 | 9.7879e-05 | 0.0 | 0.05 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0.0011631 | 0.0011631 | 0.0011631 | 0.0 | 0.58 +MPI Sync| 0.00015136 | 0.00015136 | 0.00015136 | 0.0 | 0.08 +Other | | 1.971e-05 | | | 0.01 + +Particle moves = 5585400 (5.59M) +Cells touched = 5682200 (5.68M) +Particle comms = 0 (0K) +Boundary collides = 0 (0K) +Boundary exits = 0 (0K) +SurfColl checks = 0 (0K) +SurfColl occurs = 0 (0K) +Surf reactions = 0 (0K) +Collide attempts = 757351 (0.757M) +Collide occurs = 505027 (0.505M) +Reactions = 0 (0K) +Particles stuck = 0 +Axisymm bad moves = 0 + +Particle-moves/CPUsec/proc: 2.77843e+07 +Particle-moves/step: 55854 +Cell-touches/particle/step: 1.01733 +Particle comm iterations/step: 1 +Particle fraction communicated: 0 +Particle fraction colliding with boundary: 0 +Particle fraction exiting boundary: 0 +Surface-checks/particle/step: 0 +Surface-collisions/particle/step: 0 +Surf-reactions/particle/step: 0 +Collision-attempts/particle/step: 0.135595 +Collisions/particle/step: 0.0904191 +Reactions/particle/step: 0 + +Particles: 55854 ave 55854 max 55854 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Cells: 8000 ave 8000 max 8000 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +GhostCell: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +EmptyCell: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 diff --git a/examples/region_mesh/log.27Aug26.mpi_1.region_mesh.2d b/examples/region_mesh/log.27Aug26.mpi_1.region_mesh.2d new file mode 100644 index 000000000..4e995016e --- /dev/null +++ b/examples/region_mesh/log.27Aug26.mpi_1.region_mesh.2d @@ -0,0 +1,122 @@ +SPARTA (24 Sep 2025) +Running on 1 MPI task(s) +################################################################################ +# thermal gas filling the area enclosed by a 2d surface mesh +# +# the mesh is an annulus, read from a file in the same format read_surf +# reads, so a ray cast from a point in the gas crosses both of its loops +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 2 +global gridcut 0.0 comm/sort yes + +boundary rr rr p + +create_box -5 5 -5 5 -0.5 0.5 +Created orthogonal box = (-5 -5 -0.5) to (5 5 0.5) +create_grid 40 40 1 +Created 1600 child grid cells + CPU time = 0.000863477 secs + create/ghost percent = 79.1457 20.8543 + +balance_grid rcb cell +Balance grid migrated 0 cells + CPU time = 0.000254395 secs + reassign/sort/migrate/ghost percent = 51.31 0.952456 7.77177 39.9658 + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the annulus in the file has an outer radius of 4 and an inner radius of 2 +# and is centered on the origin + +region ann mesh data.annulus +Reading 96 lines from surf file data.annulus + -4 -4 0 to 4 4 0 mesh bounding box + 37.699 enclosed mesh area + +create_particles air n 0 region ann twopass +Created 37647 particles + CPU time = 0.00909305 secs + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 +Memory usage per proc in Mbytes: + particles (ave,min,max) = 4.6875 4.6875 4.6875 + grid (ave,min,max) = 1.51379 1.51379 1.51379 + surf (ave,min,max) = 0 0 0 + modify (ave,min,max) = 0 0 0 + total (ave,min,max) = 6.20129 6.20129 6.20129 +Step CPU Np Natt Ncoll c_temp + 0 0 37647 0 0 298.58341 + 20 0.021459459 37647 6375 4473 298.58341 + 40 0.056167176 37647 6291 4258 298.58341 + 60 0.078458566 37647 6069 4076 298.58341 + 80 0.1005359 37647 5802 3840 298.58341 + 100 0.12196574 37647 5481 3607 298.58341 +Loop time of 0.121991 on 1 procs for 100 steps with 37647 particles +Performance: 819.734 timesteps/s, 30.861 Mparticle-step/s + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Move | 0.02247 | 0.02247 | 0.02247 | 0.0 | 18.42 +Coll | 0.085601 | 0.085601 | 0.085601 | 0.0 | 70.17 +Sort | 0.0090205 | 0.0090205 | 0.0090205 | 0.0 | 7.39 +Comm | 6.9983e-05 | 6.9983e-05 | 6.9983e-05 | 0.0 | 0.06 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0.0047351 | 0.0047351 | 0.0047351 | 0.0 | 3.88 +MPI Sync| 7.9022e-05 | 7.9022e-05 | 7.9022e-05 | 0.0 | 0.06 +Other | | 1.556e-05 | | | 0.01 + +Particle moves = 3764700 (3.76M) +Cells touched = 3860633 (3.86M) +Particle comms = 0 (0K) +Boundary collides = 9 (0.009K) +Boundary exits = 0 (0K) +SurfColl checks = 0 (0K) +SurfColl occurs = 0 (0K) +Surf reactions = 0 (0K) +Collide attempts = 607009 (0.607M) +Collide occurs = 412535 (0.413M) +Reactions = 0 (0K) +Particles stuck = 0 +Axisymm bad moves = 0 + +Particle-moves/CPUsec/proc: 3.08605e+07 +Particle-moves/step: 37647 +Cell-touches/particle/step: 1.02548 +Particle comm iterations/step: 1 +Particle fraction communicated: 0 +Particle fraction colliding with boundary: 2.39063e-06 +Particle fraction exiting boundary: 0 +Surface-checks/particle/step: 0 +Surface-collisions/particle/step: 0 +Surf-reactions/particle/step: 0 +Collision-attempts/particle/step: 0.161237 +Collisions/particle/step: 0.10958 +Reactions/particle/step: 0 + +Particles: 37647 ave 37647 max 37647 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Cells: 1600 ave 1600 max 1600 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +GhostCell: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +EmptyCell: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 diff --git a/examples/region_mesh/log.27Aug26.mpi_4.region_mesh b/examples/region_mesh/log.27Aug26.mpi_4.region_mesh new file mode 100644 index 000000000..311d8571b --- /dev/null +++ b/examples/region_mesh/log.27Aug26.mpi_4.region_mesh @@ -0,0 +1,123 @@ +SPARTA (24 Sep 2025) +Running on 4 MPI task(s) +################################################################################ +# thermal gas filling the volume enclosed by a triangulated surface mesh +# +# the mesh is a torus, read from an STL file by the region mesh style, +# which is a shape none of the analytic region styles can describe +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 3 +global gridcut 0.0 comm/sort yes + +boundary rr rr rr + +create_box -5 5 -5 5 -5 5 +Created orthogonal box = (-5 -5 -5) to (5 5 5) +create_grid 20 20 20 +WARNING: Could not acquire nearby ghost cells b/c grid partition is not clumped (../grid.cpp:486) +Created 8000 child grid cells + CPU time = 0.0399973 secs + create/ghost percent = 20.0147 79.9853 + +balance_grid rcb cell +Balance grid migrated 5600 cells + CPU time = 0.299996 secs + reassign/sort/migrate/ghost percent = 49.3344 2.66504 13.3774 34.6232 + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the torus in the file has a major radius of 3 and a minor radius of 1 +# and is centered on the origin with its axis along z + +region tor mesh data.torus.stl +Reading STL object torus with 576 triangles from file data.torus.stl + -4 -4 -1 to 4 4 1 mesh bounding box + 55.9049 enclosed mesh volume + +create_particles air n 0 region tor twopass +Created 56099 particles + CPU time = 0.0337464 secs + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 +Memory usage per proc in Mbytes: + particles (ave,min,max) = 1.5625 1.5625 1.5625 + grid (ave,min,max) = 1.51379 1.51379 1.51379 + surf (ave,min,max) = 0 0 0 + modify (ave,min,max) = 0 0 0 + total (ave,min,max) = 3.07629 3.07629 3.07629 +Step CPU Np Natt Ncoll c_temp + 0 0 56099 0 0 298.92493 + 20 0.9640167 56099 8453 5796 298.92493 + 40 1.8520067 56099 8089 5414 298.92493 + 60 2.7880367 56099 7458 4838 298.92493 + 80 3.8134074 56099 6749 4404 298.92493 + 100 4.7640505 56099 5991 3873 298.92493 +Loop time of 4.779 on 4 procs for 100 steps with 56099 particles +Performance: 20.925 timesteps/s, 1.174 Mparticle-step/s + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Move | 0.010177 | 0.010261 | 0.010431 | 0.1 | 0.21 +Coll | 0.027048 | 0.027708 | 0.028343 | 0.3 | 0.58 +Sort | 0.0075804 | 0.0083599 | 0.010366 | 1.3 | 0.17 +Comm | 3.4012 | 3.5247 | 3.6188 | 4.8 | 73.75 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0.11893 | 0.12648 | 0.13431 | 1.7 | 2.65 +MPI Sync| 0.99722 | 1.0814 | 1.2078 | 8.5 | 22.63 +Other | | 2.098e-05 | | | 0.00 + +Particle moves = 5609900 (5.61M) +Cells touched = 5707445 (5.71M) +Particle comms = 3853 (3.85K) +Boundary collides = 3 (0.003K) +Boundary exits = 0 (0K) +SurfColl checks = 0 (0K) +SurfColl occurs = 0 (0K) +Surf reactions = 0 (0K) +Collide attempts = 756950 (0.757M) +Collide occurs = 506143 (0.506M) +Reactions = 0 (0K) +Particles stuck = 0 +Axisymm bad moves = 0 + +Particle-moves/CPUsec/proc: 293466 +Particle-moves/step: 56099 +Cell-touches/particle/step: 1.01739 +Particle comm iterations/step: 2 +Particle fraction communicated: 0.000686822 +Particle fraction colliding with boundary: 5.34769e-07 +Particle fraction exiting boundary: 0 +Surface-checks/particle/step: 0 +Surface-collisions/particle/step: 0 +Surf-reactions/particle/step: 0 +Collision-attempts/particle/step: 0.134931 +Collisions/particle/step: 0.0902232 +Reactions/particle/step: 0 + +Particles: 14024.8 ave 14058 max 13982 min +Histogram: 1 0 1 0 0 0 0 0 0 2 +Cells: 2000 ave 2000 max 2000 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +GhostCell: 420 ave 420 max 420 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +EmptyCell: 420 ave 420 max 420 min +Histogram: 4 0 0 0 0 0 0 0 0 0 diff --git a/examples/region_mesh/log.27Aug26.mpi_4.region_mesh.2d b/examples/region_mesh/log.27Aug26.mpi_4.region_mesh.2d new file mode 100644 index 000000000..84f9d0d62 --- /dev/null +++ b/examples/region_mesh/log.27Aug26.mpi_4.region_mesh.2d @@ -0,0 +1,123 @@ +SPARTA (24 Sep 2025) +Running on 4 MPI task(s) +################################################################################ +# thermal gas filling the area enclosed by a 2d surface mesh +# +# the mesh is an annulus, read from a file in the same format read_surf +# reads, so a ray cast from a point in the gas crosses both of its loops +# +# Note: +# - The "comm/sort" option to the "global" command is used to match MPI runs. +# - The "twopass" option is used to match Kokkos runs. +# The "comm/sort" and "twopass" options should not be used for production runs. +################################################################################ + +seed 12345 +dimension 2 +global gridcut 0.0 comm/sort yes + +boundary rr rr p + +create_box -5 5 -5 5 -0.5 0.5 +Created orthogonal box = (-5 -5 -0.5) to (5 5 0.5) +create_grid 40 40 1 +WARNING: Could not acquire nearby ghost cells b/c grid partition is not clumped (../grid.cpp:486) +Created 1600 child grid cells + CPU time = 0.0440137 secs + create/ghost percent = 18.198 81.802 + +balance_grid rcb cell +Balance grid migrated 1200 cells + CPU time = 0.222461 secs + reassign/sort/migrate/ghost percent = 95.3043 3.5935 1.04958 0.0525962 + +species air.species N O +mixture air N O vstream 0.0 0.0 0.0 temp 300.0 + +global nrho 1.0e20 +global fnum 1.0e17 + +# the annulus in the file has an outer radius of 4 and an inner radius of 2 +# and is centered on the origin + +region ann mesh data.annulus +Reading 96 lines from surf file data.annulus + -4 -4 0 to 4 4 0 mesh bounding box + 37.699 enclosed mesh area + +create_particles air n 0 region ann twopass +Created 37678 particles + CPU time = 0.0188268 secs + +stats 20 +compute temp temp +stats_style step cpu np nattempt ncoll c_temp + +collide vss air air.vss + +timestep 1.0e-5 +run 100 +Memory usage per proc in Mbytes: + particles (ave,min,max) = 1.5625 1.5625 1.5625 + grid (ave,min,max) = 1.51379 1.51379 1.51379 + surf (ave,min,max) = 0 0 0 + modify (ave,min,max) = 0 0 0 + total (ave,min,max) = 3.07629 3.07629 3.07629 +Step CPU Np Natt Ncoll c_temp + 0 0 37678 0 0 300.95773 + 20 0.009582402 37678 6410 4434 300.95773 + 40 0.019269321 37678 6265 4228 300.95773 + 60 0.048919185 37678 6070 4045 300.95773 + 80 0.35980408 37678 5775 3801 300.95773 + 100 0.86410683 37678 5487 3623 300.95773 +Loop time of 0.864184 on 4 procs for 100 steps with 37678 particles +Performance: 115.716 timesteps/s, 4.360 Mparticle-step/s + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Move | 0.0075852 | 0.0092281 | 0.0099604 | 1.0 | 1.07 +Coll | 0.026225 | 0.036557 | 0.042412 | 3.2 | 4.23 +Sort | 0.0019483 | 0.0020117 | 0.0020507 | 0.1 | 0.23 +Comm | 0.54616 | 0.58986 | 0.62014 | 4.0 | 68.26 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0.023883 | 0.02496 | 0.02787 | 1.1 | 2.89 +MPI Sync| 0.17263 | 0.20155 | 0.24227 | 6.0 | 23.32 +Other | | 1.782e-05 | | | 0.00 + +Particle moves = 3767800 (3.77M) +Cells touched = 3864319 (3.86M) +Particle comms = 2670 (2.67K) +Boundary collides = 6 (0.006K) +Boundary exits = 0 (0K) +SurfColl checks = 0 (0K) +SurfColl occurs = 0 (0K) +Surf reactions = 0 (0K) +Collide attempts = 607828 (0.608M) +Collide occurs = 412809 (0.413M) +Reactions = 0 (0K) +Particles stuck = 0 +Axisymm bad moves = 0 + +Particle-moves/CPUsec/proc: 1.08999e+06 +Particle-moves/step: 37678 +Cell-touches/particle/step: 1.02562 +Particle comm iterations/step: 2 +Particle fraction communicated: 0.000708636 +Particle fraction colliding with boundary: 1.59244e-06 +Particle fraction exiting boundary: 0 +Surface-checks/particle/step: 0 +Surface-collisions/particle/step: 0 +Surf-reactions/particle/step: 0 +Collision-attempts/particle/step: 0.161322 +Collisions/particle/step: 0.109562 +Reactions/particle/step: 0 + +Particles: 9419.5 ave 9466 max 9363 min +Histogram: 1 0 1 0 0 0 0 0 0 2 +Cells: 400 ave 400 max 400 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +GhostCell: 41 ave 41 max 41 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +EmptyCell: 41 ave 41 max 41 min +Histogram: 4 0 0 0 0 0 0 0 0 0 diff --git a/src/region_mesh.cpp b/src/region_mesh.cpp new file mode 100644 index 000000000..5d3b3e540 --- /dev/null +++ b/src/region_mesh.cpp @@ -0,0 +1,800 @@ +/* ---------------------------------------------------------------------- + SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer + http://sparta.github.io + Steve Plimpton, sjplimp@gmail.com, Michael Gallis, magalli@sandia.gov + Sandia National Laboratories + + Copyright (2014) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level SPARTA directory. +------------------------------------------------------------------------- */ + +#include "math.h" +#include "stdlib.h" +#include "string.h" +#include "region_mesh.h" +#include "stl_reader.h" +#include "comm.h" +#include "input.h" +#include "math_const.h" +#include "math_extra.h" +#include "utils.h" +#include "memory.h" +#include "error.h" + +using namespace SPARTA_NS; +using namespace MathConst; + +#define BIG 1.0e20 // same "infinity" the other region styles use +#define EPSILON 1.0e-9 // relative tolerance for a degenerate ray hit +#define JITTER 1.0e-6 // relative offset used to move a degenerate ray +#define MAXJITTER 8 // max # of times a degenerate ray is moved +#define CLOSED 1.0e-6 // relative tolerance on the closure of the mesh +#define MAXBIN 1024 // max # of ray-casting bins in y or z +#define MAXLINE 1024 +#define MAXWORD 16 // more words on a line than any valid format has + +// angle between successive jittered rays, the golden angle in radians +// keeps the rays from repeating a direction that was already degenerate + +#define GOLDEN_ANGLE 2.39996322972865332 + +/* ---------------------------------------------------------------------- + return the next non-blank line of a file with any comment stripped off, + or NULL at end of file +------------------------------------------------------------------------- */ + +static char *next_line(FILE *fp, char *line) +{ + while (fgets(line,MAXLINE,fp)) { + char *ptr = strchr(line,'#'); + if (ptr) *ptr = '\0'; + if (strspn(line," \t\n\r") != strlen(line)) return line; + } + return NULL; +} + +/* ---------------------------------------------------------------------- + split a line into whitespace delimited words, return # of words + words point into line, which is modified +------------------------------------------------------------------------- */ + +static int split_line(char *line, char **words) +{ + int nwords = 0; + char *ptr = strtok(line," \t\n\r\f"); + + while (ptr && nwords < MAXWORD) { + words[nwords++] = ptr; + ptr = strtok(NULL," \t\n\r\f"); + } + + return nwords; +} + +/* ---------------------------------------------------------------------- */ + +RegMesh::RegMesh(SPARTA *sparta, int narg, char **arg) : + Region(sparta, narg, arg) +{ + if (narg < 3) error->all(FLERR,"Illegal region mesh command"); + + verts = NULL; + esize = NULL; + binfirst = binlist = NULL; + + // read the surface, every proc keeps a copy of the entire mesh + + read_mesh(arg[2]); + + // optional args + // side is parsed by the base class, everything else transforms the mesh + // transforms are applied in the order they appear, as in read_surf + + origin[0] = origin[1] = origin[2] = 0.0; + interior = 1; + + int iarg = 3; + while (iarg < narg) { + if (strcmp(arg[iarg],"origin") == 0) { + if (iarg+4 > narg) error->all(FLERR,"Illegal region mesh command"); + origin[0] = input->numeric(FLERR,arg[iarg+1]); + origin[1] = input->numeric(FLERR,arg[iarg+2]); + origin[2] = input->numeric(FLERR,arg[iarg+3]); + iarg += 4; + } else if (strcmp(arg[iarg],"trans") == 0) { + if (iarg+4 > narg) error->all(FLERR,"Illegal region mesh command"); + double dx = input->numeric(FLERR,arg[iarg+1]); + double dy = input->numeric(FLERR,arg[iarg+2]); + double dz = input->numeric(FLERR,arg[iarg+3]); + origin[0] += dx; + origin[1] += dy; + origin[2] += dz; + translate(dx,dy,dz); + iarg += 4; + } else if (strcmp(arg[iarg],"scale") == 0) { + if (iarg+4 > narg) error->all(FLERR,"Illegal region mesh command"); + double sx = input->numeric(FLERR,arg[iarg+1]); + double sy = input->numeric(FLERR,arg[iarg+2]); + double sz = input->numeric(FLERR,arg[iarg+3]); + scale(sx,sy,sz); + iarg += 4; + } else if (strcmp(arg[iarg],"rotate") == 0) { + if (iarg+5 > narg) error->all(FLERR,"Illegal region mesh command"); + double theta = input->numeric(FLERR,arg[iarg+1]); + double rx = input->numeric(FLERR,arg[iarg+2]); + double ry = input->numeric(FLERR,arg[iarg+3]); + double rz = input->numeric(FLERR,arg[iarg+4]); + if (rx == 0.0 && ry == 0.0 && rz == 0.0) + error->all(FLERR,"Illegal region mesh command"); + rotate(theta,rx,ry,rz); + iarg += 5; + } else if (strcmp(arg[iarg],"side") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal region mesh command"); + options(2,&arg[iarg]); + iarg += 2; + } else error->all(FLERR,"Illegal region mesh command"); + } + + // bounding box, enclosed volume, and the bins used by inside() + + setup(); + + // extent of the mesh + // as for the other styles, only an interior region has a bounding box + // a 2d mesh is a closed curve in x-y, so the region is a prism in z + + if (interior) { + bboxflag = 1; + extent_xlo = bblo[0]; + extent_xhi = bbhi[0]; + extent_ylo = bblo[1]; + extent_yhi = bbhi[1]; + if (meshdim == 3) { + extent_zlo = bblo[2]; + extent_zhi = bbhi[2]; + } else { + extent_zlo = -BIG; + extent_zhi = BIG; + } + } else bboxflag = 0; + + if (comm->me == 0) { + const char *what = (meshdim == 2) ? "area" : "volume"; + if (screen) { + fprintf(screen," %g %g %g to %g %g %g mesh bounding box\n", + bblo[0],bblo[1],bblo[2],bbhi[0],bbhi[1],bbhi[2]); + fprintf(screen," %g enclosed mesh %s\n",enclosed,what); + } + if (logfile) { + fprintf(logfile," %g %g %g to %g %g %g mesh bounding box\n", + bblo[0],bblo[1],bblo[2],bbhi[0],bbhi[1],bbhi[2]); + fprintf(logfile," %g enclosed mesh %s\n",enclosed,what); + } + } +} + +/* ---------------------------------------------------------------------- */ + +RegMesh::~RegMesh() +{ + memory->destroy(verts); + memory->destroy(esize); + memory->destroy(binfirst); + memory->destroy(binlist); +} + +/* ---------------------------------------------------------------------- + read the surface from an STL file or a SPARTA surf file + which one it is is detected from the contents of the file +------------------------------------------------------------------------- */ + +void RegMesh::read_mesh(char *file) +{ + int stlflag = 0; + + if (comm->me == 0) { + try { + stlflag = STLReader::is_stl_file(file); + } catch (std::exception &e) { + error->one(FLERR,e.what()); + } + } + MPI_Bcast(&stlflag,1,MPI_INT,0,world); + + if (stlflag) read_stl_file(file); + else read_surf_file(file); +} + +/* ---------------------------------------------------------------------- + read triangles from an ASCII or binary STL file +------------------------------------------------------------------------- */ + +void RegMesh::read_stl_file(char *file) +{ + STLReader reader(sparta); + double **tris; + + meshdim = 3; + nelem = reader.read_file(file,tris); + nvert = 3*nelem; + + // the reader owns the array it fills, so keep our own copy of it + + memory->create(verts,nvert,3,"region/mesh:verts"); + + for (int i = 0; i < nelem; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + verts[3*i+j][k] = tris[i][3*j+k]; +} + +/* ---------------------------------------------------------------------- + read lines or triangles from a SPARTA surf file, the same format + read_surf reads, on proc 0, then broadcast them + only the geometry is used, so a type column is skipped and the ids are + ignored, but per-surf custom attributes are not supported +------------------------------------------------------------------------- */ + +void RegMesh::read_surf_file(char *file) +{ + if (comm->me == 0) { + char line[MAXLINE]; + char *words[MAXWORD]; + double **pts = NULL; + + FILE *fp = fopen(file,"r"); + if (fp == NULL) surf_error(file,"Cannot open mesh file"); + + // 1st line of the file is a comment + + if (fgets(line,MAXLINE,fp) == NULL) + surf_error(file,"Unexpected end of surf file"); + + // header = keyword lines with counts on them + // it ends at the 1st line with no header keyword, the section keyword + + int npoint = 0; + int nline = 0; + int ntri = 0; + + while (1) { + if (next_line(fp,line) == NULL) { + line[0] = '\0'; + break; + } + if (strstr(line,"points")) npoint = atoi(line); + else if (strstr(line,"lines")) nline = atoi(line); + else if (strstr(line,"triangles")) ntri = atoi(line); + else break; + } + + if (nline && ntri) + surf_error(file,"Surf file contains both lines and triangles"); + if (nline <= 0 && ntri <= 0) + surf_error(file,"Surf file does not contain lines or triangles"); + + meshdim = nline ? 2 : 3; + nelem = nline ? nline : ntri; + nvert = meshdim*nelem; + memory->create(verts,nvert,3,"region/mesh:verts"); + + // sections, in whatever order they appear + // a Points section is optional, elements may carry their own coords + + int nelemread = 0; + + while (strlen(line)) { + if (strstr(line,"Points")) { + if (npoint <= 0) surf_error(file,"Surf file has no points count"); + memory->create(pts,npoint,3,"region/mesh:pts"); + + for (int i = 0; i < npoint; i++) { + if (next_line(fp,line) == NULL) + surf_error(file,"Unexpected end of surf file"); + int nwords = split_line(line,words); + if (nwords != 3 && nwords != 4) + surf_error(file,"Incorrect point format in surf file"); + pts[i][0] = surf_numeric(file,words[1]); + pts[i][1] = surf_numeric(file,words[2]); + pts[i][2] = (nwords == 4) ? surf_numeric(file,words[3]) : 0.0; + } + + } else if (strstr(line,"Lines") || strstr(line,"Triangles")) { + int nvper = meshdim; + + // # of words per element, with and without a leading type column + // an id is always present, and point indices replace the coords + // if the file has a Points section + + int nbase = npoint ? 1+nvper : 1+3*nvper; + if (meshdim == 2 && !npoint) nbase = 1+2*nvper; + + for (int i = 0; i < nelem; i++) { + if (next_line(fp,line) == NULL) + surf_error(file,"Unexpected end of surf file"); + int nwords = split_line(line,words); + if (nwords != nbase && nwords != nbase+1) + surf_error(file,(meshdim == 2) ? + "Incorrect line format in surf file" : + "Incorrect triangle format in surf file"); + + // skip the id, and the type column if there is one + + int iw = (nwords == nbase) ? 1 : 2; + + for (int j = 0; j < nvper; j++) { + double *v = verts[nvper*i+j]; + if (npoint) { + int ipoint = surf_inumeric(file,words[iw++]); + if (ipoint < 1 || ipoint > npoint) + surf_error(file,"Invalid point index in surf file"); + v[0] = pts[ipoint-1][0]; + v[1] = pts[ipoint-1][1]; + v[2] = pts[ipoint-1][2]; + } else { + v[0] = surf_numeric(file,words[iw++]); + v[1] = surf_numeric(file,words[iw++]); + v[2] = (meshdim == 3) ? surf_numeric(file,words[iw++]) : 0.0; + } + } + } + + nelemread = nelem; + + } else surf_error(file,"Unknown section in surf file"); + + if (next_line(fp,line) == NULL) line[0] = '\0'; + } + + memory->destroy(pts); + fclose(fp); + + if (nelemread == 0) + surf_error(file,(meshdim == 2) ? + "Surf file has no Lines section" : + "Surf file has no Triangles section"); + + if (screen) + fprintf(screen,"Reading %d %s from surf file %s\n", + nelem,(meshdim == 2) ? "lines" : "triangles",file); + if (logfile) + fprintf(logfile,"Reading %d %s from surf file %s\n", + nelem,(meshdim == 2) ? "lines" : "triangles",file); + } + + bcast_verts(); +} + +/* ---------------------------------------------------------------------- + send the mesh proc 0 read to all the other procs +------------------------------------------------------------------------- */ + +void RegMesh::bcast_verts() +{ + MPI_Bcast(&meshdim,1,MPI_INT,0,world); + MPI_Bcast(&nelem,1,MPI_INT,0,world); + MPI_Bcast(&nvert,1,MPI_INT,0,world); + + if (comm->me) memory->create(verts,nvert,3,"region/mesh:verts"); + + // allow for 3*nvert to exceed the max allowed size of a single MPI_Bcast() + + bigint ntotal = (bigint) nvert * 3; + if (ntotal < MAXSMALLINT) + MPI_Bcast(&verts[0][0],3*nvert,MPI_DOUBLE,0,world); + else { + double *source = &verts[0][0]; + bigint n = 0; + while (n < ntotal) { + int nsize = MIN(MAXSMALLINT,ntotal-n); + MPI_Bcast(&source[n],nsize,MPI_DOUBLE,0,world); + n += nsize; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void RegMesh::surf_error(const char *file, const char *mesg) +{ + char str[256]; + snprintf(str,256,"%s: %s",mesg,file); + error->one(FLERR,str); +} + +/* ---------------------------------------------------------------------- + convert a word of a surf file to a number + Input::numeric() cannot be used here, it reports a bad value with + Error::all(), which the other procs would never reach while proc 0 is + the only one reading the file +------------------------------------------------------------------------- */ + +double RegMesh::surf_numeric(const char *file, const char *word) +{ + if (!utils::is_double(word)) + surf_error(file,"Expected floating point value in surf file"); + return atof(word); +} + +/* ---------------------------------------------------------------------- */ + +int RegMesh::surf_inumeric(const char *file, const char *word) +{ + if (!utils::is_integer(word)) + surf_error(file,"Expected integer value in surf file"); + return atoi(word); +} + +/* ---------------------------------------------------------------------- + inside = 1 if x,y,z is inside the closed surface, else 0 + cast a ray in +x from the point and count the elements it crosses + an odd count means the point is inside + a 2d mesh is a closed curve in the x-y plane, so the ray is cast in that + plane and the z coord of the point does not matter +------------------------------------------------------------------------- */ + +int RegMesh::inside(double *x) +{ + if (x[0] < bblo[0] || x[0] > bbhi[0] || + x[1] < bblo[1] || x[1] > bbhi[1]) return 0; + if (meshdim == 3 && (x[2] < bblo[2] || x[2] > bbhi[2])) return 0; + + // a ray that grazes an edge or a vertex cannot be counted reliably + // move it a little across the ray direction and cast it again + + double dy = 0.0; + double dz = 0.0; + + for (int attempt = 0; attempt <= MAXJITTER; attempt++) { + int ncross = crossings(x[0],x[1]+dy,x[2]+dz); + if (ncross >= 0) return ncross & 1; + + double offset = jitter * (attempt+1); + if (meshdim == 2) { + dy = (attempt & 1) ? -offset : offset; + dz = 0.0; + } else { + double angle = GOLDEN_ANGLE * (attempt+1); + dy = offset * cos(angle); + dz = offset * sin(angle); + } + } + + // every ray was degenerate, so the point is on the surface itself + // as for the other region styles, the surface counts as inside + + return 1; +} + +/* ---------------------------------------------------------------------- + count the elements crossed by a +x ray from the point px,py,pz + return -1 if the ray grazes an edge or a vertex, so the count is unreliable +------------------------------------------------------------------------- */ + +int RegMesh::crossings(double px, double py, double pz) +{ + int iy = static_cast ((py-bblo[1]) * invbiny); + iy = MAX(0,MIN(iy,nbiny-1)); + int iz = static_cast ((pz-bblo[2]) * invbinz); + iz = MAX(0,MIN(iz,nbinz-1)); + int ibin = iz*nbiny + iy; + + if (meshdim == 2) + return crossings_line(px,py,binfirst[ibin],binfirst[ibin+1]); + return crossings_tri(px,py,pz,binfirst[ibin],binfirst[ibin+1]); +} + +/* ---------------------------------------------------------------------- + crossings of the line segments in one bin, for a 2d mesh +------------------------------------------------------------------------- */ + +int RegMesh::crossings_line(double px, double py, int mlo, int mhi) +{ + int ncross = 0; + + for (int m = mlo; m < mhi; m++) { + int ielem = binlist[m]; + double *a = verts[2*ielem]; + double *b = verts[2*ielem+1]; + + // how far the point is from each end of the segment, measured along y + // the 2 are the same sign only if the segment spans the ray + + double d0 = py - a[1]; + double d1 = b[1] - py; + + // d0+d1 is the extent of the segment in y + // comparing it to the length of the segment tests how parallel the + // segment is to the ray, independent of how long the segment is + + double dy = d0 + d1; + double epsproj = EPSILON * esize[ielem]; + if (fabs(dy) <= epsproj) continue; + + if (fabs(d0) <= epsproj || fabs(d1) <= epsproj) return -1; + if ((d0 > 0.0) != (d1 > 0.0)) continue; + + // x where the ray crosses the segment, from the interpolation weights + + double xhit = (d1*a[0] + d0*b[0]) / dy; + if (fabs(xhit-px) < epslen) return -1; // point is on the segment + if (xhit > px) ncross++; + } + + return ncross; +} + +/* ---------------------------------------------------------------------- + crossings of the triangles in one bin, for a 3d mesh +------------------------------------------------------------------------- */ + +int RegMesh::crossings_tri(double px, double py, double pz, int mlo, int mhi) +{ + int ncross = 0; + + for (int m = mlo; m < mhi; m++) { + int ielem = binlist[m]; + double *a = verts[3*ielem]; + double *b = verts[3*ielem+1]; + double *c = verts[3*ielem+2]; + + // 2x the signed areas of the 3 triangles that the point makes with each + // edge, in the y-z plane the ray projects onto + // the point projects inside the triangle if all 3 have the same sign + + double d0 = (b[1]-a[1])*(pz-a[2]) - (b[2]-a[2])*(py-a[1]); + double d1 = (c[1]-b[1])*(pz-b[2]) - (c[2]-b[2])*(py-b[1]); + double d2 = (a[1]-c[1])*(pz-c[2]) - (a[2]-c[2])*(py-c[1]); + + // d0+d1+d2 is 2x the signed area of the projected triangle, + // which is also the x component of the triangle normal + // comparing it to the length of the normal tests how edge-on the + // triangle is to the ray, independent of how big the triangle is + + double area2 = d0 + d1 + d2; + double epsproj = EPSILON * esize[ielem]; + if (fabs(area2) <= epsproj) continue; + + int nneg = 0; + int npos = 0; + int nzero = 0; + if (d0 > epsproj) npos++; + else if (d0 < -epsproj) nneg++; + else nzero++; + if (d1 > epsproj) npos++; + else if (d1 < -epsproj) nneg++; + else nzero++; + if (d2 > epsproj) npos++; + else if (d2 < -epsproj) nneg++; + else nzero++; + + if (npos && nneg) continue; // ray misses the triangle + if (nzero) return -1; // ray grazes an edge or a vertex + + // x where the ray pierces the triangle, from the barycentric coords + + double xhit = (d1*a[0] + d2*b[0] + d0*c[0]) / area2; + if (fabs(xhit-px) < epslen) return -1; // point is on the triangle + if (xhit > px) ncross++; + } + + return ncross; +} + +/* ---------------------------------------------------------------------- + bounding box, enclosed volume, tolerances, and ray-casting bins +------------------------------------------------------------------------- */ + +void RegMesh::setup() +{ + // bounding box around all the vertices + + bblo[0] = bbhi[0] = verts[0][0]; + bblo[1] = bbhi[1] = verts[0][1]; + bblo[2] = bbhi[2] = verts[0][2]; + + for (int i = 0; i < nvert; i++) + for (int k = 0; k < 3; k++) { + bblo[k] = MIN(bblo[k],verts[i][k]); + bbhi[k] = MAX(bbhi[k],verts[i][k]); + } + + // tolerances scale with the size of the mesh + // the jitter is much larger than the tolerance it has to escape + + double meshlen = MAX(bbhi[0]-bblo[0],MAX(bbhi[1]-bblo[1],bbhi[2]-bblo[2])); + if (meshlen == 0.0) error->all(FLERR,"Region mesh has zero extent"); + + epslen = EPSILON * meshlen; + jitter = JITTER * meshlen; + + // size of each element = 2x area of a triangle, length of a line + // enclosed volume from the divergence theorem, area from the shoelace sum + // the area-weighted normals of a closed surface sum to zero + + memory->create(esize,nelem,"region/mesh:esize"); + + double nsum[3] = {0.0,0.0,0.0}; + double ssum = 0.0; + double gsum = 0.0; + + if (meshdim == 3) { + for (int i = 0; i < nelem; i++) { + double *a = verts[3*i]; + double *b = verts[3*i+1]; + double *c = verts[3*i+2]; + double e1[3],e2[3],n[3]; + + MathExtra::sub3(b,a,e1); + MathExtra::sub3(c,a,e2); + MathExtra::cross3(e1,e2,n); + esize[i] = MathExtra::len3(n); + + ssum += esize[i]; + nsum[0] += n[0]; + nsum[1] += n[1]; + nsum[2] += n[2]; + + MathExtra::cross3(b,c,e1); + gsum += MathExtra::dot3(a,e1); + } + enclosed = fabs(gsum) / 6.0; + + } else { + for (int i = 0; i < nelem; i++) { + double *a = verts[2*i]; + double *b = verts[2*i+1]; + + double dx = b[0] - a[0]; + double dy = b[1] - a[1]; + esize[i] = sqrt(dx*dx + dy*dy); + + // the normal of a segment has the same length as the segment + + ssum += esize[i]; + nsum[0] += dy; + nsum[1] -= dx; + + gsum += a[0]*b[1] - b[0]*a[1]; + } + enclosed = fabs(gsum) / 2.0; + } + + if (MathExtra::len3(nsum) > CLOSED * ssum) + error->warning(FLERR,"Region mesh surface is not closed"); + + // bin the elements by their y-z extent so a +x ray only has to test + // the elements in one bin + // in 3d aim for one triangle per bin, with square bins in the y-z plane + // in 2d there is nothing to bin in z + + double ylen = bbhi[1] - bblo[1]; + double zlen = bbhi[2] - bblo[2]; + + if (meshdim == 2) { + nbiny = MAX(1,MIN(nelem,MAXBIN)); + nbinz = 1; + } else { + double binsize = sqrt(ylen*zlen/nelem); + if (binsize == 0.0) binsize = meshlen; + nbiny = MAX(1,MIN(static_cast (ylen/binsize) + 1,MAXBIN)); + nbinz = MAX(1,MIN(static_cast (zlen/binsize) + 1,MAXBIN)); + } + + invbiny = (ylen > 0.0) ? nbiny/ylen : 0.0; + invbinz = (zlen > 0.0) ? nbinz/zlen : 0.0; + + int nbin = nbiny*nbinz; + memory->create(binfirst,nbin+1,"region/mesh:binfirst"); + for (int i = 0; i <= nbin; i++) binfirst[i] = 0; + + // count the elements in each bin, then turn the counts into offsets + + int iylo,iyhi,izlo,izhi; + + for (int i = 0; i < nelem; i++) { + bin_range(i,iylo,iyhi,izlo,izhi); + for (int iz = izlo; iz <= izhi; iz++) + for (int iy = iylo; iy <= iyhi; iy++) + binfirst[iz*nbiny+iy+1]++; + } + + for (int i = 0; i < nbin; i++) binfirst[i+1] += binfirst[i]; + + memory->create(binlist,binfirst[nbin],"region/mesh:binlist"); + + int *next; + memory->create(next,nbin,"region/mesh:next"); + for (int i = 0; i < nbin; i++) next[i] = binfirst[i]; + + for (int i = 0; i < nelem; i++) { + bin_range(i,iylo,iyhi,izlo,izhi); + for (int iz = izlo; iz <= izhi; iz++) + for (int iy = iylo; iy <= iyhi; iy++) + binlist[next[iz*nbiny+iy]++] = i; + } + + memory->destroy(next); +} + +/* ---------------------------------------------------------------------- + range of bins that element I overlaps in the y-z plane +------------------------------------------------------------------------- */ + +void RegMesh::bin_range(int i, int &iylo, int &iyhi, int &izlo, int &izhi) +{ + int first = meshdim*i; + + double ylo,yhi,zlo,zhi; + ylo = yhi = verts[first][1]; + zlo = zhi = verts[first][2]; + + for (int j = 1; j < meshdim; j++) { + ylo = MIN(ylo,verts[first+j][1]); + yhi = MAX(yhi,verts[first+j][1]); + zlo = MIN(zlo,verts[first+j][2]); + zhi = MAX(zhi,verts[first+j][2]); + } + + iylo = MAX(0,MIN(static_cast ((ylo-bblo[1])*invbiny),nbiny-1)); + iyhi = MAX(0,MIN(static_cast ((yhi-bblo[1])*invbiny),nbiny-1)); + izlo = MAX(0,MIN(static_cast ((zlo-bblo[2])*invbinz),nbinz-1)); + izhi = MAX(0,MIN(static_cast ((zhi-bblo[2])*invbinz),nbinz-1)); +} + +/* ---------------------------------------------------------------------- + translate the mesh by dx,dy,dz +------------------------------------------------------------------------- */ + +void RegMesh::translate(double dx, double dy, double dz) +{ + for (int i = 0; i < nvert; i++) { + verts[i][0] += dx; + verts[i][1] += dy; + verts[i][2] += dz; + } +} + +/* ---------------------------------------------------------------------- + scale the mesh by sx,sy,sz around the origin point +------------------------------------------------------------------------- */ + +void RegMesh::scale(double sx, double sy, double sz) +{ + for (int i = 0; i < nvert; i++) { + verts[i][0] = sx*(verts[i][0]-origin[0]) + origin[0]; + verts[i][1] = sy*(verts[i][1]-origin[1]) + origin[1]; + verts[i][2] = sz*(verts[i][2]-origin[2]) + origin[2]; + } +} + +/* ---------------------------------------------------------------------- + rotate the mesh theta degrees around the axis rx,ry,rz thru the origin point +------------------------------------------------------------------------- */ + +void RegMesh::rotate(double theta, double rx, double ry, double rz) +{ + double r[3],q[4],d[3],dnew[3]; + double rotmat[3][3]; + + theta *= MY_PI/180.0; + + r[0] = rx; r[1] = ry; r[2] = rz; + MathExtra::norm3(r); + MathExtra::axisangle_to_quat(r,theta,q); + MathExtra::quat_to_mat(q,rotmat); + + for (int i = 0; i < nvert; i++) { + d[0] = verts[i][0] - origin[0]; + d[1] = verts[i][1] - origin[1]; + d[2] = verts[i][2] - origin[2]; + MathExtra::matvec(rotmat,d,dnew); + verts[i][0] = dnew[0] + origin[0]; + verts[i][1] = dnew[1] + origin[1]; + verts[i][2] = dnew[2] + origin[2]; + } +} diff --git a/src/region_mesh.h b/src/region_mesh.h new file mode 100644 index 000000000..a261ff33e --- /dev/null +++ b/src/region_mesh.h @@ -0,0 +1,132 @@ +/* ---------------------------------------------------------------------- + SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer + http://sparta.github.io + Steve Plimpton, sjplimp@gmail.com, Michael Gallis, magalli@sandia.gov + Sandia National Laboratories + + Copyright (2014) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level SPARTA directory. +------------------------------------------------------------------------- */ + +#ifdef REGION_CLASS + +RegionStyle(mesh,RegMesh) + +#else + +#ifndef SPARTA_REGION_MESH_H +#define SPARTA_REGION_MESH_H + +#include "stdio.h" +#include "region.h" + +namespace SPARTA_NS { + +class RegMesh : public Region { + public: + RegMesh(class SPARTA *, int, char **); + ~RegMesh(); + int inside(double *); + + protected: + int meshdim; // 2 if the mesh is lines, 3 if it is triangles + int nelem; // # of lines or triangles in the mesh + int nvert; // # of vertices = meshdim per element + double **verts; // nvert x 3 coords, meshdim in a row per element + double *esize; // 2x area of each tri, or length of each line + double origin[3]; // reference point for scale and rotate + double bblo[3],bbhi[3]; // bounding box around the mesh + double enclosed; // volume enclosed by the mesh, area if 2d + + int nbiny,nbinz; // # of ray-casting bins in y and z + double invbiny,invbinz; // inverse bin sizes + int *binfirst; // index in binlist of 1st elem in each bin, nbin+1 + int *binlist; // element indices, grouped by bin + + double epslen; // tolerance for a point lying on the surface + double jitter; // ray offset used to dodge a degenerate hit + + void read_mesh(char *); + void read_stl_file(char *); + void read_surf_file(char *); + void bcast_verts(); + void surf_error(const char *, const char *); + double surf_numeric(const char *, const char *); + int surf_inumeric(const char *, const char *); + + void translate(double, double, double); + void scale(double, double, double); + void rotate(double, double, double, double); + void setup(); + void bin_range(int, int &, int &, int &, int &); + int crossings(double, double, double); + int crossings_line(double, double, int, int); + int crossings_tri(double, double, double, int, int); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running SPARTA to see the offending line. + +E: Cannot open mesh file: %s + +Self-explanatory. + +E: Surf file does not contain lines or triangles: %s + +The header of the file has neither a lines nor a triangles keyword, so +there is no surface to define the region with. + +E: Surf file contains both lines and triangles: %s + +A surf file defines either a 2d or a 3d surface, not both. + +E: Incorrect point format in surf file: %s + +A line of the Points section does not have 3 or 4 values on it. + +E: Incorrect line format in surf file: %s +E: Incorrect triangle format in surf file: %s + +A line of the Lines or Triangles section does not have a valid number of +values on it. Per-surface custom attributes are not supported by the +region mesh style. + +E: Invalid point index in surf file: %s + +A line or triangle refers to a point that is not in the Points section. + +E: Expected floating point value in surf file: %s +E: Expected integer value in surf file: %s + +A value in the file could not be converted to a number. + +E: Unexpected end of surf file: %s + +The file is truncated. + +E: Region mesh has zero extent + +All the vertices in the file are coincident, so the mesh encloses +nothing. + +W: Region mesh surface is not closed + +The area-weighted normals of the surface elements in the file do not sum +to zero, which means the surface has gaps in it. A point-in-mesh test +on a surface with gaps gives arbitrary answers. + +*/ diff --git a/src/stl_reader.cpp b/src/stl_reader.cpp new file mode 100644 index 000000000..0f1ab9f89 --- /dev/null +++ b/src/stl_reader.cpp @@ -0,0 +1,403 @@ +/* ---------------------------------------------------------------------- + SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer + http://sparta.github.io + Steve Plimpton, sjplimp@gmail.com, Michael Gallis, magalli@sandia.gov + Sandia National Laboratories + + Copyright (2014) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level SPARTA directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Ported from the LAMMPS STLReader class, see stl_reader.h +------------------------------------------------------------------------- */ + +#include "ctype.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "stl_reader.h" +#include "comm.h" +#include "utils.h" +#include "memory.h" +#include "error.h" + +#include + +using namespace SPARTA_NS; + +// byte layout of a binary STL file: +// 80-byte header + 4-byte (uint32) triangle count, then per triangle +// 12 floats (normal + 3 vertices) + a 2-byte attribute count + +static const long STL_BIN_HEADER = 80 + sizeof(uint32_t); // 84 +static const long STL_BIN_PER_TRI = 12*sizeof(float) + sizeof(uint16_t); // 50 + +#define MAXLINE 1024 + +/* ---------------------------------------------------------------------- + local helpers that stand in for the LAMMPS utils and TextFileReader + classes the original version of this file uses +------------------------------------------------------------------------- */ + +// strip leading and trailing whitespace from a string + +static std::string trim(const std::string &text) +{ + std::string::size_type first = 0; + std::string::size_type last = text.size(); + + while (first < last && isspace((unsigned char) text[first])) first++; + while (last > first && isspace((unsigned char) text[last-1])) last--; + + return text.substr(first,last-first); +} + +// split a line on whitespace into a list of words + +static std::vector split_words(const char *line) +{ + std::vector words; + const char *ptr = line; + + while (*ptr) { + while (*ptr && isspace((unsigned char) *ptr)) ptr++; + const char *start = ptr; + while (*ptr && !isspace((unsigned char) *ptr)) ptr++; + if (ptr > start) words.push_back(std::string(start,ptr-start)); + } + + return words; +} + +// convert a word to a double, throw if it is not a valid number + +static double next_double(const std::string &word, const std::string &context) +{ + if (!utils::is_double(word)) + throw STLReaderException("Error parsing STL file: " + context + + ": invalid number " + word); + return atof(word.c_str()); +} + +// return the next non-blank line of a file, or NULL at end of file +// buf must be at least MAXLINE chars + +static char *next_line(FILE *fp, char *buf) +{ + while (fgets(buf,MAXLINE,fp)) { + for (char *ptr = buf; *ptr; ptr++) + if (!isspace((unsigned char) *ptr)) return buf; + } + return NULL; +} + +/* ---------------------------------------------------------------------- + a class instance is only needed for read_file(), which owns the storage + for the triangle vertices that it returns +------------------------------------------------------------------------- */ + +STLReader::STLReader(SPARTA *sparta) : Pointers(sparta) +{ + ntris = maxtris = 0; + tris = NULL; +} + +/* ---------------------------------------------------------------------- + free the storage for the triangle vertices +------------------------------------------------------------------------- */ + +STLReader::~STLReader() +{ + memory->destroy(tris); +} + +/* ---------------------------------------------------------------------- + read an STL file on proc 0 and communicate the vertices to all procs + the facet normals are discarded + the storage for the vertices is owned by the class instance, + so it is freed by the destructor and the caller must copy what it needs + reading an empty or unreadable file aborts SPARTA with an error message + return # of triangles +------------------------------------------------------------------------- */ + +int STLReader::read_file(const char *filename, double **&caller_tris) +{ + int me = comm->me; + + if (me == 0) { + try { + std::string title; + std::vector parsed = parse(filename,&title); + ntris = (int) parsed.size(); + maxtris = ntris; + utils::logmesg(sparta,"Reading STL object " + + (title.empty() ? std::string("(unnamed)") : title) + " with " + + std::to_string(ntris) + " triangles from file " + filename + "\n"); + + memory->create(tris,(ntris > 0) ? ntris : 1,9,"stl_reader:tris"); + for (int i = 0; i < ntris; i++) { + int m = 0; + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + tris[i][m++] = parsed[i].vert[j][k]; + } + } catch (std::exception &e) { + error->one(FLERR,e.what()); + } + } + + MPI_Bcast(&ntris,1,MPI_INT,0,world); + if (ntris == 0) { + std::string mesg = "STL file " + std::string(filename) + " has no triangles"; + error->all(FLERR,mesg.c_str()); + } + if (me) memory->create(tris,ntris,9,"stl_reader:tris"); + + // allow for 9*ntris to exceed the max allowed size of a single MPI_Bcast() + + bigint ntotal = (bigint) ntris * 9; + if (ntotal < MAXSMALLINT) + MPI_Bcast(&tris[0][0],9*ntris,MPI_DOUBLE,0,world); + else { + double *source = &tris[0][0]; + bigint n = 0; + while (n < ntotal) { + int nsize = MIN(MAXSMALLINT,ntotal-n); + MPI_Bcast(&source[n],nsize,MPI_DOUBLE,0,world); + n += nsize; + } + } + + caller_tris = tris; + return ntris; +} + +/* ---------------------------------------------------------------------- + 1 if the file is in STL format, else 0 + a binary STL file has a size of exactly 84 + 50*N bytes for N triangles + an ASCII STL file starts with the solid keyword + throws an STLReaderException if the file cannot be opened +------------------------------------------------------------------------- */ + +bool STLReader::is_stl_file(const std::string &filename) +{ + FILE *fp = fopen(filename.c_str(),"rb"); + if (!fp) throw STLReaderException("Cannot open mesh file " + filename); + + bool is_stl = false; + + if (fseek(fp,0,SEEK_END) == 0) { + long filesize = ftell(fp); + if (filesize >= STL_BIN_HEADER) { + uint32_t ntri_claim = 0; + if (fseek(fp,80,SEEK_SET) == 0 && + fread(&ntri_claim,sizeof(ntri_claim),1,fp) == 1) { + bigint expected = (bigint) STL_BIN_HEADER + + (bigint) ntri_claim * STL_BIN_PER_TRI; + if (expected == (bigint) filesize) is_stl = true; + } + } + } + + if (!is_stl) { + rewind(fp); + char buf[MAXLINE]; + char *line = next_line(fp,buf); + if (line && utils::strmatch(line,"^ *solid")) is_stl = true; + } + + fclose(fp); + return is_stl; +} + +/* ---------------------------------------------------------------------- + read and parse an STL file and return its triangles + independent of any SPARTA instance and does not communicate + whether the file is text or binary is detected from its contents: + a binary STL file has a size of exactly 84 + 50*N bytes for N triangles, + which is more robust than looking for the word "solid" at the start of + the file, since the header of a binary file may legally begin with it + any error while opening, reading, or parsing the file is reported by + throwing an STLReaderException + a file with zero triangles is not an error, it gives an empty vector +------------------------------------------------------------------------- */ + +std::vector +STLReader::parse(const std::string &filename, std::string *title_out) +{ + FILE *fp = fopen(filename.c_str(),"rb"); + if (!fp) throw STLReaderException("Cannot open STL file " + filename); + + // determine the file size and the triangle count claimed by a binary header + + bool is_binary = false; + if (fseek(fp,0,SEEK_END) == 0) { + long filesize = ftell(fp); + if (filesize >= STL_BIN_HEADER) { + uint32_t ntri_claim = 0; + if (fseek(fp,80,SEEK_SET) == 0 && + fread(&ntri_claim,sizeof(ntri_claim),1,fp) == 1) { + bigint expected = (bigint) STL_BIN_HEADER + + (bigint) ntri_claim * STL_BIN_PER_TRI; + if (expected == (bigint) filesize) is_binary = true; + } + } + } + rewind(fp); + + std::string title; + std::vector triangles; + + try { + if (is_binary) { + triangles = parse_binary(fp,title); + } else { + fclose(fp); + fp = NULL; + triangles = parse_text(filename,title); + } + } catch (...) { + if (fp) fclose(fp); + throw; + } + if (fp) fclose(fp); + + if (title_out) *title_out = title; + return triangles; +} + +/* ---------------------------------------------------------------------- + parse an ASCII STL file +------------------------------------------------------------------------- */ + +std::vector +STLReader::parse_text(const std::string &filename, std::string &title) +{ + char buf[MAXLINE]; + + FILE *fp = fopen(filename.c_str(),"r"); + if (!fp) throw STLReaderException("Cannot open STL file " + filename); + + char *line = next_line(fp,buf); + if (!line || !utils::strmatch(line,"^ *solid")) { + fclose(fp); + throw STLReaderException("File " + filename + " is not a valid ASCII STL file"); + } + + // solid name may be empty; use a std::string so there is no risk of running + // past the end of the buffer (as bare pointer arithmetic on "solid" would) + + std::string header(line); + std::string::size_type pos = header.find("solid"); + title = trim(header.substr(pos+5)); + + std::vector triangles; + + try { + while ((line = next_line(fp,buf))) { + std::vector words = split_words(line); + if (words.empty()) continue; + if (utils::strmatch(words[0],"^endsolid")) break; + if (!utils::strmatch(words[0],"^facet")) + throw STLReaderException(std::string("Expected 'facet' or 'endsolid' in " + "STL file, got: ") + trim(line)); + + Triangle tri; + tri.normal[0] = tri.normal[1] = tri.normal[2] = 0.0; + + // facet line is "facet normal nx ny nz"; the normal is optional and + // tolerated to be absent or unparsable (it is recomputed when needed) + + if (words.size() >= 5 && utils::strmatch(words[1],"^normal") && + utils::is_double(words[2]) && utils::is_double(words[3]) && + utils::is_double(words[4])) + for (int k = 0; k < 3; k++) tri.normal[k] = atof(words[2+k].c_str()); + + line = next_line(fp,buf); + if (!line || !utils::strmatch(line,"^ *outer *loop")) + throw STLReaderException("Error reading 'outer loop' in STL file"); + + for (int k = 0; k < 3; k++) { + line = next_line(fp,buf); + std::vector values = line ? split_words(line) : + std::vector(); + if (values.size() < 4 || values[0] != "vertex") + throw STLReaderException("Error reading vertex " + std::to_string(k+1) + + " of facet in STL file"); + for (int m = 0; m < 3; m++) + tri.vert[k][m] = next_double(values[1+m],"vertex " + std::to_string(k+1)); + } + + line = next_line(fp,buf); + if (!line || !utils::strmatch(line,"^ *endloop")) + throw STLReaderException("Error reading 'endloop' in STL file"); + line = next_line(fp,buf); + if (!line || !utils::strmatch(line,"^ *endfacet")) + throw STLReaderException("Error reading 'endfacet' in STL file"); + + triangles.push_back(tri); + } + } catch (...) { + fclose(fp); + throw; + } + + fclose(fp); + return triangles; +} + +/* ---------------------------------------------------------------------- + parse a binary STL file: 80-byte header, uint32 triangle count, then + per triangle 12 little-endian floats (normal + 3 vertices) + 2-byte attr +------------------------------------------------------------------------- */ + +std::vector +STLReader::parse_binary(FILE *fp, std::string &title) +{ + rewind(fp); + + char head[80]; + if (fread(head,1,80,fp) != 80) + throw STLReaderException("Unexpected end of binary STL file while reading header"); + + // the header is a fixed 80-byte field that need not be null terminated + + std::size_t len = 0; + while (len < sizeof(head) && head[len] != '\0') ++len; + title = trim(std::string(head,len)); + + uint32_t ntri = 0; + if (fread(&ntri,sizeof(ntri),1,fp) != 1) + throw STLReaderException("Unexpected end of binary STL file while reading " + "triangle count"); + if (ntri > (uint32_t) MAXSMALLINT) + throw STLReaderException("Number of triangles in STL file exceeds integer limit"); + + std::vector triangles; + triangles.reserve(ntri); + + float buf[12]; + uint16_t attr; + for (uint32_t i = 0; i < ntri; i++) { + if (fread(buf,sizeof(float),12,fp) != 12) + throw STLReaderException("Unexpected end of binary STL file at triangle " + + std::to_string(i+1) + " of " + std::to_string(ntri)); + if (fread(&attr,sizeof(attr),1,fp) != 1) + throw STLReaderException("Unexpected end of binary STL file reading " + "attributes of triangle " + std::to_string(i+1)); + + Triangle tri; + for (int k = 0; k < 3; k++) tri.normal[k] = buf[k]; + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + tri.vert[j][k] = buf[3 + 3*j + k]; + triangles.push_back(tri); + } + + return triangles; +} diff --git a/src/stl_reader.h b/src/stl_reader.h new file mode 100644 index 000000000..ca007eca0 --- /dev/null +++ b/src/stl_reader.h @@ -0,0 +1,123 @@ +/* ---------------------------------------------------------------------- + SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer + http://sparta.github.io + Steve Plimpton, sjplimp@gmail.com, Michael Gallis, magalli@sandia.gov + Sandia National Laboratories + + Copyright (2014) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level SPARTA directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Ported from the LAMMPS STLReader class (src/stl_reader.h, + src/stl_reader.cpp), which is used by the LAMMPS create_atoms mesh + command. The LAMMPS TextFileReader and ValueTokenizer classes that the + original uses have no SPARTA equivalent, so the ASCII parser here reads + and splits the lines itself, but the grammar it accepts, the text vs + binary detection, and the error messages are all unchanged. +------------------------------------------------------------------------- */ + +#ifndef SPARTA_STL_READER_H +#define SPARTA_STL_READER_H + +#include "stdio.h" +#include "pointers.h" +#include "spaexception.h" + +#include +#include + +namespace SPARTA_NS { + +// thrown by the STLReader class for malformed or unreadable files + +class STLReaderException : public SpartaException { + public: + explicit STLReaderException(const std::string &msg) : SpartaException(msg) {} +}; + +/* ---------------------------------------------------------------------- + read triangle meshes from files in STL format + + an STL file stores a triangle mesh as a flat list of triangles, each of + them an outward facing normal vector and the coords of its 3 vertices + both variants of the format are supported, plain text ("ASCII") and + binary, and which one a file is, is detected from its contents, not from + its name + + most of the work is done by the static parse() method, which is + independent of any SPARTA instance and reports all error conditions by + throwing an STLReaderException, so the caller decides how to handle them + + read_file() is the alternative for the case where the mesh should be read + by proc 0 only and then communicated to all the other procs. It needs a + class instance, aborts SPARTA when the file cannot be read, and stores + the vertices in an array owned by the class instance. +------------------------------------------------------------------------- */ + +class STLReader : protected Pointers { + public: + + // a single triangle of an STL mesh + + struct Triangle { + double normal[3]; // outward facing normal vector of the facet + double vert[3][3]; // x,y,z coords of the 3 vertices + }; + + STLReader(class SPARTA *); + ~STLReader() override; + + int read_file(const char *, double **&); + + static std::vector parse(const std::string &, std::string * = NULL); + + // not part of the LAMMPS class, for callers that accept more than one + // mesh format and have to decide which reader to use + + static bool is_stl_file(const std::string &); + + private: + static std::vector parse_text(const std::string &, std::string &); + static std::vector parse_binary(FILE *, std::string &); + + int ntris,maxtris; + double **tris; +}; + +} + +#endif + +/* ERROR/WARNING messages: + +E: Cannot open STL file %s + +Self-explanatory. + +E: File %s is not a valid ASCII STL file + +The file does not start with the solid keyword and its size does not +match the layout of a binary STL file either. + +E: Expected 'facet' or 'endsolid' in STL file, got: %s + +The file does not follow the ASCII STL grammar. + +E: Error reading vertex %d of facet in STL file + +A vertex line inside an outer loop is missing or has too few coords. + +E: Unexpected end of binary STL file ... + +The file is truncated. + +E: STL file %s has no triangles + +The file was parsed successfully but contains no facets. + +*/