def test_cubic_curve(self): t = np.linspace(0, 1, 80) # interpolation points s = np.linspace(0, 1, 150) # evaluation points x = np.zeros((80, 2)) # physical points # test PERIODIC curves x[:, 0] = 16 * t * t * (1 - t) * (1 - t) x[:, 1] = 1 - x[:, 0] crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.PERIODIC, t) y = crv(s) # exact solution is t^4, cubic approximation gives t^3, needs atol self.assertTrue( np.allclose(y[:, 0], 16 * s * s * (1 - s) * (1 - s), atol=1e-2)) self.assertTrue( np.allclose(y[:, 1], 1 - 16 * s * s * (1 - s) * (1 - s), atol=1e-2)) # test FREE boundary type x[:, 0] = 12 * t * t * t + 2 * t x[:, 1] = 12 * t * t * t - 3 * t * t crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.FREE, t=t) y = crv(s) self.assertTrue(np.allclose(y[:, 0], 12 * s * s * s + 2 * s)) self.assertTrue(np.allclose(y[:, 1], 12 * s * s * s - 3 * s * s)) # test NATURAL boundary type (x''(t)=0 at the boundary) x[:, 0] = t x[:, 1] = 3 crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.NATURAL, t=t) y = crv(s) self.assertTrue(np.allclose(y[:, 0], s)) self.assertTrue(np.allclose(y[:, 1], 3.0)) # test TANGENT boundary type (x'(t)=g at both endpoints) x[:, 0] = t * t + t - 1 x[:, 1] = 3 * t * t - 3 * t + 1 dx = [[2 * t[0] + 1, 6 * t[0] - 3], [2 * t[-1] + 1, 6 * t[-1] - 3]] crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.TANGENT, t=t, tangents=dx) y = crv(s) self.assertTrue(np.allclose(y[:, 0], s * s + s - 1)) self.assertTrue(np.allclose(y[:, 1], 3 * s * s - 3 * s + 1)) # test HERMITE boundary type (x'(t)=g(t) at all interior points) x[:, 0] = t * t + t - 1 x[:, 1] = 3 * t * t - 3 * t + 1 dx = np.vstack([[2 * t + 1], [6 * t - 3]]).T crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.HERMITE, t=t, tangents=dx) y = crv(s) self.assertTrue(np.allclose(y[:, 0], s * s + s - 1)) self.assertTrue(np.allclose(y[:, 1], 3 * s * s - 3 * s + 1))
def test_cubic_curve(self): t = np.linspace(0,1,80) # interpolation points s = np.linspace(0,1,150) # evaluation points x = np.zeros((80,2)) # physical points # test PERIODIC curves x[:,0] = 16*t*t*(1-t)*(1-t) x[:,1] = 1-x[:,0] crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.PERIODIC, t) y = crv(s) # exact solution is t^4, cubic approximation gives t^3, needs atol self.assertTrue(np.allclose(y[:,0], 16*s*s*(1-s)*(1-s), atol=1e-2)) self.assertTrue(np.allclose(y[:,1], 1-16*s*s*(1-s)*(1-s), atol=1e-2)) # test FREE boundary type x[:,0] = 12*t*t*t + 2*t x[:,1] = 12*t*t*t - 3*t*t crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.FREE, t=t) y = crv(s) self.assertTrue(np.allclose(y[:,0], 12*s*s*s + 2*s)) self.assertTrue(np.allclose(y[:,1], 12*s*s*s - 3*s*s )) # test NATURAL boundary type (x''(t)=0 at the boundary) x[:,0] = t x[:,1] = 3 crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.NATURAL, t=t) y = crv(s) self.assertTrue(np.allclose(y[:,0], s)) self.assertTrue(np.allclose(y[:,1], 3.0)) # test TANGENT boundary type (x'(t)=g at both endpoints) x[:,0] = t*t + t - 1 x[:,1] = 3*t*t - 3*t + 1 dx = [[2*t[ 0] + 1, 6*t[ 0]-3], [2*t[-1] + 1, 6*t[-1]-3]] crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.TANGENT, t=t, tangents=dx) y = crv(s) self.assertTrue(np.allclose(y[:,0], s*s + s - 1)) self.assertTrue(np.allclose(y[:,1], 3*s*s - 3*s + 1)) # test HERMITE boundary type (x'(t)=g(t) at all interior points) x[:,0] = t*t + t - 1 x[:,1] = 3*t*t - 3*t + 1 dx = np.vstack([[2*t + 1], [6*t-3]]).T crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.HERMITE, t=t, tangents=dx) y = crv(s) self.assertTrue(np.allclose(y[:,0], s*s + s - 1)) self.assertTrue(np.allclose(y[:,1], 3*s*s - 3*s + 1))
def test_torsion(self): # planar curves have zero torsion controlpoints = [[1, 0, 1], [1, 1, .7], [0, 1, .89], [-1, 1, 0.5], [-1, 0, 1], [-1, -.5, 1], [1, -.5, 1]] basis = BSplineBasis(4, [-3, -2, -1, 0, 1, 2, 2.5, 4, 5, 6, 7, 8, 9, 9.5], 2) crv = Curve(basis, controlpoints, rational=True) self.assertAlmostEqual(crv.torsion(.3), 0.0) # test multiple evaluation points t = np.linspace(0, 1, 10) k = crv.torsion(t) self.assertEqual(len(k.shape), 1) # is vector self.assertEqual(k.shape[0], 10) # length 10 vector self.assertTrue(np.allclose(k, 0.0)) # zero torsion for planar curves # test helix: [a*cos(t), a*sin(t), b*t] t = np.linspace(0, 6 * pi, 300) a = 3.0 b = 2.0 x = np.array([a * np.cos(t), a * np.sin(t), b * t]) crv = cf.cubic_curve(x.T, t=t) t = np.linspace(0, 6 * pi, 10) k = crv.torsion(t) # this is a helix approximation, hence atol=1e-3 self.assertTrue(np.allclose(k, b / (a**2 + b**2), atol=1e-3)) # helix have const. torsion
def _generate_instance(self): """ Internal function of the CurveDatasetGenerator that generates a problem instance containing <_num_curves> generated curves based on <_num_control_points> Control points along <_num_eval_points> uniformly spaced points with at least a minimal distance of <_min_distance> between each pair of curves. :return: Instance of curves as dict, where keys are the string names of the curves and the associated values are lists of points representing the curves """ instance = {} for i in range(self._num_curves): curve_points = np.array([]) valid_curve = False # The while loop will be executed until a valid curve is found. Each iteration of the for loop will produce # one valid curve, but it may take a while with large numbers in self._num_curves due to multiple # iterations of the while loop while not valid_curve: controlpoints = np.array([ np.array([ random.uniform(-.5, 1.5), random.uniform(-.5, 1.5), random.uniform(-.5, 1.5) ]) for _ in range(self._num_control_points) ]) curve = curve_factory.cubic_curve(controlpoints, 4) eval_points = np.linspace(0, 1, self._num_eval_points) curve_points = np.array(curve(eval_points)) # get all points outside of the unit cube and delete them rows_to_delete = np.append( np.where(curve_points < 0)[0], np.where(curve_points > 1)[0]) reference_rows = np.array(range(len(curve_points))) reference_rows = np.delete(reference_rows, rows_to_delete) # checks whether the generated curve is valid or not if len(reference_rows) < self._min_length or max( np.diff(reference_rows)) > 1: # All points are out of the unit cube or the segment which is outside of the unit cube which will be # deleted splits the curve in half, thus creating two seperate curve segments in the unit cube continue curve_points = np.delete(curve_points, rows_to_delete, axis=0) if len(instance) == 0: # First generated curve, therefore it cant be invalid in terms of minimal distance to other curves break for tmp_curve_id, tmp_curve_points in instance.items(): distances = cdist(curve_points, tmp_curve_points) if np.min(distances) <= self._min_distance: # Generates new curve, because the current one is too close to at least one other curve valid_curve = False break # valid_curve is only true if the distances to all other curves is at least <_min_distance> valid_curve = True instance[f"curve_{i}"] = curve_points return instance
def test_cubic_curve_1D(self): n_elems = 30 t = np.linspace(0, 1, n_elems) x = (t**2).reshape(-1, 1) crv = cf.cubic_curve(x, cf.Boundary.FREE, t=t.tolist()) self.assertEqual(crv.dimension, 1) self.assertFalse(crv.rational)
def test_cubic_curve(self): t = np.linspace(0,1,80) x = np.zeros((80,2)) x[:,0] = 16*t*t*(1-t)*(1-t) x[:,1] = 1-x[:,0] crv = CurveFactory.cubic_curve(x, CurveFactory.Boundary.PERIODIC, t) t = np.linspace(0,1,150) x = crv(t) # exact solution is t^4, cubic approximation gives t^3, needs atol self.assertTrue(np.allclose(x[:,0], 16*t*t*(1-t)*(1-t), atol=1e-2)) self.assertTrue(np.allclose(x[:,1], 1-16*t*t*(1-t)*(1-t), atol=1e-2))
def lissajous(a, b, d): # request a,b integers, so we have closed, periodic curves n = gcd(a,b) N = (a/n) * (b/n) # number of periods before looping # error test input if N > 1e4: # non-integer (a,b) or otherwise too irregular raise Exception('Non-periodic', 'a,b must be integers (of moderate size)') # compute a set of interpolation points numb_pts = max(3*N, 100) # using 3N interpolation points is decent enough t = np.linspace(0,2*pi/n, numb_pts) x = np.array([np.sin(a*t + d), np.sin(b*t)]) # do a cubic curve interpolation with periodic boundary conditions return curve_factory.cubic_curve(x.T, curve_factory.Boundary.PERIODIC)
def cut_square(width, height, radius, inner_radius, nel_ang, order, out): # Compute number of elements along each part rest1 = height - radius - inner_radius rest2 = width - radius - inner_radius nel_cyl = int(np.ceil(4/np.pi * (inner_radius - radius) / radius * nel_ang)) nel_rest1 = int(np.ceil(4/np.pi * rest1 / radius * nel_ang)) nel_rest2 = int(np.ceil(4/np.pi * rest2 / radius * nel_ang)) # Create quarter circles theta = np.linspace(0, np.pi/2, 2*nel_ang+1)[::-1] pts = np.array([radius * np.cos(theta), radius * np.sin(theta)]).T circle = cf.cubic_curve(pts, boundary=cf.Boundary.NATURAL).set_dimension(3) knots = circle.knots('u') inner1, inner2 = circle.split(knots[len(knots) // 2]) # Fill the cylinder patches factor = inner_radius / radius outer1, outer2 = inner1 * factor, inner2 * factor cyl1 = sf.edge_curves(inner1, outer1).set_order(4,4).refine(0, nel_cyl-1) cyl2 = sf.edge_curves(inner2, outer2).set_order(4,4).refine(0, nel_cyl-1) # Create the "curved rectangles" dist = np.sqrt(2) * radius edge1 = cf.line((0, height), (dist, height)).set_order(4).set_dimension(3).refine(nel_ang-1) rect1 = sf.edge_curves(outer1, edge1).set_order(4,4).refine(0, nel_rest1-1) edge2 = cf.line((width, dist), (width, 0)).set_order(4).set_dimension(3).refine(nel_ang-1) rect2 = sf.edge_curves(outer2, edge2).set_order(4,4).refine(0, nel_rest2-1) # Final square edge1 = rect2.section(u=0) edge2 = edge1 + (0, height - dist, 0) rect = sf.edge_curves(edge1, edge2).set_order(4,4).refine(0, nel_rest1-1) diff = 4 - order patches = [patch.lower_order(diff, diff) for patch in [cyl1, cyl2, rect1, rect2, rect]] with G2(out + '.g2') as f: f.write(patches) root = etree.Element('geometry') etree.SubElement(root, 'patchfile').text = out + '.g2' topology = etree.SubElement(root, 'topology') for mid, sid, midx, sidx, rev in [(1,2,2,1,False), (1,3,4,3,False), (2,4,4,3,False), (3,5,2,1,False), (4,5,1,3,False)]: etree.SubElement(topology, 'connection').attrib.update({ 'master': str(mid), 'slave': str(sid), 'midx': str(midx), 'sidx': str(sidx), 'reverse': 'true' if rev else 'false', }) topsets = etree.SubElement(root, 'topologysets') for name, entries in [('Circle', [(1, (3,)), (2, (3,))]), ('Left', [(1, (1,)), (3, (1,))]), ('Right', [(4, (4,)), (5, (2,))]), ('Top', [(3, (4,)), (5, (4,))]), ('Bottom', [(2, (2,)), (4, (2,))])]: topset = etree.SubElement(topsets, 'set') topset.attrib.update({'name': name, 'type': 'edge'}) for pid, indices in entries: item = etree.SubElement(topset, 'item') item.attrib['patch'] = str(pid) item.text = ' '.join(str(i) for i in indices) with open(out + '.xinp', 'wb') as f: f.write(etree.tostring( root, pretty_print=True, encoding='utf-8', xml_declaration=True, standalone=False ))
def cylinder(diam, width, front, back, side, height, re, grad, inner_elsize, nel_side, nel_bndl, nel_circ, nel_height, order, out, outer_graded, thickness): assert all(f >= width for f in [front, back, side]) rad_cyl = diam / 2 width *= rad_cyl back = back * rad_cyl - width front = front * rad_cyl - width side = side * rad_cyl - width elsize = width * 2 / nel_circ dim = 2 if height == 0.0 else 3 vx_add = 8 if dim == 3 else 0 patches = PatchDict(dim) if inner_elsize and nel_side: # Calculate grading factor based on first element size, # total length and number of elements dr = rad_cyl * inner_elsize grad = find_factor(dr, width - rad_cyl, nel_side) elif nel_bndl and grad: # Calculate first element size based on total length # and number of elements # We want nel_bndl elements inside the boundary layer # Calculate how small the inner element must be size_bndl = 1 / sqrt(re) * diam dr = (1 - grad) / (1 - grad**nel_bndl) * size_bndl # Potentially reduce element size so we get a whole number of elements # on either side of the cylinder #nel_side = int(ceil(log(1 - 1/dr * (1 - grad) * (width - rad_cyl)) / log(grad))) nel_side = int( round( log(1 - 1 / dr * (1 - grad) * (width - rad_cyl)) / log(grad))) dr = (1 - grad) / (1 - grad**nel_side) * (width - rad_cyl) else: print('Specify (inner-elsize and nel-side) or (nel-bndl and grad)', file=sys.stderr) sys.exit(1) # Graded radial space from cylinder to edge of domain radial_kts = graded_space(rad_cyl, dr, grad, nel_side) + [width] # Create a radial and divide it radial = cf.cubic_curve(np.matrix(radial_kts).T, boundary=cf.Boundary.NATURAL) radial.set_dimension(3) radial_kts = radial.knots('u') # middle = radial_kts[len(radial_kts) // 2] middle = next(k for k in radial_kts if k >= thickness * diam) radial_inner, radial_outer = radial.split(middle, 'u') radial_inner.rotate(pi / 4) dl = np.linalg.norm( radial_outer(radial_outer.knots('u')[-2]) - radial_outer.section(u=-1)) * grad # Revolve the inner radial and divide it radials = [ radial_inner.clone().rotate(v) for v in np.linspace(0, 2 * pi, 4 * nel_circ + 1) ] inner = sf.loft(radials) ikts = inner.knots('v') inner.insert_knot((ikts[0] + ikts[1]) / 2, 'v') inner.insert_knot((ikts[-1] + ikts[-2]) / 2, 'v') ikts = inner.knots('v') patches.add('iu', 'il', 'id', 'ir', inner.split([ikts[k * nel_circ] for k in range(5)][1:-1], 'v')) patches.connect( ('ir', 4, 'iu', 3), ('iu', 4, 'il', 3), ('il', 4, 'id', 3), ('id', 4, 'ir', 3), ) patches.boundary('cylinder', 'ir', 1) patches.boundary('cylinder', 'iu', 1) patches.boundary('cylinder', 'il', 1) patches.boundary('cylinder', 'id', 1) # Create an outer section rc = radial_outer.section(u=0) alpha = (sqrt(2) * width - rc[0]) / (width - rc[0]) right = ((radial_outer - rc) * alpha + rc).rotate(pi / 4) left = right.clone().rotate(pi / 2).reverse() outer = cf.line((-width, width, 0), (width, width, 0)) outer.set_order(4).refine(nel_circ - 1) inner = patches['iu'].section(u=-1) outer = sf.edge_curves(right, outer, left, inner).reverse('v') patches.add('ou', 'ol', 'od', 'or', [outer.clone().rotate(v) for v in [0, pi / 2, pi, 3 * pi / 2]]) patches.connect( ('or', 4, 'ou', 3), ('ou', 4, 'ol', 3), ('ol', 4, 'od', 3), ('od', 4, 'or', 3), ('or', 1, 'ir', 2), ('ou', 1, 'iu', 2), ('ol', 1, 'il', 2), ('od', 1, 'id', 2), ) if front > 0: la = patches['ol'].section(u=-1) lb = la.clone() - (front, 0, 0) front_srf = sf.edge_curves(lb, la).set_order(4, 4).swap().reverse('v') nel = int(ceil(log(1 - 1 / dl * (1 - grad) * front) / log(grad))) geometric_refine(front_srf, grad, nel - 1, reverse=True) patches['fr'] = front_srf patches.connect(('fr', 2, 'ol', 2, 'rev')) patches.boundary('inflow', 'fr', 1) else: patches.boundary('inflow', 'ol', 2) patches.boundary('inflow', 'ou', 4, dim=-2, add=vx_add) patches.boundary('inflow', 'od', 2, dim=-2, add=vx_add) if back > 0: la = patches['or'].section(u=-1) lb = la.clone() + (back, 0, 0) back_srf = sf.edge_curves(la, lb).set_order(4, 4).swap() if outer_graded: nel = int(ceil(log(1 - 1 / dl * (1 - grad) * back) / log(grad))) geometric_refine(back_srf, grad, nel - 1) else: #nel = int(ceil(back / dl)) nel = int(round(back / (2 * width) * nel_circ)) back_srf.refine(nel - 1, direction='u') patches['ba'] = back_srf patches.connect(('ba', 1, 'or', 2)) patches.boundary('outflow', 'ba', 2) else: patches.boundary('outflow', 'or', 2) if side > 0: la = patches['ou'].section(u=-1).reverse() lb = la + (0, side, 0) patches['up'] = sf.edge_curves(la, lb).set_order(4, 4) patches.connect(('up', 3, 'ou', 2, 'rev'), ('dn', 4, 'od', 2)) patches.boundary('top', 'up', 4) patches.boundary('bottom', 'dn', 3) if 'fr' in patches: btm = front_srf.section(v=-1) right = patches['up'].section(u=0) top = (btm + (0, side, 0)).reverse() left = (right - (front, 0, 0)).reverse() patches['upfr'] = sf.edge_curves(btm, right, top, left) patches.connect( ('upfr', 3, 'fr', 4), ('upfr', 2, 'up', 1), ('dnfr', 4, 'fr', 3), ('dnfr', 2, 'dn', 1), ) patches.boundary('wall', 'upfr', 4) patches.boundary('inflow', 'upfr', 1) patches.boundary('wall', 'dnfr', 3) patches.boundary('inflow', 'dnfr', 1) else: patches.boundary('inflow', 'up', 1) patches.boundary('inflow', 'dn', 1) if 'ba' in patches: btm = back_srf.section(v=-1) left = patches['up'].section(u=-1).reverse() top = (btm + (0, side, 0)).reverse() right = (left + (back, 0, 0)).reverse() patches['upba'] = sf.edge_curves(btm, right, top, left) patches.connect( ('upba', 3, 'ba', 4), ('upba', 1, 'up', 2), ('dnba', 4, 'ba', 3), ('dnba', 1, 'dn', 2), ) patches.boundary('wall', 'upba', 4) patches.boundary('outflow', 'upfr', 2) patches.boundary('wall', 'dnba', 3) patches.boundary('outflow', 'dnba', 2) else: patches.boundary('outflow', 'up', 2) patches.boundary('outflow', 'dn', 2) nel = int(ceil(log(1 - 1 / dl * (1 - grad) * side) / log(grad))) for uk in {'up', 'upfr', 'upba'} & patches.keys(): dk = 'dn' + uk[2:] patches[dk] = patches[uk] - (0, side + 2 * width, 0) geometric_refine(patches[uk], grad, nel - 1, direction='v') geometric_refine(patches[dk], grad, nel - 1, direction='v', reverse=True) else: patches.boundary('wall', 'ou', 2) patches.boundary('wall', 'od', 2) patches.boundary('wall', 'or', 4, dim=-2, add=vx_add) patches.boundary('wall', 'or', 2, dim=-2, add=vx_add) if 'fr' in patches: patches.boundary('wall', 'fr', 4) patches.boundary('wall', 'fr', 3) patches.boundary('wall', 'ol', 2, dim=-2, add=vx_add) patches.boundary('wall', 'ol', 4, dim=-2, add=vx_add) if 'ba' in patches: patches.boundary('wall', 'ba', 4) patches.boundary('wall', 'ba', 3) if height > 0.0: names = [ 'iu', 'il', 'id', 'ir', 'ou', 'ol', 'od', 'or', 'fr', 'ba', 'up', 'upba', 'upfr', 'dn', 'dnba', 'dnfr' ] for pname in names: if pname not in patches: continue patch = patches[pname] patch = extrude(patch, (0, 0, height)) patch.raise_order(0, 0, 2) patch.refine(nel_height - 1, direction='w') patches[pname] = patch patches.boundary('zup', pname, 6) patches.boundary('zdown', pname, 5) patches.connect((pname, 5, pname, 6, 'per')) patches.write(out, order=order)
reverse_graft_rad_list = copy.deepcopy(graft_rad_list) reverse_graft_rad_list.reverse() possible_B = canGraft(radius_B, reverse_graft_rad_list[0], max_shrink) if possible_B[0]: shrink_B = possible_B[1] shrinkGraft(reverse_graft_rad_list, shrink_B) nb = len(graftPath) A = mainPath[pointA] B = mainPath[pointB] #splipy work # (https://pythonhosted.org/Splipy/basic_classes.html#splipy.Curve.curvature) coordinates = numpy.array([A, B]) cb = cubic_curve(x=coordinates, boundary=5, t=None, tangents=tgt) bounding = SplineObject.bounding_box(cb) x_min, x_max = bounding[0][0], bounding[0][1] y_min, y_max = bounding[1][0], bounding[1][1] z_min, z_max = bounding[2][0], bounding[2][1] fin = SplineObject.end(cb)[0] tab = numpy.linspace(0, fin, nb) L = list(SplineObject.evaluate(cb, tab)) curvat = curvature(cb, tab) max_curvature = numpy.max(curvat) tors = torsion(cb, tab) max_torsion = max(numpy.max(tors), -(numpy.min(tors)))
def flag(diam, flag_width, flag_length, width, back, flag_grad, grad, nel_rad, nel_circ, nel_flag, order, out): assert (back > width) rad_cyl = diam / 2 width *= rad_cyl back = back * rad_cyl - width # Create a circle angle = 2 * np.arcsin(flag_width / rad_cyl / 2) pts = rad_cyl * np.array( [(np.cos(a), np.sin(a)) for a in np.linspace(angle, 2 * np.pi - angle, nel_circ + 1)]) circle = cf.cubic_curve(pts, boundary=cf.Boundary.NATURAL) circle.set_dimension(3) # Subdivide it nels_side = int(round(nel_circ // 2 * 3 * np.pi / 4 / (np.pi - angle))) nels_front = (nel_circ // 2 - nels_side) * 2 S = (-nel_flag * width + nels_side * (width + back)) / (nel_flag + nels_side) kts = circle.knots('u') kts = kts[nels_side], kts[nels_side + nels_front] circ_up, circ_front, circ_down = circle.split(kts) # Extend to boundary front = cf.line((-width, width), (-width, -width)).set_order(4).refine(nels_front - 1) front = sf.edge_curves(front, circ_front).raise_order(0, 2) geometric_refine(front, grad, nel_rad - 1, direction='v', reverse=True) up = cf.line((S, width), (-width, width)).set_order(4).refine(nels_side - 1) up = sf.edge_curves(up, circ_up).raise_order(0, 2) geometric_refine(up, grad, nel_rad - 1, direction='v', reverse=True) down = cf.line((-width, -width), (S, -width)).set_order(4).refine(nels_side - 1) down = sf.edge_curves(down, circ_down).raise_order(0, 2) geometric_refine(down, grad, nel_rad - 1, direction='v', reverse=True) # Create the flag upt = circle(circle.start('u')) fl_up = cf.line((flag_length + rad_cyl, upt[1], 0), upt).raise_order(2) geometric_refine(fl_up, flag_grad, nel_flag - 1, direction='u', reverse=True) ln_up = cf.cubic_curve(np.array([((1 - i) * (width + back) + i * S, width) for i in np.linspace(0, 1, nel_flag + 1) ]), boundary=cf.Boundary.NATURAL, t=fl_up.knots('u')) fl_up = sf.edge_curves(ln_up, fl_up).raise_order(0, 2) geometric_refine(fl_up, grad, nel_rad - 1, direction='v', reverse=True) dpt = circle(circle.end('u')) fl_down = cf.line(dpt, (flag_length + rad_cyl, dpt[1], 0)) geometric_refine(fl_down, flag_grad, nel_flag - 1, direction='u') ln_down = cf.cubic_curve(np.array([ ((1 - i) * S + i * (width + back), -width) for i in np.linspace(0, 1, nel_flag + 1) ]), boundary=cf.Boundary.NATURAL, t=fl_down.knots('u')) fl_down = sf.edge_curves(ln_down, fl_down).raise_order(0, 2) geometric_refine(fl_down, grad, nel_rad - 1, direction='v', reverse=True) fl_back = cf.line((flag_length + rad_cyl, dpt[1], 0), (flag_length + rad_cyl, upt[1], 0)) ln_back = cf.line((width + back, -width, 0), (width + back, width, 0)) fl_back = sf.edge_curves(ln_back, fl_back).raise_order(2, 2).refine(40, direction='u') geometric_refine(fl_back, grad, nel_rad - 1, direction='v', reverse=True) with G2(out + '.g2') as f: f.write([up, front, down, fl_up, fl_down, fl_back]) root = etree.Element('geometry') etree.SubElement(root, 'patchfile').text = out + '.g2' topology = etree.SubElement(root, 'topology') for mid, sid, midx, sidx, rev in [(1, 2, 2, 1, False), (1, 4, 1, 2, False), (2, 3, 2, 1, False), (3, 5, 2, 1, False), (4, 6, 1, 2, False), (5, 6, 2, 1, False)]: etree.SubElement(topology, 'connection').attrib.update({ 'master': str(mid), 'slave': str(sid), 'midx': str(midx), 'sidx': str(sidx), 'reverse': 'true' if rev else 'false', }) topsets = etree.SubElement(root, 'topologysets') for name, index, entries in [('inflow', 3, [2]), ('outflow', 3, [6]), ('top', 3, [1, 4]), ('bottom', 3, [3, 5]), ('cylinder', 4, [1, 2, 3]), ('flag', 4, [4, 5, 6])]: topset = etree.SubElement(topsets, 'set') topset.attrib.update({'name': name, 'type': 'edge'}) for pid in entries: item = etree.SubElement(topset, 'item') item.attrib['patch'] = str(pid) item.text = str(index) topset = etree.SubElement(topsets, 'set') topset.attrib.update({'name': 'inflow', 'type': 'vertex'}) item = etree.SubElement(topset, 'item') item.attrib['patch'] = '2' item.text = '1 2' with open(out + '.xinp', 'wb') as f: f.write( etree.tostring(root, pretty_print=True, encoding='utf-8', xml_declaration=True, standalone=False))
def cylinder(radius, length, elements_rad, elements_len, out): square = sf.square(size=2 * radius / 3, lower_left=(-radius / 3, -radius / 3)) square.set_dimension(3) square.raise_order(2, 2) square.refine(elements_rad - 1, elements_rad - 1) pts = np.zeros((elements_rad + 1, 3)) angles = np.linspace(-np.pi / 4, np.pi / 4, elements_rad + 1) pts[:, 0] = radius * np.cos(angles) pts[:, 1] = radius * np.sin(angles) curve = cf.cubic_curve(pts, t=square.knots('v')) sector = sf.edge_curves(square.section(u=-1), curve) sector.raise_order(0, 2) sector.refine(0, elements_rad - 1) sector.swap() sectors = [ sector.clone().rotate(angle) for angle in [0, np.pi / 2, np.pi, np.pi * 3 / 2] ] patches = [ vf.extrude(patch, (0, 0, length)) for patch in [square] + sectors ] for patch in patches: patch.raise_order(0, 0, 2) patch.refine(0, 0, elements_len) with G2(out + '.g2') as f: f.write(patches) root = etree.Element('geometry') etree.SubElement(root, 'patchfile').text = out + '.g2' topology = etree.SubElement(root, 'topology') for mid, sid, midx, sidx, rev in [(1, 2, 2, 1, False), (1, 3, 4, 1, True), (1, 4, 1, 1, True), (1, 5, 3, 1, False), (2, 3, 4, 3, False), (2, 5, 3, 4, False), (3, 4, 4, 3, False), (4, 5, 4, 3, False)]: etree.SubElement(topology, 'connection').attrib.update({ 'master': str(mid), 'slave': str(sid), 'midx': str(midx), 'sidx': str(sidx), 'reverse': 'true' if rev else 'false', }) topsets = etree.SubElement(root, 'topologysets') for name, start, idx in [('wall', 2, 2), ('inflow', 1, 5), ('outflow', 1, 6)]: topset = etree.SubElement(topsets, 'set') topset.attrib.update({'name': name, 'type': 'face'}) for i in range(start, 6): item = etree.SubElement(topset, 'item') item.attrib['patch'] = str(i) item.text = str(idx) with open(out + '.xinp', 'wb') as f: f.write( etree.tostring(root, pretty_print=True, encoding='utf-8', xml_declaration=True, standalone=False))