Example #1
0
    def test_make_identical(self):
        basis1 = BSplineBasis(4, [-1, -1, 0, 0, 1, 2, 9, 9, 10, 10, 11, 12],
                              periodic=1)
        basis2 = BSplineBasis(2, [0, 0, .25, 1, 1])
        cp = [[0, 0, 0, 1], [1, 0, 0, 1.1], [2, 0, 0, 1], [0, 1, 0, .7],
              [1, 1, 0, .8], [2, 1, 0, 1], [0, 2, 0, 1], [1, 2, 0, 1.2],
              [2, 2, 0, 1]]
        surf1 = Surface(BSplineBasis(3), BSplineBasis(3), cp,
                        True)  # rational 3D
        surf2 = Surface(basis1, basis2)  # periodic 2D
        surf1.insert_knot([0.25, .5, .75], direction='v')

        Surface.make_splines_identical(surf1, surf2)

        for s in (surf1, surf2):
            self.assertEqual(s.periodic(0), False)
            self.assertEqual(s.periodic(1), False)
            self.assertEqual(s.dimension, 3)
            self.assertEqual(s.rational, True)
            self.assertEqual(s.order(), (4, 3))

            self.assertAlmostEqual(len(s.knots(0, True)), 12)
            self.assertAlmostEqual(len(s.knots(1, True)), 10)

            self.assertEqual(s.bases[1].continuity(.25), 0)
            self.assertEqual(s.bases[1].continuity(.75), 1)
            self.assertEqual(s.bases[0].continuity(.2), 2)
            self.assertEqual(s.bases[0].continuity(.9), 1)
Example #2
0
    def test_constructor(self):
        # test 3D constructor
        cp = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]]
        surf = Surface(controlpoints=cp)
        val = surf(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf[0]), 3)

        # test 2D constructor
        cp = [[0, 0], [1, 0], [0, 1], [1, 1]]
        surf2 = Surface(controlpoints=cp)
        val = surf2(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf2[0]), 2)

        # test rational 2D constructor
        cp = [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
        surf3 = Surface(controlpoints=cp, rational=True)
        val = surf3(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf3[0]), 3)

        # test rational 3D constructor
        cp = [[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1], [1, 1, 0, 1]]
        surf4 = Surface(controlpoints=cp, rational=True)
        val = surf4(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf4[0]), 4)

        # test constructor with single basis
        b = BSplineBasis(4)
        surf = Surface(b, b)
        surf.insert_knot(.3, 'u')  # change one, but not the other
        self.assertEqual(len(surf.knots('u')), 3)
        self.assertEqual(len(surf.knots('v')), 2)

        # TODO: Include a default constructor specifying nothing, or just polynomial degrees, or just knot vectors.
        #       This should create identity mappings

        # test errors and exceptions
        controlpoints = [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
        with self.assertRaises(ValueError):
            basis1 = BSplineBasis(2, [1, 1, 0, 0])
            basis2 = BSplineBasis(2, [0, 0, 1, 1])
            surf = Surface(basis1, basis2,
                           controlpoints)  # illegal knot vector
        with self.assertRaises(ValueError):
            basis1 = BSplineBasis(2, [0, 0, .5, 1, 1])
            basis2 = BSplineBasis(2, [0, 0, 1, 1])
            surf = Surface(basis1, basis2,
                           controlpoints)  # too few controlpoints
Example #3
0
def finitestrain_patch(bottom, right, top, left):
    from nutils import version
    if int(version[0]) != 4:
        raise ImportError(
            'Mismatching nutils version detected, only version 4 supported. Upgrade by \"pip install --upgrade nutils\"'
        )

    from nutils import mesh, function
    from nutils import _, log, solver

    # error test input
    if not (left.dimension == right.dimension == top.dimension ==
            bottom.dimension == 2):
        raise RuntimeError(
            'finitestrain_patch only supported for planar (2D) geometries')
    if left.rational or right.rational or top.rational or bottom.rational:
        raise RuntimeError(
            'finitestrain_patch not supported for rational splines')

    # these are given as a oriented loop, so make all run in positive parametric direction
    top.reverse()
    left.reverse()

    # in order to add spline surfaces, they need identical parametrization
    Curve.make_splines_identical(top, bottom)
    Curve.make_splines_identical(left, right)

    # create an initial mesh (correct corners) which we will morph into the right one
    p1 = bottom.order(0)
    p2 = left.order(0)
    p = max(p1, p2)
    linear = BSplineBasis(2)
    srf = Surface(linear, linear, [bottom[0], bottom[-1], top[0], top[-1]])
    srf.raise_order(p1 - 2, p2 - 2)
    for k in bottom.knots(0, True)[p1:-p1]:
        srf.insert_knot(k, 0)
    for k in left.knots(0, True)[p2:-p2]:
        srf.insert_knot(k, 1)

    # create computational mesh
    n1 = len(bottom)
    n2 = len(left)
    dim = left.dimension
    domain, geom = mesh.rectilinear(srf.knots())
    ns = function.Namespace()
    ns.basis = domain.basis('spline',
                            degree(srf),
                            knotmultiplicities=multiplicities(srf)).vector(2)
    ns.phi = domain.basis('spline',
                          degree(srf),
                          knotmultiplicities=multiplicities(srf))
    ns.eye = np.array([[1, 0], [0, 1]])
    ns.cp = controlpoints(srf)
    ns.x_i = 'cp_ni phi_n'
    ns.lmbda = 1
    ns.mu = 1

    # add total boundary conditions
    # for hard problems these will be taken in steps and multiplied by dt every
    # time (quasi-static iterations)
    constraints = np.array([[[np.nan] * n2] * n1] * dim)
    for d in range(dim):
        constraints[d, 0, :] = (left[:, d] - srf[0, :, d])
        constraints[d, -1, :] = (right[:, d] - srf[-1, :, d])
        constraints[d, :, 0] = (bottom[:, d] - srf[:, 0, d])
        constraints[d, :, -1] = (top[:, d] - srf[:, -1, d])
    # TODO: Take a close look at the logic below

    # in order to iterate, we let t0=0 be current configuration and t1=1 our target configuration
    # if solver divergeces (too large deformation), we will try with dt=0.5. If this still
    # fails we will resort to dt=0.25 until a suitable small iterations size have been found

    # dt = 1
    # t0 = 0
    # t1 = 1
    # while t0 < 1:
    # dt = t1-t0
    n = 10
    dt = 1 / n
    for i in range(n):
        # print(' ==== Quasi-static '+str(t0*100)+'-'+str(t1*100)+' % ====')
        print(' ==== Quasi-static ' + str(i / (n - 1) * 100) + ' % ====')

        # define the non-linear finite strain problem formulation
        ns.cp = np.reshape(srf[:, :, :].swapaxes(0, 1), (n1 * n2, dim),
                           order='F')
        ns.x_i = 'cp_ni phi_n'  # geometric mapping (reference geometry)
        ns.u_i = 'basis_ki ?w_k'  # displacement (unknown coefficients w_k)
        ns.X_i = 'x_i + u_i'  # displaced geometry
        ns.strain_ij = '.5 (u_i,j + u_j,i + u_k,i u_k,j)'
        ns.stress_ij = 'lmbda strain_kk eye_ij + 2 mu strain_ij'

        # try:
        residual = domain.integral(ns.eval_n('stress_ij basis_ni,j d:X'),
                                   degree=2 * p)
        cons = np.ndarray.flatten(constraints * dt, order='C')
        lhs = solver.newton('w', residual, constrain=cons).solve(
            tol=state.controlpoint_absolute_tolerance, maxiter=8)

        # store the results on a splipy object and continue
        geom = lhs.reshape((n2, n1, dim), order='F')
        srf[:, :, :] += geom.swapaxes(0, 1)

        # t0 += dt
        # t1 = 1
        # except solver.SolverError: # newton method fail to converge, try a smaller step length 'dt'
        # t1 = (t1+t0)/2
    return srf
Example #4
0
    def test_insert_knot(self):
        # more or less random 2D surface with p=[3,2] and n=[4,3]
        controlpoints = [[0, 0], [-1, 1], [0, 2], [1, -1], [1, 0], [1, 1],
                         [2, 1], [2, 2], [2, 3], [3, 0], [4, 1], [3, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        surf = Surface(basis1, basis2, controlpoints)

        # pick some evaluation point (could be anything)
        evaluation_point1 = surf(0.23, 0.37)

        surf.insert_knot(.22, 0)
        surf.insert_knot(.5, 0)
        surf.insert_knot(.7, 0)
        surf.insert_knot(.1, 1)
        surf.insert_knot(1.0 / 3, 1)
        knot1, knot2 = surf.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 11)  # 8 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones

        evaluation_point2 = surf(0.23, 0.37)

        # evaluation before and after InsertKnot should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])

        # test a rational 2D surface
        controlpoints = [[0, 0, 1], [-1, 1, .96], [0, 2, 1], [1, -1, 1],
                         [1, 0, .8], [1, 1, 1], [2, 1, .89], [2, 2, .9],
                         [2, 3, 1], [3, 0, 1], [4, 1, 1], [3, 2, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        surf = Surface(basis1, basis2, controlpoints, True)

        evaluation_point1 = surf(0.23, 0.37)

        surf.insert_knot(.22, 0)
        surf.insert_knot(.5, 0)
        surf.insert_knot(.7, 0)
        surf.insert_knot(.1, 1)
        surf.insert_knot(1.0 / 3, 1)
        knot1, knot2 = surf.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 10)  # 7 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones

        evaluation_point2 = surf(0.23, 0.37)

        # evaluation before and after InsertKnot should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])

        # test errors and exceptions
        with self.assertRaises(TypeError):
            surf.insert_knot(1, 2, 3)  # too many arguments
        with self.assertRaises(ValueError):
            surf.insert_knot("tree-fiddy", .5)  # wrong argument type
        with self.assertRaises(ValueError):
            surf.insert_knot(0, -0.2)  # Outside-domain error
        with self.assertRaises(ValueError):
            surf.insert_knot(1, 1.4)  # Outside-domain error
Example #5
0
    def test_rational_derivative(self):
        # testing the parametrization x(u,v) = [.5*u^3*(1-v)^3 / ((1-v)^3*(1-u)^3 + .5*u^3*(1-v)^3), 0]
        # dx/du   =  (6*u^2*(u - 1)^2)/(u^3 - 6*u^2 + 6*u - 2)^2
        # d2x/du2 =  -(12*u*(u^5 - 3*u^4 + 2*u^3 + 4*u^2 - 6*u + 2))/(u^3 - 6*u^2 + 6*u - 2)^3
        # d3x/du3 =  (12*(3*u^8 - 12*u^7 + 10*u^6 + 48*u^5 - 156*u^4 + 176*u^3 - 72*u^2 + 4))/(u^3 - 6*u^2 + 6*u - 2)^4
        # dx/dv   =  0
        controlpoints = [[0, 0, 1], [0, 0, 0], [0, 0, 0], [.5, 0, .5],
                         [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0],
                         [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0],
                         [0, 0, 0], [0, 0, 0]]
        basis = BSplineBasis(4)
        surf = Surface(basis, basis, controlpoints, rational=True)

        def expect_derivative(u, v):
            return (6 * u**2 * (u - 1)**2) / (u**3 - 6 * u**2 + 6 * u - 2)**2

        def expect_derivative_2(u, v):
            return -(12 * u *
                     (u**5 - 3 * u**4 + 2 * u**3 + 4 * u**2 - 6 * u + 2)) / (
                         u**3 - 6 * u**2 + 6 * u - 2)**3

        def expect_derivative_3(u, v):
            return (12 * (3 * u**8 - 12 * u**7 + 10 * u**6 + 48 * u**5 -
                          156 * u**4 + 176 * u**3 - 72 * u**2 + 4)) / (
                              u**3 - 6 * u**2 + 6 * u - 2)**4

        # insert a few more knots to spice things up
        surf.insert_knot([.3, .51], 0)
        surf.insert_knot([.41, .53, .92], 1)

        # test first derivatives
        self.assertAlmostEqual(
            surf.derivative(0.32, 0.22, d=(1, 0))[0],
            expect_derivative(0.32, 0.22))
        self.assertAlmostEqual(surf.derivative(0.32, 0.22, d=(1, 0))[1], 0)
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.22, d=(1, 0))[0],
            expect_derivative(0.71, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.62, d=(1, 0))[0],
            expect_derivative(0.71, 0.62))

        # test second derivatives
        self.assertAlmostEqual(
            surf.derivative(0.32, 0.22, d=(2, 0))[0],
            expect_derivative_2(0.32, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.22, d=(2, 0))[0],
            expect_derivative_2(0.71, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.62, d=(2, 0))[0],
            expect_derivative_2(0.71, 0.62))

        # all cross derivatives vanish in this particular example
        self.assertAlmostEqual(surf.derivative(0.32, 0.22, d=(1, 1))[0], 0)
        self.assertAlmostEqual(surf.derivative(0.32, 0.22, d=(2, 1))[0], 0)
        self.assertAlmostEqual(surf.derivative(0.32, 0.22, d=(1, 2))[0], 0)

        # test third derivatives
        self.assertAlmostEqual(
            surf.derivative(0.32, 0.22, d=(3, 0))[0],
            expect_derivative_3(0.32, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.22, d=(3, 0))[0],
            expect_derivative_3(0.71, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.71, 0.62, d=(3, 0))[0],
            expect_derivative_3(0.71, 0.62))

        # swapping u for v and symmetric logic
        surf.swap()
        self.assertAlmostEqual(
            surf.derivative(0.22, 0.32, d=(0, 2))[0],
            expect_derivative_2(0.32, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.22, 0.71, d=(0, 2))[0],
            expect_derivative_2(0.71, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.62, 0.71, d=(0, 2))[0],
            expect_derivative_2(0.71, 0.62))
        self.assertAlmostEqual(
            surf.derivative(0.22, 0.32, d=(0, 3))[0],
            expect_derivative_3(0.32, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.22, 0.71, d=(0, 3))[0],
            expect_derivative_3(0.71, 0.22))
        self.assertAlmostEqual(
            surf.derivative(0.62, 0.71, d=(0, 3))[0],
            expect_derivative_3(0.71, 0.62))