-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathsw_bonddim.m
153 lines (135 loc) · 4.2 KB
/
sw_bonddim.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
function L = sw_bonddim(C, nAtom)
% find dimensionality of a periodic bond network
%
% ### Syntax
%
% `l = sw_bonddim(c, {natom})`
%
% ### Description
%
% `l = sw_bonddim(c, {natom})` splits the given periodic bond network into
% disjunct subsystems and determines the dimensionality of each subsystem.
%
% ### Examples
%
% Check the bond dimensionality of the triangular lattice:
%
% ```
% >>tri = sw_model('triAF')>>
% >>sw_bonddim(tri.intmatrix.all)>>
% ```
%
% ### Input Arguments
%
% `C`
% : Bond list in a matrix with dimensions of $[5\times n_{bond}]$, where the meaning of
% the rows are:
% * `#1:#3` Lattice translations between the coupled atoms in
% lattice units (always integer).
% * `#4` Index of the bond starting atom.
% * `#5` Index of the bond end atom.
%
% For example for a chain along b-axis on a Bravais lattice:
% `C = [1;1;0;1;0]`
%
% `nAtom`
% : Number of atoms in the unit cell. If not given, the maximum
% atom index from the bond list is taken.
%
% ### Output Arguments
%
% `L`
% : Struct with the number of elements equal to the number of
% subsystems, it has the following fields:
% * `D` Dimensionality of the subsystem $(0\leq D\leq 3)$.
% * `base` Basis vectors spanning the subsystem stored in a
% $[3\times D]$ matrix where each column denotes a basis
% vector.
% * `site` List of sites that belong to the subsystem.
%
% reshuffle C to match the input with the output of spinw.intmatrix
% in the code
% C(1,:) is atom1
% C(2,:) is atom2
% C(3:5,:) is the transplation vector
C = C([4:5 1:3],:);
% input check
if size(C,1)~=5
error('sw_bonddim:WrongInput','The given bond matrix has wrong dimensions!')
end
% all values have to be integer
if any(floor(C(:))-ceil(C(:)))
error('sw_bonddim:WrongInput','The given bond matrix must contain only integers!')
end
% check that all index up to a maximum is present
atom = [C(1,:) C(2,:)];
if nargin<2
nAtom = max(atom);
end
% add missing indices
missing = find(~ismember(1:nAtom,atom));
if ~isempty(missing)
C = [C [missing;missing;zeros(3,numel(missing))]];
end
% sort bonds in increasing order
idx = C(2,:)<C(1,:);
C(:,idx) = flip(C(:,idx));
% store subsystems in struct
L = struct('D',cell(1,0),'base',cell(1,0),'site',cell(1,0));
iSub = 1;
% find other loops going through every subsystem
while ~isempty(C)
% start with lowest index atom as origin
atom0 = min(C(1,:));
% starting atom
L0 = [atom0;zeros(3,1)];
while any(ismember(C(1,:),L0(1,:)) | ismember(C(2,:),L0(1,:)))
% find self loops
idx0 = ismember(C(1,:),L0(1,:)) & C(1,:)==C(2,:);
% find next neighbors
idx1 = find(ismember(C(1,:),L0(1,:)) & ~idx0);
idx2 = find(ismember(C(2,:),L0(1,:)) & ~idx0);
C(:,idx2) = flip(C(:,idx2));
idx = [find(idx0) unique([idx1 idx2])];
% add new atoms to the L list
for ii = 1:numel(idx)
dL = bsxfun(@plus,L0(2:4,L0(1,:)==C(1,idx(ii))),C(3:5,idx(ii)));
L0 = [L0 [repmat(C(2,idx(ii)),1,size(dL,2));dL]]; %#ok<AGROW>
end
% remove neighbors from bond list
C(:,idx) = [];
end
% find all combination of translation vectors within subsystem
idx = unique(L0(1,:));
% basis vectors
V = zeros(3,0);
ii = 1;
while ii <= numel(idx) && size(V,2)<3
lSel = L0(2:4,L0(1,:)==idx(ii));
% normalize vectors
%lSel = bsxfun(@rdivide,lSel,sum(lSel.^2,1));
%lSel(isnan(lSel)) = 0;
% keep unique ones only
%lSel = sw_uniquetol(lSel,1e-6);
lSel = unique(lSel','rows')';
V = orth([V reshape(bsxfun(@minus,permute(lSel,[2 3 1]),permute(lSel,[3 2 1])),[],3)']);
ii = ii + 1;
end
% store the subsystem basis vectors
L(iSub).base = V;
L(iSub).D = size(V,2);
if L(iSub).D == 3
% pretty 3D
L(iSub).base = eye(3);
end
L(iSub).site = unique([atom0 idx]);
iSub = iSub + 1;
end
% sort according to decreasing dimensionality
[~,idx] = sort([L.D],'descend');
L = L(idx);
end
function C = flip(C)
% flip bond atom1 --> atom2
C = [C(2,:);C(1,:);-C(3:5,:)];
end