Generated using an elaborate script, but also works with curved surfaces
//Parameters
w = 50;
l = 50;
nw = 10;
nl = 10;
h = (w/nw)*0.25;
//Base Surface
srf = Rectangle.ByWidthLength(w,l).Patch();
//Points Grid
p00 = srf.PointAtParameter((0..1..#(nw*3)+1)<1>,(0..1..#(nl*3)+1)<2>);
n00 = srf.NormalAtParameter((0..1..#(nw*3)+1)<1>,(0..1..#(nl*3)+1)<2>);
//Quad 01
p10 = List.TakeEveryNthItem(p00,6,1);
n11 = List.TakeEveryNthItem(n00,6,1);
p11 = p10.Translate(n11,h);
p12 = List.TakeEveryNthItem(p00,6,2);
p13 = List.TakeEveryNthItem(p00,6,3);
p14 = List.TakeEveryNthItem(p11<1>,6,2);
p15 = List.TakeEveryNthItem(p11<1>,6,4);
p16 = List.TakeEveryNthItem(p13<1>,6,3);
p17 = List.TakeEveryNthItem(p12<1>,6,2);
p18 = List.Clean(List.Transpose(List.Transpose([p14,p15,p16,p17])<1>),false);
pg1 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p18,List.Count(p18<1><2>)>3)["in"]);
//Quad 02
p20 = List.TakeEveryNthItem(p00,6,4);
n21 = List.TakeEveryNthItem(n00,6,4);
p21 = p20.Translate(n21,h);
p24 = List.TakeEveryNthItem(p21<1>,6,3);
p25 = List.TakeEveryNthItem(p21<1>,6,1);
p28 = List.Clean(List.Transpose(List.Transpose([p17,p16,p24,p25])<1>),false);
pg2 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p28,List.Count(p28<1><2>)>3)["in"]);
//Quad 03
p31 = List.TakeEveryNthItem(p00,6,5);
p32 = List.TakeEveryNthItem(p00,6,6);
p36 = List.TakeEveryNthItem(p32<1>,6,2);
p37 = List.TakeEveryNthItem(p31<1>,6,3);
p38 = List.Clean(List.Transpose(List.Transpose([p25,p24,p37,p36])<1>),false);
pg3 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p38,List.Count(p38<1><2>)>3)["in"]);
//Quad 04
p41 = List.DropItems(p14,1);
p42 = List.DropItems(p15,1);
p48 = List.Clean(List.Transpose(List.Transpose([p36,p37,p42,p41])<1>),false);
pg4 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p48,List.Count(p48<1><2>)>3)["in"]);
//Tri 01
p57 = List.TakeEveryNthItem(p20<1>,6,3);
p58 = List.Clean(List.Transpose(List.Transpose([p16,p24,p57])<1>),false);
pg5 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p58,List.Count(p58<1><2>)>2)["in"]);
//Tri 02
p68 = List.Clean(List.Transpose(List.Transpose([p37,p24,p57])<1>),false);
pg6 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p68,List.Count(p68<1><2>)>2)["in"]);
//Tri 03
p77 = List.TakeEveryNthItem(p10<1>,6,2);
p78 = List.Clean(List.Transpose(List.Transpose([p77,p14,p17])<1>),false);
pg7 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p78,List.Count(p78<1><2>)>2)["in"]);
//Tri 04
p87 = List.DropItems(List.TakeEveryNthItem(p10<1>,6,2),1);
p88 = List.Clean(List.Transpose(List.Transpose([p36,p41,p87])<1>),false);
pg8 = Surface.ByPerimeterPoints(List.FilterByBoolMask(p88,List.Count(p88<1><2>)>2)["in"]);
//Quad 05
q14 = List.TakeEveryNthItem(p11<1>,6,0)<1>;
q15 = List.TakeEveryNthItem(p12<1>,6,6)<1>;
q16 = List.TakeEveryNthItem(p13<1>,6,5);
q18 = List.Clean(List.Transpose(List.Transpose([p15,q14,q15,q16])<1>),false);
qg1 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q18,List.Count(q18<1><2>)>3)["in"]);
//Quad 06
q24 = List.TakeEveryNthItem(p21<1>,6,5);
q25 = List.DropItems(p25<1>,1);
q28 = List.Clean(List.Transpose(List.Transpose([q24,q16,q15,q25])<1>),false);
qg2 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q28,List.Count(q28<1><2>)>3)["in"]);
//Quad 07
q34 = List.TakeEveryNthItem(p32<1>,6,6);
q35 = List.TakeEveryNthItem(p31<1>,6,5);
q38 = List.Clean(List.Transpose(List.Transpose([q34,q35,q24,q25])<1>),false);
qg3 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q38,List.Count(q38<1><2>)>3)["in"]);
//Quad 08
q44 = List.DropItems(p15,1);
q45 = List.DropItems(q14,1);
q48 = List.Clean(List.Transpose(List.Transpose([q44,q35,q34,q45])<1>),false);
qg4 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q48,List.Count(q48<1><2>)>3)["in"]);
//Tri 05
q54 = List.TakeEveryNthItem(p20<1>,6,5);
q58 = List.Clean(List.Transpose(List.Transpose([q16,q24,q54])<1>),false);
qg5 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q58,List.Count(q58<1><2>)>2)["in"]);
//Tri 06
q68 = List.Clean(List.Transpose(List.Transpose([q54,q24,q35])<1>),false);
qg6 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q68,List.Count(q68<1><2>)>2)["in"]);
//Tri 07
q74 = List.TakeEveryNthItem(p10<1>,6,0)<1>;
q78 = List.Clean(List.Transpose(List.Transpose([q14,q15,q74])<1>),false);
qg7 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q78,List.Count(q78<1><2>)>2)["in"]);
//Tri 08
q84 = List.DropItems(q14,1);
q85 = List.DropItems(q15,1);
q88 = List.Clean(List.Transpose(List.Transpose([q34,q84,q85])<1>),false);
qg8 = Surface.ByPerimeterPoints(List.FilterByBoolMask(q88,List.Count(q88<1><2>)>2)["in"]);
//Quad 09
r11 = List.TakeEveryNthItem(p21<1>,6,4);
r12 = List.TakeEveryNthItem(p20<1>,6,3);
r18 = List.Clean(List.Transpose(List.Transpose([p15,r11,r12,p16])<1>),false);
rg1 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r18,List.Count(r18<1><2>)>3)["in"]);
//Quad 10
r28 = List.Clean(List.Transpose(List.Transpose([p42,p37,r12,r11])<1>),false);
rg2 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r28,List.Count(r28<1><2>)>3)["in"]);
//Quad 11
r38 = List.Clean(List.Transpose(List.Transpose([r11,p15,q16,q54])<1>),false);
rg3 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r38,List.Count(r38<1><2>)>3)["in"]);
//Quad 12
r48 = List.Clean(List.Transpose(List.Transpose([r11,q54,q35,p42])<1>),false);
rg4 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r48,List.Count(r48<1><2>)>3)["in"]);
//Quad 13
r51 = List.TakeEveryNthItem(p11<1>,6,1);
r58 = List.Clean(List.Transpose(List.Transpose([r51,p77,p17,p25])<1>),false);
rg5 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r58,List.Count(r58<1><2>)>3)["in"]);
//Quad 14
r61 = List.DropItems(p77,1);
r62 = List.DropItems(r51,1);
r68 = List.Clean(List.Transpose(List.Transpose([p25,p36,r61,r62])<1>),false);
rg6 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r68,List.Count(r68<1><2>)>3)["in"]);
//Quad 15
r71 = List.DropItems(r51<1>,1);
r78 = List.Clean(List.Transpose(List.Transpose([r71,q25,q15,q74])<1>),false);
rg7 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r78,List.Count(r78<1><2>)>3)["in"]);
//Quad 16
r81 = List.DropItems(List.DropItems(r51,1)<1>,1);
r82 = List.DropItems(q74,1);
r88 = List.Clean(List.Transpose(List.Transpose([q25,r81,r82,q34])<1>),false);
rg8 = Surface.ByPerimeterPoints(List.FilterByBoolMask(r88,List.Count(r88<1><2>)>3)["in"]);
pn1 = List.Flatten([pg1,pg2,pg3,pg4,pg5,pg6,pg7,pg8,qg1,qg2,qg3,qg4,qg5,qg6,qg7,qg8,rg1,rg2,rg3,rg4,rg5,rg6,rg7,rg8],-1);
//Punctures
b11 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,2)<1>,6,2);
b12 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,3)<1>,6,3);
b13 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,2)<1>,6,0);
b14 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,3)<1>,6,5);
b21 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,5)<1>,6,3);
b22 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,6)<1>,6,2);
b23 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,5)<1>,6,5);
b24 = List.TakeEveryNthItem(List.TakeEveryNthItem(p00,6,6)<1>,6,0);
sp1 = List.Flatten([b11,b13,b21,b23],-1);
ep1 = List.Flatten([b12,b14,b22,b24],-1);
bl1 = Line.ByStartPointEndPoint(sp1,ep1).TrimByParameter(0.2,0.8);
tk1 = Math.Average(bl1.Length);
d01 = bl1.DistanceTo(srf.PointAtParameter(0.5,0.5));
tk2 = Math.RemapRange(d01,tk1/10,tk1/3);
dr1 = srf.NormalAtPoint(bl1.PointAtParameter(0.5));
sl1 = Solid.ByUnion(PolyCurve.ByThickeningCurve(bl1,tk2,dr1).Patch().Thicken(tk2));
pn2 = List.Flatten(pn1.SubtractFrom(sl1),-1);