From 700ecae058c00f1b6bdb1da33da100fef4ec4185 Mon Sep 17 00:00:00 2001 From: Duc Le Date: Mon, 4 Nov 2024 02:40:13 +0000 Subject: [PATCH 1/6] Add ADR proposal and LSWT draft --- .../001_use_atomic_simulation_environment.md | 35 +++++++ docs/developers/adr/README.md | 39 ++++++++ .../design/001_linear_spinwave_theory.md | 95 +++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 docs/developers/adr/001_use_atomic_simulation_environment.md create mode 100644 docs/developers/adr/README.md create mode 100644 docs/developers/design/001_linear_spinwave_theory.md diff --git a/docs/developers/adr/001_use_atomic_simulation_environment.md b/docs/developers/adr/001_use_atomic_simulation_environment.md new file mode 100644 index 0000000..bc01b50 --- /dev/null +++ b/docs/developers/adr/001_use_atomic_simulation_environment.md @@ -0,0 +1,35 @@ +# PySpinW will use the Atomic Simulation Environment as a dependency + +## Context + +The [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) is a Python library for setting up, running, visualizing and analyzing atomistic simulations. +Primarily, it supports `calculators` based on density function theory or force fields. +In most cases these codes are not written in Python but `ase` provides an interface to drive the calculations from Python. +In particular it has an `Atoms` [class](https://wiki.fysik.dtu.dk/ase/ase/atoms.html) which embodies a collection of atoms which can be the lattice which SpinW calculations need. +Each `Atom` in an `Atoms` object has a `position` and magnetic moment `magmom`, as well as `charge` and `mass` which SpinW does not need. +Most importantly, the `Atoms` can be visualized using the `ase.visualize.view` [function](https://wiki.fysik.dtu.dk/ase/ase/visualize/visualize.html) +which provides an internal viewer (`ase.gui`) as well as interface to a variety of external viewers. +Finally, there is a spacegroup package with a `crystal` [constructor](https://wiki.fysik.dtu.dk/ase/ase/spacegroup/spacegroup.html) which creates an `Atoms` object with a particular space group symmetry. +Thus much of the functionality provided by the current `genlattice` and `addatom` methods could be outsourced to `ase` reducing the amount of code needed to be written in PySpinW. + + +## Decision + +We will use the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) as a dependency in PySpinW to handle constructing and manipulating a lattice. + + +## Status + +Proposed + + +## Consequences + +This adds a significant dependency to the project. The possible downsides are: + +* Needing to adapt spinw code to the `Atoms` class which may not be flexible enough for our needs. +* Risk that the `ase` project becomes abandoned (considered low as it has a large user base and an STFC staff member is a contributor). + +The advantages is: + +* Saving a large amount of coding in order to write a `Lattice` class or the lattice handling part of the `spinw` class. diff --git a/docs/developers/adr/README.md b/docs/developers/adr/README.md new file mode 100644 index 0000000..e7164d6 --- /dev/null +++ b/docs/developers/adr/README.md @@ -0,0 +1,39 @@ +# Architectural Decision Records + +Significant architectural choices in the PySpinW project will use this workflow: + +1. A pull request which creates a new markdown file in this folder with the proposed architectural design choice is opened. +2. Detailed design documentation supporting the decision will be placed separately into markdown files in the [design](../design) folder and should be referenced in the ADR file. +3. Project members and interested parties will comment on the pull request. If discussion meetings were convened about the decision, they should be minuted or summarised in comments on the PR. +4. The MD file is modified in light of the comments. +5. The PR is merged or closed without merging. Merging the PR signals that the proposed design decision is accepted. + + +## File name format + +The files in this folder should named as `NNN-` where `NNN` is a sequential number. + + +## Template + +ADRs in PySpinW will use the template suggested in [this blog post](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions.html): + +``` +# Title + +## Context + +Detailed information should refer to design documents in the [design](../design) folder. + +## Decision + +"We will..." + +## Status + +Proposed / Accepted / Deprecated / Superseded + +## Consequences +``` + +The ADR file should be short - not more than approximately one page if printed out. Detailed designs should be in the [design](../design) folder. diff --git a/docs/developers/design/001_linear_spinwave_theory.md b/docs/developers/design/001_linear_spinwave_theory.md new file mode 100644 index 0000000..d663ea1 --- /dev/null +++ b/docs/developers/design/001_linear_spinwave_theory.md @@ -0,0 +1,95 @@ +# The Maths behind Linear Spin Wave Theory Calculations + +This documentation describes the maths behind linear spin wave theory calculations as implemented in the (Matlab) [SpinW](https://github.com/spinw/spinw) code. +A fuller description can be found in the papers of [S. Petit (2011)](https://doi.org/10.1051/sfn/201112006) and [Toth and Lake (2015)](https://doi.org/10.1088/0953-8984/27/16/166002). +(We shall mostly be using the notation of Petit as this is what is used in the SpinW Matlab code). + + +## Introduction + +Spin waves are collective excitations (normal modes) of a lattice of atomic spins +(atoms with unfilled electronic shells and hence a net magnetic moment) coupled by exchange interactions. +These excitations can be described using a semiclassical approach using an equation of motion in which +the internal magnetic field generated by the moment on one atom causes a torque on its neighbour. [citation needed] +The resulting wave is a precession of the spins about their ordered direction, with a net phase between site. +Another way of thinking about these excitations is as (quantised) quasiparticles in a field theory. +This is "linear spin wave theory" and its quasiparticles are "magnons". + + +## The Holstein-Primakoff transformation + +Consider a single atom with total spin quantum number $S$, which can be in states labelled by $`S_z=-S,-S+1,...,S-1,S`$. +In the ordered state, this spin is in the state with maximum $`S_z=S`$. +A small deviation from this (i.e. initiating a spin wave) will change the state to $`S_z=S-1`$. +This can be described by the spin lowering operator $`\hat{S}^-`$. +Likewise, restoring the ordered state from this deviation is described by the spin raising operator $`\hat{S}^+`$. + +Now, the _Holstein-Primakoff_ transformation is a mapping between these lowering and raising operators +to bosonic creation $`\hat{b}^{\dagger}`$ and annihilation $`\hat{b}`$ operators as follows (we drop the hats): + +```math +S^+ = b \hbar \sqrt{2S - b^{\dagger}b} \\ +S^- = b^{\dagger} \hbar \sqrt{2S - b^{\dagger}b} \\ +S^z = \hbar (S - b^{\dagger}b) +``` + +The number of magnons is $`b^{\dagger}b`$ and $`S_z`$ is the projection of the spins along the local ordered moment direction. +We thus see that when no magnons are excited this corresponds to the fully ordered state, +and that as more magnons are excited the spins become canted perpendicular to this direction, +as the ladder (raising/lowering) operators can be related to the $x$ and $y$ spin components by $`S^{\pm} = S^x \pm iS^y`$. + +The term in the square root is usually expanded in a Taylor series in practical calculations, +and usually only the first order (linear) term is retained which is equivalent to neglecting the $`b^{\dagger}b`$ term in the square root. +This is strictly only valid when $2S$ is large (to see this, rearrange to get $`\sqrt{1-b^{\dagger}b/2S}`$). +Thus, _linear spin wave theory_ is said to be only valid for large $S$ systems. + + +## Local spin directions + +We see in the above that mapping to the bosonic operators $`b^{\dagger}, b`$ requires the Hamiltonian +to be described in terms of the local spin ordered moment direction, since it describes small deviations from this direction. + +We thus define a set of rotation matrices $`R_i^{\alpha}`$ which transforms a spin vector $`\mathbf{S}'_i` +in the local coordinate system (where $z$ is along the ordered moment direction) +to a vector $`\mathbf{S}_i`$ in a Cartesian coordinate system connected to the crystal lattice: +(In SpinW, this Cartesian system is defined by $x||a$, $z$ perpendicular to $a$ and $c$ and $y$ perpendicular to $x$ and $z$). + +```math +\mathbf{S}_i = R_i \mathbf{S}'_i +``` + +where $`R_i`$ is a $3 \times 3$ matrix. +Additionally, to more easily map to the operators $S^z$, $S^-$ ($b^{\dagger}) and $S^+$ ($b$) operators above, +we will define the following vectors from the columns of $`R_i`$ for each spin: + +```math +\mathbf{z}_i = R_i^1 + i R_i^2 \\ +\mathbf{\eta}_i = R_i^3 +``` + +that is $`z_i`$ is formed from the first and second column of $`R_i`$ whilst $`\eta_i`$ from the third column of $`R_i`$. +This is so that we can express the spin vector (in the local coordinate system) in terms of the bosonic operators as: + +```math +\mathbf{S}'_i = \sqrt{\frac{S}{2}}\left( \mathbf{z}_i^* b_i + \mathbf{z}_ib_i^{\dagger} \right) + \mathbf{\eta}_i \left( S_i - b_i^{\dagger} b \right) +``` + +where we have made the linear approximation and taken: + +```math +S^x = \frac{(S^+ + S^-)}{2} = \sqrt{frac{S}{2}}(b + b^{\dagger}) \\ +S^y = \frac{(S^+ - S^-)}{2i} = \frac{\sqrt{S}}{i\sqrt{2}}(b - b^{\dagger}) \\ +S^z = S - b^{\dagger}b +``` + + +## The Heisenberg Hamiltonian + + + + + +## The Bogoliubov transformation + + +## Solving the quadratic form From 6a1ccc1c4d66cfedf6c34d6432e5cd6574baf5f7 Mon Sep 17 00:00:00 2001 From: Duc Le Date: Mon, 4 Nov 2024 23:01:50 +0000 Subject: [PATCH 2/6] [no ci] Update LSWT up to Hamiltonian. Update ase ADR after RW comments --- .../001_use_atomic_simulation_environment.md | 1 + .../design/001_linear_spinwave_theory.md | 171 ++++++++++++++++-- 2 files changed, 154 insertions(+), 18 deletions(-) diff --git a/docs/developers/adr/001_use_atomic_simulation_environment.md b/docs/developers/adr/001_use_atomic_simulation_environment.md index bc01b50..7a8e03c 100644 --- a/docs/developers/adr/001_use_atomic_simulation_environment.md +++ b/docs/developers/adr/001_use_atomic_simulation_environment.md @@ -28,6 +28,7 @@ Proposed This adds a significant dependency to the project. The possible downsides are: * Needing to adapt spinw code to the `Atoms` class which may not be flexible enough for our needs. +* If `ase` changes its code this might break anything we might build on top of it. * Risk that the `ase` project becomes abandoned (considered low as it has a large user base and an STFC staff member is a contributor). The advantages is: diff --git a/docs/developers/design/001_linear_spinwave_theory.md b/docs/developers/design/001_linear_spinwave_theory.md index d663ea1..2fbb56a 100644 --- a/docs/developers/design/001_linear_spinwave_theory.md +++ b/docs/developers/design/001_linear_spinwave_theory.md @@ -27,20 +27,25 @@ Likewise, restoring the ordered state from this deviation is described by the sp Now, the _Holstein-Primakoff_ transformation is a mapping between these lowering and raising operators to bosonic creation $`\hat{b}^{\dagger}`$ and annihilation $`\hat{b}`$ operators as follows (we drop the hats): -```math -S^+ = b \hbar \sqrt{2S - b^{\dagger}b} \\ -S^- = b^{\dagger} \hbar \sqrt{2S - b^{\dagger}b} \\ -S^z = \hbar (S - b^{\dagger}b) -``` -The number of magnons is $`b^{\dagger}b`$ and $`S_z`$ is the projection of the spins along the local ordered moment direction. +$$S^+ = b \sqrt{2S - b^{\dagger}b}$$ +$$S^- = b^{\dagger} \sqrt{2S - b^{\dagger}b}$$ +$$S^z = (S - b^{\dagger}b)$$ + +(We've also neglected the spin quantum $n\hbar$ in this treatment compared to standard texts in accordance with Petit and Toth and Lake). +(Note also that the $`\sqrt{2S}`$ in the above refers to the total spin quantum number $S$, which is also often termed the "spin length". +This is because in some of the literature it is taken to represent the magnitude of the ordered moment rather than a (half integral) quantum number. +As such, SpinW does not restrict $S$ to taking integer or half-integer values. +The main effect of changing $S$ is to scale the magnon energies. + +The number of magnons is $`b^{\dagger}b`$ and $`S^z`$ is the projection of the spins along the local ordered moment direction. We thus see that when no magnons are excited this corresponds to the fully ordered state, and that as more magnons are excited the spins become canted perpendicular to this direction, as the ladder (raising/lowering) operators can be related to the $x$ and $y$ spin components by $`S^{\pm} = S^x \pm iS^y`$. The term in the square root is usually expanded in a Taylor series in practical calculations, and usually only the first order (linear) term is retained which is equivalent to neglecting the $`b^{\dagger}b`$ term in the square root. -This is strictly only valid when $2S$ is large (to see this, rearrange to get $`\sqrt{1-b^{\dagger}b/2S}`$). +This is strictly only valid when $2S$ is large (to see this, rearrange to get $`\sqrt{\frac{1-b^{\dagger}b}{2S}}`$). Thus, _linear spin wave theory_ is said to be only valid for large $S$ systems. @@ -49,43 +54,173 @@ Thus, _linear spin wave theory_ is said to be only valid for large $S$ systems. We see in the above that mapping to the bosonic operators $`b^{\dagger}, b`$ requires the Hamiltonian to be described in terms of the local spin ordered moment direction, since it describes small deviations from this direction. -We thus define a set of rotation matrices $`R_i^{\alpha}`$ which transforms a spin vector $`\mathbf{S}'_i` +We thus define a set of rotation matrices $`R_i^{\alpha}`$ which transforms a spin vector $`\mathbf{S}'_i`$ in the local coordinate system (where $z$ is along the ordered moment direction) -to a vector $`\mathbf{S}_i`$ in a Cartesian coordinate system connected to the crystal lattice: -(In SpinW, this Cartesian system is defined by $x||a$, $z$ perpendicular to $a$ and $c$ and $y$ perpendicular to $x$ and $z$). +to a vector $`\mathbf{S}_i`$ in a Cartesian coordinate system connected to the crystal lattice +(In SpinW, this Cartesian system is defined by $x \parallel a$, $z \perp (a, c)$ and $y \perp (x, z$): ```math \mathbf{S}_i = R_i \mathbf{S}'_i ``` where $`R_i`$ is a $3 \times 3$ matrix. -Additionally, to more easily map to the operators $S^z$, $S^-$ ($b^{\dagger}) and $S^+$ ($b$) operators above, +Additionally, to more easily map to the operators $S^z$, $S^-$ ($`b^{\dagger}`$) and $S^+$ ($b$) operators above, we will define the following vectors from the columns of $`R_i`$ for each spin: ```math -\mathbf{z}_i = R_i^1 + i R_i^2 \\ -\mathbf{\eta}_i = R_i^3 +\mathbf{z}_i = R_i^1 + i R_i^2 +``` +```math +\boldsymbol{\eta}_i = R_i^3 ``` that is $`z_i`$ is formed from the first and second column of $`R_i`$ whilst $`\eta_i`$ from the third column of $`R_i`$. This is so that we can express the spin vector (in the local coordinate system) in terms of the bosonic operators as: ```math -\mathbf{S}'_i = \sqrt{\frac{S}{2}}\left( \mathbf{z}_i^* b_i + \mathbf{z}_ib_i^{\dagger} \right) + \mathbf{\eta}_i \left( S_i - b_i^{\dagger} b \right) +\mathbf{S}'_i = \sqrt{\frac{S}{2}}\left( \mathbf{z}_i^* b_i + \mathbf{z}_ib_i^{\dagger} \right) + \boldsymbol{\eta}_i \left( S_i - b_i^{\dagger} b_i \right) ``` where we have made the linear approximation and taken: +$$S^x = \frac{(S^+ + S^-)}{2} = \sqrt{\frac{S}{2}}(b + b^{\dagger}) $$ +$$S^y = \frac{(S^+ - S^-)}{2i} = \frac{\sqrt{S}}{i\sqrt{2}}(b - b^{\dagger}) $$ +$$S^z = S - b^{\dagger}b $$ + + +## The Hamiltonian + +We can now express the exchange Hamiltonian: + +```math +\mathcal{H} = \sum_{i\neq j} \mathbf{S}_i J_{ij} \mathbf{S}_j +``` + +in terms of the bosonic operators: + +```math +\mathcal{H} = \sum_{i\neq j} \left[ + \sqrt{\frac{S_i}{2}}\left( \mathbf{z}_i^{*\intercal} b_i + \mathbf{z}^{\intercal}_ib_i^{\dagger} \right) + \boldsymbol{\eta}_i \left( S_i - b_i^{\dagger} b_i \right) + \right] J_{ij} \left[ + \sqrt{\frac{S_j}{2}}\left( \mathbf{z}_j^* b_j + \mathbf{z}_jb_j^{\dagger} \right) + \boldsymbol{\eta}_j \left( S_j - b_j^{\dagger} b_j \right) + \right] +``` + +where the operators $`b_i`$, $`b^{\dagger}_i`$ and vectors $`\mathbf{z}_i`$ and $`\boldsymbol{\eta}_i`$ relate to each site $i$ in real-space, +and $`J_{ij}`$ is a tensor represented by a $3 \times 3$ matrix. +(Note that the vector $\mathbf{z}$ is complex and we use the asterisk to denote complex conjugation +and the $\intercal$ symbol to indicate vector or matrix transpose). + +Now in the above equation, the sum over site indices $i$ and $j$ extends over all space, +but in SpinW we deal exclusively with periodic (crystalline) systems, so we will separate out each index $i$ ($j$) +into components $i'$ ($j'$) within a unit cell and components $m$ ($n$) between the first and $m^{\mathrm{th}}$ ($n^{\mathrm{th}}$) unit cell. +The sum over sites within the unit cell thus becomes finite, but we still have an infinite sum over unit cells $`\sum_{m,n}`$. +As we are looking for wave-like solutions to the Hamiltonian, the next step is thus to perform a Fourier transform to obtain a sum over +$\mathbf{q}$ vectors in the first Brillouin zone. + +To do this we first need to re-express the sum over unit cells as a sum over distances +$`\mathbf{r}_m`$ and $`\boldsymbol{\delta}=\mathbf{r}_m - \mathbf{r}_n`$. +After Fourier transforming both the operators $b$, $b^{\dagger}$ and the exchange interactions $J$, +we can use the identity $`\sum_{r} \exp(i(\mathbf{q}-\mathbf{q}')\cdot\mathbf{r}) = \delta_{\mathbf{qq}'}`$ to obtain: + +```math +\mathcal{H} = \sum_{\mathbf{q}} \sum_{i'\neq j'} \left[ + \sqrt{\frac{S_{i'}}{2}}\left( \mathbf{z}_{i'}^* b_{i'}(\mathbf{q}) + \mathbf{z}_{i'}b_{i'}^{\dagger}(-\mathbf{q}) \right) + + \boldsymbol{\eta}_i \left( S_{i'} - b_{i'}(\mathbf{q}) b_{i'}^{\dagger}(-\mathbf{q}) \right) + \right]^{\intercal} J(\mathbf{q}) \left[ + \sqrt{\frac{S_{j'}}{2}}\left( \mathbf{z}_{j'}^* b_{j'}(\mathbf{q}) + \mathbf{z}_{j'}b_{j'}^{\dagger}(-\mathbf{q}) \right) + + \boldsymbol{\eta}_j \left( S_{j'} - b_{j'}(\mathbf{q}) b_{j'}^{\dagger}(-\mathbf{q}) \right) + \right] +``` + +where the sum over $`\mathbf{q}`$ extends over both positive and negative vectors within the first Brillouin zone. +Noting that the boson operators obey the commutation relation + +```math +[b_{i'}, b_{j'}^{\dagger}] = \delta_{i', j'} +``` + +and that the $`\mathbf{z}`$ and $`\boldsymbol{\eta}`$ vectors are perpendicular, we can rewrite the Hamiltonian as a matrix equation +if we define a column vector $\mathbf{X}$ as composed of the boson operators within the unit cell: + +```math +\mathbf{X}_m = \left(b_{m,1}, b_{m,2}, \ldots, b_{m,L}, b^{\dagger}_{m,1}, b^{\dagger}_{m,2}, \ldots, b^{\dagger}_{m,L} \right) +``` + +where $L$ is the number of sites within the unit cell, giving: + +```math +\mathcal{H} = \sum_{\mathbf{q}} \mathbf{X}^{*\intercal}(\mathbf{q}) \mathrm{h}(\mathbf{q}) \mathbf{X}(\mathbf{q}) +``` + +where the hermitian matrix $`\mathrm{h}(\mathbf{q})`$ is + +```math +\mathrm{h}(\mathbf{q}) = \left[ \begin{array}{cc} +\mathrm{A}(\mathbf{q}) - \mathrm{C} && \mathrm{B}(\mathbf{q}) \\ +\mathrm{B}^{*\intercal}(\mathbf{q}) && \mathrm{A}(\mathbf{q}) - \mathrm{C} +\end{array} \right] +``` + +where the $`(i,j)`$ elements (we drop the primes) are: + +```math +\mathrm{A}(\mathbf{q})_{ij} = \frac{\sqrt{S_i S_j}}{2} \mathbf{z}_i^{\intercal} \mathrm{J}_{ij}(\mathbf{q}) \mathbf{z}^* +``` ```math -S^x = \frac{(S^+ + S^-)}{2} = \sqrt{frac{S}{2}}(b + b^{\dagger}) \\ -S^y = \frac{(S^+ - S^-)}{2i} = \frac{\sqrt{S}}{i\sqrt{2}}(b - b^{\dagger}) \\ -S^z = S - b^{\dagger}b +\mathrm{B}(\mathbf{q})_{ij} = \frac{\sqrt{S_i S_j}}{2} \mathbf{z}_i^{\intercal} \mathrm{J}_{ij}(\mathbf{q}) \mathbf{z} ``` +```math +\mathrm{C}_{ij} = \delta_{ij} \sum_{\mathcal{l}} S_{\mathcal{l}} \boldsymbol{\eta}_i^{\intercal} \mathrm{J}_{i\mathcal{l}}(\mathbf{q}=\mathbf{0}) \boldsymbol{\eta}_{\mathcal{l}} +``` + +The eigenvalues of $`\mathrm{h}(\mathbf{q})`$ are the magnon energies and its eigenvectors can be used to calculate the neutron cross-section. +Now, often we speak of $`\mathrm{h}(\mathbf{q})`$ as the "Hamiltonian" but strictly the Hamiltonian (the operator which yields the total energy) +is $`\mathcal{H}`$ which is the sum of $`\mathrm{h}(\mathbf{q})`$ over all $`\mathbf{q}`$ in the Brillouin zone. +Nonetheless, in order to calculate the inelastic neutron spectra, the quantity we need to calculate (and diagonalise) is $`\mathrm{h}(\mathbf{q})`$. + + +### Code for calculating the "Hamiltonian" matrix + +Despite the disclaimer above, in the rest of the text we will use "Hamiltonian matrix" to refer to the hermitian matrix $`\mathrm{h}(\mathbf{q})`$. +As can be seen from the equations for the submatrices $\mathrm{A}(\mathbf{q})$, $\mathrm{B}(\mathbf{q})$, and $\mathrm{C}$ above, +the calculation can naturally be divided into a $`\mathbf{q}`$-indepdent part +(involving the prefactor $`\sqrt{S_i S_j}/2`$ and the $\mathbf{z}$ and $\boldsymbol{\eta}$ vectors) +and a $`\mathbf{q}`$-dependent part (involving the Fourier transform of the exchange interactions $`\mathrm{J}_{ij}(\mathbf{q})`$ where $i,j$ label sites within the unit cell). + +The code to calculate the Hamiltonian is entirely in the [spinwave.m](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%2540spinw/spinwave.m) file. +First, the `intmatrix` method of the `spinw` object is called to compute $`J_{ij}`$ in real-space +(in [line 508](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L508)). +Next the magnetic structure vectors $`\mathbf{z}`$ and $`\boldsymbol{\eta}`$ are calculated from the magnetic propagation vector and magnetic basis +(in [lines 555-590](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L555-L590)). + +`spinwave.m` uses Matlab vectorisation (using `bsxfun`) in order to speed up calculations, so it needs to expand these vectors to cover the full basis +(there are $L$ spins in the unit cell but the boson operator basis is $2L$ because it includes both creation and anihilation operators) +using `repmat` and then compute the vector transpose (`zedL` and `etaL`) using `permute` in +[lines 608-612](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L608-L612). + +It next computes the $\mathbf{q}$-independent parts of the submatrices $`\mathrm{A}`$ (called `AD0` in the code), +$`\mathrm{B}`$ (called `BC0`), and $`\mathrm{C}`$ (called `A20` [upper left submatrix] and `D20` [lower right submatrix] in the code) in +[lines 614-641](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L614-L641). +These lines also include computing the indices $i$ (`atom1`) and $j$ (`atom2`) which are eventually passed to `accumarray` to actually construct the matrix. + +[Lines 856-934](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L614-L641) +contain the calculation of the $\mathbf{q}$-dependent part of the Hamitonian and forming it into a square matrix. +First the phase factor $\exp(i\boldsymbol{\delta}\cdot\mathbf{q})$ is computed in +[line 871](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L871), +then each submatrix $`\mathrm{A}`$ (split into `A1` for upper left and `D1` for lower right pars) and $`\mathrm{B}`$ is multiplied by this phase factor +in [lines 874-876](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L874-L876) using `bsxfun`. +Finally `accumarray` is used to construct the square matrix and the diagonal submatrix $`\mathrm{C}`$ added in +[lines 898-900](https://github.com/SpinW/spinw/blob/73f604ab4d84084d872d1f5fdf46dbc54e14cdd7/swfiles/%40spinw/spinwave.m#L898-L900). -## The Heisenberg Hamiltonian +### Takin implementation +As an alternative to the vectorized Matlab code, there is an independent implementation of the formulism in Toth & Lake in the +[takin](https://arxiv.org/pdf/1903.02632) code which +[uses a loop over the sites of the unit cell](https://github.com/ILLGrenoble/takin/blob/master/tlibs2/libs/magdyn/hamilton.h#L175-L264) +which is more transparent with respects to the equations in the paper. From 21d1cc562e34b4dd8be6b928a8d9414abc635347 Mon Sep 17 00:00:00 2001 From: Lucas Wilkins Date: Tue, 5 Nov 2024 16:35:52 +0000 Subject: [PATCH 3/6] Update 001_use_atomic_simulation_environment.md Added some more notes to the ASE docs --- docs/developers/adr/001_use_atomic_simulation_environment.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/developers/adr/001_use_atomic_simulation_environment.md b/docs/developers/adr/001_use_atomic_simulation_environment.md index 7a8e03c..88bf31c 100644 --- a/docs/developers/adr/001_use_atomic_simulation_environment.md +++ b/docs/developers/adr/001_use_atomic_simulation_environment.md @@ -34,3 +34,5 @@ This adds a significant dependency to the project. The possible downsides are: The advantages is: * Saving a large amount of coding in order to write a `Lattice` class or the lattice handling part of the `spinw` class. +* Reading of CIF files is supported by ASE +* Some plotting is already supported by ASE From 5344be726e37023dc78c3c501d3c67ae6b8b44a7 Mon Sep 17 00:00:00 2001 From: Lucas Wilkins Date: Wed, 6 Nov 2024 17:58:44 +0000 Subject: [PATCH 4/6] Create 004_magnetic_lattice.md (#16) * Create 004_magnetic_lattice.md * Apply suggestions from code review * Update docs/developers/adr/004_magnetic_lattice.md --------- Co-authored-by: Duc Le --- docs/developers/adr/004_magnetic_lattice.md | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/developers/adr/004_magnetic_lattice.md diff --git a/docs/developers/adr/004_magnetic_lattice.md b/docs/developers/adr/004_magnetic_lattice.md new file mode 100644 index 0000000..85074e0 --- /dev/null +++ b/docs/developers/adr/004_magnetic_lattice.md @@ -0,0 +1,28 @@ +# Classes for different kinds of magnetic structures + +## Context + +SpinW has different methods for dealing with different kinds of simulation, some simulations only work for systems decribed by a single (possibly complex) propagation vector, some (e.g. "biquadratic") only work +when the propagation vector is (0,0,0). It seems that a useful distinction is between systems where every unique magnetic state is explicitly represented, and ones where it is implicitly defined. +The notion of commensurability maps on to this. Commensurate propagation vectors permit a finite (though potentially large) explicit representation. + +The plan is to make separate classes for these descriptions, provide some degree of conversion between the two, and associate appropriate calculations with each one. +1) The explicit structure - every unique site is described explicity - explcit supercell, only (0,0,0), supports biquadratic +2) The implicit structure - described by a unit cell, and a single propagation vector - implicit supercell, supports incommensurate and true helical structures. The impilcit structure requires the "trick" used in spinw to calculate intensities at +/- the propagation vector. + +In both cases the classes should implement a method to return the set of `zed` and `eta` vectors needed for the spin wave calculations as detailed in [this doc](../design/001_linear_spinwave_theory.md#local-spin-directions). + +In addition, it would be useful if the user can specify a set of propagation vector(s) and basis(es) in the explicit representation rather than every spin orientation in the unit cell, but this is an implementation detail to be discussed later. + +## Decision + +We will create two classes for handling the magnetic structure, a `CommensurateStructure` for the "explicit" representation and a `RotatingFrameStructure` for the "implicit" representation. + +## Status + +Accepted + +## Advantages + +* Clear distinction between two kinds of description +* Separation of code From 93cdffab9a9a2f73e949ea1bb2c3e108ac8fa140 Mon Sep 17 00:00:00 2001 From: Lucas Wilkins Date: Wed, 6 Nov 2024 18:00:48 +0000 Subject: [PATCH 5/6] Backwards compatibility layer (#14) * Draft * Update docs/developers/adr/03_backwards_compatibility_layer.md * Update docs/developers/adr/03_backwards_compatibility_layer.md --- .../adr/03_backwards_compatibility_layer.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/developers/adr/03_backwards_compatibility_layer.md diff --git a/docs/developers/adr/03_backwards_compatibility_layer.md b/docs/developers/adr/03_backwards_compatibility_layer.md new file mode 100644 index 0000000..237ff80 --- /dev/null +++ b/docs/developers/adr/03_backwards_compatibility_layer.md @@ -0,0 +1,25 @@ +# PySpinW will have a backwards compatibility layer + +## Context + +A clean class structure for pySpinW will entail making some relatively large changes to the intended use, this +might be off-putting to some users, and will break compatibility with existing scripts. + +One big change is that there won't be a single big, stateful class, but lots of smaller stateless classes. + +However, it would not be difficult to maintain existing syntax by putting all the new stuff into a stateful class that +closely resembles the original matlab. + +## Decision + +Create a class that mimics the original spinW interface, backed by the new objects. +In particular, this class will only expose functionality which is currently in the Matlab version (and will omit new functionality written for Python) in order to encourage users to migrate. + +## Status + +Accepted + +## Consequences + +* Will take time to do +* Might prevent users from migrating, and become permanent From f1e6c555843fab90419775a3fb317013be936e02 Mon Sep 17 00:00:00 2001 From: Lucas Wilkins Date: Wed, 6 Nov 2024 18:15:33 +0000 Subject: [PATCH 6/6] Requirements for linter (#19) --- .github/workflows/lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8993820..83585c7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,6 +18,7 @@ jobs: run: | python -m pip install --upgrade pip pip install pylint + pip install -r requirements.txt - name: Analysing the code with pylint run: | pylint --disable C $(git ls-files '*.py')