Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3cbcefe
rough initial enzyme support via chainrules.jl
kylebeggs Jan 28, 2026
4c64025
feat(enzyme): convert to native EnzymeRules with BLAS optimizations
kylebeggs Jan 29, 2026
cb85d56
feat(enzyme): add shape parameter differentiation and unified backwar…
kylebeggs Jan 30, 2026
b38b1d1
fix dependabot
kylebeggs Jan 30, 2026
a67f4b7
fix dependabot try 2
kylebeggs Jan 30, 2026
76244af
mv dependabot.yml
kylebeggs Jan 30, 2026
532a24f
fix(enzyme): add polynomial section backward pass for Partial operator
kylebeggs Jan 31, 2026
07141d9
refactor(test): use DifferentiationInterface for autodiff tests
kylebeggs Feb 5, 2026
24fda7b
feat(autodiff): add Interpolator construction rrule and autodiff docs
kylebeggs Feb 5, 2026
8f611e3
format
kylebeggs Feb 6, 2026
dd7eacb
fix(ci): resolve PR #76 CI failures across platforms
kylebeggs Feb 6, 2026
92ea158
fix(enzyme): handle Duplicated return types and SVector immutability
kylebeggs Feb 6, 2026
b190c60
docs(autodiff): switch examples to AutoMooncake backend
kylebeggs Feb 12, 2026
1cc04b9
test(backward): improve coverage for backward.jl uncovered paths
kylebeggs Feb 12, 2026
bffe514
test(rng): seed all rand/randn calls for deterministic CI
kylebeggs Feb 12, 2026
90eafac
test(autodiff): add Laplacian PHS order coverage and 3D partial tests
kylebeggs Feb 12, 2026
e813938
format
kylebeggs Feb 12, 2026
9b605a8
fix(docs): update MathJax config for DocumenterVitepress v0.3.0
kylebeggs Feb 13, 2026
70abc91
chore(docs): add compat bounds to docs/Project.toml
kylebeggs Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
enable-beta-ecosystems: true # Julia ecosystem
updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
ignore:
- dependency-name: "crate-ci/typos"
update-types: ["version-update:semver-patch", "version-update:semver-minor"]
- package-ecosystem: "julia"
directories:
- "/"
- "/docs"
- "/test"
schedule:
interval: "daily"
groups:
all-julia-packages:
patterns:
- "*"
20 changes: 0 additions & 20 deletions .github/workflows/dependabot.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/downgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-downgrade-compat@v1
with:
skip: LinearAlgebra, Random, Statistics
skip: LinearAlgebra, Random, Statistics, Enzyme, EnzymeCore, Mooncake, ChainRulesCore, FiniteDifferences
projects: ., test, docs
- uses: julia-actions/julia-buildpkg@v1
env:
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ The package requires `Vector{AbstractVector}` input format (not matrices). Each
- The package requires Julia 1.10+ (see Project.toml compatibility)
- Uses KernelAbstractions.jl for GPU/CPU parallelization
- Data must be in `Vector{AbstractVector}` format (not matrices) - each point needs inferrable dimension (e.g., `SVector{2,Float64}`)
- **Autodiff examples**: Always use DifferentiationInterface.jl for AD examples in docs and tests. This provides a unified interface over Enzyme.jl and Mooncake.jl backends.

---

Expand Down
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@ StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
SymRCM = "286e6d88-80af-4590-acc9-0001b223b9bd"

[weakdeps]
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6"

[extensions]
RadialBasisFunctionsChainRulesCoreExt = "ChainRulesCore"
RadialBasisFunctionsEnzymeExt = ["Enzyme", "EnzymeCore"]
RadialBasisFunctionsMooncakeExt = ["ChainRulesCore", "Mooncake"]

[compat]
ChainRulesCore = "1.20"
ChunkSplitters = "3"
Combinatorics = "1"
Distances = "0.9, 0.10"
Enzyme = "0.13"
EnzymeCore = "0.8"
FiniteDifferences = "0.12.33"
KernelAbstractions = "0.9.34"
LinearAlgebra = "1"
Expand Down
2 changes: 1 addition & 1 deletion benchmark/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"

[compat]
BenchmarkTools = "1.5"
RadialBasisFunctions = "0.2.5"
RadialBasisFunctions = "0.3"
julia = "1.9"
7 changes: 7 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6"
RadialBasisFunctions = "79ee0514-adf7-4479-8807-6f72ea8967e8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[compat]
Documenter = "1"
DocumenterVitepress = "0.3"
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ makedocs(;
pages = [
"Home" => "index.md",
"Getting Started" => "getting_started.md",
"Automatic Differentiation" => "autodiff.md",
"Quick Reference" => "quickref.md",
"Theory" => "theory.md",
"Internals" => "internals.md",
Expand Down
18 changes: 13 additions & 5 deletions docs/src/.vitepress/config.mts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { defineConfig } from 'vitepress'
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
import mathjax3 from "markdown-it-mathjax3";
import { mathjaxPlugin } from './mathjax-plugin'
import footnote from "markdown-it-footnote";
import path from 'path'

const mathjax = mathjaxPlugin()

function getBaseRepository(base: string): string {
if (!base || base === '/') return '/';
const parts = base.split('/').filter(Boolean);
Expand All @@ -18,6 +20,8 @@ const navTemp = {
nav: [
{ text: 'Home', link: '/index' },
{ text: 'Getting Started', link: '/getting_started' },
{ text: 'Autodiff', link: '/autodiff' },
{ text: 'Quick Reference', link: '/quickref' },
{ text: 'Theory', link: '/theory' },
{ text: 'Internals', link: '/internals' },
{ text: 'API', link: '/api' }
Expand Down Expand Up @@ -45,6 +49,9 @@ export default defineConfig({
],

vite: {
plugins: [
mathjax.vitePlugin,
],
define: {
__DEPLOY_ABSPATH__: JSON.stringify('/'),
},
Expand All @@ -68,11 +75,10 @@ export default defineConfig({
},
},
markdown: {
math: true,
config(md) {
md.use(tabsMarkdownPlugin),
md.use(mathjax3),
md.use(footnote)
md.use(tabsMarkdownPlugin);
md.use(footnote);
mathjax.markdownConfig(md);
},
theme: {
light: "github-light",
Expand All @@ -92,6 +98,8 @@ export default defineConfig({
sidebar: [
{ text: 'Home', link: '/index' },
{ text: 'Getting Started', link: '/getting_started' },
{ text: 'Autodiff', link: '/autodiff' },
{ text: 'Quick Reference', link: '/quickref' },
{ text: 'Theory', link: '/theory' },
{ text: 'Internals', link: '/internals' },
{ text: 'API', link: '/api' }
Expand Down
161 changes: 161 additions & 0 deletions docs/src/.vitepress/mathjax-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// adapter from https://github.com/orgs/vuepress-theme-hope/discussions/5178#discussioncomment-15642629
// mathjax-plugin.ts
// @ts-ignore
import MathJax from '@mathjax/src'
import type { Plugin as VitePlugin } from 'vite'
import type MarkdownIt from 'markdown-it'
import { tex as mdTex } from '@mdit/plugin-tex'

const mathjaxStyleModuleID = 'virtual:mathjax-styles.css'

interface MathJaxOptions {
font?: string
}

async function initializeMathJax(options: MathJaxOptions = {}) {
const font = options.font || 'mathjax-newcm'

const config: any = {
loader: {
load: [
'input/tex',
'output/svg',
'[tex]/boldsymbol',
'[tex]/braket',
'[tex]/mathtools',
],
},
tex: {
tags: 'ams',
packages: {
'[+]': ['boldsymbol', 'braket', 'mathtools'],
},
},
output: {
font,
displayOverflow: 'linebreak',
mtextInheritFont: true,
},
svg: {
fontCache: 'none', // critical: avoids async font loading
},
}

await MathJax.init(config)

const fontData = MathJax.config.svg?.fontData

if (fontData?.dynamicFiles) {
const dynamicFiles = fontData.dynamicFiles
const dynamicPrefix: string =
fontData.OPTIONS?.dynamicPrefix || fontData.options?.dynamicPrefix

if (dynamicPrefix) {
await Promise.all(
Object.keys(dynamicFiles).map(async (name) => {
try {
await import(/* @vite-ignore */ `${dynamicPrefix}/${name}.js`)
dynamicFiles[name]?.setup?.(MathJax.startup.output.font)
} catch {
// Silently ignore missing dynamic files
}
}),
)
}
}
}

export function mathjaxPlugin(options: MathJaxOptions = {}) {
let adaptor: any
let initialized = false

async function ensureInitialized() {
if (!initialized) {
await initializeMathJax(options)
adaptor = MathJax.startup.adaptor
initialized = true
}
}

function renderMath(content: string, displayMode: boolean): string {
if (!initialized) {
throw new Error('MathJax not initialized')
}

const node = MathJax.tex2svg(content, { display: displayMode })

// Prevent Vue from touching MathJax output
adaptor.setAttribute(node, 'v-pre', '')

let html = adaptor.outerHTML(node)

// Preserve spaces inside mjx-break (SVG only)
html = html.replace(
/<mjx-break(.*?)>(.*?)<\/mjx-break>/g,
(_: string, attr: string, inner: string) =>
`<mjx-break${attr}>${inner.replace(/ /g, '&nbsp;')}</mjx-break>`,
)

// Wrap only display equations (not inline math)
html = html.replace(
/(<mjx-container[^>]*display="true"[^>]*>)([\s\S]*?)(<\/mjx-container>)/,
'<div class="mjx-scroll-wrapper">$1$2$3</div>'
)

return html
}

function getMathJaxStyles(): string {
return initialized
? adaptor.textContent(MathJax.svgStylesheet()) || ''
: ''
}

function resetMathJax(): void {
if (!initialized) return
MathJax.texReset()
MathJax.typesetClear()
}

function viteMathJax(): VitePlugin {
const virtualModuleID = '\0' + mathjaxStyleModuleID

return {
name: 'mathjax-styles',

resolveId(id) {
if (id === mathjaxStyleModuleID) {
return virtualModuleID
}
},

async load(id) {
if (id === virtualModuleID) {
await ensureInitialized()
return getMathJaxStyles()
}
},
}
}

function mdMathJax(md: MarkdownIt): void {
mdTex(md, {
render: renderMath,
})

const orig = md.render
md.render = function (...args) {
resetMathJax()
return orig.apply(this, args)
}
}

const init = ensureInitialized()

return {
vitePlugin: viteMathJax(),
markdownConfig: mdMathJax,
styleModuleID: mathjaxStyleModuleID,
init,
}
}
Loading
Loading