Skip to content

Function 2D

Module: basis_function_2d.py

This module provides the abstract base class for all 2D finite element basis functions used in the FE2D code. It defines the interface for computing basis functions and their derivatives in reference coordinates.

Classes:

Name Description
BasisFunction2D

Abstract base class for 2D finite element basis functions

Dependencies
  • abc: For abstract base class functionality
Key Features
  • Abstract interface for 2D basis function evaluation
  • Support for first and second order derivatives
  • Reference coordinate system (xi, eta) implementation
  • Unified interface for different polynomial bases
  • Common structure for Legendre, Jacobi, and Chebyshev implementations
Authors

Thivin Anandh (http://thivinanandh.github.io/)

Version Info

27/Dec/2024: Initial version: Thivin Anandh D

References

None

Basis2DQNChebyshev2

Bases: BasisFunction2D

A specialized implementation of two-dimensional basis functions using Chebyshev polynomials for Q1 elements.

This class provides a complete implementation for computing basis functions and their derivatives in two dimensions, specifically designed for use in variational physics-informed neural networks (VPINNs) with domain decomposition. The basis functions are constructed using Chebyshev polynomials through Jacobi polynomial representations.

The class inherits from BasisFunction2D and implements all required methods for computing function values and derivatives. The implementation follows the methodology described in hp-VPINNs research by Ehsan Kharazmi et al.

Attributes:

Name Type Description
num_shape_functions int

Total number of shape functions in the 2D element. Must be a perfect square as it represents tensor product of 1D functions.

Methods:

Name Description
value

Computes values of all basis functions at given points

gradx

Computes x-derivatives of all basis functions

grady

Computes y-derivatives of all basis functions

gradxx

Computes second x-derivatives of all basis functions

gradyy

Computes second y-derivatives of all basis functions

gradxy

Computes mixed xy-derivatives of all basis functions

Implementation Details
  • Basis functions are constructed as tensor products of 1D test functions
  • Test functions are derived from normalized Jacobi polynomials
  • Special cases are handled for first few polynomial degrees in derivatives
  • All computations maintain double precision (float64)
  • Efficient vectorized operations using numpy arrays
Example
basis = Basis2DQNChebyshev2(num_shape_functions=16)  # Creates 4x4 basis functions
xi = np.linspace(-1, 1, 100)
eta = np.linspace(-1, 1, 100)
values = basis.value(xi, eta)
x_derivatives = basis.gradx(xi, eta)
Notes
  • num_shape_functions must be a perfect square
  • All coordinate inputs (xi, eta) should be in the range [-1, 1]
  • Implementation optimized for vectorized operations on multiple points
  • Based on hp-VPINNs methodology: https://github.com/ehsankharazmi/hp-VPINNs/
References

Kharazmi, E., et al. "hp-VPINNs: Variational Physics-Informed Neural Networks With Domain Decomposition"

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
class Basis2DQNChebyshev2(BasisFunction2D):
    """A specialized implementation of two-dimensional basis functions using Chebyshev polynomials for Q1 elements.

    This class provides a complete implementation for computing basis functions and their derivatives
    in two dimensions, specifically designed for use in variational physics-informed neural networks
    (VPINNs) with domain decomposition. The basis functions are constructed using Chebyshev polynomials
    through Jacobi polynomial representations.

    The class inherits from BasisFunction2D and implements all required methods for computing
    function values and derivatives. The implementation follows the methodology described in
    hp-VPINNs research by Ehsan Kharazmi et al.

    Attributes:
        num_shape_functions (int): Total number of shape functions in the 2D element.
            Must be a perfect square as it represents tensor product of 1D functions.

    Methods:
        value(xi, eta): Computes values of all basis functions at given points
        gradx(xi, eta): Computes x-derivatives of all basis functions
        grady(xi, eta): Computes y-derivatives of all basis functions
        gradxx(xi, eta): Computes second x-derivatives of all basis functions
        gradyy(xi, eta): Computes second y-derivatives of all basis functions
        gradxy(xi, eta): Computes mixed xy-derivatives of all basis functions

    Implementation Details:
        - Basis functions are constructed as tensor products of 1D test functions
        - Test functions are derived from normalized Jacobi polynomials
        - Special cases are handled for first few polynomial degrees in derivatives
        - All computations maintain double precision (float64)
        - Efficient vectorized operations using numpy arrays

    Example:
        ```python
        basis = Basis2DQNChebyshev2(num_shape_functions=16)  # Creates 4x4 basis functions
        xi = np.linspace(-1, 1, 100)
        eta = np.linspace(-1, 1, 100)
        values = basis.value(xi, eta)
        x_derivatives = basis.gradx(xi, eta)
        ```

    Notes:
        - num_shape_functions must be a perfect square
        - All coordinate inputs (xi, eta) should be in the range [-1, 1]
        - Implementation optimized for vectorized operations on multiple points
        - Based on hp-VPINNs methodology: https://github.com/ehsankharazmi/hp-VPINNs/

    References:
        Kharazmi, E., et al. "hp-VPINNs: Variational Physics-Informed Neural Networks
        With Domain Decomposition"
    """

    def __init__(self, num_shape_functions: int):
        super().__init__(num_shape_functions)

    def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
        """Evaluates Jacobi polynomial at specified points.

        Computes values of nth degree Jacobi polynomial with parameters (a,b)
        at given points x.

        Args:
            n: Degree of Jacobi polynomial. Must be non-negative integer.
            a: First parameter of Jacobi polynomial
            b: Second parameter of Jacobi polynomial
            x: Points at which to evaluate polynomial
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of Jacobi polynomial at input points
                Shape: Same as input x

        Notes:
            Wrapper around scipy.special.jacobi that ensures float64 precision
            and proper array handling.
        """
        x = np.array(x, dtype=np.float64)
        return jacobi(n, a, b)(x)

    ## Helper Function
    def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """Computes x-component test functions.

        Evaluates the x-direction test functions constructed as differences
        of normalized Jacobi polynomials.

        Args:
            n_test: Number of test functions to compute
            x: Points at which to evaluate functions
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of test functions at input points
                Shape: (n_test, n_points)

        Notes:
            Test functions are constructed as differences of normalized Jacobi
            polynomials following hp-VPINNs methodology.
        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, x) / self.jacobi_wrapper(
                n + 1, -1 / 2, -1 / 2, 1
            ) - self.jacobi_wrapper(n - 1, -1 / 2, -1 / 2, x) / self.jacobi_wrapper(
                n - 1, -1 / 2, -1 / 2, 1
            )
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
        """Computes y-component test functions.

        Evaluates the y-direction test functions constructed as differences
        of normalized Jacobi polynomials.

        Args:
            n_test: Number of test functions to compute
            y: Points at which to evaluate functions
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of test functions at input points
                Shape: (n_test, n_points)

        Notes:
            Test functions are constructed as differences of normalized Jacobi
            polynomials following hp-VPINNs methodology.
        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, y) / self.jacobi_wrapper(
                n + 1, -1 / 2, -1 / 2, 1
            ) - self.jacobi_wrapper(n - 1, -1 / 2, -1 / 2, y) / self.jacobi_wrapper(
                n - 1, -1 / 2, -1 / 2, 1
            )
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """Computes first and second derivatives of test functions.

        Calculates derivatives of test functions constructed from Jacobi
        polynomials, handling special cases for n=1,2 separately.

        Args:
            n_test: Number of test functions
            x: Points at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            tuple(np.ndarray, np.ndarray): First and second derivatives
                First element: First derivatives, shape (n_test, n_points)
                Second element: Second derivatives, shape (n_test, n_points)

        Notes:
            Special cases for n=1,2 ensure proper derivative calculations
            following hp-VPINNs methodology.
        """
        d1test_total = []
        d2test_total = []
        for n in range(1, n_test + 1):
            if n == 1:
                d1test = (
                    ((n + 1) / 2)
                    * self.jacobi_wrapper(n, 1 / 2, 1 / 2, x)
                    / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
                )
                d2test = (
                    ((n + 2) * (n + 1) / (2 * 2))
                    * self.jacobi_wrapper(n - 1, 3 / 2, 3 / 2, x)
                    / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
                )
                d1test_total.append(d1test)
                d2test_total.append(d2test)
            elif n == 2:
                d1test = ((n + 1) / 2) * self.jacobi_wrapper(
                    n, 1 / 2, 1 / 2, x
                ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                    (n - 1) / 2
                ) * self.jacobi_wrapper(
                    n - 2, 1 / 2, 1 / 2, x
                ) / self.jacobi_wrapper(
                    n - 1, -1 / 2, -1 / 2, 1
                )
                d2test = (
                    ((n + 2) * (n + 1) / (2 * 2))
                    * self.jacobi_wrapper(n - 1, 3 / 2, 3 / 2, x)
                    / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
                )
                d1test_total.append(d1test)
                d2test_total.append(d2test)
            else:
                d1test = ((n + 1) / 2) * self.jacobi_wrapper(
                    n, 1 / 2, 1 / 2, x
                ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                    (n - 1) / 2
                ) * self.jacobi_wrapper(
                    n - 2, 1 / 2, 1 / 2, x
                ) / self.jacobi_wrapper(
                    n - 1, -1 / 2, -1 / 2, 1
                )
                d2test = ((n + 2) * (n + 1) / (2 * 2)) * self.jacobi_wrapper(
                    n - 1, 3 / 2, 3 / 2, x
                ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                    (n) * (n - 1) / (2 * 2)
                ) * self.jacobi_wrapper(
                    n - 3, 3 / 2, 3 / 2, x
                ) / self.jacobi_wrapper(
                    n - 1, -1 / 2, -1 / 2, 1
                )
                d1test_total.append(d1test)
                d2test_total.append(d2test)
        return np.asarray(d1test_total), np.asarray(d2test_total)

    def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Evaluates basis functions at given coordinates.

        Computes values of all basis functions at specified (xi,eta) points
        using tensor product of 1D test functions.

        Args:
            xi: x-coordinates at which to evaluate functions
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate functions
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of all basis functions
                Shape: (num_shape_functions, n_points)

        Notes:
            Basis functions are constructed as products of 1D test functions
            in x and y directions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * test_y
            )

        return values

    def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Computes x-derivatives of basis functions.

        Evaluates partial derivatives with respect to x of all basis
        functions at given coordinates.

        Args:
            xi: x-coordinates at which to evaluate derivatives
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of x-derivatives
                Shape: (num_shape_functions, n_points)

        Notes:
            Uses product rule with x-derivatives of test functions in
            x-direction and values in y-direction.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * test_y
            )

        return values

    def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Computes y-derivatives of basis functions.

        Evaluates partial derivatives with respect to y of all basis
        functions at given coordinates.

        Args:
            xi: x-coordinates at which to evaluate derivatives
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of y-derivatives
                Shape: (num_shape_functions, n_points)

        Notes:
            Uses product rule with values in x-direction and y-derivatives
            of test functions in y-direction.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_test_y
            )

        return values

    def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Computes second x-derivatives of basis functions.

        Evaluates second partial derivatives with respect to x of all basis
        functions at given coordinates.

        Args:
            xi: x-coordinates at which to evaluate derivatives
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of second x-derivatives
                Shape: (num_shape_functions, n_points)

        Notes:
            Uses product rule with second x-derivatives of test functions in
            x-direction and values in y-direction.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_grad_x = self.dtest_fcn(num_shape_func_in_1d, xi)[1]
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_grad_x[i, :] * test_y
            )

        return values

    def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Computes second x-derivatives of basis functions.

        Evaluates second partial derivatives with respect to x of all basis
        functions at given coordinates.

        Args:
            xi: x-coordinates at which to evaluate derivatives
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of second x-derivatives
                Shape: (num_shape_functions, n_points)

        Notes:
            Uses product rule with second x-derivatives of test functions in
            x-direction and y derivative values in y-direction.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * grad_test_y
            )

        return values

    def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """Computes second x-derivatives of basis functions.

        Evaluates second partial derivatives with respect to x of all basis
        functions at given coordinates.

        Args:
            xi: x-coordinates at which to evaluate derivatives
                Shape: (n_points,)
            eta: y-coordinates at which to evaluate derivatives
                Shape: (n_points,)

        Returns:
            np.ndarray: Values of second x-derivatives
                Shape: (num_shape_functions, n_points)

        Notes:
            Uses product rule with second y-derivatives of test functions in
            x-direction and values in y-direction.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_grad_y = self.dtest_fcn(num_shape_func_in_1d, eta)[1]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_grad_y
            )

        return values

dtest_fcn(n_test, x)

Computes first and second derivatives of test functions.

Calculates derivatives of test functions constructed from Jacobi polynomials, handling special cases for n=1,2 separately.

Parameters:

Name Type Description Default
n_test int

Number of test functions

required
x ndarray

Points at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Name Type Description
tuple (ndarray, ndarray)

First and second derivatives First element: First derivatives, shape (n_test, n_points) Second element: Second derivatives, shape (n_test, n_points)

Notes

Special cases for n=1,2 ensure proper derivative calculations following hp-VPINNs methodology.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """Computes first and second derivatives of test functions.

    Calculates derivatives of test functions constructed from Jacobi
    polynomials, handling special cases for n=1,2 separately.

    Args:
        n_test: Number of test functions
        x: Points at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        tuple(np.ndarray, np.ndarray): First and second derivatives
            First element: First derivatives, shape (n_test, n_points)
            Second element: Second derivatives, shape (n_test, n_points)

    Notes:
        Special cases for n=1,2 ensure proper derivative calculations
        following hp-VPINNs methodology.
    """
    d1test_total = []
    d2test_total = []
    for n in range(1, n_test + 1):
        if n == 1:
            d1test = (
                ((n + 1) / 2)
                * self.jacobi_wrapper(n, 1 / 2, 1 / 2, x)
                / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
            )
            d2test = (
                ((n + 2) * (n + 1) / (2 * 2))
                * self.jacobi_wrapper(n - 1, 3 / 2, 3 / 2, x)
                / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
            )
            d1test_total.append(d1test)
            d2test_total.append(d2test)
        elif n == 2:
            d1test = ((n + 1) / 2) * self.jacobi_wrapper(
                n, 1 / 2, 1 / 2, x
            ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                (n - 1) / 2
            ) * self.jacobi_wrapper(
                n - 2, 1 / 2, 1 / 2, x
            ) / self.jacobi_wrapper(
                n - 1, -1 / 2, -1 / 2, 1
            )
            d2test = (
                ((n + 2) * (n + 1) / (2 * 2))
                * self.jacobi_wrapper(n - 1, 3 / 2, 3 / 2, x)
                / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1)
            )
            d1test_total.append(d1test)
            d2test_total.append(d2test)
        else:
            d1test = ((n + 1) / 2) * self.jacobi_wrapper(
                n, 1 / 2, 1 / 2, x
            ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                (n - 1) / 2
            ) * self.jacobi_wrapper(
                n - 2, 1 / 2, 1 / 2, x
            ) / self.jacobi_wrapper(
                n - 1, -1 / 2, -1 / 2, 1
            )
            d2test = ((n + 2) * (n + 1) / (2 * 2)) * self.jacobi_wrapper(
                n - 1, 3 / 2, 3 / 2, x
            ) / self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, 1) - (
                (n) * (n - 1) / (2 * 2)
            ) * self.jacobi_wrapper(
                n - 3, 3 / 2, 3 / 2, x
            ) / self.jacobi_wrapper(
                n - 1, -1 / 2, -1 / 2, 1
            )
            d1test_total.append(d1test)
            d2test_total.append(d2test)
    return np.asarray(d1test_total), np.asarray(d2test_total)

gradx(xi, eta)

Computes x-derivatives of basis functions.

Evaluates partial derivatives with respect to x of all basis functions at given coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate derivatives Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of x-derivatives Shape: (num_shape_functions, n_points)

Notes

Uses product rule with x-derivatives of test functions in x-direction and values in y-direction.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Computes x-derivatives of basis functions.

    Evaluates partial derivatives with respect to x of all basis
    functions at given coordinates.

    Args:
        xi: x-coordinates at which to evaluate derivatives
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of x-derivatives
            Shape: (num_shape_functions, n_points)

    Notes:
        Uses product rule with x-derivatives of test functions in
        x-direction and values in y-direction.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * test_y
        )

    return values

gradxx(xi, eta)

Computes second x-derivatives of basis functions.

Evaluates second partial derivatives with respect to x of all basis functions at given coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate derivatives Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of second x-derivatives Shape: (num_shape_functions, n_points)

Notes

Uses product rule with second x-derivatives of test functions in x-direction and values in y-direction.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Computes second x-derivatives of basis functions.

    Evaluates second partial derivatives with respect to x of all basis
    functions at given coordinates.

    Args:
        xi: x-coordinates at which to evaluate derivatives
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of second x-derivatives
            Shape: (num_shape_functions, n_points)

    Notes:
        Uses product rule with second x-derivatives of test functions in
        x-direction and values in y-direction.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_grad_x = self.dtest_fcn(num_shape_func_in_1d, xi)[1]
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_grad_x[i, :] * test_y
        )

    return values

gradxy(xi, eta)

Computes second x-derivatives of basis functions.

Evaluates second partial derivatives with respect to x of all basis functions at given coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate derivatives Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of second x-derivatives Shape: (num_shape_functions, n_points)

Notes

Uses product rule with second x-derivatives of test functions in x-direction and y derivative values in y-direction.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Computes second x-derivatives of basis functions.

    Evaluates second partial derivatives with respect to x of all basis
    functions at given coordinates.

    Args:
        xi: x-coordinates at which to evaluate derivatives
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of second x-derivatives
            Shape: (num_shape_functions, n_points)

    Notes:
        Uses product rule with second x-derivatives of test functions in
        x-direction and y derivative values in y-direction.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * grad_test_y
        )

    return values

grady(xi, eta)

Computes y-derivatives of basis functions.

Evaluates partial derivatives with respect to y of all basis functions at given coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate derivatives Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of y-derivatives Shape: (num_shape_functions, n_points)

Notes

Uses product rule with values in x-direction and y-derivatives of test functions in y-direction.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Computes y-derivatives of basis functions.

    Evaluates partial derivatives with respect to y of all basis
    functions at given coordinates.

    Args:
        xi: x-coordinates at which to evaluate derivatives
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of y-derivatives
            Shape: (num_shape_functions, n_points)

    Notes:
        Uses product rule with values in x-direction and y-derivatives
        of test functions in y-direction.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_test_y
        )

    return values

gradyy(xi, eta)

Computes second x-derivatives of basis functions.

Evaluates second partial derivatives with respect to x of all basis functions at given coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate derivatives Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate derivatives Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of second x-derivatives Shape: (num_shape_functions, n_points)

Notes

Uses product rule with second y-derivatives of test functions in x-direction and values in y-direction.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Computes second x-derivatives of basis functions.

    Evaluates second partial derivatives with respect to x of all basis
    functions at given coordinates.

    Args:
        xi: x-coordinates at which to evaluate derivatives
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate derivatives
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of second x-derivatives
            Shape: (num_shape_functions, n_points)

    Notes:
        Uses product rule with second y-derivatives of test functions in
        x-direction and values in y-direction.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_grad_y = self.dtest_fcn(num_shape_func_in_1d, eta)[1]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_grad_y
        )

    return values

jacobi_wrapper(n, a, b, x)

Evaluates Jacobi polynomial at specified points.

Computes values of nth degree Jacobi polynomial with parameters (a,b) at given points x.

Parameters:

Name Type Description Default
n int

Degree of Jacobi polynomial. Must be non-negative integer.

required
a int

First parameter of Jacobi polynomial

required
b int

Second parameter of Jacobi polynomial

required
x ndarray

Points at which to evaluate polynomial Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of Jacobi polynomial at input points Shape: Same as input x

Notes

Wrapper around scipy.special.jacobi that ensures float64 precision and proper array handling.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
    """Evaluates Jacobi polynomial at specified points.

    Computes values of nth degree Jacobi polynomial with parameters (a,b)
    at given points x.

    Args:
        n: Degree of Jacobi polynomial. Must be non-negative integer.
        a: First parameter of Jacobi polynomial
        b: Second parameter of Jacobi polynomial
        x: Points at which to evaluate polynomial
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of Jacobi polynomial at input points
            Shape: Same as input x

    Notes:
        Wrapper around scipy.special.jacobi that ensures float64 precision
        and proper array handling.
    """
    x = np.array(x, dtype=np.float64)
    return jacobi(n, a, b)(x)

test_fcnx(n_test, x)

Computes x-component test functions.

Evaluates the x-direction test functions constructed as differences of normalized Jacobi polynomials.

Parameters:

Name Type Description Default
n_test int

Number of test functions to compute

required
x ndarray

Points at which to evaluate functions Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of test functions at input points Shape: (n_test, n_points)

Notes

Test functions are constructed as differences of normalized Jacobi polynomials following hp-VPINNs methodology.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """Computes x-component test functions.

    Evaluates the x-direction test functions constructed as differences
    of normalized Jacobi polynomials.

    Args:
        n_test: Number of test functions to compute
        x: Points at which to evaluate functions
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of test functions at input points
            Shape: (n_test, n_points)

    Notes:
        Test functions are constructed as differences of normalized Jacobi
        polynomials following hp-VPINNs methodology.
    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, x) / self.jacobi_wrapper(
            n + 1, -1 / 2, -1 / 2, 1
        ) - self.jacobi_wrapper(n - 1, -1 / 2, -1 / 2, x) / self.jacobi_wrapper(
            n - 1, -1 / 2, -1 / 2, 1
        )
        test_total.append(test)
    return np.asarray(test_total, np.float64)

test_fcny(n_test, y)

Computes y-component test functions.

Evaluates the y-direction test functions constructed as differences of normalized Jacobi polynomials.

Parameters:

Name Type Description Default
n_test int

Number of test functions to compute

required
y ndarray

Points at which to evaluate functions Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of test functions at input points Shape: (n_test, n_points)

Notes

Test functions are constructed as differences of normalized Jacobi polynomials following hp-VPINNs methodology.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
    """Computes y-component test functions.

    Evaluates the y-direction test functions constructed as differences
    of normalized Jacobi polynomials.

    Args:
        n_test: Number of test functions to compute
        y: Points at which to evaluate functions
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of test functions at input points
            Shape: (n_test, n_points)

    Notes:
        Test functions are constructed as differences of normalized Jacobi
        polynomials following hp-VPINNs methodology.
    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n + 1, -1 / 2, -1 / 2, y) / self.jacobi_wrapper(
            n + 1, -1 / 2, -1 / 2, 1
        ) - self.jacobi_wrapper(n - 1, -1 / 2, -1 / 2, y) / self.jacobi_wrapper(
            n - 1, -1 / 2, -1 / 2, 1
        )
        test_total.append(test)
    return np.asarray(test_total, np.float64)

value(xi, eta)

Evaluates basis functions at given coordinates.

Computes values of all basis functions at specified (xi,eta) points using tensor product of 1D test functions.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate functions Shape: (n_points,)

required
eta ndarray

y-coordinates at which to evaluate functions Shape: (n_points,)

required

Returns:

Type Description
ndarray

np.ndarray: Values of all basis functions Shape: (num_shape_functions, n_points)

Notes

Basis functions are constructed as products of 1D test functions in x and y directions.

Source code in scirex/core/sciml/fe/basis_2d_qn_chebyshev_2.py
def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """Evaluates basis functions at given coordinates.

    Computes values of all basis functions at specified (xi,eta) points
    using tensor product of 1D test functions.

    Args:
        xi: x-coordinates at which to evaluate functions
            Shape: (n_points,)
        eta: y-coordinates at which to evaluate functions
            Shape: (n_points,)

    Returns:
        np.ndarray: Values of all basis functions
            Shape: (num_shape_functions, n_points)

    Notes:
        Basis functions are constructed as products of 1D test functions
        in x and y directions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * test_y
        )

    return values

Basis2DQNJacobi

Bases: BasisFunction2D

A specialized implementation of two-dimensional basis functions using Jacobi polynomials for QN elements.

This class provides a complete implementation for computing basis functions and their derivatives in two dimensions, specifically designed for use in variational physics-informed neural networks (VPINNs) with domain decomposition. The basis functions are constructed using Jacobi polynomials with efficient derivative computations.

The class inherits from BasisFunction2D and implements all required methods for computing function values and first/second order derivatives. The implementation follows the methodology described in hp-VPINNs research.

Attributes:

Name Type Description
num_shape_functions int

Total number of shape functions in the 2D element. Must be a perfect square as it represents tensor product of 1D functions.

Methods:

Name Description
jacobi_wrapper

Evaluates Jacobi polynomial at given points

djacobi

Computes kth derivative of Jacobi polynomial

test_fcnx

Computes x-component test functions

test_fcny

Computes y-component test functions

dtest_fcn

Computes first derivatives of test functions

ddtest_fcn

Computes second derivatives of test functions

value

Computes values of all basis functions

gradx

Computes x-derivatives of all basis functions

grady

Computes y-derivatives of all basis functions

gradxx

Computes second x-derivatives of all basis functions

gradyy

Computes second y-derivatives of all basis functions

gradxy

Computes mixed xy-derivatives of all basis functions

Implementation Details
  • Basis functions are constructed as tensor products of 1D test functions
  • Test functions are derived from Jacobi polynomials with parameters (0,0)
  • All computations maintain double precision (float64)
  • Efficient vectorized operations using numpy arrays
Example
basis = Basis2DQNJacobi(num_shape_functions=16)  # Creates 4x4 basis functions
xi = np.linspace(-1, 1, 100)
eta = np.linspace(-1, 1, 100)
values = basis.value(xi, eta)
x_derivatives = basis.gradx(xi, eta)
Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
class Basis2DQNJacobi(BasisFunction2D):
    """
    A specialized implementation of two-dimensional basis functions using Jacobi polynomials for QN elements.

    This class provides a complete implementation for computing basis functions and their derivatives
    in two dimensions, specifically designed for use in variational physics-informed neural networks
    (VPINNs) with domain decomposition. The basis functions are constructed using Jacobi polynomials
    with efficient derivative computations.

    The class inherits from BasisFunction2D and implements all required methods for computing
    function values and first/second order derivatives. The implementation follows the methodology
    described in hp-VPINNs research.

    Attributes:
        num_shape_functions (int): Total number of shape functions in the 2D element.
            Must be a perfect square as it represents tensor product of 1D functions.

    Methods:
        jacobi_wrapper(n, a, b, x): Evaluates Jacobi polynomial at given points
        djacobi(n, a, b, x, k): Computes kth derivative of Jacobi polynomial
        test_fcnx(n_test, x): Computes x-component test functions
        test_fcny(n_test, y): Computes y-component test functions
        dtest_fcn(n_test, x): Computes first derivatives of test functions
        ddtest_fcn(n_test, x): Computes second derivatives of test functions
        value(xi, eta): Computes values of all basis functions
        gradx(xi, eta): Computes x-derivatives of all basis functions
        grady(xi, eta): Computes y-derivatives of all basis functions
        gradxx(xi, eta): Computes second x-derivatives of all basis functions
        gradyy(xi, eta): Computes second y-derivatives of all basis functions
        gradxy(xi, eta): Computes mixed xy-derivatives of all basis functions

    Implementation Details:
        - Basis functions are constructed as tensor products of 1D test functions
        - Test functions are derived from Jacobi polynomials with parameters (0,0)
        - All computations maintain double precision (float64)
        - Efficient vectorized operations using numpy arrays

    Example:
        ```python
        basis = Basis2DQNJacobi(num_shape_functions=16)  # Creates 4x4 basis functions
        xi = np.linspace(-1, 1, 100)
        eta = np.linspace(-1, 1, 100)
        values = basis.value(xi, eta)
        x_derivatives = basis.gradx(xi, eta)
        ```
    """

    def __init__(self, num_shape_functions: int):
        super().__init__(num_shape_functions)

    def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
        """
        Evaluate the Jacobi polynomial of degree `n` with parameters `a` and `b` at the given points `x`.

        Args:
            n (int): Degree of the Jacobi polynomial.
            a (float): First parameter of the Jacobi polynomial.
            b (float): Second parameter of the Jacobi polynomial.
            x (np.ndarray): Points at which to evaluate the Jacobi polynomial.

        Returns:
            np.ndarray: Values of the Jacobi polynomial at the given points `x`.
        """

        x = np.array(x, dtype=np.float64)
        return jacobi(n, a, b)(x)

    # Derivative of the Jacobi polynomials
    def djacobi(self, n: int, a: int, b: int, x: np.ndarray, k: int) -> np.ndarray:
        """
        Evaluate the k-th derivative of the Jacobi polynomial of degree n with parameters a and b at the given points x.

        Args:
            n (int): Degree of the Jacobi polynomial.
            a (float): First parameter of the Jacobi polynomial.
            b (float): Second parameter of the Jacobi polynomial.
            x (np.ndarray): Points at which to evaluate the Jacobi polynomial.
            k (int): Order of the derivative.

        Returns:
            np.ndarray: Values of the k-th derivative of the Jacobi polynomial at the given points x.

        Raises:
            ValueError: If the derivative order is not 1 or 2
        """
        x = np.array(x, dtype=np.float64)
        if k == 1:
            return jacobi(n, a, b).deriv()(x)
        if k == 2:
            return jacobi(n, a, b).deriv(2)(x)
        else:
            print(f"Invalid derivative order {k} in {__name__}.")
            raise ValueError("Derivative order should be 1 or 2.")

    ## Helper Function
    def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Compute the x-component of the test functions for a given number of test functions and x-coordinates.

        Args:
            n_test (int): Number of test functions.
            x (np.ndarray): x-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the x-component of the test functions.

        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n - 1, 0, 0, x)
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
        """
        Compute the y-component of the test functions for a given number of test functions and y-coordinates.

        Args:
            n_test (int): Number of test functions.
            y (np.ndarray): y-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the y-component of the test functions.

        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n - 1, 0, 0, y)
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

        Args:
            n_test (int): Number of test functions.
            x (np.ndarray): x-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the x-derivatives of the test functions.
        """
        d1test_total = []
        for n in range(1, n_test + 1):
            d1test = self.djacobi(n - 1, 0, 0, x, 1)
            d1test_total.append(d1test)
        return np.asarray(d1test_total)

    def ddtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

        Args:
            n_test (int): Number of test functions.
            x (np.ndarray): x-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the x-derivatives of the test functions.
        """
        d1test_total = []
        for n in range(1, n_test + 1):
            d1test = self.djacobi(n - 1, 0, 0, x, 2)
            d1test_total.append(d1test)
        return np.asarray(d1test_total)

    def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the values of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * test_y
            )

        return values

    def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the x-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * test_y
            )

        return values

    def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the y-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_test_y
            )

        return values

    def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the xx-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_grad_x = self.ddtest_fcn(num_shape_func_in_1d, xi)
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_grad_x[i, :] * test_y
            )

        return values

    def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the xy-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * grad_test_y
            )

        return values

    def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the yy-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_grad_y = self.ddtest_fcn(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_grad_y
            )

        return values

ddtest_fcn(n_test, x)

Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
x ndarray

x-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-derivatives of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def ddtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

    Args:
        n_test (int): Number of test functions.
        x (np.ndarray): x-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the x-derivatives of the test functions.
    """
    d1test_total = []
    for n in range(1, n_test + 1):
        d1test = self.djacobi(n - 1, 0, 0, x, 2)
        d1test_total.append(d1test)
    return np.asarray(d1test_total)

djacobi(n, a, b, x, k)

Evaluate the k-th derivative of the Jacobi polynomial of degree n with parameters a and b at the given points x.

Parameters:

Name Type Description Default
n int

Degree of the Jacobi polynomial.

required
a float

First parameter of the Jacobi polynomial.

required
b float

Second parameter of the Jacobi polynomial.

required
x ndarray

Points at which to evaluate the Jacobi polynomial.

required
k int

Order of the derivative.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the k-th derivative of the Jacobi polynomial at the given points x.

Raises:

Type Description
ValueError

If the derivative order is not 1 or 2

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def djacobi(self, n: int, a: int, b: int, x: np.ndarray, k: int) -> np.ndarray:
    """
    Evaluate the k-th derivative of the Jacobi polynomial of degree n with parameters a and b at the given points x.

    Args:
        n (int): Degree of the Jacobi polynomial.
        a (float): First parameter of the Jacobi polynomial.
        b (float): Second parameter of the Jacobi polynomial.
        x (np.ndarray): Points at which to evaluate the Jacobi polynomial.
        k (int): Order of the derivative.

    Returns:
        np.ndarray: Values of the k-th derivative of the Jacobi polynomial at the given points x.

    Raises:
        ValueError: If the derivative order is not 1 or 2
    """
    x = np.array(x, dtype=np.float64)
    if k == 1:
        return jacobi(n, a, b).deriv()(x)
    if k == 2:
        return jacobi(n, a, b).deriv(2)(x)
    else:
        print(f"Invalid derivative order {k} in {__name__}.")
        raise ValueError("Derivative order should be 1 or 2.")

dtest_fcn(n_test, x)

Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
x ndarray

x-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-derivatives of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

    Args:
        n_test (int): Number of test functions.
        x (np.ndarray): x-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the x-derivatives of the test functions.
    """
    d1test_total = []
    for n in range(1, n_test + 1):
        d1test = self.djacobi(n - 1, 0, 0, x, 1)
        d1test_total.append(d1test)
    return np.asarray(d1test_total)

gradx(xi, eta)

This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the x-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * test_y
        )

    return values

gradxx(xi, eta)

This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the xx-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the xx-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_grad_x = self.ddtest_fcn(num_shape_func_in_1d, xi)
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_grad_x[i, :] * test_y
        )

    return values

gradxy(xi, eta)

This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the xy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the xy-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * grad_test_y
        )

    return values

grady(xi, eta)

This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the y-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the y-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_test_y
        )

    return values

gradyy(xi, eta)

This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the yy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the yy-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_grad_y = self.ddtest_fcn(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_grad_y
        )

    return values

jacobi_wrapper(n, a, b, x)

Evaluate the Jacobi polynomial of degree n with parameters a and b at the given points x.

Parameters:

Name Type Description Default
n int

Degree of the Jacobi polynomial.

required
a float

First parameter of the Jacobi polynomial.

required
b float

Second parameter of the Jacobi polynomial.

required
x ndarray

Points at which to evaluate the Jacobi polynomial.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the Jacobi polynomial at the given points x.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
    """
    Evaluate the Jacobi polynomial of degree `n` with parameters `a` and `b` at the given points `x`.

    Args:
        n (int): Degree of the Jacobi polynomial.
        a (float): First parameter of the Jacobi polynomial.
        b (float): Second parameter of the Jacobi polynomial.
        x (np.ndarray): Points at which to evaluate the Jacobi polynomial.

    Returns:
        np.ndarray: Values of the Jacobi polynomial at the given points `x`.
    """

    x = np.array(x, dtype=np.float64)
    return jacobi(n, a, b)(x)

test_fcnx(n_test, x)

Compute the x-component of the test functions for a given number of test functions and x-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
x ndarray

x-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-component of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Compute the x-component of the test functions for a given number of test functions and x-coordinates.

    Args:
        n_test (int): Number of test functions.
        x (np.ndarray): x-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the x-component of the test functions.

    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n - 1, 0, 0, x)
        test_total.append(test)
    return np.asarray(test_total, np.float64)

test_fcny(n_test, y)

Compute the y-component of the test functions for a given number of test functions and y-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
y ndarray

y-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the y-component of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
    """
    Compute the y-component of the test functions for a given number of test functions and y-coordinates.

    Args:
        n_test (int): Number of test functions.
        y (np.ndarray): y-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the y-component of the test functions.

    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n - 1, 0, 0, y)
        test_total.append(test)
    return np.asarray(test_total, np.float64)

value(xi, eta)

This method returns the values of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_jacobi.py
def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the values of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * test_y
        )

    return values

Basis2DQNLegendre

Bases: BasisFunction2D

A specialized implementation of two-dimensional basis functions using Legendre polynomials for Q1 elements.

This class provides a complete implementation for computing basis functions and their derivatives in two dimensions, specifically designed for use in variational physics-informed neural networks (VPINNs) with domain decomposition. The basis functions are constructed using Legendre polynomials implemented through Jacobi polynomial representations with parameters (0,0).

The class inherits from BasisFunction2D and implements all required methods for computing function values and derivatives up to second order.

Attributes:

Name Type Description
num_shape_functions int

Total number of shape functions in the 2D element. Must be a perfect square as it represents tensor product of 1D functions.

Methods:

Name Description
jacobi_wrapper

Evaluates Jacobi polynomial at given points

test_fcnx

Computes x-component test functions

test_fcny

Computes y-component test functions

dtest_fcn

Computes first and second derivatives of test functions

value

Computes values of all basis functions

gradx

Computes x-derivatives of all basis functions

grady

Computes y-derivatives of all basis functions

gradxx

Computes second x-derivatives of all basis functions

gradyy

Computes second y-derivatives of all basis functions

gradxy

Computes mixed xy-derivatives of all basis functions

Implementation Details
  • Basis functions are constructed as tensor products of 1D test functions
  • Test functions use Legendre polynomials via Jacobi polynomials with (0,0) parameters
  • Special cases handled for n=1,2 in derivative calculations
  • All computations maintain double precision (float64)
  • Efficient vectorized operations using numpy arrays
Example
basis = Basis2DQNLegendre(num_shape_functions=16)  # Creates 4x4 basis functions
xi = np.linspace(-1, 1, 100)
eta = np.linspace(-1, 1, 100)
values = basis.value(xi, eta)
x_derivatives = basis.gradx(xi, eta)
Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
class Basis2DQNLegendre(BasisFunction2D):
    """
    A specialized implementation of two-dimensional basis functions using Legendre polynomials for Q1 elements.

    This class provides a complete implementation for computing basis functions and their derivatives
    in two dimensions, specifically designed for use in variational physics-informed neural networks
    (VPINNs) with domain decomposition. The basis functions are constructed using Legendre polynomials
    implemented through Jacobi polynomial representations with parameters (0,0).

    The class inherits from BasisFunction2D and implements all required methods for computing
    function values and derivatives up to second order.

    Attributes:
        num_shape_functions (int): Total number of shape functions in the 2D element.
            Must be a perfect square as it represents tensor product of 1D functions.

    Methods:
        jacobi_wrapper(n, a, b, x): Evaluates Jacobi polynomial at given points
        test_fcnx(n_test, x): Computes x-component test functions
        test_fcny(n_test, y): Computes y-component test functions
        dtest_fcn(n_test, x): Computes first and second derivatives of test functions
        value(xi, eta): Computes values of all basis functions
        gradx(xi, eta): Computes x-derivatives of all basis functions
        grady(xi, eta): Computes y-derivatives of all basis functions
        gradxx(xi, eta): Computes second x-derivatives of all basis functions
        gradyy(xi, eta): Computes second y-derivatives of all basis functions
        gradxy(xi, eta): Computes mixed xy-derivatives of all basis functions

    Implementation Details:
        - Basis functions are constructed as tensor products of 1D test functions
        - Test functions use Legendre polynomials via Jacobi polynomials with (0,0) parameters
        - Special cases handled for n=1,2 in derivative calculations
        - All computations maintain double precision (float64)
        - Efficient vectorized operations using numpy arrays

    Example:
        ```python
        basis = Basis2DQNLegendre(num_shape_functions=16)  # Creates 4x4 basis functions
        xi = np.linspace(-1, 1, 100)
        eta = np.linspace(-1, 1, 100)
        values = basis.value(xi, eta)
        x_derivatives = basis.gradx(xi, eta)
        ```
    """

    def __init__(self, num_shape_functions: int):
        super().__init__(num_shape_functions)

    def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
        """
        Evaluate the Jacobi polynomial of degree n with parameters a and b at the given points x.

        Args:
            n (int): Degree of the Jacobi polynomial.
            a (int): First parameter of the Jacobi polynomial.
            b (int): Second parameter of the Jacobi polynomial.
            x (np.ndarray): Points at which to evaluate the Jacobi polynomial.

        Returns:
            np.ndarray: Values of the Jacobi polynomial at the given points.
        """
        x = np.array(x, dtype=np.float64)
        return jacobi(n, a, b)(x)

    ## Helper Function
    def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Compute the x-component of the test functions for a given number of test functions and x-coordinates.

        Args:
            n_test (int): Number of test functions.
            x (np.ndarray): x-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the x-component of the test functions.
        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n + 1, 0, 0, x) - self.jacobi_wrapper(
                n - 1, 0, 0, x
            )
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
        """
        Compute the y-component of the test functions for a given number of test functions and y-coordinates.

        Args:
            n_test (int): Number of test functions.
            y (np.ndarray): y-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the y-component of the test functions.
        """
        test_total = []
        for n in range(1, n_test + 1):
            test = self.jacobi_wrapper(n + 1, 0, 0, y) - self.jacobi_wrapper(
                n - 1, 0, 0, y
            )
            test_total.append(test)
        return np.asarray(test_total, np.float64)

    def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

        Args:
            n_test (int): Number of test functions.
            x (np.ndarray): x-coordinates at which to evaluate the test functions.

        Returns:
            np.ndarray: Values of the x-derivatives of the test functions.
        """
        d1test_total = []
        d2test_total = []
        for n in range(1, n_test + 1):
            if n == 1:
                d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x)
                d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                    n - 1, 2, 2, x
                )
                d1test_total.append(d1test)
                d2test_total.append(d2test)
            elif n == 2:
                d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x) - (
                    (n) / 2
                ) * self.jacobi_wrapper(n - 2, 1, 1, x)
                d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                    n - 1, 2, 2, x
                )
                d1test_total.append(d1test)
                d2test_total.append(d2test)
            else:
                d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x) - (
                    (n) / 2
                ) * self.jacobi_wrapper(n - 2, 1, 1, x)
                d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                    n - 1, 2, 2, x
                ) - ((n) * (n + 1) / (2 * 2)) * self.jacobi_wrapper(n - 3, 2, 2, x)
                d1test_total.append(d1test)
                d2test_total.append(d2test)
        return np.asarray(d1test_total), np.asarray(d2test_total)

    def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the values of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * test_y
            )

        return values

    def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the x-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * test_y
            )

        return values

    def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the y-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_test_y
            )

        return values

    def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the xx-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_grad_x = self.dtest_fcn(num_shape_func_in_1d, xi)[1]
        test_y = self.test_fcny(num_shape_func_in_1d, eta)
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_grad_x[i, :] * test_y
            )

        return values

    def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the xy-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
        grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                grad_test_x[i, :] * grad_test_y
            )

        return values

    def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
            eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

        Returns:
            np.ndarray: Values of the yy-derivatives of the basis functions.
        """
        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
        test_x = self.test_fcnx(num_shape_func_in_1d, xi)
        grad_grad_y = self.dtest_fcn(num_shape_func_in_1d, eta)[1]
        values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

        for i in range(num_shape_func_in_1d):
            values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
                test_x[i, :] * grad_grad_y
            )

        return values

dtest_fcn(n_test, x)

Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
x ndarray

x-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-derivatives of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def dtest_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Compute the x-derivatives of the test functions for a given number of test functions and x-coordinates.

    Args:
        n_test (int): Number of test functions.
        x (np.ndarray): x-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the x-derivatives of the test functions.
    """
    d1test_total = []
    d2test_total = []
    for n in range(1, n_test + 1):
        if n == 1:
            d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x)
            d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                n - 1, 2, 2, x
            )
            d1test_total.append(d1test)
            d2test_total.append(d2test)
        elif n == 2:
            d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x) - (
                (n) / 2
            ) * self.jacobi_wrapper(n - 2, 1, 1, x)
            d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                n - 1, 2, 2, x
            )
            d1test_total.append(d1test)
            d2test_total.append(d2test)
        else:
            d1test = ((n + 2) / 2) * self.jacobi_wrapper(n, 1, 1, x) - (
                (n) / 2
            ) * self.jacobi_wrapper(n - 2, 1, 1, x)
            d2test = ((n + 2) * (n + 3) / (2 * 2)) * self.jacobi_wrapper(
                n - 1, 2, 2, x
            ) - ((n) * (n + 1) / (2 * 2)) * self.jacobi_wrapper(n - 3, 2, 2, x)
            d1test_total.append(d1test)
            d2test_total.append(d2test)
    return np.asarray(d1test_total), np.asarray(d2test_total)

gradx(xi, eta)

This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the x-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * test_y
        )

    return values

gradxx(xi, eta)

This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the xx-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the xx-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_grad_x = self.dtest_fcn(num_shape_func_in_1d, xi)[1]
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_grad_x[i, :] * test_y
        )

    return values

gradxy(xi, eta)

This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the xy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the xy-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    grad_test_x = self.dtest_fcn(num_shape_func_in_1d, xi)[0]
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            grad_test_x[i, :] * grad_test_y
        )

    return values

grady(xi, eta)

This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the y-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the y-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_test_y = self.dtest_fcn(num_shape_func_in_1d, eta)[0]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_test_y
        )

    return values

gradyy(xi, eta)

This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the yy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the yy-derivatives of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    grad_grad_y = self.dtest_fcn(num_shape_func_in_1d, eta)[1]
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * grad_grad_y
        )

    return values

jacobi_wrapper(n, a, b, x)

Evaluate the Jacobi polynomial of degree n with parameters a and b at the given points x.

Parameters:

Name Type Description Default
n int

Degree of the Jacobi polynomial.

required
a int

First parameter of the Jacobi polynomial.

required
b int

Second parameter of the Jacobi polynomial.

required
x ndarray

Points at which to evaluate the Jacobi polynomial.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the Jacobi polynomial at the given points.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def jacobi_wrapper(self, n: int, a: int, b: int, x: np.ndarray) -> np.ndarray:
    """
    Evaluate the Jacobi polynomial of degree n with parameters a and b at the given points x.

    Args:
        n (int): Degree of the Jacobi polynomial.
        a (int): First parameter of the Jacobi polynomial.
        b (int): Second parameter of the Jacobi polynomial.
        x (np.ndarray): Points at which to evaluate the Jacobi polynomial.

    Returns:
        np.ndarray: Values of the Jacobi polynomial at the given points.
    """
    x = np.array(x, dtype=np.float64)
    return jacobi(n, a, b)(x)

test_fcnx(n_test, x)

Compute the x-component of the test functions for a given number of test functions and x-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
x ndarray

x-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the x-component of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def test_fcnx(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Compute the x-component of the test functions for a given number of test functions and x-coordinates.

    Args:
        n_test (int): Number of test functions.
        x (np.ndarray): x-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the x-component of the test functions.
    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n + 1, 0, 0, x) - self.jacobi_wrapper(
            n - 1, 0, 0, x
        )
        test_total.append(test)
    return np.asarray(test_total, np.float64)

test_fcny(n_test, y)

Compute the y-component of the test functions for a given number of test functions and y-coordinates.

Parameters:

Name Type Description Default
n_test int

Number of test functions.

required
y ndarray

y-coordinates at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the y-component of the test functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def test_fcny(self, n_test: int, y: np.ndarray) -> np.ndarray:
    """
    Compute the y-component of the test functions for a given number of test functions and y-coordinates.

    Args:
        n_test (int): Number of test functions.
        y (np.ndarray): y-coordinates at which to evaluate the test functions.

    Returns:
        np.ndarray: Values of the y-component of the test functions.
    """
    test_total = []
    for n in range(1, n_test + 1):
        test = self.jacobi_wrapper(n + 1, 0, 0, y) - self.jacobi_wrapper(
            n - 1, 0, 0, y
        )
        test_total.append(test)
    return np.asarray(test_total, np.float64)

value(xi, eta)

This method returns the values of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

x-coordinates at which to evaluate the basis functions.

required
eta ndarray

y-coordinates at which to evaluate the basis functions.

required

Returns:

Type Description
ndarray

np.ndarray: Values of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre.py
def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the values of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): x-coordinates at which to evaluate the basis functions.
        eta (np.ndarray): y-coordinates at which to evaluate the basis functions.

    Returns:
        np.ndarray: Values of the basis functions.
    """
    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))
    test_x = self.test_fcnx(num_shape_func_in_1d, xi)
    test_y = self.test_fcny(num_shape_func_in_1d, eta)
    values = np.zeros((self.num_shape_functions, len(xi)), dtype=np.float64)

    for i in range(num_shape_func_in_1d):
        values[num_shape_func_in_1d * i : num_shape_func_in_1d * (i + 1), :] = (
            test_x[i, :] * test_y
        )

    return values

Basis2DQNLegendreSpecial

Bases: BasisFunction2D

A specialized implementation of two-dimensional basis functions using Legendre polynomials for Q1 elements.

This class provides a complete implementation for computing basis functions and their derivatives in two dimensions. The basis functions are constructed using a special formulation based on differences of consecutive Legendre polynomials.

The class inherits from BasisFunction2D and implements all required methods for computing function values and derivatives up to second order.

Attributes:

Name Type Description
num_shape_functions int

Total number of shape functions in the 2D element. Must be a perfect square as it represents tensor product of 1D functions.

Methods:

Name Description
test_fcn

Computes test functions using Legendre polynomial differences

test_grad_fcn

Computes first derivatives of test functions

test_grad_grad_fcn

Computes second derivatives of test functions

value

Computes values of all basis functions

gradx

Computes x-derivatives of all basis functions

grady

Computes y-derivatives of all basis functions

gradxx

Computes second x-derivatives of all basis functions

gradyy

Computes second y-derivatives of all basis functions

gradxy

Computes mixed xy-derivatives of all basis functions

Implementation Details
  • Basis functions are constructed using differences of consecutive Legendre polynomials
  • Test functions are created using Pn+1(x) - Pn-1(x) where Pn is the nth Legendre polynomial
  • All computations maintain numerical precision using numpy arrays
  • Efficient vectorized operations for multiple point evaluations
  • Tensor product construction for 2D basis functions
Example
basis = Basis2DQNLegendreSpecial(num_shape_functions=16)  # Creates 4x4 basis functions
xi = np.linspace(-1, 1, 100)
eta = np.linspace(-1, 1, 100)
values = basis.value(xi, eta)
x_derivatives = basis.gradx(xi, eta)
Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
class Basis2DQNLegendreSpecial(BasisFunction2D):
    """
    A specialized implementation of two-dimensional basis functions using Legendre polynomials for Q1 elements.

    This class provides a complete implementation for computing basis functions and their derivatives
    in two dimensions. The basis functions are constructed using a special formulation based on
    differences of consecutive Legendre polynomials.

    The class inherits from BasisFunction2D and implements all required methods for computing
    function values and derivatives up to second order.

    Attributes:
        num_shape_functions (int): Total number of shape functions in the 2D element.
            Must be a perfect square as it represents tensor product of 1D functions.

    Methods:
        test_fcn(n_test, x): Computes test functions using Legendre polynomial differences
        test_grad_fcn(n_test, x): Computes first derivatives of test functions
        test_grad_grad_fcn(n_test, x): Computes second derivatives of test functions
        value(xi, eta): Computes values of all basis functions
        gradx(xi, eta): Computes x-derivatives of all basis functions
        grady(xi, eta): Computes y-derivatives of all basis functions
        gradxx(xi, eta): Computes second x-derivatives of all basis functions
        gradyy(xi, eta): Computes second y-derivatives of all basis functions
        gradxy(xi, eta): Computes mixed xy-derivatives of all basis functions

    Implementation Details:
        - Basis functions are constructed using differences of consecutive Legendre polynomials
        - Test functions are created using Pn+1(x) - Pn-1(x) where Pn is the nth Legendre polynomial
        - All computations maintain numerical precision using numpy arrays
        - Efficient vectorized operations for multiple point evaluations
        - Tensor product construction for 2D basis functions

    Example:
        ```python
        basis = Basis2DQNLegendreSpecial(num_shape_functions=16)  # Creates 4x4 basis functions
        xi = np.linspace(-1, 1, 100)
        eta = np.linspace(-1, 1, 100)
        values = basis.value(xi, eta)
        x_derivatives = basis.gradx(xi, eta)
        ```
    """

    def __init__(self, num_shape_functions: int):
        super().__init__(num_shape_functions)

    def test_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Calculate the test function values for a given number of tests and input values.

        Args:
            n_test (int): The number of test functions to calculate.
            x (np.ndarray): The input values at which to evaluate the test functions.

        Returns:
            np.ndarray: An array containing the results of the test functions at the given input values.
        """
        test_total = []
        for n in range(1, n_test + 1):
            obj1 = legendre(n + 1)
            obj2 = legendre(n - 1)
            test = obj1(x) - obj2(x)
            test_total.append(test)
        return np.asarray(test_total)

    def test_grad_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Calculate the gradient of the test function at a given point.

        Args:
            n_test (int): The number of test cases to evaluate.
            x (np.ndarray): The input value at which to evaluate the function.

        Returns:
            np.ndarray: An array containing the results of the test cases.
        """
        test_total = []
        for n in range(1, n_test + 1):
            obj1 = legendre(n + 1).deriv()
            obj2 = legendre(n - 1).deriv()
            test = obj1(x) - obj2(x)
            test_total.append(test)
        return np.asarray(test_total)

    def test_grad_grad_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
        """
        Calculate the gradient of the second derivative of a function using Legendre polynomials.

        Args:
            n_test (int): The number of test cases to evaluate.
            x (np.ndarray): The input value at which to evaluate the function.

        Returns:
            np.ndarray: An array containing the results of the test cases.
        """
        test_total = []
        for n in range(1, n_test + 1):
            obj1 = legendre(n + 1).deriv(2)
            obj2 = legendre(n - 1).deriv(2)
            test = obj1(x) - obj2(x)

            test_total.append(test)
        return np.asarray(test_total)

    def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the values of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinates.
            eta (np.ndarray): The eta coordinates.

        Returns:
            np.ndarray: The values of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
        test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_x[i, :] * test_function_y
            )

        return values

    def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinates.
            eta (np.ndarray): The eta coordinates.

        Returns:
            np.ndarray: The x-derivatives of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_grad_x = self.test_grad_fcn(num_shape_func_in_1d, xi)
        test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_grad_x[i, :] * test_function_y
            )

        return values

    def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinates.
            eta (np.ndarray): The eta coordinates.

        Returns:
            np.ndarray: The y-derivatives of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
        test_function_grad_y = self.test_grad_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_x[i, :] * test_function_grad_y
            )

        return values

    def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The xx-derivatives of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_grad_grad_x = self.test_grad_grad_fcn(num_shape_func_in_1d, xi)
        test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_grad_grad_x[i, :] * test_function_y
            )

        return values

    def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The xy-derivatives of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_grad_x = self.test_grad_fcn(num_shape_func_in_1d, xi)
        test_function_grad_y = self.test_grad_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_grad_x[i, :] * test_function_grad_y
            )

        return values

    def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

        Args:
            xi (np.ndarray): The xi coordinates.
            eta (np.ndarray): The eta coordinates.

        Returns:
            np.ndarray: The yy-derivatives of the basis functions.
        """
        values = np.zeros((self.num_shape_functions, len(xi)))

        num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

        test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
        test_function_grad_grad_y = self.test_grad_grad_fcn(num_shape_func_in_1d, eta)

        # Generate an outer product of the test functions to generate the basis functions
        for i in range(num_shape_func_in_1d):
            values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
                test_function_x[i, :] * test_function_grad_grad_y
            )

        return values

gradx(xi, eta)

This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinates.

required
eta ndarray

The eta coordinates.

required

Returns:

Type Description
ndarray

np.ndarray: The x-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the x-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinates.
        eta (np.ndarray): The eta coordinates.

    Returns:
        np.ndarray: The x-derivatives of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_grad_x = self.test_grad_fcn(num_shape_func_in_1d, xi)
    test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_grad_x[i, :] * test_function_y
        )

    return values

gradxx(xi, eta)

This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The xx-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xx-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The xx-derivatives of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_grad_grad_x = self.test_grad_grad_fcn(num_shape_func_in_1d, xi)
    test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_grad_grad_x[i, :] * test_function_y
        )

    return values

gradxy(xi, eta)

This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The xy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the xy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The xy-derivatives of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_grad_x = self.test_grad_fcn(num_shape_func_in_1d, xi)
    test_function_grad_y = self.test_grad_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_grad_x[i, :] * test_function_grad_y
        )

    return values

grady(xi, eta)

This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinates.

required
eta ndarray

The eta coordinates.

required

Returns:

Type Description
ndarray

np.ndarray: The y-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the y-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinates.
        eta (np.ndarray): The eta coordinates.

    Returns:
        np.ndarray: The y-derivatives of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
    test_function_grad_y = self.test_grad_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_x[i, :] * test_function_grad_y
        )

    return values

gradyy(xi, eta)

This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinates.

required
eta ndarray

The eta coordinates.

required

Returns:

Type Description
ndarray

np.ndarray: The yy-derivatives of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the yy-derivatives of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinates.
        eta (np.ndarray): The eta coordinates.

    Returns:
        np.ndarray: The yy-derivatives of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
    test_function_grad_grad_y = self.test_grad_grad_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_x[i, :] * test_function_grad_grad_y
        )

    return values

test_fcn(n_test, x)

Calculate the test function values for a given number of tests and input values.

Parameters:

Name Type Description Default
n_test int

The number of test functions to calculate.

required
x ndarray

The input values at which to evaluate the test functions.

required

Returns:

Type Description
ndarray

np.ndarray: An array containing the results of the test functions at the given input values.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def test_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Calculate the test function values for a given number of tests and input values.

    Args:
        n_test (int): The number of test functions to calculate.
        x (np.ndarray): The input values at which to evaluate the test functions.

    Returns:
        np.ndarray: An array containing the results of the test functions at the given input values.
    """
    test_total = []
    for n in range(1, n_test + 1):
        obj1 = legendre(n + 1)
        obj2 = legendre(n - 1)
        test = obj1(x) - obj2(x)
        test_total.append(test)
    return np.asarray(test_total)

test_grad_fcn(n_test, x)

Calculate the gradient of the test function at a given point.

Parameters:

Name Type Description Default
n_test int

The number of test cases to evaluate.

required
x ndarray

The input value at which to evaluate the function.

required

Returns:

Type Description
ndarray

np.ndarray: An array containing the results of the test cases.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def test_grad_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Calculate the gradient of the test function at a given point.

    Args:
        n_test (int): The number of test cases to evaluate.
        x (np.ndarray): The input value at which to evaluate the function.

    Returns:
        np.ndarray: An array containing the results of the test cases.
    """
    test_total = []
    for n in range(1, n_test + 1):
        obj1 = legendre(n + 1).deriv()
        obj2 = legendre(n - 1).deriv()
        test = obj1(x) - obj2(x)
        test_total.append(test)
    return np.asarray(test_total)

test_grad_grad_fcn(n_test, x)

Calculate the gradient of the second derivative of a function using Legendre polynomials.

Parameters:

Name Type Description Default
n_test int

The number of test cases to evaluate.

required
x ndarray

The input value at which to evaluate the function.

required

Returns:

Type Description
ndarray

np.ndarray: An array containing the results of the test cases.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def test_grad_grad_fcn(self, n_test: int, x: np.ndarray) -> np.ndarray:
    """
    Calculate the gradient of the second derivative of a function using Legendre polynomials.

    Args:
        n_test (int): The number of test cases to evaluate.
        x (np.ndarray): The input value at which to evaluate the function.

    Returns:
        np.ndarray: An array containing the results of the test cases.
    """
    test_total = []
    for n in range(1, n_test + 1):
        obj1 = legendre(n + 1).deriv(2)
        obj2 = legendre(n - 1).deriv(2)
        test = obj1(x) - obj2(x)

        test_total.append(test)
    return np.asarray(test_total)

value(xi, eta)

This method returns the values of the basis functions at the given (xi, eta) coordinates.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinates.

required
eta ndarray

The eta coordinates.

required

Returns:

Type Description
ndarray

np.ndarray: The values of the basis functions.

Source code in scirex/core/sciml/fe/basis_2d_qn_legendre_special.py
def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    This method returns the values of the basis functions at the given (xi, eta) coordinates.

    Args:
        xi (np.ndarray): The xi coordinates.
        eta (np.ndarray): The eta coordinates.

    Returns:
        np.ndarray: The values of the basis functions.
    """
    values = np.zeros((self.num_shape_functions, len(xi)))

    num_shape_func_in_1d = int(np.sqrt(self.num_shape_functions))

    test_function_x = self.test_fcn(num_shape_func_in_1d, xi)
    test_function_y = self.test_fcn(num_shape_func_in_1d, eta)

    # Generate an outer product of the test functions to generate the basis functions
    for i in range(num_shape_func_in_1d):
        values[i * num_shape_func_in_1d : (i + 1) * num_shape_func_in_1d, :] = (
            test_function_x[i, :] * test_function_y
        )

    return values

BasisFunction2D

An abstract base class defining the interface for two-dimensional finite element basis functions.

This class serves as a template for implementing various types of 2D basis functions (Legendre, Jacobi, Chebyshev, etc.) used in finite element computations. It defines the required methods for function evaluation and derivatives.

Attributes:

Name Type Description
num_shape_functions int

Number of shape functions in the element. Typically a perfect square for tensor-product bases.

Methods:

Name Description
value

Evaluates basis functions at given reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of basis functions at (xi, eta)

gradx

Computes x-derivatives at reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of x-derivatives at (xi, eta)

grady

Computes y-derivatives at reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of y-derivatives at (xi, eta)

gradxx

Computes second x-derivatives at reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of second x-derivatives at (xi, eta)

gradxy

Computes mixed derivatives at reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of mixed derivatives at (xi, eta)

gradyy

Computes second y-derivatives at reference coordinates Args: xi (float): First reference coordinate eta (float): Second reference coordinate Returns: float: Values of second y-derivatives at (xi, eta)

Notes
  • All coordinate inputs (xi, eta) should be in the reference element range
  • Subclasses must implement all abstract methods
  • Used as base class for specific polynomial implementations:
    • Legendre polynomials (normal and special variants)
    • Jacobi polynomials
    • Chebyshev polynomials
Source code in scirex/core/sciml/fe/basis_function_2d.py
class BasisFunction2D:
    """
    An abstract base class defining the interface for two-dimensional finite element basis functions.

    This class serves as a template for implementing various types of 2D basis functions
    (Legendre, Jacobi, Chebyshev, etc.) used in finite element computations. It defines
    the required methods for function evaluation and derivatives.

    Attributes:
        num_shape_functions (int): Number of shape functions in the element.
            Typically a perfect square for tensor-product bases.

    Methods:
        value(xi, eta): Evaluates basis functions at given reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of basis functions at (xi, eta)

        gradx(xi, eta): Computes x-derivatives at reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of x-derivatives at (xi, eta)

        grady(xi, eta): Computes y-derivatives at reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of y-derivatives at (xi, eta)

        gradxx(xi, eta): Computes second x-derivatives at reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of second x-derivatives at (xi, eta)

        gradxy(xi, eta): Computes mixed derivatives at reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of mixed derivatives at (xi, eta)

        gradyy(xi, eta): Computes second y-derivatives at reference coordinates
            Args:
                xi (float): First reference coordinate
                eta (float): Second reference coordinate
            Returns:
                float: Values of second y-derivatives at (xi, eta)

    Notes:
        - All coordinate inputs (xi, eta) should be in the reference element range
        - Subclasses must implement all abstract methods
        - Used as base class for specific polynomial implementations:
            - Legendre polynomials (normal and special variants)
            - Jacobi polynomials
            - Chebyshev polynomials
    """

    def __init__(self, num_shape_functions):
        self.num_shape_functions = num_shape_functions

    @abstractmethod
    def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Evaluates the basis function at the given xi and eta coordinates.

        Args:
            xi (float): The xi coordinate.
            eta (float): The eta coordinate.

        Returns:
            float: The value of the basis function at ( xi, eta).
        """
        pass

    @abstractmethod
    def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Computes the partial derivative of the basis function with respect to xi.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The partial derivative of the basis function with respect to xi.
        """
        pass

    @abstractmethod
    def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Computes the partial derivative of the basis function with respect to eta.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The partial derivative of the basis function with respect to eta.
        """
        pass

    @abstractmethod
    def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Computes the second partial derivative of the basis function with respect to xi.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The second partial derivative of the basis function with respect to xi.
        """
        pass

    @abstractmethod
    def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Computes the mixed partial derivative of the basis function with respect to xi and eta.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The mixed partial derivative of the basis function with respect to xi and eta.
        """
        pass

    @abstractmethod
    def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
        """
        Computes the second partial derivative of the basis function with respect to eta.

        Args:
            xi (np.ndarray): The xi coordinate.
            eta (np.ndarray): The eta coordinate.

        Returns:
            np.ndarray: The second partial derivative of the basis function with respect to eta.
        """
        pass

gradx(xi, eta) abstractmethod

Computes the partial derivative of the basis function with respect to xi.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The partial derivative of the basis function with respect to xi.

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def gradx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Computes the partial derivative of the basis function with respect to xi.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The partial derivative of the basis function with respect to xi.
    """
    pass

gradxx(xi, eta) abstractmethod

Computes the second partial derivative of the basis function with respect to xi.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The second partial derivative of the basis function with respect to xi.

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def gradxx(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Computes the second partial derivative of the basis function with respect to xi.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The second partial derivative of the basis function with respect to xi.
    """
    pass

gradxy(xi, eta) abstractmethod

Computes the mixed partial derivative of the basis function with respect to xi and eta.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The mixed partial derivative of the basis function with respect to xi and eta.

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def gradxy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Computes the mixed partial derivative of the basis function with respect to xi and eta.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The mixed partial derivative of the basis function with respect to xi and eta.
    """
    pass

grady(xi, eta) abstractmethod

Computes the partial derivative of the basis function with respect to eta.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The partial derivative of the basis function with respect to eta.

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def grady(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Computes the partial derivative of the basis function with respect to eta.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The partial derivative of the basis function with respect to eta.
    """
    pass

gradyy(xi, eta) abstractmethod

Computes the second partial derivative of the basis function with respect to eta.

Parameters:

Name Type Description Default
xi ndarray

The xi coordinate.

required
eta ndarray

The eta coordinate.

required

Returns:

Type Description
ndarray

np.ndarray: The second partial derivative of the basis function with respect to eta.

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def gradyy(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Computes the second partial derivative of the basis function with respect to eta.

    Args:
        xi (np.ndarray): The xi coordinate.
        eta (np.ndarray): The eta coordinate.

    Returns:
        np.ndarray: The second partial derivative of the basis function with respect to eta.
    """
    pass

value(xi, eta) abstractmethod

Evaluates the basis function at the given xi and eta coordinates.

Parameters:

Name Type Description Default
xi float

The xi coordinate.

required
eta float

The eta coordinate.

required

Returns:

Name Type Description
float ndarray

The value of the basis function at ( xi, eta).

Source code in scirex/core/sciml/fe/basis_function_2d.py
@abstractmethod
def value(self, xi: np.ndarray, eta: np.ndarray) -> np.ndarray:
    """
    Evaluates the basis function at the given xi and eta coordinates.

    Args:
        xi (float): The xi coordinate.
        eta (float): The eta coordinate.

    Returns:
        float: The value of the basis function at ( xi, eta).
    """
    pass