xref: /libCEED/python/tests/test-2-elemrestriction.py (revision 9ba83ac0e4b1fca39d6fa6737a318a9f0cbc172d)
1*9ba83ac0SJeremy L Thompson# Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors
23d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
30ef72598Sjeremylt#
43d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
50ef72598Sjeremylt#
63d8e8822SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
70ef72598Sjeremylt
80ef72598Sjeremylt# @file
90ef72598Sjeremylt# Test Ceed ElemRestriction functionality
100ef72598Sjeremylt
110ef72598Sjeremyltimport os
120ef72598Sjeremyltimport libceed
130ef72598Sjeremyltimport numpy as np
140ef72598Sjeremyltimport check
150ef72598Sjeremylt
160ef72598Sjeremylt# -------------------------------------------------------------------------------
170ef72598Sjeremylt# Test creation, use, and destruction of an element restriction
180ef72598Sjeremylt# -------------------------------------------------------------------------------
190ef72598Sjeremylt
200ef72598Sjeremylt
210ef72598Sjeremyltdef test_200(ceed_resource):
220ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
230ef72598Sjeremylt
24c3a5a609SJeremy L Thompson    num_elem = 3
250ef72598Sjeremylt
26c3a5a609SJeremy L Thompson    x = ceed.Vector(num_elem + 1)
2780a9ef05SNatalie Beams    a = np.arange(10, 10 + num_elem + 1, dtype=ceed.scalar_type())
280ef72598Sjeremylt    x.set_array(a, cmode=libceed.USE_POINTER)
290ef72598Sjeremylt
30c3a5a609SJeremy L Thompson    ind = np.zeros(2 * num_elem, dtype="int32")
31c3a5a609SJeremy L Thompson    for i in range(num_elem):
320ef72598Sjeremylt        ind[2 * i + 0] = i
330ef72598Sjeremylt        ind[2 * i + 1] = i + 1
34c3a5a609SJeremy L Thompson    r = ceed.ElemRestriction(num_elem, 2, 1, 1, num_elem + 1, ind,
350ef72598Sjeremylt                             cmode=libceed.USE_POINTER)
360ef72598Sjeremylt
37c3a5a609SJeremy L Thompson    y = ceed.Vector(2 * num_elem)
380ef72598Sjeremylt    y.set_value(0)
390ef72598Sjeremylt
400ef72598Sjeremylt    r.apply(x, y)
410ef72598Sjeremylt
420ef72598Sjeremylt    with y.array_read() as y_array:
43c3a5a609SJeremy L Thompson        for i in range(2 * num_elem):
440ef72598Sjeremylt            assert 10 + (i + 1) // 2 == y_array[i]
450ef72598Sjeremylt
460ef72598Sjeremylt# -------------------------------------------------------------------------------
470ef72598Sjeremylt# Test creation, use, and destruction of a strided element restriction
480ef72598Sjeremylt# -------------------------------------------------------------------------------
490ef72598Sjeremylt
500ef72598Sjeremylt
510ef72598Sjeremyltdef test_201(ceed_resource):
520ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
530ef72598Sjeremylt
54c3a5a609SJeremy L Thompson    num_elem = 3
550ef72598Sjeremylt
56c3a5a609SJeremy L Thompson    x = ceed.Vector(2 * num_elem)
5780a9ef05SNatalie Beams    a = np.arange(10, 10 + 2 * num_elem, dtype=ceed.scalar_type())
580ef72598Sjeremylt    x.set_array(a, cmode=libceed.USE_POINTER)
590ef72598Sjeremylt
600ef72598Sjeremylt    strides = np.array([1, 2, 2], dtype="int32")
61c3a5a609SJeremy L Thompson    r = ceed.StridedElemRestriction(num_elem, 2, 1, 2 * num_elem, strides)
620ef72598Sjeremylt
63c3a5a609SJeremy L Thompson    y = ceed.Vector(2 * num_elem)
640ef72598Sjeremylt    y.set_value(0)
650ef72598Sjeremylt
660ef72598Sjeremylt    r.apply(x, y)
670ef72598Sjeremylt
680ef72598Sjeremylt    with y.array_read() as y_array:
69c3a5a609SJeremy L Thompson        for i in range(2 * num_elem):
700ef72598Sjeremylt            assert 10 + i == y_array[i]
710ef72598Sjeremylt
720ef72598Sjeremylt# -------------------------------------------------------------------------------
730ef72598Sjeremylt# Test creation and destruction of a blocked element restriction
740ef72598Sjeremylt# -------------------------------------------------------------------------------
750ef72598Sjeremylt
760ef72598Sjeremylt
770ef72598Sjeremyltdef test_202(ceed_resource, capsys):
780ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
790ef72598Sjeremylt
80c3a5a609SJeremy L Thompson    num_elem = 8
81c3a5a609SJeremy L Thompson    elem_size = 2
82c3a5a609SJeremy L Thompson    num_blk = 2
83c3a5a609SJeremy L Thompson    blk_size = 5
840ef72598Sjeremylt
85c3a5a609SJeremy L Thompson    x = ceed.Vector(num_elem + 1)
8680a9ef05SNatalie Beams    a = np.arange(10, 10 + num_elem + 1, dtype=ceed.scalar_type())
87c3a5a609SJeremy L Thompson    x.set_array(a, cmode=libceed.COPY_VALUES)
880ef72598Sjeremylt
89c3a5a609SJeremy L Thompson    ind = np.zeros(2 * num_elem, dtype="int32")
90c3a5a609SJeremy L Thompson    for i in range(num_elem):
910ef72598Sjeremylt        ind[2 * i + 0] = i
920ef72598Sjeremylt        ind[2 * i + 1] = i + 1
93c3a5a609SJeremy L Thompson    r = ceed.BlockedElemRestriction(num_elem, elem_size, blk_size, 1, 1,
94c3a5a609SJeremy L Thompson                                    num_elem + 1, ind, cmode=libceed.COPY_VALUES)
950ef72598Sjeremylt
96c3a5a609SJeremy L Thompson    y = ceed.Vector(num_blk * blk_size * elem_size)
970ef72598Sjeremylt    y.set_value(0)
980ef72598Sjeremylt
99c3a5a609SJeremy L Thompson    # NoTranspose
1000ef72598Sjeremylt    r.apply(x, y)
10156c48462SJeremy L Thompson    layout = r.get_e_layout()
102c3a5a609SJeremy L Thompson    with y.array_read() as y_array:
103c3a5a609SJeremy L Thompson        for i in range(elem_size):
104c3a5a609SJeremy L Thompson            for j in range(1):
105c3a5a609SJeremy L Thompson                for k in range(num_elem):
106c3a5a609SJeremy L Thompson                    block = int(k / blk_size)
107c3a5a609SJeremy L Thompson                    elem = k % blk_size
108c3a5a609SJeremy L Thompson                    indx = (i * blk_size + elem) * \
109c3a5a609SJeremy L Thompson                        layout[0] + j * blk_size * layout[1] + \
110c3a5a609SJeremy L Thompson                        block * blk_size * layout[2]
111c3a5a609SJeremy L Thompson                assert y_array[indx] == a[ind[k * elem_size + i]]
1120ef72598Sjeremylt
1130ef72598Sjeremylt    x.set_value(0)
1140ef72598Sjeremylt    r.T.apply(y, x)
115c3a5a609SJeremy L Thompson    with x.array_read() as x_array:
116c3a5a609SJeremy L Thompson        for i in range(num_elem + 1):
117c3a5a609SJeremy L Thompson            assert x_array[i] == (10 + i) * (2.0 if i >
118c3a5a609SJeremy L Thompson                                             0 and i < num_elem else 1.0)
1190ef72598Sjeremylt
1200ef72598Sjeremylt# -------------------------------------------------------------------------------
1210ef72598Sjeremylt# Test creation, use, and destruction of a blocked element restriction
1220ef72598Sjeremylt# -------------------------------------------------------------------------------
1230ef72598Sjeremylt
1240ef72598Sjeremylt
125c3a5a609SJeremy L Thompsondef test_208(ceed_resource):
1260ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1270ef72598Sjeremylt
128c3a5a609SJeremy L Thompson    num_elem = 8
129c3a5a609SJeremy L Thompson    elem_size = 2
130c3a5a609SJeremy L Thompson    num_blk = 2
131c3a5a609SJeremy L Thompson    blk_size = 5
1320ef72598Sjeremylt
133c3a5a609SJeremy L Thompson    x = ceed.Vector(num_elem + 1)
13480a9ef05SNatalie Beams    a = np.arange(10, 10 + num_elem + 1, dtype=ceed.scalar_type())
135c3a5a609SJeremy L Thompson    x.set_array(a, cmode=libceed.COPY_VALUES)
1360ef72598Sjeremylt
137c3a5a609SJeremy L Thompson    ind = np.zeros(2 * num_elem, dtype="int32")
138c3a5a609SJeremy L Thompson    for i in range(num_elem):
1390ef72598Sjeremylt        ind[2 * i + 0] = i
1400ef72598Sjeremylt        ind[2 * i + 1] = i + 1
141c3a5a609SJeremy L Thompson    r = ceed.BlockedElemRestriction(num_elem, elem_size, blk_size, 1, 1,
142c3a5a609SJeremy L Thompson                                    num_elem + 1, ind, cmode=libceed.COPY_VALUES)
1430ef72598Sjeremylt
144c3a5a609SJeremy L Thompson    y = ceed.Vector(blk_size * elem_size)
1450ef72598Sjeremylt    y.set_value(0)
1460ef72598Sjeremylt
147c3a5a609SJeremy L Thompson    # NoTranspose
1480ef72598Sjeremylt    r.apply_block(1, x, y)
14956c48462SJeremy L Thompson    layout = r.get_e_layout()
150c3a5a609SJeremy L Thompson    with y.array_read() as y_array:
151c3a5a609SJeremy L Thompson        for i in range(elem_size):
152c3a5a609SJeremy L Thompson            for j in range(1):
153c3a5a609SJeremy L Thompson                for k in range(blk_size, num_elem):
154c3a5a609SJeremy L Thompson                    block = int(k / blk_size)
155c3a5a609SJeremy L Thompson                    elem = k % blk_size
156c3a5a609SJeremy L Thompson                    indx = (i * blk_size + elem) * layout[0] + j * blk_size * \
157c3a5a609SJeremy L Thompson                        layout[1] + block * blk_size * \
158c3a5a609SJeremy L Thompson                        layout[2] - blk_size * elem_size
159c3a5a609SJeremy L Thompson                assert y_array[indx] == a[ind[k * elem_size + i]]
1600ef72598Sjeremylt
1610ef72598Sjeremylt    x.set_value(0)
1620ef72598Sjeremylt    r.T.apply_block(1, y, x)
163c3a5a609SJeremy L Thompson    with x.array_read() as x_array:
164c3a5a609SJeremy L Thompson        for i in range(blk_size, num_elem + 1):
165c3a5a609SJeremy L Thompson            assert x_array[i] == (10 + i) * (2.0 if i >
166c3a5a609SJeremy L Thompson                                             blk_size and i < num_elem else 1.0)
1670ef72598Sjeremylt
1680ef72598Sjeremylt# -------------------------------------------------------------------------------
1690ef72598Sjeremylt# Test getting the multiplicity of the indices in an element restriction
1700ef72598Sjeremylt# -------------------------------------------------------------------------------
1710ef72598Sjeremylt
1720ef72598Sjeremylt
1730ef72598Sjeremyltdef test_209(ceed_resource):
1740ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1750ef72598Sjeremylt
176c3a5a609SJeremy L Thompson    num_elem = 3
1770ef72598Sjeremylt
178c3a5a609SJeremy L Thompson    ind = np.zeros(4 * num_elem, dtype="int32")
179c3a5a609SJeremy L Thompson    for i in range(num_elem):
1800ef72598Sjeremylt        ind[4 * i + 0] = i * 3 + 0
1810ef72598Sjeremylt        ind[4 * i + 1] = i * 3 + 1
1820ef72598Sjeremylt        ind[4 * i + 2] = i * 3 + 2
1830ef72598Sjeremylt        ind[4 * i + 3] = i * 3 + 3
184c3a5a609SJeremy L Thompson    r = ceed.ElemRestriction(num_elem, 4, 1, 1, 3 * num_elem + 1, ind,
1850ef72598Sjeremylt                             cmode=libceed.USE_POINTER)
1860ef72598Sjeremylt
1870ef72598Sjeremylt    mult = r.get_multiplicity()
1880ef72598Sjeremylt
1890ef72598Sjeremylt    with mult.array_read() as mult_array:
190c3a5a609SJeremy L Thompson        for i in range(3 * num_elem + 1):
191c3a5a609SJeremy L Thompson            val = 1 + (1 if (i > 0 and i < 3 * num_elem and i % 3 == 0) else 0)
1920ef72598Sjeremylt            assert val == mult_array[i]
1930ef72598Sjeremylt
1940ef72598Sjeremylt# -------------------------------------------------------------------------------
1950ef72598Sjeremylt# Test creation and view of an element restriction
1960ef72598Sjeremylt# -------------------------------------------------------------------------------
1970ef72598Sjeremylt
1980ef72598Sjeremylt
1990ef72598Sjeremyltdef test_210(ceed_resource, capsys):
2000ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2010ef72598Sjeremylt
202c3a5a609SJeremy L Thompson    num_elem = 3
2030ef72598Sjeremylt
204c3a5a609SJeremy L Thompson    ind = np.zeros(2 * num_elem, dtype="int32")
205c3a5a609SJeremy L Thompson    for i in range(num_elem):
2060ef72598Sjeremylt        ind[2 * i + 0] = i + 0
2070ef72598Sjeremylt        ind[2 * i + 1] = i + 1
208c3a5a609SJeremy L Thompson    r = ceed.ElemRestriction(num_elem, 2, 1, 1, num_elem + 1, ind,
2090ef72598Sjeremylt                             cmode=libceed.USE_POINTER)
2100ef72598Sjeremylt
2110ef72598Sjeremylt    print(r)
2120ef72598Sjeremylt
2130ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
2140ef72598Sjeremylt    assert not stderr
2150ef72598Sjeremylt    assert stdout == ref_stdout
2160ef72598Sjeremylt
2170ef72598Sjeremylt# -------------------------------------------------------------------------------
2180ef72598Sjeremylt# Test creation and view of a strided element restriction
2190ef72598Sjeremylt# -------------------------------------------------------------------------------
2200ef72598Sjeremylt
2210ef72598Sjeremylt
2220ef72598Sjeremyltdef test_211(ceed_resource, capsys):
2230ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2240ef72598Sjeremylt
225c3a5a609SJeremy L Thompson    num_elem = 3
2260ef72598Sjeremylt
2270ef72598Sjeremylt    strides = np.array([1, 2, 2], dtype="int32")
228e7f679fcSJeremy L Thompson    r = ceed.StridedElemRestriction(num_elem, 2, 1, num_elem * 2, strides)
2290ef72598Sjeremylt
2300ef72598Sjeremylt    print(r)
2310ef72598Sjeremylt
2320ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
2330ef72598Sjeremylt    assert not stderr
2340ef72598Sjeremylt    assert stdout == ref_stdout
2350ef72598Sjeremylt
2360ef72598Sjeremylt# -------------------------------------------------------------------------------
2370ef72598Sjeremylt# Test creation and view of a blocked strided element restriction
2380ef72598Sjeremylt# -------------------------------------------------------------------------------
2390ef72598Sjeremylt
2400ef72598Sjeremylt
2410ef72598Sjeremyltdef test_212(ceed_resource, capsys):
2420ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2430ef72598Sjeremylt
244c3a5a609SJeremy L Thompson    num_elem = 3
2450ef72598Sjeremylt
2460ef72598Sjeremylt    strides = np.array([1, 2, 2], dtype="int32")
247c3a5a609SJeremy L Thompson    r = ceed.BlockedStridedElemRestriction(
248e7f679fcSJeremy L Thompson        num_elem, 2, 2, 1, num_elem * 2, strides)
2490ef72598Sjeremylt
2500ef72598Sjeremylt    print(r)
2510ef72598Sjeremylt
2520ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
2530ef72598Sjeremylt    assert not stderr
2540ef72598Sjeremylt    assert stdout == ref_stdout
2550ef72598Sjeremylt
2560ef72598Sjeremylt# -------------------------------------------------------------------------------
257709403c1SSebastian Grimberg# Test creation, use, and destruction of an oriented element restriction
258709403c1SSebastian Grimberg# -------------------------------------------------------------------------------
259709403c1SSebastian Grimberg
260709403c1SSebastian Grimberg
261709403c1SSebastian Grimbergdef test_213(ceed_resource):
262709403c1SSebastian Grimberg    ceed = libceed.Ceed(ceed_resource)
263709403c1SSebastian Grimberg
264709403c1SSebastian Grimberg    num_elem = 3
265709403c1SSebastian Grimberg
266709403c1SSebastian Grimberg    x = ceed.Vector(num_elem + 1)
267709403c1SSebastian Grimberg    a = np.arange(10, 10 + num_elem + 1, dtype=ceed.scalar_type())
268709403c1SSebastian Grimberg    x.set_array(a, cmode=libceed.USE_POINTER)
269709403c1SSebastian Grimberg
270709403c1SSebastian Grimberg    ind = np.zeros(2 * num_elem, dtype="int32")
271709403c1SSebastian Grimberg    orients = np.zeros(2 * num_elem, dtype="bool")
272709403c1SSebastian Grimberg    for i in range(num_elem):
273709403c1SSebastian Grimberg        ind[2 * i + 0] = i
274709403c1SSebastian Grimberg        ind[2 * i + 1] = i + 1
275709403c1SSebastian Grimberg        # flip the dofs on element 1, 3, ...
276709403c1SSebastian Grimberg        orients[2 * i + 0] = (i % 2) > 0
277709403c1SSebastian Grimberg        orients[2 * i + 1] = (i % 2) > 0
278709403c1SSebastian Grimberg    r = ceed.OrientedElemRestriction(
279709403c1SSebastian Grimberg        num_elem,
280709403c1SSebastian Grimberg        2,
281709403c1SSebastian Grimberg        1,
282709403c1SSebastian Grimberg        1,
283709403c1SSebastian Grimberg        num_elem + 1,
284709403c1SSebastian Grimberg        ind,
285709403c1SSebastian Grimberg        orients,
286709403c1SSebastian Grimberg        cmode=libceed.USE_POINTER)
287709403c1SSebastian Grimberg
288709403c1SSebastian Grimberg    y = ceed.Vector(2 * num_elem)
289709403c1SSebastian Grimberg    y.set_value(0)
290709403c1SSebastian Grimberg
291709403c1SSebastian Grimberg    r.apply(x, y)
292709403c1SSebastian Grimberg
293709403c1SSebastian Grimberg    with y.array_read() as y_array:
294709403c1SSebastian Grimberg        for i in range(num_elem):
295709403c1SSebastian Grimberg            for j in range(2):
296709403c1SSebastian Grimberg                k = j + 2 * i
297709403c1SSebastian Grimberg                assert 10 + (k + 1) // 2 == y_array[k] * pow(-1, i % 2)
298709403c1SSebastian Grimberg
299709403c1SSebastian Grimberg# -------------------------------------------------------------------------------
300709403c1SSebastian Grimberg# Test creation, use, and destruction of a curl-oriented element restriction
301709403c1SSebastian Grimberg# -------------------------------------------------------------------------------
302709403c1SSebastian Grimberg
303709403c1SSebastian Grimberg
304709403c1SSebastian Grimbergdef test_214(ceed_resource):
305709403c1SSebastian Grimberg    ceed = libceed.Ceed(ceed_resource)
306709403c1SSebastian Grimberg
307709403c1SSebastian Grimberg    num_elem = 3
308709403c1SSebastian Grimberg
309709403c1SSebastian Grimberg    x = ceed.Vector(num_elem + 1)
310709403c1SSebastian Grimberg    a = np.arange(10, 10 + num_elem + 1, dtype=ceed.scalar_type())
311709403c1SSebastian Grimberg    x.set_array(a, cmode=libceed.USE_POINTER)
312709403c1SSebastian Grimberg
313709403c1SSebastian Grimberg    ind = np.zeros(2 * num_elem, dtype="int32")
314709403c1SSebastian Grimberg    curl_orients = np.zeros(3 * 2 * num_elem, dtype="int8")
315709403c1SSebastian Grimberg    for i in range(num_elem):
316709403c1SSebastian Grimberg        ind[2 * i + 0] = i
317709403c1SSebastian Grimberg        ind[2 * i + 1] = i + 1
318709403c1SSebastian Grimberg        curl_orients[3 * 2 * i] = curl_orients[3 * 2 * (i + 1) - 1] = 0
319709403c1SSebastian Grimberg        if i % 2 > 0:
320709403c1SSebastian Grimberg            # T = [0  -1]
321709403c1SSebastian Grimberg            #     [-1  0]
322709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 1] = 0
323709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 2] = -1
324709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 3] = -1
325709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 4] = 0
326709403c1SSebastian Grimberg        else:
327709403c1SSebastian Grimberg            # T = I
328709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 1] = 1
329709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 2] = 0
330709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 3] = 0
331709403c1SSebastian Grimberg            curl_orients[3 * 2 * i + 4] = 1
332709403c1SSebastian Grimberg    r = ceed.CurlOrientedElemRestriction(
333709403c1SSebastian Grimberg        num_elem,
334709403c1SSebastian Grimberg        2,
335709403c1SSebastian Grimberg        1,
336709403c1SSebastian Grimberg        1,
337709403c1SSebastian Grimberg        num_elem + 1,
338709403c1SSebastian Grimberg        ind,
339709403c1SSebastian Grimberg        curl_orients,
340709403c1SSebastian Grimberg        cmode=libceed.USE_POINTER)
341709403c1SSebastian Grimberg
342709403c1SSebastian Grimberg    y = ceed.Vector(2 * num_elem)
343709403c1SSebastian Grimberg    y.set_value(0)
344709403c1SSebastian Grimberg
345709403c1SSebastian Grimberg    r.apply(x, y)
346709403c1SSebastian Grimberg
347709403c1SSebastian Grimberg    with y.array_read() as y_array:
348709403c1SSebastian Grimberg        for i in range(num_elem):
349709403c1SSebastian Grimberg            for j in range(2):
350709403c1SSebastian Grimberg                k = j + 2 * i
351709403c1SSebastian Grimberg                if i % 2 > 0:
352709403c1SSebastian Grimberg                    assert j != 0 or 10 + i + 1 == -y_array[k]
353709403c1SSebastian Grimberg                    assert j != 1 or 10 + i == -y_array[k]
354709403c1SSebastian Grimberg                else:
355709403c1SSebastian Grimberg                    assert 10 + (k + 1) // 2 == y_array[k]
356709403c1SSebastian Grimberg
357709403c1SSebastian Grimberg# -------------------------------------------------------------------------------
358