def build_nullspace(V): """Function to build PETSc nullspace for 3D elasticity""" # Create list of vectors for null space index_map = V.dofmap.index_map bs = V.dofmap.index_map_bs ns = [la.create_petsc_vector(index_map, bs) for i in range(6)] with ExitStack() as stack: vec_local = [stack.enter_context(x.localForm()) for x in ns] basis = [np.asarray(x) for x in vec_local] # Get dof indices for each subspace (x, y and z dofs) dofs = [V.sub(i).dofmap.list.array for i in range(3)] # Build translational nullspace basis for i in range(3): basis[i][dofs[i]] = 1.0 # Build rotational nullspace basis x = V.tabulate_dof_coordinates() dofs_block = V.dofmap.list.array x0, x1, x2 = x[dofs_block, 0], x[dofs_block, 1], x[dofs_block, 2] basis[3][dofs[0]] = -x1 basis[3][dofs[1]] = x0 basis[4][dofs[0]] = x2 basis[4][dofs[2]] = -x0 basis[5][dofs[2]] = x1 basis[5][dofs[1]] = -x2 la.orthonormalize(ns) assert la.is_orthonormal(ns) return PETSc.NullSpace().create(vectors=ns)
def test_nullspace_orthogonal(mesh, degree): """Test that null spaces orthogonalisation""" V = VectorFunctionSpace(mesh, ('Lagrange', degree)) nullspace = build_elastic_nullspace(V) assert not la.is_orthonormal(nullspace) la.orthonormalize(nullspace) assert la.is_orthonormal(nullspace)
def test_nullspace_check(mesh, degree): V = VectorFunctionSpace(mesh, ('Lagrange', degree)) u, v = TrialFunction(V), TestFunction(V) E, nu = 2.0e2, 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) def sigma(w, gdim): return 2.0 * mu * ufl.sym(grad(w)) + lmbda * ufl.tr( grad(w)) * ufl.Identity(gdim) a = form(inner(sigma(u, mesh.geometry.dim), grad(v)) * dx) # Assemble matrix and create compatible vector A = assemble_matrix(a) A.assemble() # Create null space basis and test nullspace = build_elastic_nullspace(V) la.orthonormalize(nullspace) ns = PETSc.NullSpace().create(vectors=nullspace) assert ns.test(A) # Create incorrect null space basis and test nullspace = build_broken_elastic_nullspace(V) la.orthonormalize(nullspace) ns = PETSc.NullSpace().create(vectors=nullspace) assert not ns.test(A)
def rigid_motions_nullspace(V: _fem.FunctionSpace): """ Function to build nullspace for 2D/3D elasticity. Parameters: =========== V The function space """ _x = _fem.Function(V) # Get geometric dim gdim = V.mesh.geometry.dim assert gdim == 2 or gdim == 3 # Set dimension of nullspace dim = 3 if gdim == 2 else 6 # Create list of vectors for null space nullspace_basis = [_x.vector.copy() for _ in range(dim)] with ExitStack() as stack: vec_local = [stack.enter_context(x.localForm()) for x in nullspace_basis] basis = [np.asarray(x) for x in vec_local] dofs = [V.sub(i).dofmap.list.array for i in range(gdim)] # Build translational null space basis for i in range(gdim): basis[i][dofs[i]] = 1.0 # Build rotational null space basis x = V.tabulate_dof_coordinates() dofs_block = V.dofmap.list.array x0, x1, x2 = x[dofs_block, 0], x[dofs_block, 1], x[dofs_block, 2] if gdim == 2: basis[2][dofs[0]] = -x1 basis[2][dofs[1]] = x0 elif gdim == 3: basis[3][dofs[0]] = -x1 basis[3][dofs[1]] = x0 basis[4][dofs[0]] = x2 basis[4][dofs[2]] = -x0 basis[5][dofs[2]] = x1 basis[5][dofs[1]] = -x2 _la.orthonormalize(nullspace_basis) assert _la.is_orthonormal(nullspace_basis) return PETSc.NullSpace().create(vectors=nullspace_basis)
def build_nullspace(V, x): """Function to build null space for 2D elasticity""" # Create list of vectors for null space ns = [x.copy() for i in range(3)] with ExitStack() as stack: vec_local = [stack.enter_context(x.localForm()) for x in ns] basis = [np.asarray(x) for x in vec_local] # Build null space basis dofs = [V.sub(i).dofmap.list.array for i in range(2)] for i in range(2): basis[i][dofs[i]] = 1.0 x = V.tabulate_dof_coordinates() basis[2][dofs[0]] = -x[dofs[0], 1] basis[2][dofs[1]] = x[dofs[1], 0] la.orthonormalize(ns) return ns