Skip to content

Add native RKKY interlayer coupling (ext_RKKY)#403

Open
SanthoshSivasubramani wants to merge 4 commits into
mumax:masterfrom
SanthoshSivasubramani:feature/native-rkky
Open

Add native RKKY interlayer coupling (ext_RKKY)#403
SanthoshSivasubramani wants to merge 4 commits into
mumax:masterfrom
SanthoshSivasubramani:feature/native-rkky

Conversation

@SanthoshSivasubramani

Copy link
Copy Markdown

Summary

Adds a native RKKY (interlayer exchange) coupling term, exposed to the input
script as ext_RKKY(region1, region2, J), where J is the areal coupling
strength in J/m2 (J < 0 for antiferromagnetic / synthetic-antiferromagnet
coupling).

Related discussion: #402.

Motivation

mumax3 has no native RKKY term today. The established approach is to repurpose
the Heisenberg exchange between two regions, as in the existing test/rkky.mx3:

scale := (RKKY * c) / (2 * Aex.Average())
ext_scaleExchange(0, 1, scale)

This has two limitations:

  1. It needs a manual, geometry dependent conversion from the physical areal
    coupling (J/m2) to a dimensionless exchange scale factor.
  2. The exchange field only couples immediately adjacent cells (an empty
    Msat=0 neighbour is treated as self), so it cannot couple two magnetic
    layers separated by a nonmagnetic spacer, which is the usual SAF geometry.

ext_RKKY takes the physical J directly, and locates the partner cell by
scanning the z column, so the coupling spans a spacer gap.

Implementation

The term is added to the effective field as

B = J / (Msat * dz) * m_partner

consistent with the exchange field convention. For adjacent layers this is
torque identical to ext_InterExchange with A_inter = J * dz / 2 (the two
differ only by a component parallel to m, which exerts no torque).

Files:

  • cuda/rkky.cu : kernel addrkky
  • cuda/rkky.go : host wrapper AddRKKY
  • cuda/rkky_wrapper.go : cuda2go generated wrapper
  • engine/rkky.go : ext_RKKY field term
  • test/rkky_native.mx3, test/rkky_gap.mx3 : regression tests

Validation (NVIDIA L4, CUDA 12.3)

  • Field magnitude matches the analytic J/(Msat*dz) to 6 significant figures.
  • Angular dependence is exactly bilinear (B proportional to m_partner).
  • Antiferromagnetic sign is correct (energy minimum at antiparallel).
  • Coupling propagates across a nonmagnetic spacer (test/rkky_gap.mx3), where
    ext_InterExchange gives zero.
  • Torque matches ext_scaleExchange / ext_InterExchange for adjacent layers.

Both regression tests pass.

Notes

This registers the effective field term, so dynamics and field driven relax
are correct. It does not yet register an energy density, so E_total does not
include the RKKY contribution; that can be added as a follow up if preferred.

Adds a bilinear RKKY interlayer coupling field term exposed to the scripting API as ext_RKKY(region1, region2, J), with J the areal coupling strength in J/m2 (J<0 antiferromagnetic). The effective field is B = J/(Msat*dz)*m_partner. The partner cell is located by scanning the z column, so the coupling spans a nonmagnetic spacer gap between layers, which ext_InterExchange (nearest neighbour only) cannot do. For adjacent layers the torque is identical to ext_InterExchange with A_inter = J*dz/2.

Files: cuda/rkky.cu (kernel), cuda/rkky.go (host wrapper), cuda/rkky_wrapper.go (cuda2go generated), engine/rkky.go (ext_RKKY field term), test/rkky_native.mx3 and test/rkky_gap.mx3 (regression tests).
Copilot AI review requested due to automatic review settings July 3, 2026 05:49

Copilot AI 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

Adds a native RKKY (interlayer exchange) coupling term to the simulation effective field, exposed to mx3 scripts as ext_RKKY(region1, region2, J), including CUDA implementation and regression tests (adjacent layers + spacer-gap coupling).

Changes:

  • Introduces a new CUDA kernel (addrkky) plus Go host wrapper to add the RKKY effective field contribution.
  • Registers a new engine field term (B_rkky) and the script function ext_RKKY(...).
  • Adds two mx3 regression tests validating adjacent-layer and spacer-gap coupling behavior.

Reviewed changes

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

Show a summary per file
File Description
engine/rkky.go Engine-side ext_RKKY registration and B_rkky field-term wiring.
cuda/rkky.cu CUDA kernel that finds partner cells along z and accumulates the RKKY field.
cuda/rkky.go Host-side kernel launch wrapper and argument setup.
cuda/rkky_wrapper.go Auto-generated CUDA2GO wrapper + embedded PTX for addrkky.
test/rkky_native.mx3 Regression test for adjacent-layer coupling field magnitude/direction.
test/rkky_gap.mx3 Regression test for coupling across a nonmagnetic spacer gap.

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

Comment thread engine/rkky.go
Comment on lines +39 to +45
func RKKY(region1, region2 int, J float64) {
rkkyPairs = append(rkkyPairs, rkkyPair{region1, region2, J})
if !rkkyRegistered {
AddFieldTerm(B_rkky)
rkkyRegistered = true
}
}
Comment thread cuda/rkky.cu Outdated
Comment on lines +51 to +69
// locate the nearest partner-region cell in the same (x,y) column along z
int P = -1;
int best = Nz + 1;
for (int jz = 0; jz < Nz; jz++) {
if (jz == iz) {
continue;
}
int Q = idx(ix, iy, jz);
if (regions[Q] == partner) {
int d = (jz > iz) ? (jz - iz) : (iz - jz);
if (d < best) {
best = d;
P = Q;
}
}
}
if (P < 0) {
return;
}
Comment thread test/rkky_native.mx3 Outdated
Comment on lines +4 to +5
// Layer 0 (region 100) is +z, layer 1 (region 101) is +x, so the field in
// region 100 points along +x scaled by J/(Msat*dz).
Comment thread test/rkky_native.mx3 Outdated
m.setRegion(100, uniform(0, 0, 1))
m.setRegion(101, uniform(1, 0, 0))
Run(0)
ExpectV("B_rkky adjacent", B_rkky.Region(100).Average(), vector(-2.22222, 0, 0), 1e-3)
Comment thread test/rkky_gap.mx3 Outdated
m.setRegion(100, uniform(0, 0, 1))
m.setRegion(101, uniform(1, 0, 0))
Run(0)
ExpectV("B_rkky across spacer", B_rkky.Region(100).Average(), vector(-2.22222, 0, 0), 1e-3)
cuda/rkky.cu: locate the partner by scanning outward from iz and stopping at the first hit (O(distance) instead of O(Nz)); the nearest-partner result is unchanged.

test/rkky_native.mx3, test/rkky_gap.mx3: also assert the field on region 101 (the other side of the pair), and correct a comment about the field sign for J<0.
Register the RKKY field via SetEffectiveField as a built-in effective-field term instead of AddFieldTerm, so it does not pollute the user-defined B_custom and is not removed by RemoveCustomFields().
Addresses Copilot review: (1) apply the areal coupling only at the interface cell so it is independent of layer thickness (was applied to every cell, over-counting thick layers); (2) validate region ids via defRegionId; (3) overwrite an existing pair instead of appending a duplicate; (4) register the RKKY energy (E_rkky, Edens_rkky) so E_total includes it. Added test/rkky_thick.mx3 (2-cell layers: field halves, energy thickness-independent). VM-validated on L4: all tests OK.
@SanthoshSivasubramani

Copy link
Copy Markdown
Author

Thanks for the review — pushed a01f2bd addressing the comments:

  • Interface-only coupling. The areal field is now applied only at the interface cell (buried cells that have a same-region neighbour toward the partner are skipped), so the coupling is independent of layer thickness. Added test/rkky_thick.mx3 (2-cell-thick layers) asserting the layer-averaged field halves and E_rkky stays thickness-independent.
  • Region-id validation. ext_RKKY now validates both ids via defRegionId.
  • Duplicate pairs. Calling ext_RKKY again for the same region pair now overwrites the coupling instead of appending a duplicate.
  • Energy. Registered E_rkky / Edens_rkky via the standard -1/2 M·B density (exact for this linear field), so E_total includes the RKKY energy.
  • Both regions are asserted in rkky_native.mx3 and rkky_gap.mx3.

On the O(Nz) z-column scan: this is kept intentionally — scanning the column is what lets the coupling span a non-magnetic spacer gap, and Nz is small for layered SAF stacks, so the cost is negligible.

Validated on an NVIDIA L4 (CUDA 12.3): all tests pass.

Sign up for free to 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.

2 participants