classdef HW9_2DIsing < handle
    %HW9_2DIsing Summary of this class goes here
    %   This is a class comprised of a GUI that gives the user the ability
    %   to control the 2D_Ising model code.
    
    properties
        
        B %Magnetic field
        J %Interaction Strength
        Beta %1/KT
        f_stop = 1; %when you press the stop button, the value of this variable will be changed and the while-loop will break
        Fig =[];    %Figure handle
    end
    
    methods
        
        function obj = HW9_gui(obj)
            % This creates the GUI
            
            obj.Fig = figure('visible','on','Position',[365,350,610,450]); %making an invisible figure with the given position and size
            
            fedit1 = uicontrol('Style','edit','Position',[525,390,60,20]); %making an editable text
            set(fedit1,'String','0'); %set a default value in the editable text
            ftext1 = uicontrol('Style','text','Position',[495,387,30,20],'String','B'); %making an static text
            
            fedit2 = uicontrol('Style','edit','Position',[525,350,60,20]); %making another editable text
            set(fedit2,'String','-0.2'); %setting a default value
            ftext2 = uicontrol('Style','text','Position',[495,347,30,20],'String','J'); %making another static text
            
            fedit3 = uicontrol('Style','edit','Position',[525,310,60,20]);
            set(fedit3,'String','10');
            ftext3 = uicontrol('Style','text','Position',[495,307,30,20],'String','Beta');
            
            %making a push-button called Run. When you bush the button the
            %function 'run_call' will be called
            frun = uicontrol('Style','pushbutton','Position',[500,190,40,30],'String','Run','Callback',@run_call);
            
            %making another push-button called Stop. When you push this
            %button the function 'stop_call' will be called.
            fstop = uicontrol('Style','pushbutton','Position',[550,190,40,30],'String','Stop','Callback',@stop_call);
            
            fplot = axes('Units','pixels','Position',[50,50,435,380]); %making a figure in the GUI
            
            obj.Fig.Visible = 'on'; %making your GUI visible
            
            set([fedit1,ftext1,fedit2,ftext2,fedit3,ftext3,frun,fstop,fplot],'Units','normalized'); %aligning the positions
            
            function run_call(~,~) %called when the Run button is pushed
                
                obj.B = str2double(get(fedit1,'String'));     %Magnetic field
                obj.J = str2double(get(fedit2,'String'));
                obj.Beta = str2double(get(fedit3,'String'));  %1/KbT   
                obj.HW9_spins %calling spins method
                
            end
            
            function stop_call(~,~) %called when the stop button is pushed
                
                obj.f_stop = 0; %changing the value of fstop
                
            end
            
        end
        
        function HW9_spins(obj)
            %this method contain the code for 2D-Ising model
            
            %Check if the figure has been created by GUI
            %If not, create figure and set close function
            if isempty(obj.Fig)
                obj.Fig=figure();
            end
            
            
            N=100;  %Number of spins
            obj.f_stop = 1;
            %Start with random orientation
            Spins=double(randn(N,N)>0);
            Spins(Spins==0)=-1;
            
            imshow(Spins,[],'InitialMagnification',400)
            s=sprintf('Beta=%g, J=%g, B=%g',obj.Beta,obj.J,obj.B);
            title(s)
            %Run Markov Chain Monte Carlo
            
            nn=0;
            while 1 %We use 'break' statements to stop while loop
                
                % This is for the GUI stop button
                if obj.f_stop == 0  %when the stop button is pushed this if-loop whill be run and the while-loop will break
                    break
                end
                
                nn=nn+1;    %counter for display
                
                %Pick site and flip spin
                IDX=ceil(N*rand);
                IDY=ceil(N*rand);
                SpinsTest=Spins;
                SpinsTest(IDX,IDY)=-Spins(IDX,IDY);
                
                %Energy from nearest neighbor interactions
                E_Spin=obj.J*(sum(sum(Spins(1:end-1,:).*Spins(2:end,:)))+... %Y neighbor
                    sum(Spins(1,:).*Spins(end,:))+... %Y periodic BC
                    sum(sum(Spins(:,1:end-1).*Spins(:,2:end)))+... %X neighbor
                    sum(Spins(:,1).*Spins(:,end))); %X periodic BC
                
                E_SpinTest=obj.J*(sum(sum(SpinsTest(1:end-1,:).*SpinsTest(2:end,:)))+... %Y neighbor
                    sum(SpinsTest(1,:).*SpinsTest(end,:))+... %Y periodic BC
                    sum(sum(SpinsTest(:,1:end-1).*SpinsTest(:,2:end)))+... %X neighbor
                    sum(SpinsTest(:,1).*SpinsTest(:,end))); %X periodic BC
                
                %Energy from Interactions with feild
                E_Field=-obj.B*sum(Spins(:));
                E_FieldTest=-obj.B*sum(SpinsTest(:));
                
                %Total Energy (Hamiltonian)
                H=E_Spin+E_Field;
                HTest=E_SpinTest+E_FieldTest;
                
                %Test acceptance probability for Metropolis-Hastings
                Alpha=exp(-obj.Beta*(HTest-H));
                
                %Metropolis-Hastings rule
                if rand()< (Alpha)
                    Spins(IDX,IDY)=-Spins(IDX,IDY);
                end
                
                ShowIter=1000;
                %Show every ShowIter interations
                if (nn/ShowIter==round(nn/ShowIter))
                    pause(.01);
                    %If figure is closed, then break (this is one way)
                    if ~ishandle(obj.Fig)
                        break
                    end
                    imshow(Spins,[],'InitialMagnification',400)
                end
            end
            
        end
        
    end
    
end

