Method 1: Construct mesh elements manually
We can triangulate a periodic quad-lattice on the surface:
n = {180, 20}; (* number of points in each direction *)
pts = Table[
g[4. Pi/n[[1]] t, 2. Pi/ n[[2]] θ], {t, n[[1]]}, {θ, n[[2]]}];
idcs = {{{1, 2, 4}, {1, 4, 3}}, {{1, 2, 3}, {2, 4, 3}}}; (* for a diamond pattern *)
tri = 1 +
Array[Function[quad, quad[[#]] & /@ idcs[[Mod[+##, 2, 1]]]][Tuples[
{Mod[#1 + {-1, 0}, Dimensions[pts][[1]]],
Mod[#2 + {-1, 0}, Dimensions[pts][[2]]]}].{Length[First@pts], 1}] &,
Most@Dimensions[pts]];
Needs["NDSolve`FEM`"].
bmesh = ToBoundaryMesh[
"Coordinates" -> Flatten[pts, 1],
"BoundaryElements" -> {TriangleElement[Flatten[tri, 2]]}
]
emesh = ToElementMesh[bmesh]
(*
ElementMesh[{{-4.86396, 1.5}, {-3.32664, 3.32664}, {-1.5, 1.5}},
{TetrahedronElement["<" 21544 ">"]}]
*)
MeshRegion@emesh

Notes:
Tuple
generates the indices of the quadrilaterals in each row (#1) & column (
#2`), wrapping around at the end of the domain to close up the tube:
Tuples[{Mod[#1 + {-1, 0}, Dimensions[pts][[1]]],
Mod[#2 + {-1, 0}, Dimensions[pts][[2]]]}]
The dot product with {Length[First@pts], 1}
converts a {row, column}
pair to the index of the corresponding point in pts
.
We triangulate the quadrilaterals by alternating which diagonal is used. The variable idcs
contains two lists of two triangles, representing both ways. The integers themselves are indices of the quadrilateral (given by Tuples[..].{Length[..], 1}
above).
idcs = {{{1, 2, 4}, {1, 4, 3}}, (* 1-4 diagonal *)
{{1, 2, 3}, {2, 4, 3}}}; (* 2-3 diagonal *)
Method 2: Mesh the domain and apply parametrization
This takes more advantage of FEM/ElementMesh capabilities. First mesh the domain. Then apply g
to map domain mesh coordinates onto to the surface. Use these coordinates and the domain mesh to construct a boundary mesh on the surface. Finally, use ToElementMesh
to construct a mesh of the solid.
Needs["NDSolve`FEM`"]
tscale = 4; θscale = 0.5; (* scale roughly proportional to speeds *)
dom = ToElementMesh[FullRegion[2], {{0, tscale}, {0, θscale}}, (* domain *)
MaxCellMeasure -> {"Area" -> 0.001}];
coords = g[4 Pi #1/tscale, 2 Pi #2/θscale] & @@@ dom["Coordinates"]; (* apply g *)
bmesh2 = ToBoundaryMesh[
"Coordinates" -> coords,
"BoundaryElements" -> dom["MeshElements"]
];
emesh2 = ToElementMesh@ bmesh2
(*
ElementMesh[{{-4.86407, 1.5}, {-3.32362, 3.32362}, {-1.49991, 1.49991}},
{TetrahedronElement["<" 5581 ">"]}]
*)
MeshRegion@ emesh2

Note: I thought I would have to glue the boundaries together by hand, but ToBoundaryMesh
seems to handle it for me. :D
DiscretizeGraphics
$\endgroup$ – user21 Jun 11 '15 at 16:23ParametricRegion
and then useToElementMesh
- some examples are in the documentation, see also the tutorial to element mesh generation. $\endgroup$ – user21 Jun 11 '15 at 16:33