{"id":45096813,"url":"https://github.com/giacomoguidotto/anypinn","last_synced_at":"2026-05-04T14:02:35.009Z","repository":{"id":319111294,"uuid":"1074208236","full_name":"giacomoguidotto/anypinn","owner":"giacomoguidotto","description":"🤖 A modular and flexible solution to build Physics-Informed Neural Networks (PINNs) for any mathematical problem.","archived":false,"fork":false,"pushed_at":"2026-05-04T09:40:51.000Z","size":102929,"stargazers_count":7,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-04T10:31:30.051Z","etag":null,"topics":["pinn","python","pytorch","pytorch-lightning","uv"],"latest_commit_sha":null,"homepage":"https://anypinn.guidotto.dev/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"johnthagen/python-blueprint","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/giacomoguidotto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-10-11T10:53:25.000Z","updated_at":"2026-05-04T09:36:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/giacomoguidotto/anypinn","commit_stats":null,"previous_names":["giacomoguidotto/pinn","giacomoguidotto/anypinn"],"tags_count":91,"template":false,"template_full_name":null,"purl":"pkg:github/giacomoguidotto/anypinn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giacomoguidotto%2Fanypinn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giacomoguidotto%2Fanypinn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giacomoguidotto%2Fanypinn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giacomoguidotto%2Fanypinn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/giacomoguidotto","download_url":"https://codeload.github.com/giacomoguidotto/anypinn/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giacomoguidotto%2Fanypinn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32610278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pinn","python","pytorch","pytorch-lightning","uv"],"created_at":"2026-02-19T19:03:39.748Z","updated_at":"2026-05-04T14:02:35.003Z","avatar_url":"https://github.com/giacomoguidotto.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/giacomoguidotto/anypinn/main/assets/logo.png\" alt=\"AnyPINN\" width=\"160\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eAnyPINN\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eSolve differential equations with Physics-Informed Neural Networks.\u003c/strong\u003e\u003cbr\u003e\n  \u003csub\u003eModular. Training-agnostic. Inverse-problem-first.\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/giacomoguidotto/anypinn/actions\"\u003e\u003cimg src=\"https://github.com/giacomoguidotto/anypinn/actions/workflows/ci.yaml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/anypinn/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/anypinn\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/astral-sh/uv\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json\" alt=\"uv\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/astral-sh/ruff\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\" alt=\"Ruff\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://docs.astral.sh/ty/\"\u003e\u003cimg src=\"https://img.shields.io/badge/ty-typed-blue\" alt=\"Type checked with ty\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\nMost PINN libraries make you wire up every loss term, collocation grid, and training loop by hand before you see a single result. AnyPINN gives you a working experiment in one command and then lets you peel back every layer when you're ready.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/giacomoguidotto/anypinn/main/examples/allen_cahn/results/allen-cahn.png\" alt=\"Allen-Cahn equation\"/\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/giacomoguidotto/anypinn/main/examples/lorenz/results/lorenz.png\" alt=\"Lorenz system\"/\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/giacomoguidotto/anypinn/main/examples/sir_inverse/results/sir-inverse.png\" alt=\"SIR inverse problem\"/\u003e\n\u003c/p\u003e\n\n## 🚀 Quick Start\n\nThe fastest way to start is from the terminal. The command below generates a complete, runnable project interactively, no manual setup needed. [uvx](https://docs.astral.sh/uv/guides/tools/) lets you run it without installing anything permanently:\n\n```bash\nuvx anypinn create my-project\n```\n\n[pipx](https://pipx.pypa.io/stable/installation/) works the same way:\n\n```bash\npipx run anypinn create my-project\n```\n\nRun `anypinn create --help` to see all available flags and templates. For a full walkthrough covering project structure, configuration, training, and next steps, see the [Getting Started](docs/getting-started.md) guide.\n\n## 👥 Who Is This For?\n\nAnyPINN is built around **progressive complexity**. Start simple, go deeper only when you need to.\n\n| User                  | Goal                                               | How                                                                   |\n| --------------------- | -------------------------------------------------- | --------------------------------------------------------------------- |\n| **Experimenter**      | Run a known problem, tweak parameters, see results | Pick a built-in template, change config, press start                  |\n| **Researcher**        | Define new physics or custom constraints           | Subclass `Constraint` and `Problem`, use the provided training engine |\n| **Framework builder** | Custom training loops, novel architectures         | Use `anypinn.core` directly, no Lightning required                 |\n\n## 💡 Examples\n\nThe `examples/` directory has ready-made, self-contained scripts covering epidemic models, oscillators, predator-prey dynamics, and more, from a minimal ~80-line core-only script to full Lightning stacks. They're a great source of inspiration when defining your own problem.\n\n## 🔬 Defining Your Own Problem\n\nIf you want to go beyond the built-in templates, here is the full workflow for defining a custom inverse problem.\n\n### 1: Define the ODE/PDE\n\nImplement a function matching the `ODECallable` protocol:\n\n```python\nfrom torch import Tensor\nfrom anypinn.core import ArgsRegistry\n\ndef my_ode(x: Tensor, y: Tensor, args: ArgsRegistry) -\u003e Tensor:\n    \"\"\"Return dy/dx given current state y and position x.\"\"\"\n    k = args[\"k\"](x)        # learnable or fixed parameter\n    return -k * y           # simple exponential decay\n```\n\n### 2: Configure hyperparameters\n\n```python\nfrom dataclasses import dataclass\nfrom anypinn.problems import ODEHyperparameters\n\n@dataclass(frozen=True, kw_only=True)\nclass MyHyperparameters(ODEHyperparameters):\n    pde_weight: float = 1.0\n    ic_weight: float = 10.0\n    data_weight: float = 5.0\n```\n\n### 3: Build the problem\n\n```python\nfrom anypinn.problems import ODEInverseProblem, ODEProperties\n\nprops = ODEProperties(ode=my_ode, args={\"k\": param}, y0=y0)\nproblem = ODEInverseProblem(\n    ode_props=props,\n    fields={\"u\": field},\n    params={\"k\": param},\n    hp=hp,\n)\n```\n\n### 4: Train\n\n```python\nimport pytorch_lightning as pl\nfrom anypinn.lightning import PINNModule\n\n# With Lightning (batteries included)\nmodule = PINNModule(problem, hp)\ntrainer = pl.Trainer(max_epochs=50_000)\ntrainer.fit(module, datamodule=dm)\n\n# Or with your own training loop (core only, no Lightning)\noptimizer = torch.optim.Adam(problem.parameters(), lr=1e-3)\nfor batch in dataloader:\n    optimizer.zero_grad()\n    loss = problem.training_loss(batch, log=my_log_fn)\n    loss.backward()\n    optimizer.step()\n```\n\n## 🏗️ Architecture\n\nAnyPINN is split into four layers with a strict dependency direction: outer layers depend on inner ones, never the reverse.\n\n```mermaid\ngraph TD\n    EXP[\"Your Experiment / Generated Project\"]\n\n    EXP --\u003e CAT\n    EXP --\u003e LIT\n\n    subgraph CAT[\"anypinn.catalog\"]\n        direction LR\n        CA1[SIR / SEIR]\n        CA2[DampedOscillator]\n        CA3[LotkaVolterra]\n    end\n\n    subgraph LIT[\"anypinn.lightning (optional)\"]\n        direction LR\n        L1[PINNModule]\n        L2[Callbacks]\n        L3[PINNDataModule]\n    end\n\n    subgraph PROB[\"anypinn.problems\"]\n        direction LR\n        P1[ResidualsConstraint]\n        P2[ICConstraint]\n        P3[DataConstraint]\n        P4[ODEInverseProblem]\n    end\n\n    subgraph CORE[\"anypinn.core (standalone · pure PyTorch)\"]\n        direction LR\n        C1[Problem · Constraint]\n        C2[Field · Parameter]\n        C3[Config · Context]\n    end\n\n    CAT --\u003e|depends on| PROB\n    CAT --\u003e|depends on| CORE\n    LIT --\u003e|depends on| CORE\n    PROB --\u003e|depends on| CORE\n```\n\n### `anypinn.core`: The Math Layer\n\nPure PyTorch. Defines what a PINN problem _is_, with no opinions about training.\n\n- **`Problem`**: aggregates constraints, fields, and parameters. Provides `training_loss()` and `predict()`.\n- **`Constraint`** (ABC): a single loss term. Subclass it to express any physics equation, boundary condition, or data-matching objective.\n- **`Field`**: MLP mapping input coordinates to state variables (e.g., `t → [S, I, R]`).\n- **`Parameter`**: learnable scalar or function-valued parameter (e.g., `β` in SIR).\n- **`InferredContext`**: runtime domain bounds and validation references, extracted from data and injected into constraints automatically.\n\n### `anypinn.lightning`: The Training Engine _(optional)_\n\nA thin wrapper plugging a `Problem` into PyTorch Lightning:\n\n- **`PINNModule`**: `LightningModule` wrapping any `Problem`. Handles optimizer setup, context injection, and prediction.\n- **`PINNDataModule`**: abstract data module managing loading, config-driven collocation sampling, and context creation. Collocation strategy is selected via `TrainingDataConfig.collocation_sampler` (`\"random\"`, `\"uniform\"`, `\"latin_hypercube\"`, `\"log_uniform_1d\"`, or `\"adaptive\"`).\n- **Callbacks**: SMMA-based early stopping, formatted progress bars, data scaling, prediction writers.\n\n### `anypinn.problems`: ODE/PDE Building Blocks\n\nReady-made constraints for ODE/PDE problems:\n\n- **`ResidualsConstraint`**: `‖dy/dt − f(t, y)‖²` via autograd\n- **`ICConstraint`**: `‖y(t₀) − y₀‖²`\n- **`DataConstraint`**: `‖prediction − observed data‖²`\n- **`ODEInverseProblem`**: composes all three with configurable weights\n\n### `anypinn.catalog`: Problem-Specific Building Blocks\n\nDrop-in ODE/PDE functions and `DataModule`s for specific systems. See `anypinn/catalog/` for the full list.\n\n## 🤝 Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, code style guidelines, and the pull request workflow.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiacomoguidotto%2Fanypinn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiacomoguidotto%2Fanypinn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiacomoguidotto%2Fanypinn/lists"}