def test_multiplicity(self): surf = Surface() surf.refine(1) surf.raise_order(1) surf.refine(1) self.assertTrue( np.allclose(multiplicities(surf), [[3, 1, 2, 1, 3], [3, 1, 2, 1, 3]]))
def test_raise_order(self): # more or less random 2D surface with p=[2,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(3, [0, 0, 0, .4, 1, 1, 1]) basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1]) surf = Surface(basis1, basis2, controlpoints) self.assertEqual(surf.order()[0], 3) self.assertEqual(surf.order()[1], 3) evaluation_point1 = surf( 0.23, 0.37) # pick some evaluation point (could be anything) surf.raise_order(1, 2) self.assertEqual(surf.order()[0], 4) self.assertEqual(surf.order()[1], 5) evaluation_point2 = surf(0.23, 0.37) # evaluation before and after RaiseOrder 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) self.assertEqual(surf.order()[0], 3) self.assertEqual(surf.order()[1], 3) evaluation_point1 = surf(0.23, 0.37) surf.raise_order(1, 2) self.assertEqual(surf.order()[0], 4) self.assertEqual(surf.order()[1], 5) evaluation_point2 = surf(0.23, 0.37) # evaluation before and after RaiseOrder should remain unchanged self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
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
def test_multiplicity(self): surf = Surface() surf.refine(1) surf.raise_order(1) surf.refine(1) self.assertTrue(np.allclose(multiplicities(surf), [[3, 1, 2, 1, 3], [3, 1, 2, 1, 3]]))