diff --git a/src/struphy/bsplines/bsplines.py b/src/struphy/bsplines/bsplines.py index 9974a9ff2..a659e4c61 100644 --- a/src/struphy/bsplines/bsplines.py +++ b/src/struphy/bsplines/bsplines.py @@ -16,7 +16,7 @@ """ -import cunumpy as xp +from struphy.utils.arrays import xp as np __all__ = [ "find_span", @@ -105,7 +105,7 @@ def scaling_vector(knots, degree, span): Scaling vector with elements (p + 1)/(t[i + p + 1] - t[i]) """ - x = xp.zeros(degree + 1, dtype=float) + x = np.zeros(degree + 1, dtype=float) for il in range(degree + 1): i = span - il @@ -148,9 +148,9 @@ def basis_funs(knots, degree, x, span, normalize=False): by using 'left' and 'right' temporary arrays that are one element shorter. """ - left = xp.empty(degree, dtype=float) - right = xp.empty(degree, dtype=float) - values = xp.empty(degree + 1, dtype=float) + left = np.empty(degree, dtype=float) + right = np.empty(degree, dtype=float) + values = np.empty(degree + 1, dtype=float) values[0] = 1.0 @@ -164,7 +164,7 @@ def basis_funs(knots, degree, x, span, normalize=False): saved = left[j - r] * temp values[j + 1] = saved - if normalize: + if normalize == True: values = values * scaling_vector(knots, degree, span) return values @@ -205,7 +205,7 @@ def basis_funs_1st_der(knots, degree, x, span): # Compute derivatives at x using formula based on difference of splines of degree deg - 1 # ------- # j = 0 - ders = xp.empty(degree + 1, dtype=float) + ders = np.empty(degree + 1, dtype=float) saved = degree * values[0] / (knots[span + 1] - knots[span + 1 - degree]) ders[0] = -saved @@ -261,11 +261,11 @@ def basis_funs_all_ders(knots, degree, x, span, n): - innermost loops are replaced with vector operations on slices. """ - left = xp.empty(degree) - right = xp.empty(degree) - ndu = xp.empty((degree + 1, degree + 1)) - a = xp.empty((2, degree + 1)) - ders = xp.zeros((n + 1, degree + 1)) # output array + left = np.empty(degree) + right = np.empty(degree) + ndu = np.empty((degree + 1, degree + 1)) + a = np.empty((2, degree + 1)) + ders = np.zeros((n + 1, degree + 1)) # output array # Number of derivatives that need to be effectively computed # Derivatives higher than degree are = 0. @@ -304,7 +304,7 @@ def basis_funs_all_ders(knots, degree, x, span, n): j1 = 1 if (rk > -1) else -rk j2 = k - 1 if (r - 1 <= pk) else degree - r a[s2, j1 : j2 + 1] = (a[s1, j1 : j2 + 1] - a[s1, j1 - 1 : j2]) * ndu[pk + 1, rk + j1 : rk + j2 + 1] - d += xp.dot(a[s2, j1 : j2 + 1], ndu[rk + j1 : rk + j2 + 1, pk]) + d += np.dot(a[s2, j1 : j2 + 1], ndu[rk + j1 : rk + j2 + 1, pk]) if r <= pk: a[s2, k] = -a[s1, k - 1] * ndu[pk + 1, r] d += a[s2, k] * ndu[r, pk] @@ -362,7 +362,7 @@ def collocation_matrix(knots, degree, xgrid, periodic, normalize=False): nx = len(xgrid) # Collocation matrix as 2D Numpy array (dense storage) - mat = xp.zeros((nx, nb), dtype=float) + mat = np.zeros((nx, nb), dtype=float) # Indexing of basis functions (periodic or not) for a given span if periodic: @@ -418,12 +418,12 @@ def histopolation_matrix(knots, degree, xgrid, periodic): # Number of integrals if periodic: el_b = breakpoints(knots, degree) - xgrid = xp.array([el_b[0]] + list(xgrid) + [el_b[-1]]) + xgrid = np.array([el_b[0]] + list(xgrid) + [el_b[-1]]) ni = len(xgrid) - 1 # Histopolation matrix of M-splines as 2D Numpy array (dense storage) - his = xp.zeros((ni, nbD), dtype=float) + his = np.zeros((ni, nbD), dtype=float) # Collocation matrix of B-splines col = collocation_matrix(knots, degree, xgrid, False, normalize=False) @@ -434,7 +434,7 @@ def histopolation_matrix(knots, degree, xgrid, periodic): for k in range(j + 1): his[i, j % nbD] += col[i, k] - col[i + 1, k] - if xp.abs(his[i, j % nbD]) < 1e-14: + if np.abs(his[i, j % nbD]) < 1e-14: his[i, j % nbD] = 0.0 # add first to last integration interval in case of periodic splines @@ -470,7 +470,7 @@ def breakpoints(knots, degree): else: endsl = -degree - return xp.unique(knots[slice(degree, endsl)]) + return np.unique(knots[slice(degree, endsl)]) # ============================================================================== @@ -501,13 +501,13 @@ def greville(knots, degree, periodic): n = len(T) - 2 * p - 1 if periodic else len(T) - p - 1 # Compute greville abscissas as average of p consecutive knot values - xg = xp.around([sum(T[i : i + p]) / p for i in range(s, s + n)], decimals=15) + xg = np.around([sum(T[i : i + p]) / p for i in range(s, s + n)], decimals=15) # If needed apply periodic boundary conditions if periodic: a = T[p] b = T[-p] - xg = xp.around((xg - a) % (b - a) + a, decimals=15) + xg = np.around((xg - a) % (b - a) + a, decimals=15) return xg @@ -537,7 +537,7 @@ def elements_spans(knots, degree): >>> from psydac.core.bsplines import make_knots, elements_spans >>> p = 3 ; n = 8 - >>> grid = xp.arange( n-p+1 ) + >>> grid = np.arange( n-p+1 ) >>> knots = make_knots( breaks=grid, degree=p, periodic=False ) >>> spans = elements_spans( knots=knots, degree=p ) >>> spans @@ -549,13 +549,13 @@ def elements_spans(knots, degree): 2) This function could be written in two lines: breaks = breakpoints( knots, degree ) - spans = xp.searchsorted( knots, breaks[:-1], side='right' ) - 1 + spans = np.searchsorted( knots, breaks[:-1], side='right' ) - 1 """ breaks = breakpoints(knots, degree) nk = len(knots) ne = len(breaks) - 1 - spans = xp.zeros(ne, dtype=int) + spans = np.zeros(ne, dtype=int) ie = 0 for ik in range(degree, nk - degree): @@ -600,13 +600,13 @@ def make_knots(breaks, degree, periodic): # Consistency checks assert len(breaks) > 1 - assert all(xp.diff(breaks) > 0) + assert all(np.diff(breaks) > 0) assert degree > 0 if periodic: assert len(breaks) > degree p = degree - T = xp.zeros(len(breaks) + 2 * p, dtype=float) + T = np.zeros(len(breaks) + 2 * p, dtype=float) T[p:-p] = breaks if periodic: @@ -671,13 +671,13 @@ def quadrature_grid(breaks, quad_rule_x, quad_rule_w): assert min(quad_rule_x) >= -1 assert max(quad_rule_x) <= +1 - quad_rule_x = xp.asarray(quad_rule_x) - quad_rule_w = xp.asarray(quad_rule_w) + quad_rule_x = np.asarray(quad_rule_x) + quad_rule_w = np.asarray(quad_rule_w) ne = len(breaks) - 1 nq = len(quad_rule_x) - quad_x = xp.zeros((ne, nq), dtype=float) - quad_w = xp.zeros((ne, nq), dtype=float) + quad_x = np.zeros((ne, nq), dtype=float) + quad_w = np.zeros((ne, nq), dtype=float) # Compute location and weight of quadrature points from basic rule for ie, (a, b) in enumerate(zip(breaks[:-1], breaks[1:])): @@ -724,7 +724,7 @@ def basis_ders_on_quad_grid(knots, degree, quad_grid, nders, normalize=False): # TODO: check if it is safe to compute span only once for each element ne, nq = quad_grid.shape - basis = xp.zeros((ne, degree + 1, nders + 1, nq), dtype=float) + basis = np.zeros((ne, degree + 1, nders + 1, nq), dtype=float) # Loop over elements for ie in range(ne): @@ -735,7 +735,7 @@ def basis_ders_on_quad_grid(knots, degree, quad_grid, nders, normalize=False): span = find_span(knots, degree, xq) ders = basis_funs_all_ders(knots, degree, xq, span, nders) - if normalize: + if normalize == True: ders = ders * scaling_vector(knots, degree, span) basis[ie, :, :, iq] = ders.transpose() diff --git a/src/struphy/bsplines/bsplines_kernels.py b/src/struphy/bsplines/bsplines_kernels.py index 9fa1a9521..17374f178 100644 --- a/src/struphy/bsplines/bsplines_kernels.py +++ b/src/struphy/bsplines/bsplines_kernels.py @@ -83,13 +83,7 @@ def find_span(t: "Final[float[:]]", p: "int", eta: "float") -> "int": @pure def basis_funs( - t: "Final[float[:]]", - p: "int", - eta: "float", - span: "int", - left: "float[:]", - right: "float[:]", - values: "float[:]", + t: "Final[float[:]]", p: "int", eta: "float", span: "int", left: "float[:]", right: "float[:]", values: "float[:]" ): """ Parameters @@ -601,13 +595,7 @@ def basis_funs_and_der( @pure @stack_array("values_b") def basis_funs_1st_der( - t: "Final[float[:]]", - p: "int", - eta: "float", - span: "int", - left: "float[:]", - right: "float[:]", - values: "float[:]", + t: "Final[float[:]]", p: "int", eta: "float", span: "int", left: "float[:]", right: "float[:]", values: "float[:]" ): """ Parameters diff --git a/src/struphy/bsplines/evaluation_kernels_1d.py b/src/struphy/bsplines/evaluation_kernels_1d.py index 6510eafff..a6ec8b7a5 100644 --- a/src/struphy/bsplines/evaluation_kernels_1d.py +++ b/src/struphy/bsplines/evaluation_kernels_1d.py @@ -61,12 +61,7 @@ def evaluation_kernel_1d(p1: int, basis1: "Final[float[:]]", ind1: "Final[int[:] @pure @stack_array("tmp1", "tmp2") def evaluate( - kind1: int, - t1: "Final[float[:]]", - p1: int, - ind1: "Final[int[:,:]]", - coeff: "Final[float[:]]", - eta1: float, + kind1: int, t1: "Final[float[:]]", p1: int, ind1: "Final[int[:,:]]", coeff: "Final[float[:]]", eta1: float ) -> float: """ Point-wise evaluation of a spline. diff --git a/src/struphy/bsplines/evaluation_kernels_3d.py b/src/struphy/bsplines/evaluation_kernels_3d.py index a6c900616..8ccaa252b 100644 --- a/src/struphy/bsplines/evaluation_kernels_3d.py +++ b/src/struphy/bsplines/evaluation_kernels_3d.py @@ -246,212 +246,47 @@ def evaluate_tensor_product( for i3 in range(len(eta3)): if kind == 0: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 1, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 1, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 11: spline_values[i1, i2, i3] = evaluate_3d( - 2, - 1, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 2, 1, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 12: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 2, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 2, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 13: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 1, - 2, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 1, 2, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 21: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 2, - 2, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 2, 2, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 22: spline_values[i1, i2, i3] = evaluate_3d( - 2, - 1, - 2, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 2, 1, 2, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 23: spline_values[i1, i2, i3] = evaluate_3d( - 2, - 2, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 2, 2, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 3: spline_values[i1, i2, i3] = evaluate_3d( - 2, - 2, - 2, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 2, 2, 2, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 41: spline_values[i1, i2, i3] = evaluate_3d( - 3, - 1, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 3, 1, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 42: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 3, - 1, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 3, 1, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) elif kind == 43: spline_values[i1, i2, i3] = evaluate_3d( - 1, - 1, - 3, - t1, - t2, - t3, - p1, - p2, - p3, - ind1, - ind2, - ind3, - coeff, - eta1[i1], - eta2[i2], - eta3[i3], + 1, 1, 3, t1, t2, t3, p1, p2, p3, ind1, ind2, ind3, coeff, eta1[i1], eta2[i2], eta3[i3] ) @@ -1216,17 +1051,7 @@ def eval_spline_mpi( b3 = bd3 value = eval_spline_mpi_kernel( - pn[0] - kind[0], - pn[1] - kind[1], - pn[2] - kind[2], - b1, - b2, - b3, - span1, - span2, - span3, - _data, - starts, + pn[0] - kind[0], pn[1] - kind[1], pn[2] - kind[2], b1, b2, b3, span1, span2, span3, _data, starts ) return value @@ -1371,17 +1196,7 @@ def eval_spline_mpi_tensor_product_fast( b3 = bd3 values[i, j, k] = eval_spline_mpi_kernel( - pn[0] - kind[0], - pn[1] - kind[1], - pn[2] - kind[2], - b1, - b2, - b3, - span1, - span2, - span3, - _data, - starts, + pn[0] - kind[0], pn[1] - kind[1], pn[2] - kind[2], b1, b2, b3, span1, span2, span3, _data, starts ) @@ -1447,17 +1262,7 @@ def eval_spline_mpi_tensor_product_fixed( b3[:] = b3s[k, :] values[i, j, k] = eval_spline_mpi_kernel( - pn[0] - kind[0], - pn[1] - kind[1], - pn[2] - kind[2], - b1, - b2, - b3, - span1, - span2, - span3, - _data, - starts, + pn[0] - kind[0], pn[1] - kind[1], pn[2] - kind[2], b1, b2, b3, span1, span2, span3, _data, starts ) @@ -1515,16 +1320,7 @@ def eval_spline_mpi_matrix( continue # point not in process domain values[i, j, k] = eval_spline_mpi( - eta1[i, j, k], - eta2[i, j, k], - eta3[i, j, k], - _data, - kind, - pn, - tn1, - tn2, - tn3, - starts, + eta1[i, j, k], eta2[i, j, k], eta3[i, j, k], _data, kind, pn, tn1, tn2, tn3, starts ) @@ -1586,16 +1382,7 @@ def eval_spline_mpi_sparse_meshgrid( continue # point not in process domain values[i, j, k] = eval_spline_mpi( - eta1[i, 0, 0], - eta2[0, j, 0], - eta3[0, 0, k], - _data, - kind, - pn, - tn1, - tn2, - tn3, - starts, + eta1[i, 0, 0], eta2[0, j, 0], eta3[0, 0, k], _data, kind, pn, tn1, tn2, tn3, starts ) @@ -1645,16 +1432,7 @@ def eval_spline_mpi_markers( continue # point not in process domain values[ip] = eval_spline_mpi( - markers[ip, 0], - markers[ip, 1], - markers[ip, 2], - _data, - kind, - pn, - tn1, - tn2, - tn3, - starts, + markers[ip, 0], markers[ip, 1], markers[ip, 2], _data, kind, pn, tn1, tn2, tn3, starts ) @@ -1675,39 +1453,20 @@ def get_spans(eta1: float, eta2: float, eta3: float, args_derham: "DerhamArgumen # get spline values at eta bsplines_kernels.b_d_splines_slim( - args_derham.tn1, - args_derham.pn[0], - eta1, - int(span1), - args_derham.bn1, - args_derham.bd1, + args_derham.tn1, args_derham.pn[0], eta1, int(span1), args_derham.bn1, args_derham.bd1 ) bsplines_kernels.b_d_splines_slim( - args_derham.tn2, - args_derham.pn[1], - eta2, - int(span2), - args_derham.bn2, - args_derham.bd2, + args_derham.tn2, args_derham.pn[1], eta2, int(span2), args_derham.bn2, args_derham.bd2 ) bsplines_kernels.b_d_splines_slim( - args_derham.tn3, - args_derham.pn[2], - eta3, - int(span3), - args_derham.bn3, - args_derham.bd3, + args_derham.tn3, args_derham.pn[2], eta3, int(span3), args_derham.bn3, args_derham.bd3 ) return span1, span2, span3 def eval_0form_spline_mpi( - span1: int, - span2: int, - span3: int, - args_derham: "DerhamArguments", - form_coeffs: "float[:,:,:]", + span1: int, span2: int, span3: int, args_derham: "DerhamArguments", form_coeffs: "float[:,:,:]" ) -> float: """Single-point evaluation of Derham 0-form spline defined by form_coeffs, given N-spline values (in bn) and knot span indices span.""" @@ -1843,11 +1602,7 @@ def eval_2form_spline_mpi( def eval_3form_spline_mpi( - span1: int, - span2: int, - span3: int, - args_derham: "DerhamArguments", - form_coeffs: "float[:,:,:]", + span1: int, span2: int, span3: int, args_derham: "DerhamArguments", form_coeffs: "float[:,:,:]" ) -> float: """Single-point evaluation of Derham 0-form spline defined by form_coeffs, given D-spline values (in bd) and knot span indices span.""" diff --git a/src/struphy/bsplines/tests/test_bsplines_kernels.py b/src/struphy/bsplines/tests/test_bsplines_kernels.py index c1010dd08..1a16712c1 100644 --- a/src/struphy/bsplines/tests/test_bsplines_kernels.py +++ b/src/struphy/bsplines/tests/test_bsplines_kernels.py @@ -1,9 +1,10 @@ import time -import cunumpy as xp import pytest from psydac.ddm.mpi import mpi as MPI +from struphy.utils.arrays import xp as np + @pytest.mark.parametrize("Nel", [[8, 9, 10]]) @pytest.mark.parametrize("p", [[1, 2, 1], [2, 1, 2], [3, 4, 3]]) @@ -33,9 +34,9 @@ def test_bsplines_span_and_basis(Nel, p, spl_kind): # Random points in domain of process n_pts = 100 dom = derham.domain_array[rank] - eta1s = xp.random.rand(n_pts) * (dom[1] - dom[0]) + dom[0] - eta2s = xp.random.rand(n_pts) * (dom[4] - dom[3]) + dom[3] - eta3s = xp.random.rand(n_pts) * (dom[7] - dom[6]) + dom[6] + eta1s = np.random.rand(n_pts) * (dom[1] - dom[0]) + dom[0] + eta2s = np.random.rand(n_pts) * (dom[4] - dom[3]) + dom[3] + eta3s = np.random.rand(n_pts) * (dom[7] - dom[6]) + dom[6] # struphy find_span t0 = time.time() @@ -59,18 +60,18 @@ def test_bsplines_span_and_basis(Nel, p, spl_kind): if rank == 0: print(f"psydac find_span_p : {t1 - t0}") - assert xp.allclose(span1s, span1s_psy) - assert xp.allclose(span2s, span2s_psy) - assert xp.allclose(span3s, span3s_psy) + assert np.allclose(span1s, span1s_psy) + assert np.allclose(span2s, span2s_psy) + assert np.allclose(span3s, span3s_psy) # allocate tmps - bn1 = xp.empty(derham.p[0] + 1, dtype=float) - bn2 = xp.empty(derham.p[1] + 1, dtype=float) - bn3 = xp.empty(derham.p[2] + 1, dtype=float) + bn1 = np.empty(derham.p[0] + 1, dtype=float) + bn2 = np.empty(derham.p[1] + 1, dtype=float) + bn3 = np.empty(derham.p[2] + 1, dtype=float) - bd1 = xp.empty(derham.p[0], dtype=float) - bd2 = xp.empty(derham.p[1], dtype=float) - bd3 = xp.empty(derham.p[2], dtype=float) + bd1 = np.empty(derham.p[0], dtype=float) + bd2 = np.empty(derham.p[1], dtype=float) + bd3 = np.empty(derham.p[2], dtype=float) # struphy b_splines_slim val1s, val2s, val3s = [], [], [] @@ -102,13 +103,13 @@ def test_bsplines_span_and_basis(Nel, p, spl_kind): # compare for val1, val1_psy in zip(val1s, val1s_psy): - assert xp.allclose(val1, val1_psy) + assert np.allclose(val1, val1_psy) for val2, val2_psy in zip(val2s, val2s_psy): - assert xp.allclose(val2, val2_psy) + assert np.allclose(val2, val2_psy) for val3, val3_psy in zip(val3s, val3s_psy): - assert xp.allclose(val3, val3_psy) + assert np.allclose(val3, val3_psy) # struphy b_d_splines_slim val1s_n, val2s_n, val3s_n = [], [], [] @@ -130,13 +131,13 @@ def test_bsplines_span_and_basis(Nel, p, spl_kind): # compare for val1, val1_psy in zip(val1s_n, val1s_psy): - assert xp.allclose(val1, val1_psy) + assert np.allclose(val1, val1_psy) for val2, val2_psy in zip(val2s_n, val2s_psy): - assert xp.allclose(val2, val2_psy) + assert np.allclose(val2, val2_psy) for val3, val3_psy in zip(val3s_n, val3s_psy): - assert xp.allclose(val3, val3_psy) + assert np.allclose(val3, val3_psy) # struphy d_splines_slim span1s, span2s, span3s = [], [], [] @@ -174,22 +175,22 @@ def test_bsplines_span_and_basis(Nel, p, spl_kind): # compare for val1, val1_psy in zip(val1s, val1s_psy): - assert xp.allclose(val1, val1_psy) + assert np.allclose(val1, val1_psy) for val2, val2_psy in zip(val2s, val2s_psy): - assert xp.allclose(val2, val2_psy) + assert np.allclose(val2, val2_psy) for val3, val3_psy in zip(val3s, val3s_psy): - assert xp.allclose(val3, val3_psy) + assert np.allclose(val3, val3_psy) for val1, val1_psy in zip(val1s_d, val1s_psy): - assert xp.allclose(val1, val1_psy) + assert np.allclose(val1, val1_psy) for val2, val2_psy in zip(val2s_d, val2s_psy): - assert xp.allclose(val2, val2_psy) + assert np.allclose(val2, val2_psy) for val3, val3_psy in zip(val3s_d, val3s_psy): - assert xp.allclose(val3, val3_psy) + assert np.allclose(val3, val3_psy) if __name__ == "__main__": diff --git a/src/struphy/bsplines/tests/test_eval_spline_mpi.py b/src/struphy/bsplines/tests/test_eval_spline_mpi.py index 923fc8ea6..e40af4124 100644 --- a/src/struphy/bsplines/tests/test_eval_spline_mpi.py +++ b/src/struphy/bsplines/tests/test_eval_spline_mpi.py @@ -1,10 +1,11 @@ from sys import int_info from time import sleep -import cunumpy as xp import pytest from psydac.ddm.mpi import mpi as MPI +from struphy.utils.arrays import xp as np + @pytest.mark.parametrize("Nel", [[8, 9, 10]]) @pytest.mark.parametrize("p", [[1, 2, 3], [3, 1, 2]]) @@ -37,9 +38,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): # Random points in domain of process dom = derham.domain_array[rank] - eta1s = xp.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] - eta2s = xp.random.rand(n_markers) * (dom[4] - dom[3]) + dom[3] - eta3s = xp.random.rand(n_markers) * (dom[7] - dom[6]) + dom[6] + eta1s = np.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] + eta2s = np.random.rand(n_markers) * (dom[4] - dom[3]) + dom[3] + eta3s = np.random.rand(n_markers) * (dom[7] - dom[6]) + dom[6] for eta1, eta2, eta3 in zip(eta1s, eta2s, eta3s): comm.Barrier() @@ -55,13 +56,13 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span3 = bsp.find_span(tn3, derham.p[2], eta3) # non-zero spline values at eta - bn1 = xp.empty(derham.p[0] + 1, dtype=float) - bn2 = xp.empty(derham.p[1] + 1, dtype=float) - bn3 = xp.empty(derham.p[2] + 1, dtype=float) + bn1 = np.empty(derham.p[0] + 1, dtype=float) + bn2 = np.empty(derham.p[1] + 1, dtype=float) + bn3 = np.empty(derham.p[2] + 1, dtype=float) - bd1 = xp.empty(derham.p[0], dtype=float) - bd2 = xp.empty(derham.p[1], dtype=float) - bd3 = xp.empty(derham.p[2], dtype=float) + bd1 = np.empty(derham.p[0], dtype=float) + bd2 = np.empty(derham.p[1], dtype=float) + bd3 = np.empty(derham.p[2], dtype=float) bsp.b_d_splines_slim(tn1, derham.p[0], eta1, span1, bn1, bd1) bsp.b_d_splines_slim(tn2, derham.p[1], eta2, span2, bn2, bd2) @@ -82,8 +83,8 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): # compare spline evaluation routines in V0 val = eval3d(*derham.p, bn1, bn2, bn3, ind_n1, ind_n2, ind_n3, x0[0]) - val_mpi = eval3d_mpi(*derham.p, bn1, bn2, bn3, span1, span2, span3, x0_psy._data, xp.array(x0_psy.starts)) - assert xp.allclose(val, val_mpi) + val_mpi = eval3d_mpi(*derham.p, bn1, bn2, bn3, span1, span2, span3, x0_psy._data, np.array(x0_psy.starts)) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V1 val = eval3d(derham.p[0] - 1, derham.p[1], derham.p[2], bd1, bn2, bn3, ind_d1, ind_n2, ind_n3, x1[0]) @@ -98,9 +99,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x1_psy[0]._data, - xp.array(x1_psy[0].starts), + np.array(x1_psy[0].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) val = eval3d(derham.p[0], derham.p[1] - 1, derham.p[2], bn1, bd2, bn3, ind_n1, ind_d2, ind_n3, x1[1]) val_mpi = eval3d_mpi( @@ -114,9 +115,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x1_psy[1]._data, - xp.array(x1_psy[1].starts), + np.array(x1_psy[1].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) val = eval3d(derham.p[0], derham.p[1], derham.p[2] - 1, bn1, bn2, bd3, ind_n1, ind_n2, ind_d3, x1[2]) val_mpi = eval3d_mpi( @@ -130,9 +131,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x1_psy[2]._data, - xp.array(x1_psy[2].starts), + np.array(x1_psy[2].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V2 val = eval3d(derham.p[0], derham.p[1] - 1, derham.p[2] - 1, bn1, bd2, bd3, ind_n1, ind_d2, ind_d3, x2[0]) @@ -147,9 +148,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x2_psy[0]._data, - xp.array(x2_psy[0].starts), + np.array(x2_psy[0].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) val = eval3d(derham.p[0] - 1, derham.p[1], derham.p[2] - 1, bd1, bn2, bd3, ind_d1, ind_n2, ind_d3, x2[1]) val_mpi = eval3d_mpi( @@ -163,9 +164,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x2_psy[1]._data, - xp.array(x2_psy[1].starts), + np.array(x2_psy[1].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) val = eval3d(derham.p[0] - 1, derham.p[1] - 1, derham.p[2], bd1, bd2, bn3, ind_d1, ind_d2, ind_n3, x2[2]) val_mpi = eval3d_mpi( @@ -179,9 +180,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x2_psy[2]._data, - xp.array(x2_psy[2].starts), + np.array(x2_psy[2].starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V3 val = eval3d(derham.p[0] - 1, derham.p[1] - 1, derham.p[2] - 1, bd1, bd2, bd3, ind_d1, ind_d2, ind_d3, x3[0]) @@ -196,9 +197,9 @@ def test_eval_kernels(Nel, p, spl_kind, n_markers=10): span2, span3, x3_psy._data, - xp.array(x3_psy.starts), + np.array(x3_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) @pytest.mark.parametrize("Nel", [[8, 9, 10]]) @@ -229,9 +230,9 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): # Random points in domain of process dom = derham.domain_array[rank] - eta1s = xp.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] - eta2s = xp.random.rand(n_markers) * (dom[4] - dom[3]) + dom[3] - eta3s = xp.random.rand(n_markers) * (dom[7] - dom[6]) + dom[6] + eta1s = np.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] + eta2s = np.random.rand(n_markers) * (dom[4] - dom[3]) + dom[3] + eta3s = np.random.rand(n_markers) * (dom[7] - dom[6]) + dom[6] for eta1, eta2, eta3 in zip(eta1s, eta2s, eta3s): comm.Barrier() @@ -250,14 +251,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x0_psy._data, derham.spline_types_pyccel["0"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V1 # 1st component @@ -286,14 +287,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x1_psy[0]._data, derham.spline_types_pyccel["1"][0], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # 2nd component val = evaluate_3d( @@ -321,14 +322,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x1_psy[1]._data, derham.spline_types_pyccel["1"][1], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # 3rd component val = evaluate_3d( @@ -356,14 +357,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x1_psy[2]._data, derham.spline_types_pyccel["1"][2], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V2 # 1st component @@ -392,14 +393,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x2_psy[0]._data, derham.spline_types_pyccel["2"][0], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # 2nd component val = evaluate_3d( @@ -427,14 +428,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x2_psy[1]._data, derham.spline_types_pyccel["2"][1], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # 3rd component val = evaluate_3d( @@ -462,14 +463,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x2_psy[2]._data, derham.spline_types_pyccel["2"][2], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) # compare spline evaluation routines in V3 val = evaluate_3d( @@ -495,14 +496,14 @@ def test_eval_pointwise(Nel, p, spl_kind, n_markers=10): eta3, x3_psy._data, derham.spline_types_pyccel["3"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), ) - assert xp.allclose(val, val_mpi) + assert np.allclose(val, val_mpi) @pytest.mark.parametrize("Nel", [[8, 9, 10]]) @@ -543,13 +544,13 @@ def test_eval_tensor_product(Nel, p, spl_kind, n_markers=10): # Random points in domain of process dom = derham.domain_array[rank] - eta1s = xp.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] - eta2s = xp.random.rand(n_markers + 1) * (dom[4] - dom[3]) + dom[3] - eta3s = xp.random.rand(n_markers + 2) * (dom[7] - dom[6]) + dom[6] + eta1s = np.random.rand(n_markers) * (dom[1] - dom[0]) + dom[0] + eta2s = np.random.rand(n_markers + 1) * (dom[4] - dom[3]) + dom[3] + eta3s = np.random.rand(n_markers + 2) * (dom[7] - dom[6]) + dom[6] - vals = xp.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) - vals_mpi = xp.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) - vals_mpi_fast = xp.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) + vals = np.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) + vals_mpi = np.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) + vals_mpi_fast = np.zeros((n_markers, n_markers + 1, n_markers + 2), dtype=float) comm.Barrier() sleep(0.02 * (rank + 1)) @@ -572,11 +573,11 @@ def test_eval_tensor_product(Nel, p, spl_kind, n_markers=10): eta3s, x0_psy._data, derham.spline_types_pyccel["0"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), vals_mpi, ) t1 = time.time() @@ -590,19 +591,19 @@ def test_eval_tensor_product(Nel, p, spl_kind, n_markers=10): eta3s, x0_psy._data, derham.spline_types_pyccel["0"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), vals_mpi_fast, ) t1 = time.time() if rank == 0: print("v0 eval_spline_mpi_tensor_product_fast:".ljust(40), t1 - t0) - assert xp.allclose(vals, vals_mpi) - assert xp.allclose(vals, vals_mpi_fast) + assert np.allclose(vals, vals_mpi) + assert np.allclose(vals, vals_mpi_fast) # compare spline evaluation routines in V3 t0 = time.time() @@ -632,11 +633,11 @@ def test_eval_tensor_product(Nel, p, spl_kind, n_markers=10): eta3s, x3_psy._data, derham.spline_types_pyccel["3"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), vals_mpi, ) t1 = time.time() @@ -650,19 +651,19 @@ def test_eval_tensor_product(Nel, p, spl_kind, n_markers=10): eta3s, x3_psy._data, derham.spline_types_pyccel["3"], - xp.array(derham.p), + np.array(derham.p), tn1, tn2, tn3, - xp.array(x0_psy.starts), + np.array(x0_psy.starts), vals_mpi_fast, ) t1 = time.time() if rank == 0: print("v3 eval_spline_mpi_tensor_product_fast:".ljust(40), t1 - t0) - assert xp.allclose(vals, vals_mpi) - assert xp.allclose(vals, vals_mpi_fast) + assert np.allclose(vals, vals_mpi) + assert np.allclose(vals, vals_mpi_fast) @pytest.mark.parametrize("Nel", [[8, 9, 10]]) @@ -700,10 +701,7 @@ def test_eval_tensor_product_grid(Nel, p, spl_kind, n_markers=10): # Histopolation grids spaces = derham.Vh_fem["3"].spaces ptsG, wtsG, spans, bases, subs = prepare_projection_of_basis( - spaces, - spaces, - derham.Vh["3"].starts, - derham.Vh["3"].ends, + spaces, spaces, derham.Vh["3"].starts, derham.Vh["3"].ends ) eta1s = ptsG[0].flatten() eta2s = ptsG[1].flatten() @@ -712,15 +710,15 @@ def test_eval_tensor_product_grid(Nel, p, spl_kind, n_markers=10): spans_f, bns_f, bds_f = derham.prepare_eval_tp_fixed([eta1s, eta2s, eta3s]) # output arrays - vals = xp.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) - vals_mpi_fixed = xp.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) - vals_mpi_grid = xp.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) + vals = np.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) + vals_mpi_fixed = np.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) + vals_mpi_grid = np.zeros((eta1s.size, eta2s.size, eta3s.size), dtype=float) comm.Barrier() sleep(0.02 * (rank + 1)) - print(f"rank {rank} | {eta1s =}") - print(f"rank {rank} | {eta2s =}") - print(f"rank {rank} | {eta3s =}\n") + print(f"rank {rank} | {eta1s = }") + print(f"rank {rank} | {eta2s = }") + print(f"rank {rank} | {eta3s = }\n") comm.Barrier() # compare spline evaluation routines @@ -750,20 +748,20 @@ def test_eval_tensor_product_grid(Nel, p, spl_kind, n_markers=10): *bds_f, x3_psy._data, derham.spline_types_pyccel["3"], - xp.array(derham.p), - xp.array(x0_psy.starts), + np.array(derham.p), + np.array(x0_psy.starts), vals_mpi_fixed, ) t1 = time.time() if rank == 0: print("v3 eval_spline_mpi_tensor_product_fixed:".ljust(40), t1 - t0) - assert xp.allclose(vals, vals_mpi_fixed) + assert np.allclose(vals, vals_mpi_fixed) field = derham.create_spline_function("test", "L2") field.vector = x3_psy - assert xp.allclose(field.vector._data, x3_psy._data) + assert np.allclose(field.vector._data, x3_psy._data) t0 = time.time() field.eval_tp_fixed_loc(spans_f, bds_f, out=vals_mpi_fixed) @@ -771,7 +769,7 @@ def test_eval_tensor_product_grid(Nel, p, spl_kind, n_markers=10): if rank == 0: print("v3 field.eval_tp_fixed:".ljust(40), t1 - t0) - assert xp.allclose(vals, vals_mpi_fixed) + assert np.allclose(vals, vals_mpi_fixed) if __name__ == "__main__": diff --git a/src/struphy/compile_struphy.mk b/src/struphy/compile_struphy.mk index 2aaec6cc6..62b310eab 100644 --- a/src/struphy/compile_struphy.mk +++ b/src/struphy/compile_struphy.mk @@ -5,7 +5,7 @@ PYTHON := python3 SO_EXT := $(shell $(PYTHON) -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))") LIBDIR := $(shell $(PYTHON) -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") -struphy_path := $(shell $(PYTHON) -c "import struphy; print(struphy.__path__[0])") +struphy_path := $(shell $(PYTHON) -c "import struphy as _; print(_.__path__[0])") # Arguments to this script are: STRUPHY_SOURCES := $(sources) diff --git a/src/struphy/conftest.py b/src/struphy/conftest.py index 05e10b55e..5a936455c 100644 --- a/src/struphy/conftest.py +++ b/src/struphy/conftest.py @@ -1,14 +1,18 @@ def pytest_addoption(parser): + parser.addoption("--fast", action="store_true") parser.addoption("--with-desc", action="store_true") parser.addoption("--vrbose", action="store_true") + parser.addoption("--verification", action="store_true") parser.addoption("--show-plots", action="store_true") parser.addoption("--nclones", type=int, default=1) - parser.addoption("--model-name", type=str, default="Maxwell") def pytest_generate_tests(metafunc): # This is called for every test. Only get/set command line arguments - # if the argument is specified in the list of test "fixturenames".]) + # if the argument is specified in the list of test "fixturenames". + option_value = metafunc.config.option.fast + if "fast" in metafunc.fixturenames and option_value is not None: + metafunc.parametrize("fast", [option_value]) option_value = metafunc.config.option.with_desc if "with_desc" in metafunc.fixturenames and option_value is not None: @@ -18,6 +22,10 @@ def pytest_generate_tests(metafunc): if "vrbose" in metafunc.fixturenames and option_value is not None: metafunc.parametrize("vrbose", [option_value]) + option_value = metafunc.config.option.verification + if "verification" in metafunc.fixturenames and option_value is not None: + metafunc.parametrize("verification", [option_value]) + option_value = metafunc.config.option.nclones if "nclones" in metafunc.fixturenames and option_value is not None: metafunc.parametrize("nclones", [option_value]) @@ -25,7 +33,3 @@ def pytest_generate_tests(metafunc): option_value = metafunc.config.option.show_plots if "show_plots" in metafunc.fixturenames and option_value is not None: metafunc.parametrize("show_plots", [option_value]) - - option_value = metafunc.config.option.model_name - if "model_name" in metafunc.fixturenames and option_value is not None: - metafunc.parametrize("model_name", [option_value]) diff --git a/src/struphy/console/compile.py b/src/struphy/console/compile.py index d92f31285..0cb628b18 100644 --- a/src/struphy/console/compile.py +++ b/src/struphy/console/compile.py @@ -4,17 +4,7 @@ def struphy_compile( - language, - compiler, - compiler_config, - omp_pic, - omp_feec, - delete, - status, - verbose, - dependencies, - time_execution, - yes, + language, compiler, compiler_config, omp_pic, omp_feec, delete, status, verbose, dependencies, time_execution, yes ): """Compile Struphy kernels. All files that contain "kernels" are detected automatically and saved to state.yml. @@ -197,9 +187,9 @@ def struphy_compile( deps = depmod.get_dependencies(ker.replace(".py", so_suffix)) deps_li = deps.split(" ") print("-" * 28) - print(f"{ker =}") + print(f"{ker = }") for dep in deps_li: - print(f"{dep =}") + print(f"{dep = }") else: # struphy and psydac (change dir not to be in source path) @@ -268,11 +258,11 @@ def struphy_compile( # only install (from .whl) if psydac not up-to-date if psydac_ver < struphy_ver: print( - f"You have psydac version {psydac_ver}, but version {struphy_ver} is available. Please re-install struphy (e.g. pip install .)\n", + f"You have psydac version {psydac_ver}, but version {struphy_ver} is available. Please re-install struphy (e.g. pip install .)\n" ) sys.exit(1) else: - print("Psydac is not installed. To install it, please re-install struphy (e.g. pip install .)\n") + print(f"Psydac is not installed. To install it, please re-install struphy (e.g. pip install .)\n") sys.exit(1) else: diff --git a/src/struphy/console/format.py b/src/struphy/console/format.py index 7ba6795c4..747e2d0c1 100644 --- a/src/struphy/console/format.py +++ b/src/struphy/console/format.py @@ -409,7 +409,7 @@ def parse_path(directory): for filename in files: if re.search(r"__\w+__", root): continue - if (filename.endswith(".py") or filename.endswith(".ipynb")) and not re.search(r"__\w+__", filename): + if filename.endswith(".py") and not re.search(r"__\w+__", filename): file_path = os.path.join(root, filename) python_files.append(file_path) # exit() @@ -484,9 +484,7 @@ def get_python_files(input_type, path=None): # python_files = [f for f in files if f.endswith(".py") and os.path.isfile(f)] python_files = [ - os.path.join(repopath, f) - for f in files - if (f.endswith(".py") or f.endswith(".ipynb")) and os.path.isfile(os.path.join(repopath, f)) + os.path.join(repopath, f) for f in files if f.endswith(".py") and os.path.isfile(os.path.join(repopath, f)) ] if not python_files: @@ -578,7 +576,7 @@ def parse_json_file_to_html(json_file_path, html_output_path): "", "", "
Total Issues: {total_issues}
Number of files: {total_files}
-""", +""" ) # Navigation menu @@ -755,7 +753,7 @@ def parse_json_file_to_html(json_file_path, html_output_path): f"""{display_name}{code} - "
f"{message}{display_name}:{row}:{column}{display_name}:{row}:{column}Fix Available ({fix.get('applicability', 'Unknown')}): "
- f"ruff check --select ALL --fix {display_name}
ruff check --select ALL --fix {display_name}"
)
html_content.append("Cannot read file {filename} or invalid row {row}.
Cannot read file {filename} or invalid row {row}.