// Auto-generated by hull_geo_builder.py — DO NOT HAND-EDIT.
// EXPORT CONTROLLED — ITAR USML Category XX
// Module: M04   R_outer=162.0mm  R_inner=146.0mm  wall=16.0mm
// radial_layers=8 (EXACT, transfinite — never a size-heuristic guess)
// circumferential_divisions=24 (4 quadrants x 6)  axial_divisions=11  length=215.0mm
// element_type=hex
SetFactory("Built-in");
Geometry.Tolerance = 1e-6;

// -- Cross-section at Z=0: annulus built as 4 quadrant patches --------------
// See module docstring: Transfinite Surface needs a 3/4-curve boundary, so
// the annulus is split into 4 quadrants {outer arc, radial, inner arc, radial}.
Point(1) = { 162.000000, 0.000000, 0, 1.0 };
Point(2) = { 0.000000, 162.000000, 0, 1.0 };
Point(3) = { -162.000000, 0.000000, 0, 1.0 };
Point(4) = { -0.000000, -162.000000, 0, 1.0 };
Point(5) = { 146.000000, 0.000000, 0, 1.0 };
Point(6) = { 0.000000, 146.000000, 0, 1.0 };
Point(7) = { -146.000000, 0.000000, 0, 1.0 };
Point(8) = { -0.000000, -146.000000, 0, 1.0 };
Point(9) = { 0, 0, 0, 1.0 };
Circle(1) = { 1, 9, 2 };
Circle(2) = { 2, 9, 3 };
Circle(3) = { 3, 9, 4 };
Circle(4) = { 4, 9, 1 };
Circle(5) = { 5, 9, 6 };
Circle(6) = { 6, 9, 7 };
Circle(7) = { 7, 9, 8 };
Circle(8) = { 8, 9, 5 };
Line(9) = { 5, 1 };
Line(10) = { 6, 2 };
Line(11) = { 7, 3 };
Line(12) = { 8, 4 };
Curve Loop(100) = { 9, 1, -10, -5 };
ann0 = news; Plane Surface(ann0) = { 100 };
Transfinite Curve { 1, 5 } = 7 Using Progression 1;
Transfinite Curve { 9, 10 } = 8 Using Progression 1;
Transfinite Surface { ann0 };
Curve Loop(101) = { 10, 2, -11, -6 };
ann1 = news; Plane Surface(ann1) = { 101 };
Transfinite Curve { 2, 6 } = 7 Using Progression 1;
Transfinite Curve { 10, 11 } = 8 Using Progression 1;
Transfinite Surface { ann1 };
Curve Loop(102) = { 11, 3, -12, -7 };
ann2 = news; Plane Surface(ann2) = { 102 };
Transfinite Curve { 3, 7 } = 7 Using Progression 1;
Transfinite Curve { 11, 12 } = 8 Using Progression 1;
Transfinite Surface { ann2 };
Curve Loop(103) = { 12, 4, -9, -8 };
ann3 = news; Plane Surface(ann3) = { 103 };
Transfinite Curve { 4, 8 } = 7 Using Progression 1;
Transfinite Curve { 12, 9 } = 8 Using Progression 1;
Transfinite Surface { ann3 };

// -- Radial Transfinite constraint: EXACT layer count through the wall -----
// Each quadrant's 2 radial lines are constrained to 8 nodes — a hard
// mesh-topology constraint, not a size hint (cannot silently collapse to 1
// layer the way a free/Delaunay tet mesh driven by -clmax could).
Recombine Surface{ ann0[] };
Recombine Surface{ ann1[] };
Recombine Surface{ ann2[] };
Recombine Surface{ ann3[] };

// -- Extrude along +Z for the full module length --------------------------
// Layers{1} with 11 subdivisions = exact axial transfinite layer count.
ext0[] = Extrude {0, 0, 215.0} {
  Surface{ ann0 }; Layers{ 11 }; Recombine;
};
ext1[] = Extrude {0, 0, 215.0} {
  Surface{ ann1 }; Layers{ 11 }; Recombine;
};
ext2[] = Extrude {0, 0, 215.0} {
  Surface{ ann2 }; Layers{ 11 }; Recombine;
};
ext3[] = Extrude {0, 0, 215.0} {
  Surface{ ann3 }; Layers{ 11 }; Recombine;
};

// extQ[] index convention for `Extrude {...} { Surface{annQ}; ... }`:
//   extQ[0]=top(AFT) face of quadrant Q; extQ[1]=extruded VOLUME;
//   extQ[2..5]=4 swept side surfaces IN THE ORDER of Curve Loop(100+Q) =
//   {rad_a, outer_a, -rad_b, -inner_a}, i.e. extQ[2]=side(rad_a),
//   extQ[3]=side(outer_a), extQ[4]=side(rad_b), extQ[5]=side(inner_a).
// This is Gmsh's documented Extrude behavior but is NOT re-derived/verified
// in this dev checkout (no gmsh interpreter available — see repo docstring).
// VERIFY on the box (real gmsh 4.13.1): confirm Physical Surface("OUTER")
// lies at R~=R_outer everywhere before trusting the pressure-load BC. If a
// real run shows a different index, fix ONLY this literal (extQ[3] below) —
// the transfinite radial-layer topology is unaffected either way.
Physical Surface("FWD_FACE") = { ann0, ann1, ann2, ann3 };
Physical Surface("AFT_FACE") = { ext0[0], ext1[0], ext2[0], ext3[0] };
Physical Surface("OUTER") = { ext0[3], ext1[3], ext2[3], ext3[3] };
Physical Volume("HULL_VOLUME") = { ext0[1], ext1[1], ext2[1], ext3[1] };

// element_type=hex: mesh stays linear (C3D8) here; run `gmsh -order 2` (or Mesh.SecondOrderIncomplete) downstream for C3D20R, matching gate_gmsh_mesh.py's C3D20R convention.
Mesh.ElementOrder = 1;
Mesh 3;
Coherence Mesh;
