Rigid Motion Null Space Giving Random Displacement

Hello Everyone, using help from the solution of my previous question in the forum Circular Symmetry Boundary Condition on a sector of circle - #7 by dokken.
I tried limiting the rigid body motion occurring in my solution using the rigid motion null-space. However, the displacements are coming random. Expected uy displacement is

Here is the MWE:

cl__1 = 0.001;
Point(1) = {0.01, 0.07000000000000001, 0, cl__1};
Point(2) = {0.03, 0.07000000000000001, 0, cl__1};
Point(3) = {0.03, 0.08, 0, cl__1};
Point(4) = {0.01, 0.08, 0, cl__1};
Point(5) = {0.04, 0.07000000000000001, 0, cl__1};
Point(6) = {0.06, 0.07000000000000001, 0, cl__1};
Point(7) = {0.06, 0.08, 0, cl__1};
Point(8) = {0.04, 0.08, 0, cl__1};
Point(9) = {0.07000000000000001, 0.07000000000000001, 0, cl__1};
Point(10) = {0.09, 0.07000000000000001, 0, cl__1};
Point(11) = {0.09, 0.08, 0, cl__1};
Point(12) = {0.07000000000000001, 0.08, 0, cl__1};
Point(13) = {0, 0.06, 0, cl__1};
Point(14) = {0.1, 0.06, 0, cl__1};
Point(15) = {0.1, 0.09, 0, cl__1};
Point(16) = {0, 0.09, 0, cl__1};
Point(17) = {0, 0, 0, cl__1};
Point(18) = {0.1, 0, 0, cl__1};
Point(19) = {0.15, 0.1, 0, cl__1};
Point(20) = {-0.05, 0.1, 0, cl__1};
Line(1) = {4, 1};
Line(2) = {1, 2};
Line(3) = {2, 3};
Line(4) = {3, 4};
Line(5) = {8, 5};
Line(6) = {5, 6};
Line(7) = {6, 7};
Line(8) = {7, 8};
Line(9) = {12, 9};
Line(10) = {9, 10};
Line(11) = {10, 11};
Line(12) = {11, 12};
Line(13) = {13, 14};
Line(14) = {14, 15};
Line(15) = {15, 16};
Line(16) = {16, 13};
Line(17) = {17, 18};
Line(18) = {18, 19};
Line(19) = {19, 20};
Line(20) = {20, 17};
Curve Loop(1) = {1, 2, 3, 4};
Plane Surface(1) = {1};
Curve Loop(2) = {5, 6, 7, 8};
Plane Surface(2) = {2};
Curve Loop(3) = {9, 10, 11, 12};
Plane Surface(3) = {3};
Curve Loop(4) = {1, 2, 3, 4, -8, -7, -6, -5, -12, -11, -10, -9, -15, -14, -13, -16};
Plane Surface(4) = {4};
Curve Loop(5) = {16, 13, 14, 15, -20, -19, -18, -17};
Plane Surface(5) = {5};
Physical Line("bottom") = {17};
Physical Line("right") = {18};
Physical Line("top") = {19};
Physical Line("left") = {20};
Physical Line("EF") = {13};
Physical Line("FG") = {14};
Physical Line("GH") = {19};
Physical Line("HE") = {16};
Physical Line("IJ") = {2};
Physical Line("JK") = {3};
Physical Line("KL") = {4};
Physical Line("LI") = {1};
Physical Line("MN") = {6};
Physical Line("NO") = {7};
Physical Line("OP") = {8};
Physical Line("PM") = {5};
Physical Line("QR") = {10};
Physical Line("RS") = {11};
Physical Line("ST") = {12};
Physical Line("TQ") = {9};
Physical Surface("my_surface") = {5};
Physical Surface("EFGH") = {4};
Physical Surface("IJKL") = {1};
Physical Surface("MNOP") = {2};
Physical Surface("QRST") = {3};
Field[1] = Box;
Field[1].Thickness = 0;
Field[1].VIn = 0;
Field[1].VOut = 0;
Field[1].XMax = 0;
Field[1].XMin = 0;
Field[1].YMax = 0;
Field[1].YMin = 0;
Field[1].ZMax = 0;
Field[1].ZMin = 0;

Here is the code:

import gmsh
import os
import numpy as np
import matplotlib.pyplot as plt
import sys
from mpi4py import MPI
from petsc4py import PETSc
from dolfinx.cpp.mesh import to_type, cell_entity_type
import dolfinx.cpp as _cpp
from dolfinx import mesh, fem, io, common, default_scalar_type, la
import dolfinx.fem.petsc
from dolfinx.io import VTXWriter, distribute_entity_data, gmshio
from dolfinx.mesh import create_mesh, meshtags_from_entities, locate_entities
from dolfinx.plot import vtk_mesh
from dolfinx.io import XDMFFile
from ufl import (FacetNormal, FiniteElement, as_matrix, Identity, Measure, TestFunction, TrialFunction, VectorElement, as_vector, div, dot, ds, dx, inner, lhs, grad, nabla_grad, rhs, sym)
from dolfinx_mpc.utils import (create_point_to_point_constraint, determine_closest_block, rigid_motions_nullspace)
from dolfinx_mpc import LinearProblem, MultiPointConstraint

mesh_path = "WPright-medium.msh"
domain, cell_markers, facet_markers = gmshio.read_from_msh(mesh_path, MPI.COMM_WORLD, gdim=2)

import ufl

gdim = 2

def strain(u, repr ="vectorial"):
    eps_t = sym(grad(u))
    if repr =="vectorial":
        return as_vector([eps_t[0,0], eps_t[1,1], 2*eps_t[0,1]])
    elif repr =="tensorial":
        return eps_t

E = fem.Constant(domain, 200000000000.0)
nu = fem.Constant(domain,0.3)

lmbda = E*nu/(1+nu)/(1-2*nu)
mu = E/2/(1+nu)

C = as_matrix([[lmbda+2*mu, lmbda, 0.0],[lmbda, lmbda+2*mu,  0.0],[0.0, 0.0, mu]])

def stress(u, repr ="vectorial"):
    sigv = dot(C, strain(u))
    if repr =="vectorial":
        return sigv
    elif repr =="tensorial":
        return as_matrix([[sigv[0], sigv[2]], [sigv[2], sigv[1]]])


def rigid_motions_nullspace(V: fem.FunctionSpaceBase):
    """
    Function to build nullspace for 2D/3D elasticity.

    Args:
        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)]
    from contextlib import ExitStack

    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.reshape(-1) 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.reshape(-1)
        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, float(500 * np.finfo(_x.x.array.dtype).resolution))
    return PETSc.NullSpace().create(vectors=nullspace_basis)  # type: ignore


# Define Function Space
degree = 2
V = fem.functionspace(domain, ("P",degree, (gdim,)))

#Cyclic Symmetry Condition
def periodic_relation(x):
    out_x = np.zeros(x.shape)
    out_x[0] = x[1]*(-0.05/0.1)
    out_x[1] = x[1]
    return out_x


#Define Variational Problem
du = TrialFunction(V)
u_ = TestFunction(V)
a_form = inner(stress(du),strain(u_))*dx
T = fem.Constant(domain, 1000000.0)

n = FacetNormal(domain)


ds = ufl.Measure("ds", domain=domain, subdomain_data=facet_markers)
L_form = dot(T*n,u_) * ds(3)

# Dirichlet bc at a point with both ux = 0
def point1(x):
    return np.isclose(x[0], 0.05) & np.isclose(x[1], 0)

def point2(x):
    return np.isclose(x[0], 0.05) & np.isclose(x[1], 0.1)

constrained_vertex1 = locate_entities(domain, 0, point1)
constrained_vertex2 = locate_entities(domain, 0, point2)
constrained_dof1 = fem.locate_dofs_topological(V.sub(0), 0, constrained_vertex1)
constrained_dof2 = fem.locate_dofs_topological(V.sub(0), 0, constrained_vertex2)

u1_bc = fem.Constant(domain, 0.0)
bc_x1 = fem.dirichletbc(u1_bc, constrained_dof1, V.sub(0))

u2_bc = fem.Constant(domain, 0.0)
bc_x2 = fem.dirichletbc(u2_bc, constrained_dof2, V.sub(0))

bcs = [bc_x1, bc_x2]
    
with common.Timer("~~Periodic: Compute mpc condition"):
    mpc = MultiPointConstraint(V)
    mpc.create_periodic_constraint_topological(V.sub(0), facet_markers, 2, periodic_relation, bcs, default_scalar_type(1))
    mpc.finalize()
    print(len(mpc.slaves))


null_space = rigid_motions_nullspace(mpc.function_space)

ksp_rtol = 1e-8 * np.finfo(default_scalar_type).resolution
petsc_options = {
    "ksp_rtol": ksp_rtol,
    "pc_type": "gamg",
    "pc_gamg_type": "agg",
    "pc_gamg_coarse_eq_limit": 1000,
    "pc_gamg_sym_graph": True,
    "mg_levels_ksp_type": "chebyshev",
    "mg_levels_pc_type": "jacobi",
    "mg_levels_esteig_ksp_type": "cg",
    "matptap_via": "scalable",
    "pc_gamg_square_graph": 2,
    "pc_gamg_threshold": 0.02,
    # ,"help": None, "ksp_view": None
}

uh = fem.Function(mpc.function_space, name="Displacement")

WPsolve = LinearProblem(a_form, L_form, mpc, u=uh, bcs=bcs, petsc_options=petsc_options)
WPsolve.A.setNearNullSpace(null_space)
uh = WPsolve.solve()
uh.name = "u"
null_space.remove(uh.vector)

mpc.homogenize(uh)
mpc.backsubstitution(uh)
uh.x.scatter_forward()
                

So what displacement do you get by running your current script (in y-direction)?

Hello Jorgen, I get my displacements as follows:
uy displacement

ux displacement

u-magnitude

Dear Jorgen, any suggestion in order to resolve this issue?