% FID from a 1D-periodic system including RF % the use of symmetry can be disabled by setting testmode to a non-zero value M=2; % spins per cell N=3; % number of cells r=1.5; % internal distance (A) R=3; % distance between cells testmode=0; % set to do calculation with/without using symmetry vRF=0; % amplitude of RF (phase is zero); inccs=0; % include shifts? shifts=[0 0]; % (isotropic) chemical shifts of spins thet=45*pi/180.0; % angle (relative to z) maxorder=floor(N/2); % maximum coupling 'order' % calculate positions of spins (in xz plane) baseco=zeros(M,3); baseco(1,:)=[ 0 0 0]; if M>1 baseco(2,:)=[ r*cos(thet) 0 r*sin(thet)]; if M>2 baseco(3,:)=[r*cos(-thet) 0 r*sin(-thet)]; end end sw=20000; % spectral width for histogram bins=512; % number of bins in histogram Hist=zeros(1,bins); disp('Co-ordinates'); % show nuclei positions disp(baseco); vector=[ R 0 0 ]; % intercell vector total=M*N; % total number of spins distances=zeros(M,total); couplings=zeros(M,total); incrf=(vRF~=0); % whether to include RF or not for j=1:M for k=1:M % loop over spin pairs iv=baseco(j,:)-baseco(k,:); % internuclear vector (within cell) for celln=0:N-1 % loop over cells if ( (celln~=0) | (j~=k) ) % don't include coupling of spin with itself! tb=iv+celln*vector; if (2*celln>N) % choose shortest distance (in cells) between counting cells forward, and cells backward tb=iv-(N-celln)*vector; else if ( (2*celln==N) & (kspin2) | (celln~=0) % skip spin1<=spin2 within cell sk=M*celln+spin2; % convert to spin index masksk=bitshift(1,total-sk); % mask for state of 'other' spin if celln coup=0.25*couplings(spin1,sk); % scaling factor of 0.5 for couplings outside cell (otherwise couplings are double counted) else coup=0.5*couplings(spin1,sk); end mask=bitor(masksk,maskj); % flip mask for spin pair for jj=1:cblksize % loop over ket states cstate=cstates(jj); if j==k % zz terms (only in diagonal blocks) if xor(bitand(cstate,maskj),bitand(cstate,masksk)) H(jj,jj)=H(jj,jj)-coup; % one spin up, one spin down else H(jj,jj)=H(jj,jj)+coup; % both spins in same state end end nstate=bitxor(cstate,mask); % new state from flipping both spins if state_to_block(nstate+1)==j % is new state in set j ? destr=state_to_index(nstate+1); % get index of (symmetrised) state H(destr,jj)=H(destr,jj)-coup; % xx, yy terms end end end end end end case {1,-1} % +/-1 terms for jj=1:cblksize % loop over ket states cstate=cstates(jj); if coher==1 % +1 coherence for spin=1:M flipmask=bitcmp(bitshift(1,M-spin),total); nstate=bitand(cstate,flipmask); % clear bit (set to alpha state) if state_to_block(nstate+1)==j % is new state in set j? (note that if spin was already in alpha state, "new" state cannot be in set j) where=state_to_index(nstate+1); % index of (symmetrised) state H(where,jj)=rfplus; sigma(where,jj)=1.0; % F- end end else for spin=1:M flipmask=bitshift(1,M-spin); nstate=bitor(cstate,flipmask); % set bit (set to beta state) if state_to_block(nstate+1)==j % is new state in set j? H(state_to_index(nstate+1),jj)=rfminus; end end end end end scalef=scalefacs(rblksize,cblksize); % sqrt(N/(rblksize*cblksize)); for m=startk:endk % loop over k values of interest if (haseig(cblksize,m)~=0) & (haseig(rblksize,m)~=0) % is there a symmetrised state with this value of k? s=0.0; sig=0.0; for ii=1:rblksize % loop over (symmetrised) bra states for jj=1:cblksize % loop over (symmetrised) ket states wh=mod(m*(jj-ii),N); % exp(i*k*(col-row)/N) if wh~=0 s=s+H(ii,jj)*eigfacs(wh); % accumulate Hamiltonian element if coher==1 sig=sig+sigma(ii,jj)*eigfacs(wh); % accumulate density matrix element end else s=s+H(ii,jj); if coher==1 sig=sig+sigma(ii,jj); end end end end % store element in correct place in eigenvalue blocks Hsym{m}(reigptrs(m),ceigptrs(m))=s*scalef; if coher==1 sigmasym{m}(reigptrs(m),ceigptrs(m))=sig*scalef; end end end end end end starttime=cputime; Hist=zeros(1,bins); for k=startk:endk % loop over k values of interest disp(sprintf('k=%i',k)); HH=(Hsym{k}+Hsym{k}')/2; % force Hamiltonian to be Hermitian Hist=calcsignal(Hist,sw/bins,HH,sigmasym{k}); % accumulate spectral histogram end end %disp(sprintf('Time taken for signal calculation: %g',cputime-starttime)); fscale=[-bins/2+1:bins/2]*(sw/1000)/bins; bar(fscale,Hist); xlabel('frequency / kHz'); if testmode~=0 title('Without symmetry'); else title('With symmetry'); end