Skip to content
Snippets Groups Projects
symMinimization.m 11.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    function [G, angle, Type, kappa] = symMinimization(print_Input,print_statPoint,print_Output,make_FunctionPlot, InputPath) %(Q_hom,B_eff)
    
    
    syms v1 v2 q1 q2 q3 q12 b1 b2 b3
    
    
    % -------- Options ----------
    % % print_Input = false;  %effective quantities
    % print_Input = true;
    % % print_statPoint = false;
    % print_statPoint = true;
    % print_Minimizer = true;
    % % make_FunctionPlot = false;
    % make_FunctionPlot = true;
    
    print_Uniqueness = false;         
    check_StationaryPoints = false;   % could be added to Input-Parameters..
    compare_with_Classification = false;  %maybe added later --- 
    
    
    %fprintf('Functions to be minimized:')
    f_plus(v1,v2,q1,q2,q3,q12,b1,b2,b3) = q1*v1^4 + q2*v2^4+2*q3*v1^2*v2^2-2*(q1*b1*v1^2+ q2*b2*v2^2+sqrt(2)*q3*b3*v1*v2)...
                                            + q12*(v1^2*v2^2-b2*v1^2-b1*v2^2+b1*b2);
    f_minus(v1,v2,q1,q2,q3,q12,b1,b2,b3) = q1*v1^4 + q2*v2^4+2*q3*v1^2*v2^2+2*(q1*b1*v1^2+ q2*b2*v2^2+sqrt(2)*q3*b3*v1*v2)...
                                            + q12*(v1^2*v2^2+b2*v1^2+b1*v2^2+b1*b2);
    
    
    % ---- Fix parameters
    
    
    if ~exist('InputPath','var')
         % third parameter does not exist, so default it to something
          absPath = "/home/klaus/Desktop/DUNE/dune-microstructure/outputs";
     end
    
    
    % 1. Import effective quantities from CellSolver-Code:
    %read as sparse Matrix...
    try %absolutePath
        Qmat = spconvert(load(absPath + '' + "/QMatrix.txt"));
        Bmat = spconvert(load(absPath + '' + "/BMatrix.txt"));
    %     fprintf('Use absolute Path')
    catch ME  % use relativePath
        Qmat = spconvert(load('../outputs/QMatrix.txt'));
        Bmat = spconvert(load('../outputs/BMatrix.txt'));
    %     fprintf('Use relative Path')
    end
    %convert to full matrix... 
    Qmat = full(Qmat);
    Bmat = full(Bmat);
    
    
    
    
    
    % --- TODO CHECK: assert if Q is orthotropic ???  check ifq13=q31=q23=q32= 0 ?
    
    
    
    if print_Input
        fprintf('effective quadratic form:')
        Qmat
        fprintf('effective prestrain')
        Bmat
        
        % check if Q is (close to..) symmetric
        % könnte Anti-symmetric part berechnen und schauen dass dieser klein?
        % Test: issymmetric(Qmat) does not work for float matrices?
        % symmetric part 0.5*(Qmat+Qmat')
        % anti-symmetric part 0.5*(Qmat-Qmat')
    
        if norm(0.5*(Qmat-Qmat'),'fro') < 1e-8
    
            fprintf('Qmat (close to) symmetric \n')
    
            norm(0.5*(Qmat-Qmat'),'fro') % TEST
    
        else
            fprintf('Qmat not symmetric \n')
        end
        
        
        % Check if B_eff is diagonal this is equivalent to b3 == 0
    
        if abs(Bmat(3)) < 1e-8
    
            fprintf('B_eff is diagonal (b3 == 0) \n')
        else
            fprintf('B_eff is  NOT diagonal (b3 != 0)  \n')
        end
    end
    
    
    
    
    % CAST VALUES TO SYM FIRST? This is done anyway..
    % % Substitute effective quantitites      
    f_plus = subs(f_plus,{q1, q2, q3, q12, b1, b2, b3}, {Qmat(1,1), Qmat(2,2), Qmat(3,3), Qmat(1,2), ...
                                                         Bmat(1), Bmat(2), Bmat(3)});
    
    f_minus = subs(f_minus,{q1, q2, q3, q12, b1, b2, b3}, {Qmat(1,1), Qmat(2,2), Qmat(3,3), Qmat(1,2), ...
                                                         Bmat(1), Bmat(2), Bmat(3)});
    
    
    % Compute the Gradients 
    df_plusx = diff(f_plus,v1);
    df_plusy = diff(f_plus,v2);
    df_minusx = diff(f_minus,v1);
    df_minusy = diff(f_minus,v2);
    
    % Setup Equations Grad(f) = 0 
    eq1 = df_plusx == 0;
    eq2 = df_plusy == 0;
    eqns_plus = [eq1, eq2];
    eq3 = df_minusx == 0;
    eq4 = df_minusy == 0;
    eqns_minus = [eq3, eq4];
    
    % -------  Symbolically Solve Equations: 
    % More robust (works even for values b_3 ~ 1e-08 ): 
    S_plus = solve(eqns_plus,v1,v2,'MaxDegree' , 5);  
    S_minus = solve(eqns_minus,v1,v2,'MaxDegree' , 5);
    
    A_plus = S_plus.v1;
    B_plus = S_plus.v2;
    A_minus = S_minus.v1;
    B_minus = S_minus.v2;
    
    if check_StationaryPoints
        %---------- TEST if Grad(f) = 0 ---------------------
        fprintf('Testing equation grad(f) = 0  with stationary points')
        for i = 1:size(A_plus,1)
            fprintf('Testing %d.point (f_plus): ',i )
            [ double(subs(subs(df_plusx,v1,A_plus(i)),v2,B_plus(i))), double(subs(subs(df_plusy,v1,A_plus(i)),v2,B_plus(i))) ]
        end
        for i = 1:size(A_minus,1)
            fprintf('Testing %d.point (f_minus): ',i )
            [double(subs(subs(df_minusx,v1,A_minus(i)),v2,B_minus(i))), double(subs(subs(df_minusy,v1,A_minus(i)),v2,B_minus(i)))]
        end
        % ------------------------------------
    end
    
    % --- Extract only Real-Solutions
    % fprintf('real stationary points of f_plus:')
    tmp1 = A_plus(imag(double(A_plus))==0 & imag(double(B_plus)) == 0);
    tmp2 = B_plus(imag(double(A_plus))==0 & imag(double(B_plus)) == 0);
    A_plus = tmp1;
    B_plus = tmp2;
    SP_plus = [A_plus,B_plus];
    
    % fprintf('real stationary points of f_minus:')
    tmp1 = A_minus(imag(double(A_minus))==0 & imag(double(B_minus)) == 0);
    tmp2 = B_minus(imag(double(A_minus))==0 & imag(double(B_minus)) == 0);
    A_minus = tmp1;
    B_minus = tmp2;
    SP_minus = [A_minus,B_minus];
    
    % TODO one should use f_plus.subs(A_plus..) to compute function value symbolically?
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    % in the end only the stationaryPoints are used.. should be ok to compare function values numerically
    
    
    % Determine global Minimizer from stationary points:
    % fprintf('function values at stationary points (f_plus):')
    T_plus = arrayfun(@(v1,v2) double(f_plus(v1,v2,q1,q2,q3,q12,b1,b2,b3)),A_plus,B_plus,'UniformOutput', false);
    T_plus = cell2mat(T_plus);
    
    %Test: use Substitution
    % subs(f_plus,{v1, v2}, {A_plus,B_plus})
    
    % fprintf('function values at stationary points (f_minus):')
    T_minus = arrayfun(@(v1,v2) double(f_minus(v1,v2,q1,q2,q3,q12,b1,b2,b3)),A_minus,B_minus,'UniformOutput', false);
    T_minus = cell2mat(T_minus);
    
    %Test: use Substitution
    % T_minus = subs(f_minus,{v1, v2}, {A_minus,B_minus})
    % double(T_minus)
    
    if print_statPoint
        fprintf('real stationary points of f_plus: ')
    %     SP_Plus     %alternative: output as symbolic (can be unwieldy)
        double(SP_plus)
        fprintf('real stationary points of f_minus:')
    %     SP_Minus     %alternative: output as symbolic (can be unwieldy)
        double(SP_minus)
        fprintf('function values at stationary points (f_plus):')
        T_plus
        fprintf('function values at stationary points (f_minus):')
        T_minus
    end
    
    % --- Find Stationary Point(s) with minimum Value 
    [Min_plus,MinIdx_plus] = min(T_plus, [], 'all', 'linear');    %find one min...
    [Min_minus,MinIdx_minus] = min(T_minus, [], 'all', 'linear');
    % [Min_minus,MinIdx_minus] = min(T_minus)                     % works with symbolic too
    
    % Compare Minimizers of f_plus & f_minus
    [globalMinimizerValue,GlobalIdx] = min([Min_plus,Min_minus]); 
    
    if GlobalIdx == 1     %Min_plus   % i.e. Global Minimizer is given by f_plus
        GlobalMinimizer = SP_plus(MinIdx_plus,:);
        sign = 1.0;
    elseif GlobalIdx == 2  %Min_minus % i.e. Global Minimizer is given by f_minus
        GlobalMinimizer = SP_minus(MinIdx_minus,:);
        sign = -1.0; 
    end
    
    % ------ Check if there are more SP with the same value...
     MinIndices_minus = find(T_minus(:) == globalMinimizerValue);    % Find indices of All Minima
     MinIndices_plus  = find(T_plus(:) == globalMinimizerValue);    % Find indices of All Minima                   
     numMinSP_minus = size(MinIndices_minus,1);   % One of these is always >= 2 due to the structure of the roots..
     numMinSP_plus  = size(MinIndices_plus,1);
        
    %     AllMinSP_minus = SP_minus(MinIndices_minus,:)
    %     AllMinSP_minus = double(SP_minus(MinIndices_minus,:))
    %     AllMin = T_minus(MinIndices)  %bereits klar dass diese selben funktionswert haben..
          
        Minimizer = sign*(GlobalMinimizer'*GlobalMinimizer);  % global minimizing Matrix G*
        MinimizerCount = 1;
        % different Stationary Points might correspond to the same minimizing
        % Matrix G*... check this: 
        
        % Compare only with other StationaryPoints/Minimizers
        % remove Index of Minimizer
        if GlobalIdx == 1     
            MinIndices_plus = MinIndices_plus(MinIndices_plus~=MinIdx_plus);
        elseif GlobalIdx == 2  
            MinIndices_minus = MinIndices_minus(MinIndices_minus~=MinIdx_minus);
        end
        
        MinIndices = cat(1,MinIndices_plus,MinIndices_minus);  %[Minimizers-Indices f_plus, Minimizer-Indices f_minus]
        
        for i = 1:(numMinSP_minus+numMinSP_plus-1)  % -1: dont count Minimizer itself.. 
            idx = MinIndices(i);   
            
            if i > numMinSP_plus
                SP = SP_minus(idx,:);
            else
                SP = SP_plus(idx,:); 
            end
            
    %         SP_value = T_minus(idx) % not needed? 
            Matrix = sign*(SP'*SP);
    
    
            if norm(double(Matrix-Minimizer),'fro') < 1e-8   %check is this sufficient here?
    %             fprintf('both StationaryPoints correspond to the same(Matrix-)Minimizer')
    
    %             fprintf('StationaryPoint corresponds to a different (Matrix-)Minimizer')
    
                MinimizerCount = MinimizerCount + 1;
            end
        end
    % ----------------------------------------------------------------------------------------------------------------
    
    
    
    % Output Uniqueness of Minimizers:
    if print_Uniqueness
        if MinimizerCount == 1
            fprintf('Unique Minimzier')
        elseif MinimizerCount == 2
            fprintf('Two Minimziers')
        else
            fprintf('1-Parameter family of Minimziers')
        end
    end
    
    
    
    
    
    % --- determine the angle of the Minimizer
    % a1 = Minimizer(1,1)
    % a2 = Minimizer(2,2)
    a1 = double(Minimizer(1,1));
    a2 = double(Minimizer(2,2));
    
    % compute the angle <(e,e_1) where Minimizer = kappa* (e (x) e)
    e = [sqrt((a1/(a1+a2))), sqrt((a2/(a1+a2)))];    % always positive under sqrt here .. basically takes absolute value here
    angle = atan2(e(2), e(1)); 
    
    % compute curvature kappa
    kappa = (a1 + a2);
    
    % % CHeck off diagonal entries:
    % sqrt(a1*a2);
    % double(Minimizer);
    
    G = double(Minimizer);
    
    
    
    % --- "Classification" / Determine the TYPE of Minimizer by using 
    % the number of solutions (Uniqueness?)
    % the angle (axial- or non-axial Minimizer)
    
    % (Alternative compute det[GlobalMinimizer' e1']  where e1 = [1 0] ?)
    
    % Check Uniqueness -- Options: unique/twoMinimizers/1-ParameterFamily
    if MinimizerCount == 1
    %     fprintf('Unique Minimzier')
        % Check if Minimizer is axial or non-axial:
    
        if (abs(angle-pi/2) < 1e-8 || abs(angle) < 1e-8) % axial Minimizer
    
         Type = 3;
        else % non-axial Minimizer   
         Type = 1;
        end
    elseif MinimizerCount == 2
    %     fprintf('Two Minimziers')
        % Check if Minimizer is axial or non-axial:
    
        if (abs(angle-pi/2) < 1e-8 || abs(angle) < 1e-8) % axial Minimizer
    
            Type = 3;
        else % non-axial Minimizer   
            fprintf('ERROR: Two non-axial Minimizers cannot happen!')
        end
    else
    %     fprintf('1-Parameter family of Minimziers')
        % Check if Minimizer is axial or non-axial:
    
        if (abs(angle-pi/2) < 1e-8 || abs(angle) < 1e-8) % axial Minimizer
    
    %         fprintf('ERROR: axial Minimizers cannot happen for 1-Parameter Family!')
        else % non-axial Minimizer   
            Type = 2;
        end
    end
    % ------------------------------------------------------------------------------------------------------
    
    
    
    
    if print_Output
        fprintf(' --------- Output symMinimization --------')
        fprintf('Global Minimizer v: (%d,%d) \n', GlobalMinimizer(1),GlobalMinimizer(2) )
        fprintf('Global Minimizer Value f(v): %d \n', sym(globalMinimizerValue) ) %cast to symbolic
        %     fprintf('Global Minimizer Value : %d', globalMinimizerValue )
        
        fprintf('Global Minimizer G: \n' )
        G 
        fprintf("Angle = %d \n", angle)
        fprintf("Curvature = %d \n", kappa)
        fprintf("Type = %i \n", Type)
        fprintf(' --------- -------------------- --------')
    end
    
    
    
    if make_FunctionPlot  
        fsurf(@(x,y) f_plus(x,y,q1,q2,q3,q12,b1,b2,b3)) % Plot functions
        hold on
        plot3(double(A_plus),double(B_plus),T_plus,'g*')
        %Plot GlobalMinimizer:
        hold on
        plot3(double(GlobalMinimizer(1)),double(GlobalMinimizer(2)),globalMinimizerValue, 'o', 'Color','c')
        % view(90,0)
        % view(2)
    
        figure
        fsurf(@(x,y) f_minus(x,y,q1,q2,q3,q12,b1,b2,b3))
        hold on
        plot3(double(A_minus),double(B_minus),T_minus,'g*')
        hold on
        plot3(double(GlobalMinimizer(1)), double(GlobalMinimizer(2)),globalMinimizerValue, 'o', 'Color','c')
    end
    
    
    return 
    
    
    % Write symbolic solution to txt-File in Latex format
    % fileID = fopen('txt.txt','w');
    % fprintf(fileID,'%s' , latex(S_plus.v1));
    % fclose(fileID);