diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 878508f3058cc8e163ac276631b7336800545fad..6b4d76de1f850cb5c1c8866adb358a7ac7661593 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,29 @@ jobs: curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/main/prepare-and-run-flake8.sh . ./prepare-and-run-flake8.sh "$(basename $GITHUB_REPOSITORY)" examples test + pylint: + name: Pylint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: "Main Script" + run: | + sudo apt update + sudo apt install openmpi-bin libopenmpi-dev + + CONDA_ENVIRONMENT=.test-conda-env-py3.yml + echo "- mpi4py" >> $CONDA_ENVIRONMENT + echo "- scipy" >> $CONDA_ENVIRONMENT + echo "-------------------------------------------" + cat $CONDA_ENVIRONMENT + echo "-------------------------------------------" + USE_CONDA_BUILD=1 + + curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-pylint.sh + + . ./prepare-and-run-pylint.sh "$(basename $GITHUB_REPOSITORY)" test/*.py \ + $(find examples -name '*.py') + pytest3: name: Pytest on Py3 runs-on: ubuntu-latest diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b0f0aa6ce26727c33f0820c68cbc204c81976fd9..a0f265290e65a39f10f6a9c36193278817c3d038 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -106,3 +106,14 @@ Flake8: - python3 except: - tags + +Pylint: + script: | + EXTRA_INSTALL="pybind11 make numpy scipy matplotlib mpi4py" + curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-pylint.sh + . ./prepare-and-run-pylint.sh "$CI_PROJECT_NAME" test/*.py \ + $(find examples -name '*.py') + tags: + - python3 + except: + - tags diff --git a/.pylintrc-local.yml b/.pylintrc-local.yml new file mode 100644 index 0000000000000000000000000000000000000000..be1948583b86a81c56b102f4c159e1282e5d31dd --- /dev/null +++ b/.pylintrc-local.yml @@ -0,0 +1,11 @@ +- arg: ignore + val: + - mappers + - gas_dynamics + - burgers.py + - diffusion.py + - dt_finding.py + - nd_calculus.py + - pml.py + - poisson.py + - second_order.py diff --git a/examples/dagrt-fusion.py b/examples/dagrt-fusion.py index 779a783cc991f5a5be1979142c1d45a2bd27789b..436d5c9d026b417ced96ed77e1a4afe2a44ee330 100755 --- a/examples/dagrt-fusion.py +++ b/examples/dagrt-fusion.py @@ -1294,8 +1294,7 @@ def main(): else: if not SKIP_TESTS: # Run tests. - from py.test import main - result = main([__file__]) + result = pytest.main([__file__]) assert result == 0 # Run examples. diff --git a/grudge/discretization.py b/grudge/discretization.py index 125f2ca7c4a0dcdec6f163c4df2abecff79ea161..a15f43736f5e784ccbc7e7a2a00cb90cf335b544 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -110,7 +110,7 @@ class DiscretizationCollection: return True else: return self.mpi_communicator.Get_rank() \ - == self._get_management_rank_index() + == self.get_management_rank_index() def _set_up_distributed_communication(self, mpi_communicator, array_context): from_dd = sym.DOFDesc("vol", sym.QTAG_NONE) @@ -383,9 +383,7 @@ class DiscretizationCollection: def is_volume_where(self, where): from grudge import sym - return ( - where is None - or where == sym.VTAG_ALL) + return where is None or sym.as_dofdesc(where).is_volume() @property def order(self): diff --git a/grudge/eager.py b/grudge/eager.py index 32eccaaa99f4893873db6465c2ba249db2d353b8..22dd4298af53c277168f4d5c3203bd6e879e3b4b 100644 --- a/grudge/eager.py +++ b/grudge/eager.py @@ -60,7 +60,7 @@ class EagerDGDiscretization(DiscretizationCollection): return op.local_d_dx(self, xyz_axis, vec) def div(self, vecs): - return op.local_d_dx(self, vecs) + return op.local_div(self, vecs) def weak_grad(self, *args): return op.weak_local_grad(self, *args) diff --git a/grudge/models/__init__.py b/grudge/models/__init__.py index 6b2d4e59e8c503d123a1790112afc9ce7c1eeef1..8486bd2e059f0026081cc88a90bb258a5a08f9d5 100644 --- a/grudge/models/__init__.py +++ b/grudge/models/__init__.py @@ -48,6 +48,9 @@ class TimeDependentOperator(Operator): class HyperbolicOperator(Operator): """A base class for hyperbolic Discontinuous Galerkin operators.""" + def max_eigenvalue(self, t, fields, discr): + raise NotImplementedError + def estimate_rk4_timestep(self, discr, t=None, fields=None): """Estimate the largest stable timestep for an RK4 method. """ diff --git a/grudge/models/em.py b/grudge/models/em.py index d8fbdb4ee0d967b8531530c9c6ff8c1752151f03..244d324e0749ef48d19a67af9ab0be5c3156aa0c 100644 --- a/grudge/models/em.py +++ b/grudge/models/em.py @@ -323,7 +323,9 @@ class MaxwellOperator(HyperbolicOperator): return 1/sqrt(self.epsilon*self.mu) # a number else: import grudge.symbolic as sym - return sym.NodalMax()(1/sym.FunctionSymbol("sqrt")(self.epsilon*self.mu)) + return sym.NodalMax("vol")( + 1 / sym.sqrt(self.epsilon * self.mu) + ) def max_eigenvalue(self, t, fields=None, discr=None, context={}): if self.fixed_material: diff --git a/grudge/models/gas_dynamics/__init__.py b/grudge/models/gas_dynamics/__init__.py index 8c86c8e0aed0c4cae043cec274f171122668f4cc..7562bae3148bdf6e4d3833a737b4939c52a595ff 100644 --- a/grudge/models/gas_dynamics/__init__.py +++ b/grudge/models/gas_dynamics/__init__.py @@ -661,7 +661,7 @@ class GasDynamicsOperator(TimeDependentOperator): result = RestrictToBoundary(tag)(self.sensor()) return cse(to_bdry_quad(result), "bdry_sensor") - from grudge.symbolic import SubstitutionMapper + from grudge.symbolic.mappers import SubstitutionMapper return SubstitutionMapper(subst_func)(expr) # }}} diff --git a/grudge/models/wave.py b/grudge/models/wave.py index a06295bb4743c671c9ce33c5bd00258733f96923..5fc65a70e2235ea03d33ef95ad7e91e302f313c4 100644 --- a/grudge/models/wave.py +++ b/grudge/models/wave.py @@ -110,7 +110,7 @@ class WeakWaveOperator(HyperbolicOperator): warn("Inhomogeneous Dirichlet conditions on the wave equation " "are still having issues.") - dir_g = sym.Field("dir_bc_u") + dir_g = sym.var("dir_bc_u") dir_bc = flat_obj_array(2*dir_g - dir_u, dir_v) else: dir_bc = flat_obj_array(-dir_u, dir_v) @@ -254,7 +254,7 @@ class VariableCoefficientWeakWaveOperator(HyperbolicOperator): warn("Inhomogeneous Dirichlet conditions on the wave equation " "are still having issues.") - dir_g = sym.Field("dir_bc_u") + dir_g = sym.var("dir_bc_u") dir_bc = flat_obj_array(dir_c, 2*dir_g - dir_u, dir_v) else: dir_bc = flat_obj_array(dir_c, -dir_u, dir_v) @@ -310,7 +310,7 @@ class VariableCoefficientWeakWaveOperator(HyperbolicOperator): self.radiation_tag]) def max_eigenvalue(self, t, fields=None, discr=None): - return sym.NodalMax()(sym.FunctionSymbol("fabs")(self.c)) + return sym.NodalMax("vol")(sym.fabs(self.c)) # }}} diff --git a/grudge/op.py b/grudge/op.py index a9a514e5ffdb415ab0359d07a76815d2dcbfe22f..b8204cf16e9254f0df68c1d8781b94914b165376 100644 --- a/grudge/op.py +++ b/grudge/op.py @@ -364,7 +364,7 @@ def norm(dcoll, vec, p, dd=None): if isinstance(vec, np.ndarray): if p == 2: return sum( - norm(dcoll, vec[idx], dd=dd)**2 + norm(dcoll, vec[idx], p, dd=dd)**2 for idx in np.ndindex(vec.shape))**0.5 elif p == np.inf: return max( diff --git a/grudge/symbolic/mappers/__init__.py b/grudge/symbolic/mappers/__init__.py index fcbb89ea3e0645b3e6b30fd6a5b83089862fa89b..799a0bc5e1a311a54a17309a746121946f86309c 100644 --- a/grudge/symbolic/mappers/__init__.py +++ b/grudge/symbolic/mappers/__init__.py @@ -502,7 +502,7 @@ class OperatorSpecializer(CSECachingMapperMixin, IdentityMapper): IdentityMapper.map_common_subexpression def map_operator_binding(self, expr): - from grudge.symbolic.primitives import BoundaryPair + from grudge.symbolic.primitives import TracePair from grudge.symbolic.mappers.type_inference import ( type_info, QuadratureRepresentation) @@ -520,7 +520,7 @@ class OperatorSpecializer(CSECachingMapperMixin, IdentityMapper): field_repr_tag = field_type.repr_tag except AttributeError: # boundary pairs are not assigned types - assert isinstance(expr.field, BoundaryPair) + assert isinstance(expr.field, TracePair) has_quad_operand = False else: has_quad_operand = isinstance(field_repr_tag, diff --git a/grudge/symbolic/operators.py b/grudge/symbolic/operators.py index 5a48a12a8551757713af6413cfc92143a0a1857d..b6c385b1612f87e42aa4ceb0a5beb6704cb14193 100644 --- a/grudge/symbolic/operators.py +++ b/grudge/symbolic/operators.py @@ -424,12 +424,11 @@ class FilterOperator(ElementwiseLinearOperator): for mid in ldis.generate_mode_identifiers()] # build filter matrix + import numpy.linalg as la vdm = ldis.vandermonde() - from grudge.tools import leftsolve mat = np.asarray( - leftsolve(vdm, - np.dot(vdm, np.diag(filter_coeffs))), - order="C") + la.solve(vdm.T, np.diag(filter_coeffs) @ vdm.T).T, + order="C") return mat @@ -448,7 +447,7 @@ class AveragingOperator(ElementwiseLinearOperator): if dd_in != dd_out: raise ValueError("dd_in and dd_out must be identical") - super(FilterOperator, self).__init__(dd_in, dd_out) + super().__init__(dd_in, dd_out) def matrix(self, eg): # average matrix, so that AVE*fields = cellaverage(fields) diff --git a/grudge/symbolic/tools.py b/grudge/symbolic/tools.py index 12d8c47fe66a473e2d380c83e3ea09c95b0dd1aa..7907060ce3bc5a64642805d22976f4c5e1096348 100644 --- a/grudge/symbolic/tools.py +++ b/grudge/symbolic/tools.py @@ -58,7 +58,7 @@ def split_sym_operator_for_multirate(state_vector, sym_operator, killers.append(IndexGroupKillerSubstMap(kill_set)) - from grudge.symbolic import \ + from grudge.symbolic.mappers import \ SubstitutionMapper, \ CommutativeConstantFoldingMapper diff --git a/test/mesh_data.py b/test/mesh_data.py index 14cee46d54aa1fbb823479d51ede6c5c1e419fe2..fbe2712fc70ecc811aae9721a62831cb09ff30df 100644 --- a/test/mesh_data.py +++ b/test/mesh_data.py @@ -31,7 +31,7 @@ class Curve2DMeshBuilder(MeshBuilder): def get_mesh(self, resolution, mesh_order): from meshmode.mesh.generation import make_curve_mesh return make_curve_mesh( - self.curve_fn, + self.curve_fn, # pylint: disable=no-member np.linspace(0.0, 1.0, resolution + 1), mesh_order) diff --git a/test/test_grudge.py b/test/test_grudge.py index edbdc10362b300a4bfc14a3d894a02a276d3f996..8401caf5b87d53adb68c062250ab8991aaa641cf 100644 --- a/test/test_grudge.py +++ b/test/test_grudge.py @@ -166,7 +166,7 @@ def _ellipse_surface_area(radius, aspect_ratio): # NOTE: hardcoded value so we don't need scipy for the test ellip_e = 1.2110560275684594 else: - from scipy.special import ellipe + from scipy.special import ellipe # pylint: disable=no-name-in-module ellip_e = ellipe(eccentricity) return 4.0 * radius * ellip_e