Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Port Stokes to new SystemKernels - #327

Draft
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system
Draft

Port Stokes to new SystemKernels#327
alexfikl wants to merge 5 commits into
inducer:mainfrom
alexfikl:stokes-system

Conversation

@alexfikl

Copy link
Copy Markdown
Collaborator

Probably better viewed commit by commit, since the second commit adds type annotations and is a bit noisy.

Comment thread.basedpyright/baseline.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates pytential’s symbolic Stokes machinery to use Sumpy’s newer SystemKernel APIs (e.g. StokesletSystemKernel, StressletSystemKernel) instead of the older per-component kernels, while also adding/cleaning up type annotations to reduce the pyright baseline footprint.

Changes:

  • Port Stokeslet/Stresslet wrapper implementations from component kernels to system kernels and replace derivative handling with AxisTargetDerivative.
  • Introduce/expand typing (including ABC base operator, annotated attributes, and @override markers).
  • Remove now-obsolete pyright baseline suppressions for pytential/symbolic/stokes.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

FileDescription
pytential/symbolic/stokes.pyMigrates symbolic Stokes wrappers/operators to SystemKernels and refactors derivative/stress expressions with added typing.
.basedpyright/baseline.jsonDrops baseline entries corresponding to typing issues that are addressed by the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py Outdated
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
Comment threadpytential/symbolic/stokes.py
@alexfikl
alexfiklforce-pushed the stokes-system branch 2 times, most recently from 00ed9e5 to 438f06dCompareJune 27, 2026 16:26
@alexfikl
alexfikl marked this pull request as ready for review June 27, 2026 16:54
@inducer

Copy link
Copy Markdown
Owner

Thanks for making this! Do you think it would also be possible to replace all the *Wrapper classes with a generic system-kernel applier? If not, what are the obstacles?

@alexfikl

alexfikl commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Well, using the Stokes kernels as an example (and the component order from Pozrikidis), we'd need

$$\begin{aligned} \mathcal{S} & = \int G_{ij}(x, y) q_j(y), \\\ \mathcal{S}^* & = \int G_{ji}(x, y) q_j(y) \end{aligned} \qquad \begin{aligned} \mathcal{D} & = \int n_k(y) T_{ijk}(x, y) q_i(y), \\\ \mathcal{D}^* & = \int n_k(x) T_{ijk}(x, y) q_j(y) \end{aligned}$$

where the star ones are just the adjoints. I haven't looked too much how these look for $\mathcal{S}', \mathcal{S}'', \mathcal{D}'$ since they're not very used, but once these are constructed we can probably just extend things like sym.normal_derivative to work on them (?).

Just thinking out loud a bit.. ideally, we'd have something like

apply(system_kernel, density, direction1, direction2, direction3, ...)

We can probably get away with letting the SystemKernel return a tuple of ndim - 1 indices to dot into with the first one being the density and the rest being the direction vectors. This should allow using

u=apply(stokeslet, density)
traction=apply(stresslet, density, normal, adjoint=True)
D=apply(stresslet, density, normal, adjoint=False)
sigma=apply(stresslet, density, adjoint=True)

to compute the double layer potential or the traction or the full stress tensor (i.e. skipping the normal just doesn't dot). Something like that? Not sure what else would be needed here..

@inducer

Copy link
Copy Markdown
Owner

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

@alexfikl

Copy link
Copy Markdown
CollaboratorAuthor

So, in order to make the apply generic, given your example, we'd need something like density_contraction_axis (axes?) and normal_contraction_axis (left-over would implicitly be "output")?

Yeah, separating them is fine. The normal here would be specifically for the double layer / normal derivative type usage, right?

One thing that I'm not sure about is some of my older Stokes work, where I wanted to get the tangential stress, which, if I recall correctly was something like this

$$\tau = t_k(x) \int T_{ijk}(x, y) q_j(y) dy$$

Is this worth shoving in here somehow or is it too specific? i.e. I can contract with the density to get the "stress tensor" and then it's my job (not pytential's) to know how to contract to get the normal/tangential stress.

@alexfikl
alexfikl marked this pull request as draft August 28, 2026 14:11
Comment threadtest/test_symbolic.py
# {{{ test_system_kernel_int_g

@pytest.mark.parametrize("dim", [2, 3])
def test_system_kernel_int_g(dim: int) -> None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved interface issues:

  • How would one do a double-layer (e.g. Laplace)?
  • stress case doesn't work.
  • More of Isuru's use cases.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@alexfikl@inducer