Exemple #1
0
def test_lr_spline_insert_line_multiple():
    LR = init_tensor_product_LR_spline(1, 1, [0, 1, 2, 3], [0, 1, 2])
    M1 = Meshline(0, 2, constant_value=0.5, axis=1)  # horizontal split
    M2 = Meshline(0, 1, constant_value=1.5, axis=0)  # vertical split
    LR.insert_line(M1)
    LR.insert_line(M2)

    # expected functions
    b1 = BSpline(1, 1, [0, 1, 1.5], [0, 0.5, 1])
    b2 = BSpline(1, 1, [1, 1.5, 2], [0, 0.5, 1])
    b3 = BSpline(1, 1, [0, 1, 2], [0.5, 1, 2])
    b4 = BSpline(1, 1, [1, 2, 3], [0, 1, 2])

    assert b1 in LR.S
    assert b2 in LR.S
    assert b3 in LR.S
    assert b3 in LR.S
    assert len(LR.S) == 4

    expected_elements = [
        Element(0, 0, 1, 0.5),
        Element(1, 0, 1.5, 0.5),
        Element(1.5, 0, 2, 0.5),
        Element(0, 0.5, 1, 1),
        Element(1, 0.5, 1.5, 1),
        Element(1.5, 0.5, 2, 1),
        Element(2, 0, 3, 1),
        Element(0, 1, 1, 2),
        Element(1, 1, 2, 2),
        Element(2, 1, 3, 2)
    ]

    assert all([LR.contains_element(e) for e in expected_elements])
    assert len(LR.M) == 10
Exemple #2
0
    def merge_meshlines(self,
                        meshline: Meshline) -> typing.Tuple[bool, Meshline]:
        """
        Tests the meshline against all currently stored meshlines, and combines, updates and deletes
        meshlines as needed. Returns true if the meshline is already in the list of previous meshlines.
        There are three cases:

            1. The new meshline overlaps with a previous mesh line, but is not contained by the previous one.
            2. The new meshline is completely contained in a previous mesh line, (may in fact be equal)
            3. The new meshline is completely disjoint from all other meshlines.

        :param meshline: meshline to test against previous meshlines.
        :return: true if meshline was previously found, false otherwise.
        """
        tol = 1.0e-14
        meshlines_to_remove = []

        for old_meshline in self.meshlines:
            if not old_meshline._similar(meshline):
                # the two meshlines are not comparable, continue.
                continue
            if meshline == old_meshline:
                # meshline already exists, no point in continuing
                return True, meshline

            if old_meshline.contains(meshline):
                # meshline is completely contained in the old meshline

                if meshline.multiplicity > old_meshline.multiplicity:
                    if abs(old_meshline.start - meshline.start) < tol and abs(
                            old_meshline.stop - meshline.stop) < tol:
                        # if the new multiplicity is greater than the old one, and the endpoints coincide, keep the
                        # new line and remove the old line.
                        meshlines_to_remove.append(old_meshline)

                elif old_meshline.multiplicity >= meshline.multiplicity:
                    return True, old_meshline

            elif old_meshline.overlaps(meshline):
                if old_meshline.multiplicity < meshline.multiplicity:
                    if old_meshline.start > meshline.start:
                        old_meshline.start = meshline.start
                    if old_meshline.stop < meshline.stop:
                        old_meshline.stop = meshline.stop
                elif old_meshline.multiplicity > meshline.multiplicity:
                    if old_meshline.start < meshline.start:
                        meshline.start = old_meshline.start
                    if old_meshline.stop > meshline.stop:
                        meshline.stop = old_meshline.stop
                else:
                    if old_meshline.start < meshline.start:
                        meshline.start = old_meshline.start
                    if old_meshline.stop > meshline.stop:
                        meshline.stop = old_meshline.stop

                    meshlines_to_remove.append(old_meshline)

        for old_meshline in meshlines_to_remove:
            self.meshlines.remove(old_meshline)
        return False, meshline
Exemple #3
0
def test_meshline_equals():
    m1 = Meshline(0.1, 1.9, constant_value=1, axis=0)
    m2 = Meshline(0.1, 1.9, constant_value=1.2, axis=0)
    m3 = Meshline(0.1, 1.9, constant_value=1, axis=1)

    assert m1 == m1
    assert m1 != m2
    assert m1 != m3
Exemple #4
0
def test_lr_spline_unique_basis_functions():
    LR = init_tensor_product_LR_spline(1, 1, [0, 0, 1, 1], [0, 1, 2])
    m = Meshline(0, 2, constant_value=0.5, axis=0)
    LR.insert_line(m, debug=False)
    m = Meshline(0, 1, constant_value=0.5, axis=1)
    LR.insert_line(m, debug=False)

    c = Counter(LR.S)
    assert all([count == 1 for count in c.values()])
Exemple #5
0
    def get_minimal_span_meshline(e: Element, axis) -> Meshline:
        """
        Finds the shortest possible meshline in direction prescribed by axis that splits at least one supported
        B-spline on the element.

        :param e: element to refine by
        :param axis: direction to look for split, 0 vertical, 1 horizontal
        :return: minimal span meshline
        """

        smallest_start = None
        smallest_stop = None
        for basis in e.supported_b_splines:
            k = basis.knots_v if axis == 0 else basis.knots_u
            current_length = abs(k[-1] - k[0])
            if smallest_start is None or smallest_stop is None or current_length < (
                    smallest_stop - smallest_start):
                smallest_start = k[0]
                smallest_stop = k[-1]

        constant_value = e.midpoint[axis]

        new_meshline = Meshline(smallest_start, smallest_stop, constant_value,
                                axis)
        return new_meshline
Exemple #6
0
def test_meshline_overlaps():
    m1 = Meshline(0, 1, constant_value=0.5, axis=1)
    m2 = Meshline(0, 2, constant_value=0.5, axis=1)
    m3 = Meshline(0.5, 1.5, constant_value=0.5, axis=1)
    m4 = Meshline(0.5, 1.5, constant_value=0.5, axis=0)
    m5 = Meshline(0.5, 1.5, constant_value=0.4, axis=1)

    assert m1.overlaps(m2)
    assert m1.overlaps(m3)
    assert not m1.overlaps(m4)
    assert not m1.overlaps(m5)
Exemple #7
0
def test_meshline_contains():
    m1 = Meshline(0, 2, constant_value=1, axis=0)
    m2 = Meshline(0.1, 1.9, constant_value=1, axis=0)
    m3 = Meshline(0.1, 1.9, constant_value=1.2, axis=0)
    m4 = Meshline(0.1, 1.9, constant_value=1, axis=1)

    assert m1.contains(m2)
    assert not m1.contains(m3)
    assert not m1.contains(m4)
Exemple #8
0
def test_lr_spline_dimension_bilinear():
    ku = [0, 0, 1, 2, 2]
    kv = [0, 0, 1, 1]

    du = 1
    dv = 1

    LR = init_tensor_product_LR_spline(du, dv, ku, kv)
    m = Meshline(1, 2, constant_value=0.5, axis=1)
    LR.insert_line(m)
    assert len(LR.S) == 7
Exemple #9
0
def test_lr_spline_overloading_count_bilinear():
    LR = init_tensor_product_LR_spline(1, 1, [0, 0, 1, 2, 3, 4, 5, 6, 6],
                                       [0, 0, 1, 2, 3, 4, 5, 6, 6])

    m1 = Meshline(2, 4, constant_value=3.5, axis=0)
    m2 = Meshline(2, 4, constant_value=2.5, axis=0)
    m3 = Meshline(2, 4, constant_value=2.5, axis=1)
    m4 = Meshline(2, 4, constant_value=3.5, axis=1)

    # culprit = 3, 3.5, 4 x 2 3 4
    LR.insert_line(m1, debug=True)
    LR.insert_line(m2, debug=True)
    LR.insert_line(m3, debug=True)
    LR.insert_line(m4, debug=True)

    for e in LR.M:
        c = Counter(e.supported_b_splines)
        assert all([count == 1 for count in c.values()])

    for e in LR.M:
        assert len(e.supported_b_splines) in [4, 5]
Exemple #10
0
def test_meshline_number_of_knots():
    b1 = BSpline(1, 1, [0, 1, 2], [0, 1, 2])
    m1 = Meshline(0, 2, constant_value=1, axis=0)
    m2 = Meshline(0, 2, constant_value=0.5, axis=1)

    assert m1.number_of_knots_contained(b1) == 1
    assert m2.number_of_knots_contained(b1) == 0
Exemple #11
0
def test_meshline_init():
    start = 0
    stop = 1
    axis = 0
    constant_value = 0.5

    m = Meshline(start, stop, constant_value, axis)

    assert m.start == start
    assert m.stop == stop
    assert m.constant_value == constant_value
    assert m.axis == axis
    assert m.multiplicity == 1
def test_aux_split_methods():
    d1 = 2
    d2 = 2
    ku = [0, 1, 2, 4]
    kv = [1, 2, 4, 5]
    B = BSpline(d1, d2, ku, kv)

    m = Meshline(0, 5, constant_value=3, axis=0)
    eps = 1.0E-14
    b1, b2 = split_single_basis_function(m, B)

    assert b1.weight == 1
    assert (b2.weight - 1 / 3) < eps
    assert np.allclose(b1.knots_u, [0, 1, 2, 3])
    assert np.allclose(b2.knots_u, [1, 2, 3, 4])
Exemple #13
0
def test_lr_spline_global_knot_vector():
    ku = [0, 0, 1, 2, 3, 3]
    kv = [0, 0, 0.5, 1, 1]

    du = 1
    dv = 1

    LR = init_tensor_product_LR_spline(du, dv, ku, kv)

    np.testing.assert_array_almost_equal([0, 1, 2, 3], LR.global_knots_u)
    np.testing.assert_array_almost_equal([0, 0.5, 1], LR.global_knots_v)

    m = Meshline(start=0, stop=0.5, constant_value=1.5, axis=0)
    LR.insert_line(m)
    np.testing.assert_array_almost_equal([0, 1, 1.5, 2, 3], LR.global_knots_u)
Exemple #14
0
def test_meshline_splits_element():
    start = 0
    stop = 1
    constant_value = 0.5

    m1 = Meshline(start, stop, constant_value, 0)
    m2 = Meshline(start, stop, constant_value, 1)
    e1 = Element(0, 0, 1, 1)
    e2 = Element(0, 0, 0.4, 1)
    e3 = Element(0, 0, 0.5, 1)

    assert m1.splits_element(e1)
    assert not m1.splits_element(e2)
    assert not m1.splits_element(e3)

    assert m2.splits_element(e1)
    assert m2.splits_element(e2)
    assert m2.splits_element(e3)
Exemple #15
0
def test_meshline_splits_basis():
    start = 0
    stop = 1
    constant_value = 0.5
    m1 = Meshline(start, stop, constant_value, 0)
    m2 = Meshline(start, stop, constant_value, 1)

    b1 = BSpline(2, 2, [0, 1, 2, 3], [0, 1, 2, 3])
    b2 = BSpline(2, 2, [0, 1, 2, 3], [0, 0.25, 0.5, 0.75, 1])

    assert not m1.splits_basis(b1)
    assert m1.splits_basis(b2)

    assert not m2.splits_basis(b1)
    assert not m2.splits_basis(b2)
Exemple #16
0
 def get_full_span_meshline(e: Element, axis) -> Meshline:
     """
     Finds the meshline in direction prescribed by the axis that splits all the supported B-splines on the element.
     :param e: element to refine by
     :param axis: direction to look for split, 0 vertical, 1 horizontal
     :return: full span meshline
     """
     longest_start = None
     longest_stop = None
     for basis in e.supported_b_splines:
         k = basis.knots_v if axis == 0 else basis.knots_u
         current_length = abs(k[-1] - k[0])
         if longest_start is None or longest_stop is None or current_length > (
                 longest_stop - longest_start):
             longest_start = k[0]
             longest_stop = k[-1]
     constant_value = e.midpoint[axis]
     return Meshline(longest_start, longest_stop, constant_value, axis)
Exemple #17
0
def test_minimal_support_split():
    B = BSpline(1, 1, [3, 3.5, 4], [2, 3, 4])
    m = Meshline(2, 4, 2.5, axis=1)

    assert m.splits_basis(B)
Exemple #18
0
import random

from LRSplines.lr_spline import init_tensor_product_LR_spline
from LRSplines.meshline import Meshline

if __name__ == '__main__':
    LR = init_tensor_product_LR_spline(1, 1, [0, 0, 1, 2, 3, 4, 5, 6, 6], [0, 0, 1, 2, 3, 4, 5, 6, 6])

    m1 = Meshline(2, 4, constant_value=2.5, axis=0)
    m2 = Meshline(2, 4, constant_value=2.5, axis=1)
    m3 = Meshline(2, 4, constant_value=3.5, axis=1)
    m4 = Meshline(2, 4, constant_value=3.5, axis=0)

    LR.insert_line(m1)

    LR.insert_line(m2)
    LR.insert_line(m3)
    LR.insert_line(m4)

    m5 = Meshline(1, 5, constant_value=2.5, axis=0)
    m6 = Meshline(1, 5, constant_value=3.5, axis=0)
    LR.insert_line(m5)
    LR.insert_line(m6)

    for i in range(100):
        m = LR.get_minimal_span_meshline(random.choice(LR.M), axis=i % 2)
        LR.insert_line(m)

    LR.visualize_mesh(False, False)
Exemple #19
0
def init_tensor_product_LR_spline(d1: int, d2: int, ku: Vector,
                                  kv: Vector) -> 'LRSpline':
    """
    Initializes an LR spline at the tensor product level of bidegree (d1, d2).

    :param d1: first component degree
    :param d2: second component degree
    :param ku: knots in u_direction
    :param kv: knots in v_direction
    :return: corresponding LR_spline
    """

    elements = []
    basis = []
    meshlines = []

    unique_ku = np.unique(ku)
    unique_kv = np.unique(kv)

    for i in range(len(unique_ku) - 1):
        for j in range(len(unique_kv) - 1):
            elements.append(
                Element(unique_ku[i], unique_kv[j], unique_ku[i + 1],
                        unique_kv[j + 1]))

    for i in range(len(ku) - d1 - 1):
        for j in range(len(kv) - d2 - 1):
            end_u = _at_end(ku, i + d1 + 1)
            end_v = _at_end(kv, j + d2 + 1)

            # TODO: This only works if the knot vectors are p+1-extended.

            north = j == len(kv) - d2 - 2
            south = j == 0
            east = i == len(ku) - d1 - 2
            west = i == 0

            basis.append(
                BSpline(d1,
                        d2,
                        ku[i:i + d1 + 2],
                        kv[j:j + d2 + 2],
                        end_u=end_u,
                        end_v=end_v,
                        north=north,
                        south=south,
                        east=east,
                        west=west))

    for b in basis:
        for e in elements:
            if b.add_to_support_if_intersects(e):
                e.add_supported_b_spline(b)

    for i in range(len(unique_ku)):
        for j in range(len(unique_kv) - 1):
            new_m = Meshline(start=unique_kv[j],
                             stop=unique_kv[j + 1],
                             constant_value=unique_ku[i],
                             axis=0)
            new_m.set_multiplicity(ku)
            meshlines.append(new_m)
    for i in range(len(unique_kv)):
        for j in range(len(unique_ku) - 1):
            new_m = Meshline(start=unique_ku[j],
                             stop=unique_ku[j + 1],
                             constant_value=unique_kv[i],
                             axis=1)
            new_m.set_multiplicity(kv)
            meshlines.append(new_m)

    u_range = [ku[0], ku[-1]]
    v_range = [kv[0], kv[-1]]

    return LRSpline(elements, basis, meshlines, u_range, v_range, unique_ku,
                    unique_kv)
Exemple #20
0
    def insert_line(self, meshline: Meshline, debug=False) -> None:
        """
        Inserts a line in the mesh, splitting where necessary.
        Follows a four step procedure:

            Step 1: Test all BSplines against the new meshline, and if the meshline traverses the support, split the
            BSpline into B1 and B2. For both B1 and B2, check whether they are already in the set of previous
            BSplines. If they are not, add them to the list of new functions. Add the function that was split to the
            list of functions to remove.

            Step 2: Test all the new B-splines against all the meshlines already present in the mesh. They might have
            to be split further.

            Step 3: Check all elements of the mesh, and make sure that any previous elements traversed by the new
            meshline are split accordingly.

            Step 4: Make sure that all elements keep track of the basis functions they support, and that all basis
            functions keep track of the elements that support them.

        :param meshline: meshline to insert
        """

        # step 0
        # merge any existing meshlines, if the meshline already exists, we are done and can return early.
        meshline_already_exists, meshline = self.merge_meshlines(meshline)

        if meshline_already_exists:
            return

        # update the list of global tensorproduct knots
        if meshline.axis == 0:
            i = np.searchsorted(self.global_knots_u, meshline.constant_value,
                                'left')
            self.global_knots_u = np.insert(self.global_knots_u, i,
                                            meshline.constant_value)
        elif meshline.axis == 1:
            i = np.searchsorted(self.global_knots_v, meshline.constant_value,
                                'left')
            self.global_knots_v = np.insert(self.global_knots_v, i,
                                            meshline.constant_value)

        # step 1
        # split B-splines against new meshline
        new_functions = []
        functions_to_remove = []
        for basis in self.S:
            if meshline.splits_basis(basis):
                if meshline.number_of_knots_contained(
                        basis) < meshline.multiplicity:
                    self.local_split(basis, meshline, functions_to_remove,
                                     new_functions)

        purged_S = [s for s in self.S if s not in functions_to_remove]

        self.S = purged_S
        # step 2
        # split new B-splines against old meshlines
        self.meshlines.append(meshline)

        # for basis in new_functions:
        while len(new_functions) > 0:
            basis = new_functions.pop()
            split_more = False
            for m in self.meshlines:
                if m.splits_basis(basis):
                    if m.number_of_knots_contained(basis) < m.multiplicity:
                        split_more = True
                        self.local_split(basis, m, functions_to_remove,
                                         new_functions)
                        break
            if not split_more:
                self.S.append(basis)

        # step 3
        # split all marked elements against new meshline
        new_elements = []
        for element in self.M:
            if meshline.splits_element(element):
                new_elements.append(
                    element.split(axis=meshline.axis,
                                  split_value=meshline.constant_value))

        self.M += new_elements

        # step 4
        # clean up, make sure all basis functions points to correct elements
        # make sure all elements point to correct basis functions
        # TODO: This implementation is preliminary, and possibly very slow.
        for element in self.M:
            element.supported_b_splines = []
        for basis in self.S:
            basis.elements_of_support = []
            for element in self.M:
                if basis.add_to_support_if_intersects(element):
                    element.add_supported_b_spline(basis)

        # invalidate the element cache
        self.element_cache = None
        self.update_global_indices()
Exemple #21
0
def test_lr_spline_previously_split_functions():
    LR = init_tensor_product_LR_spline(2, 2, [0, 0, 0, 1, 2, 4, 5, 6, 6, 6],
                                       [0, 0, 0, 1, 2, 4, 5, 6, 6, 6])
    m = Meshline(1, 5, constant_value=3, axis=0)
    LR.insert_line(m)
Exemple #22
0
def test_meshline_overlaps_disjoint():
    m1 = Meshline(start=0, stop=2, constant_value=3, axis=0)
    m2 = Meshline(start=5, stop=6, constant_value=3, axis=0)

    assert not m1.overlaps(m2)
Exemple #23
0
def test_meshline_midpoint():
    m1 = Meshline(0, 2, constant_value=0.5, axis=1)
    m2 = Meshline(0, 2, constant_value=0.5, axis=0)

    assert m1.midpoint == (1, 0.5)
    assert m2.midpoint == (0.5, 1)