Add native RKKY interlayer coupling (ext_RKKY)#403
Add native RKKY interlayer coupling (ext_RKKY)#403SanthoshSivasubramani wants to merge 4 commits into
Conversation
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).
There was a problem hiding this comment.
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 functionext_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.
| func RKKY(region1, region2 int, J float64) { | ||
| rkkyPairs = append(rkkyPairs, rkkyPair{region1, region2, J}) | ||
| if !rkkyRegistered { | ||
| AddFieldTerm(B_rkky) | ||
| rkkyRegistered = true | ||
| } | ||
| } |
| // 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; | ||
| } |
| // 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). |
| 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) |
| 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.
|
Thanks for the review — pushed
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. |
Summary
Adds a native RKKY (interlayer exchange) coupling term, exposed to the input
script as
ext_RKKY(region1, region2, J), whereJis the areal couplingstrength in J/m2 (
J < 0for antiferromagnetic / synthetic-antiferromagnetcoupling).
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:This has two limitations:
coupling (J/m2) to a dimensionless exchange scale factor.
Msat=0neighbour is treated as self), so it cannot couple two magneticlayers separated by a nonmagnetic spacer, which is the usual SAF geometry.
ext_RKKYtakes the physicalJdirectly, and locates the partner cell byscanning the z column, so the coupling spans a spacer gap.
Implementation
The term is added to the effective field as
consistent with the exchange field convention. For adjacent layers this is
torque identical to
ext_InterExchangewithA_inter = J * dz / 2(the twodiffer only by a component parallel to m, which exerts no torque).
Files:
cuda/rkky.cu: kerneladdrkkycuda/rkky.go: host wrapperAddRKKYcuda/rkky_wrapper.go: cuda2go generated wrapperengine/rkky.go:ext_RKKYfield termtest/rkky_native.mx3,test/rkky_gap.mx3: regression testsValidation (NVIDIA L4, CUDA 12.3)
J/(Msat*dz)to 6 significant figures.Bproportional tom_partner).test/rkky_gap.mx3), whereext_InterExchangegives zero.ext_scaleExchange/ext_InterExchangefor adjacent layers.Both regression tests pass.
Notes
This registers the effective field term, so dynamics and field driven
relaxare correct. It does not yet register an energy density, so
E_totaldoes notinclude the RKKY contribution; that can be added as a follow up if preferred.