From 9c6eb9307ef359fe771c6a25a6618bc1b4188c0f Mon Sep 17 00:00:00 2001 From: Lauritz Timm <44357397+s9latimm@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:33:29 +0200 Subject: [PATCH] Fix lint --- README.md | 24 +++++++++++++-------- src/base/mesh.py | 28 ++++++++++++------------ src/base/plot.py | 29 ++++++++++++------------- src/base/shape.py | 2 +- src/nse/__main__.py | 41 ++++++++++++++++++------------------ src/nse/data.py | 4 ++-- src/nse/experiments/block.py | 12 +++++------ src/nse/experiments/foam.py | 28 ++++++++++++------------ src/nse/experiments/step.py | 14 ++++++------ src/nse/experiments/wing.py | 18 ++++++++-------- src/nse/visualize.py | 10 ++++----- 11 files changed, 107 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index b07e01b..84bd718 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,11 @@ ![UML](images/classes.svg) -## References - -- [Raissi, M. et al.: Physics Informed Deep Learning (Part II)](https://arxiv.org/pdf/1711.10566) - -## Requirements +## Setup ### Virtual Environment -#### Windows +#### Windows (Powershell) ```shell $ python -m venv .venv @@ -36,7 +32,7 @@ $ python -m venv .venv $ source ./venv/bin/activate ``` -### Packages +### Dependencies ```shell $ python -m pip install --upgrade pip @@ -47,9 +43,9 @@ $ python -m pip install -r requirements.txt ## Tools -### Navier Stokes Equation +### Navier-Stokes Equation -- [Incompressible Flow](https://en.wikipedia.org/wiki/Navier%E2%80%93Stokes_equations#Incompressible_flow) +- [Wikipedia](https://en.wikipedia.org/wiki/Navier%E2%80%93Stokes_equations#Incompressible_flow) ``` usage: nse [-h] -e {step,block,wing} [-i ] [--nu ] [--rho ] [--id ] [-n ] [-l ] [-d {cpu,cuda}] [-f] [--supervised] [-p] [-r] [--save] @@ -95,3 +91,13 @@ $ python -m src.nse -e wing --id wing -l 100:100:100:100 -i 1 --nu .01 -d cuda - ```shell $ python -m src.nse -e block ``` + +### Burgers' Equation + +- [Wikipedia](https://en.wikipedia.org/wiki/Burgers%27_equation) + +TODO + +## References + +- [Raissi, M. et al.: Physics Informed Deep Learning (Part II)](https://arxiv.org/pdf/1711.10566) diff --git a/src/base/mesh.py b/src/base/mesh.py index 7002572..c7d482c 100644 --- a/src/base/mesh.py +++ b/src/base/mesh.py @@ -1,6 +1,7 @@ from __future__ import annotations import typing as tp +from abc import abstractmethod import numpy as np @@ -151,6 +152,7 @@ def __init__(self, xs: tp.Sequence[float], ys: tp.Sequence[float]) -> None: self.__mesh[i][j] = Coordinate(x, y) def __getattr__(self, item) -> np.ndarray: + # pylint: disable=protected-access return self.map(lambda i: i.__getattribute__(item)).__mesh def __iter__(self) -> tp.Iterator: @@ -184,6 +186,7 @@ def transform(self, cloud: Cloud): return self.map(lambda i: cloud[i]) def map(self, f) -> Mesh: + # pylint: disable=protected-access copy = Mesh([], []) copy.__mesh = np.array(list(map(lambda i: np.array(list(map(f, i))), self.__mesh.copy()))) copy.__width = self.__width @@ -194,7 +197,7 @@ def map(self, f) -> Mesh: class Cloud: def __init__(self) -> None: - self.__cloud: dict[Coordinate, tp.Any] = dict() + self.__cloud: dict[Coordinate, ...] = {} def __contains__(self, coordinate: tuple[float, float] | Coordinate) -> bool: return Coordinate(*coordinate) in self.__cloud.keys() @@ -205,21 +208,13 @@ def __getitem__(self, coordinate: tuple[float, float] | Coordinate) -> tp.Any: raise KeyError(c) return self.__cloud[c] - def mesh(self, refine=0) -> Mesh: - xs = sorted({i.x for i in self.__cloud.keys()}) - ys = sorted({i.y for i in self.__cloud.keys()}) - - # if refine > 0: - # xs = (xs[:, None] + np.linspace(0., 1., refine)).ravel() - # print(xs) - # ys = (ys[:, None] + np.linspace(0., 1., refine)).ravel() - - return Mesh(xs, ys) + def mesh(self) -> Mesh: + return Mesh(sorted({i.x for i in self.__cloud.keys()}), sorted({i.y for i in self.__cloud.keys()})) def keys(self) -> list[Coordinate]: return list(self.__cloud.keys()) - def __iter__(self) -> tp.Iterator[tuple[Coordinate, tp.Any]]: + def __iter__(self) -> tp.Iterator[tuple[Coordinate, ...]]: return iter(self.__cloud.items()) def __len__(self) -> int: @@ -231,22 +226,27 @@ def __repr__(self) -> str: def __str__(self) -> str: return self.__repr__() - def add(self, coordinate: tuple[float, float] | Coordinate, value: tp.Any) -> tp.Any: + def _insert(self, coordinate: tuple[float, float] | Coordinate, value: ...) -> tp.Any: c = Coordinate(*coordinate) if c in self.__cloud: raise KeyError(c) self.__cloud[c] = value return self.__cloud[c] + @abstractmethod + def emplace(self, key: tuple | Coordinate, **kwargs) -> tp.Any: + ... + def clear(self) -> None: self.__cloud.clear() def copy(self) -> tp.Any: + # pylint: disable=protected-access cloud = Cloud() cloud.__cloud = self.__cloud.copy() return cloud - def detach(self) -> list[tuple[Coordinate, tp.Any]]: + def detach(self) -> list[tuple[Coordinate, ...]]: return list(self.__cloud.copy().items()) def numpy(self) -> np.ndarray: diff --git a/src/base/plot.py b/src/base/plot.py index d82c04f..821b337 100644 --- a/src/base/plot.py +++ b/src/base/plot.py @@ -3,9 +3,9 @@ import typing as tp from pathlib import Path -import matplotlib.colors as colors import matplotlib.pyplot as plt import numpy as np +from matplotlib import colors from matplotlib.ticker import FuncFormatter from src.base.mesh import Coordinate, Cloud @@ -27,7 +27,7 @@ SCALE: float = 5. -def draw(ax: plt.Axes, shape: Shape) -> None: +def draw_shape(ax: plt.Axes, shape: Shape) -> None: polygon = shape[::.01] ax.plot(polygon.x, polygon.y, color='k', linestyle='--', linewidth=1, zorder=999) @@ -50,15 +50,14 @@ def plot_losses( ax = fig.add_subplot(len(plots), 1, i + 1) - m = np.infty - n = -np.infty + t_min, t_max = np.infty, -np.infty for j, line in enumerate(lines): l, y = line ax.plot(np.arange(1, len(y) + 1, 1), y, label=l, color=COLORS[j]) ax.axhline(y=float(y[-1]), color=COLORS[j], linestyle='--') - m = min(m, min(y)) - n = max(n, max(y)) + y_min, y_max = min(y), max(y) + t_min, t_max = min(t_min, y_min), max(t_max, y_max) ax.set_xlabel('iter') ax.set_ylabel('err') @@ -71,7 +70,7 @@ def plot_losses( ax.set_xlim([1, len(lines[0][1])]) ax.set_xticks([1, 10**np.floor(np.log10(len(lines[0][1])))]) ax.set_yscale('log') - ax.set_yticks([10**np.floor(np.log10(n)), 10**np.floor(np.log10(m)), 10**np.ceil(np.log10(m))]) + ax.set_yticks([10**np.floor(np.log10(t_max)), 10**np.floor(np.log10(t_min)), 10**np.ceil(np.log10(t_min))]) ax.legend(loc='upper right') @@ -99,7 +98,7 @@ def __init__(self, x: np.ndarray, y: np.ndarray, path: Path = None, n: int = 1) q = (int(np.round(x.max())) - int(np.round(x.min()))) / (int(np.round(y.max())) - int(np.round(y.min()))) super().__init__(figsize=(q * SCALE, n * SCALE)) - def layout(self, ax: plt.Axes, title: str, boundary: Figure = None, figure: Figure = None) -> None: + def setup(self, ax: plt.Axes, title: str, boundary: Figure = None, figure: Figure = None) -> None: ax.pcolormesh( self.__x, self.__y, @@ -125,10 +124,10 @@ def layout(self, ax: plt.Axes, title: str, boundary: Figure = None, figure: Figu if boundary is not None: for shape in boundary: - draw(ax, shape) + draw_shape(ax, shape) if figure is not None: for shape in figure: - draw(ax, shape) + draw_shape(ax, shape) ax.set_title(title) @@ -163,7 +162,7 @@ def plot_heatmaps( label, z = plot ax = fig.add_subplot(len(plots), 1, i + 1) - fig.layout(ax, label, boundary, figure) + fig.setup(ax, label, boundary, figure) if z.min() < 0 < z.max(): slope = colors.TwoSlopeNorm(vmin=z.min(), vcenter=0, vmax=z.max()) @@ -239,7 +238,7 @@ def plot_heatmaps( format=FuncFormatter(lambda j, pos: f'{j:.1f}'), ) - ticks = list() + ticks = [] if z.min() < 0: ticks.append(z.min()) ticks.append(0) @@ -262,7 +261,7 @@ def plot_clouds( plots = [] masks = [] - for p, label, in enumerate(labels): + for label, in labels: plots.append((label, np.full(x.shape, np.nan))) masks.append(np.full(x.shape, .5)) @@ -290,7 +289,7 @@ def plot_streamlines( ) -> None: with Plot(x, y, path) as fig: ax = fig.add_subplot() - fig.layout(ax, title, boundary, figure) + fig.setup(ax, title, boundary, figure) speed = np.sqrt(np.square(u) + np.square(v)) speed = 1 + 4 * speed / speed.max() @@ -320,7 +319,7 @@ def plot_arrows( ) -> None: with Plot(x, y, path) as fig: ax = fig.add_subplot() - fig.layout(ax, title, boundary, figure) + fig.setup(ax, title, boundary, figure) for i in range(x.shape[0]): for j in range(x.shape[1]): diff --git a/src/base/shape.py b/src/base/shape.py index 9c15d03..01e96b5 100644 --- a/src/base/shape.py +++ b/src/base/shape.py @@ -213,7 +213,7 @@ def __f(self, x) -> tuple[Coordinate, Coordinate]: return upper, lower def __contains__(self, coordinate: tuple[float, float] | Coordinate) -> bool: - c = ((Coordinate(*coordinate) - self.__a) / self.__length) + c = (Coordinate(*coordinate) - self.__a) / self.__length if 0 <= c.x <= 1: upper, lower = self.__f(c.x) return lower.y <= c.y <= upper.y diff --git a/src/nse/__main__.py b/src/nse/__main__.py index 493c455..a0fef62 100644 --- a/src/nse/__main__.py +++ b/src/nse/__main__.py @@ -35,7 +35,7 @@ def main( logging.info(f'GRID: {experiment.knowledge.mesh().shape}') logging.info(f'DIMENSIONS: {experiment.dim}') logging.info(f'HIRES: {HIRES}') - logging.info(f'STEPS: {args.train}') + logging.info(f'STEPS: {n}') logging.info(f'TIMESTAMP: {TIMESTAMP}') logging.info(f'OUTPUT: {(OUTPUT_DIR / identifier).relative_to(ROOT_DIR)}') @@ -81,7 +81,7 @@ def callback(history): logging.info('PLOT: PREDICTION') plot_prediction(pbar.n, experiment, model, identifier) logging.info('PLOT: LOSS') - plot_history(pbar.n, experiment, model, identifier) + plot_history(pbar.n, model, identifier) if hires and pbar.n % 1e4 == 0: logging.info('PLOT: HIRES PREDICTION') plot_prediction(pbar.n, experiment, model, identifier, hires=True) @@ -100,7 +100,7 @@ def callback(history): logging.info('PLOT: PREDICTION') plot_prediction(n, experiment, model, identifier) logging.info('PLOT: LOSS') - plot_history(pbar.n, experiment, model, identifier) + plot_history(pbar.n, model, identifier) if hires: logging.info('PLOT: HIRES PREDICTION') @@ -175,6 +175,7 @@ def layers_type(arg: str) -> list[int]: return layers except (TypeError, ValueError): parser.error(f"argument -l/--layers: invalid value: '{arg}'") + return [] parser.add_argument( '-l', @@ -240,12 +241,12 @@ def layers_type(arg: str) -> list[int]: if __name__ == '__main__': - args = parse_cmd() - if args.plot: - (OUTPUT_DIR / args.id).mkdir(parents=True, exist_ok=args.id != TIMESTAMP) + cmd = parse_cmd() + if cmd.plot: + (OUTPUT_DIR / cmd.id).mkdir(parents=True, exist_ok=cmd.id != TIMESTAMP) logging.basicConfig(format='%(message)s', handlers=[ - logging.FileHandler(OUTPUT_DIR / args.id / 'log.txt', mode='w'), + logging.FileHandler(OUTPUT_DIR / cmd.id / 'log.txt', mode='w'), logging.StreamHandler(sys.stdout) ], encoding='utf-8', @@ -258,20 +259,20 @@ def layers_type(arg: str) -> list[int]: try: main( - EXPERIMENTS[args.experiment]( - args.nu, - args.rho, - args.intake, - args.supervised, + EXPERIMENTS[cmd.experiment]( + cmd.nu, + cmd.rho, + cmd.intake, + cmd.supervised, ), - args.train, - args.plot, - args.id, - args.device, - args.foam, - args.hires, - args.save, - args.layers, + cmd.train, + cmd.plot, + cmd.id, + cmd.device, + cmd.foam, + cmd.hires, + cmd.save, + cmd.layers, ) logging.info('EXIT: SUCCESS') except KeyboardInterrupt: diff --git a/src/nse/data.py b/src/nse/data.py index 39d4e89..f940287 100644 --- a/src/nse/data.py +++ b/src/nse/data.py @@ -67,8 +67,8 @@ class NSECloud(Cloud): def __getitem__(self, key: tuple | Coordinate) -> NSEFact: return super().__getitem__(key) - def add(self, key: tuple | Coordinate, **kwargs) -> NSEFact: - return super().add(key, NSEFact(**kwargs)) + def emplace(self, key: tuple | Coordinate, **kwargs) -> NSEFact: + return super()._insert(key, NSEFact(**kwargs)) def copy(self) -> NSECloud: return super().copy() diff --git a/src/nse/experiments/block.py b/src/nse/experiments/block.py index 4eb10a6..bd4662a 100644 --- a/src/nse/experiments/block.py +++ b/src/nse/experiments/block.py @@ -44,20 +44,20 @@ def __init__( # inlet for y in arrange(0, 2, s): u = inlet(0, 2, flow)(y) - self._knowledge.add((0, y), u=u, v=0) - self._outlet.add((10, y)) + self._knowledge.emplace((0, y), u=u, v=0) + self._outlet.emplace((10, y)) # border for x in arrange(s, 10 - s, s): - self._knowledge.add((x, 0), u=0, v=0) - self._knowledge.add((x, 2), u=0, v=0) + self._knowledge.emplace((x, 0), u=0, v=0) + self._knowledge.emplace((x, 2), u=0, v=0) for figure in self.obstruction: for c in figure[::s]: - self._knowledge.add(c, u=0, v=0) + self._knowledge.emplace(c, u=0, v=0) # training mesh = Mesh(self.x.arrange(t), self.y.arrange(t)) for c in mesh: if c not in self._knowledge and c not in self._learning and c not in self.obstruction: - self._learning.add(c) + self._learning.emplace(c) diff --git a/src/nse/experiments/foam.py b/src/nse/experiments/foam.py index cd63c7b..5a7e376 100644 --- a/src/nse/experiments/foam.py +++ b/src/nse/experiments/foam.py @@ -50,7 +50,7 @@ def __init__( p = np.flip(p, 0).transpose().flatten() for i, c in enumerate(self.__mesh): - self._knowledge.add(c, u=u[i], v=v[i], p=p[i]) + self._knowledge.emplace(c, u=u[i], v=v[i], p=p[i]) @property def mesh(self) -> Mesh: @@ -60,7 +60,7 @@ def mesh(self) -> Mesh: def __parse_velocity(path: Path) -> tuple[list[float], list[float]]: u, v = [], [] - with open(path, 'r') as file: + with open(path, 'r', encoding='utf-8') as file: lines = file.readlines() # Flag to start collecting data @@ -94,7 +94,7 @@ def __parse_velocity(path: Path) -> tuple[list[float], list[float]]: def __parse_pressure(path: Path) -> list[float]: p = [] - with open(path, 'r') as file: + with open(path, 'r', encoding='utf-8') as file: lines = file.readlines() # Flag to start collecting data @@ -109,13 +109,11 @@ def __parse_pressure(path: Path) -> list[float]: continue if munch: - ''' - match = [] - match = re.findall(r'-?\d+\.\d+', line) - # Extract tuples using regular expression - if match != []: - data.append(float(match[0])) - ''' + # match = [] + # match = re.findall(r'-?\d+\.\d+', line) + # # Extract tuples using regular expression + # if match != []: + # data.append(float(match[0])) p.append(float(line)) # Start of data section @@ -138,16 +136,16 @@ def __convert(data: list[float], model: list[tuple[int, int, int, int]]) -> np.n values = np.zeros((size_y, size_x)) head = 0 - for i in range(len(model)): - px = model[i][2] - model[i][0] - py = model[i][3] - model[i][1] + for mode in model: + px = mode[2] - mode[0] + py = mode[3] - mode[1] tail = head + px * py - part = (data[head:tail]) + part = data[head:tail] for y in range(py): for x in range(px): - values[model[i][1] + y - min_y][model[i][0] + x - min_x] = part[(py - 1 - y) * px + x] + values[mode[1] + y - min_y][mode[0] + x - min_x] = part[(py - 1 - y) * px + x] head = tail diff --git a/src/nse/experiments/step.py b/src/nse/experiments/step.py index 3b2937b..32f7250 100644 --- a/src/nse/experiments/step.py +++ b/src/nse/experiments/step.py @@ -44,25 +44,25 @@ def __init__( # inlet for y in arrange(1, 2, s): u = inlet(1, 2, flow)(y) - self._knowledge.add((0, y), u=u, v=0) - self._outlet.add((10, y)) + self._knowledge.emplace((0, y), u=u, v=0) + self._outlet.emplace((10, y)) # border for x in arrange(1, 10, s): - self._knowledge.add((x, 0), u=0, v=0) + self._knowledge.emplace((x, 0), u=0, v=0) for x in arrange(s, 10, s): - self._knowledge.add((x, 2), u=0, v=0) + self._knowledge.emplace((x, 2), u=0, v=0) for x in arrange(s, 1, s): - self._knowledge.add((x, 1), u=0, v=0) + self._knowledge.emplace((x, 1), u=0, v=0) for y in arrange(s, 1 - s, s): - self._knowledge.add((1, y), u=0, v=0) + self._knowledge.emplace((1, y), u=0, v=0) # training mesh = Mesh(self.x.arrange(t), self.y.arrange(t)) for c in mesh: if c not in self._knowledge and c not in self._learning and c not in self.obstruction: - self._learning.add(c) + self._learning.emplace(c) if supervised: self._knowledge = self.foam.knowledge diff --git a/src/nse/experiments/wing.py b/src/nse/experiments/wing.py index 71b4c26..89df316 100644 --- a/src/nse/experiments/wing.py +++ b/src/nse/experiments/wing.py @@ -28,38 +28,38 @@ def __init__( # intake for y in arrange(0, 2, .05): u = inlet * (1. - (1. - y)**2) - self._knowledge.add((0, y), u=u, v=0) + self._knowledge.emplace((0, y), u=u, v=0) # border for x in arrange(.05, 9.95, .05): - self._knowledge.add((x, 0), u=0, v=0) - self._knowledge.add((x, 2), u=0, v=0) + self._knowledge.emplace((x, 0), u=0, v=0) + self._knowledge.emplace((x, 2), u=0, v=0) for c in airfoil[::.05]: - self._knowledge.add(c, u=0, v=0) + self._knowledge.emplace(c, u=0, v=0) iline = airfoil[::.05].interpolate(-.05) for c in iline: - self._knowledge.add(c, u=0, v=0) + self._knowledge.emplace(c, u=0, v=0) mesh = Mesh(self.x.arrange(.1), self.y.arrange(.1)) for c in mesh: if c not in self._knowledge and c in iline: - self._knowledge.add(c, u=0, v=0) + self._knowledge.emplace(c, u=0, v=0) outline = airfoil[::.05].interpolate(.05) bline = outline.interpolate(.05) for c in outline: if c not in self._learning: - self._learning.add(c) + self._learning.emplace(c) for c in bline: if c not in self._learning: - self._learning.add(c) + self._learning.emplace(c) mesh = Mesh(self.x.arrange(.1, True), self.y.arrange(.1, True)) for c in mesh: if c not in self._knowledge and c not in self._learning and c not in bline: - self._learning.add(c) + self._learning.emplace(c) diff --git a/src/nse/visualize.py b/src/nse/visualize.py index a7b50e3..bc7083d 100644 --- a/src/nse/visualize.py +++ b/src/nse/visualize.py @@ -33,7 +33,7 @@ def plot_diff(n, experiment: NSEExperiment, model: Simulation, identifier: str): ('v', np.abs(v - foam.v)), ('p', np.abs(p - foam.p)), ], - path=OUTPUT_DIR / identifier / f'diff_uvp.pdf', + path=OUTPUT_DIR / identifier / 'diff_uvp.pdf', boundary=experiment.boundary, figure=experiment.obstruction, ) @@ -73,7 +73,7 @@ def plot_prediction(n, experiment: NSEExperiment, model: Simulation, identifier: ('v', v), ('p', p), ], - path=OUTPUT_DIR / identifier / f'pred_uvp_hires.pdf', + path=OUTPUT_DIR / identifier / 'pred_uvp_hires.pdf', boundary=experiment.boundary, figure=experiment.obstruction, ) @@ -152,7 +152,7 @@ def plot_prediction(n, experiment: NSEExperiment, model: Simulation, identifier: ) -def plot_history(n, experiment: NSEExperiment, model: Simulation, identifier: str): +def plot_history(n, model: Simulation, identifier: str): plot_losses( f'Loss [n={n}, $\\nu$={model.nu:.3E}, $\\rho$={model.rho:.3E}]', [ @@ -168,7 +168,7 @@ def plot_history(n, experiment: NSEExperiment, model: Simulation, identifier: st ('$\\Sigma$', [i[2] for i in model.history[1:]]), ]), ], - path=OUTPUT_DIR / identifier / f'err.pdf', + path=OUTPUT_DIR / identifier / 'err.pdf', ) @@ -199,7 +199,7 @@ def plot_foam(experiment: NSEExperiment, identifier: str): y, u, v, - path=OUTPUT_DIR / identifier / 'foam' / f'foam_str.pdf', + path=OUTPUT_DIR / identifier / 'foam' / 'foam_str.pdf', boundary=experiment.boundary, figure=experiment.obstruction, )