clear all

%%
% Ce code est le code général pour calculer n'importe quel modèle sorti de
% BeamZ. Nous pouvons comparer le résultat du multiplicateur critique
% approché par notre méthode au résultat exact calculé par la méthode des
% éléments finis pour différentes raideurs de ressort. Il faut néanmoins
% s'assurer que nous initialisons bien les DDL à bloquer pour que ça colle
% avec le modèle .BeamZ.


% Charger les données d'un fichier .mat
filename = 'Test4_symetric.mat';
load(filename)

% Obtenir le nombre de noeuds et d'éléments dans le modèle
NNode = length(Model.Nodes.XNOD);
NElem = length(Model.Elements.ELEMNOA);

% Définir les degrés de liberté bloqués
listDDLbloque = [1 2 3 3*NNode-2 3*NNode-1 3*NNode];

% Définir une série de constantes de raideur pour les ressorts
K_ressort = [2 4 6 8 10 15 20 25 40 60 80 100 1000 1e4];

% Initialiser les vecteurs pour stocker les résultats
vect_L1 = zeros(length(K_ressort),1);
vect_L_FEM = zeros(length(K_ressort),1);
vect_sum = zeros(length(K_ressort),1);
e = zeros(length(K_ressort),1);

% Cas infiniment rigide
Model.Springs(3).Value = 1e18;
Model.Materials(1).Young = 1;

% Calcul de certaines constantes pour la suite
A = Model.Geometries.A;
E = Model.Materials(1).Young;
EA = E*A;
I = E;

% Calcul des modes propres et de la matrice de rigidité dans le cas
% infiniment rigide
[K0, Ksigma, phi0, L_FEM, Re, Model, ddlLibres] = calcul_FEM(Model,listDDLbloque);
phi00 = phi0;
L0 = L_FEM;

% Boucle pour calculer le lambda approximatif en fonction de K
for i = 1:length(K_ressort)
    
    % Modifier le modèle avec la nouvelle constante de raideur pour les ressorts
    Model.Springs(3).Value = K_ressort(i);
    EI = Model.Geometries.I;
    
    
    % Calcul de Lambda1
    DH0 = 0;
    DHsigma = 0;
    Hsigma = 0;
    phi0 = phi00;

    % Parcourir tous les éléments pour calculer Lambda1
    for j = 1:NElem
        %Données
        phi0 = phi00;
        NOA = Model.Elements.ELEMNOA(j);
        NOB = Model.Elements.ELEMNOB(j);
        Le = Model.Elements.ELEMLEN(j);
        P = Model.Elements.N_STAB(j);
        phi_elem(1:3) = Re(1:3,1:3,j)'*phi0(3*NOA-2:3*NOA);
        phi_elem(4:6) = Re(4:6,4:6,j)'*phi0(3*NOB-2:3*NOB);
        phi1 = phi_elem(3);
        phi2 = phi_elem(6);

        % Calculer les coefficients alpha pour les ressorts
        if Model.Elements.ELEMSP1(j) == 3
            alpha1 = 1/(K_ressort(i)*Le);
        end
        if Model.Elements.ELEMSP2(j) == 3
            alpha2 = 1/(K_ressort(i)*Le);
        end
        if Model.Elements.ELEMSP1(j) ~= 3
            alpha1 = 0;
        end
        if Model.Elements.ELEMSP2(j) ~= 3
            alpha2 = 0;
        end

            psi = (phi_elem(5) - phi_elem(2))/Le;

            %Calcul de DH0
            DH0 = DH0 - 4*EI/Le*(alpha1*(2*phi1 + phi2 - 3*psi)^2 + alpha2*(phi1 + 2*phi2 - 3*psi)^2);

            %Calcul de DHsigma
            DHsigma = DHsigma - 2*P*Le/15*(alpha1*(2*phi1 + phi2 - 3*psi) * (4*phi1 - phi2 - 3*psi) ...
                    + alpha2*(phi1 + 2*phi2 - 3*psi)*(4*phi2 - phi1 - 3*psi));

            %Calcul de Hsigma
            Hsigma = Hsigma + P*Le/15 * (2*phi1^2 - phi1*phi2 + 2*phi2^2 - 3*(phi1+phi2)*psi + 18*psi^2);

    end

        
        L1 = -(DH0 + L0*DHsigma)/(Hsigma);

        Lambda_sum = L0 - L1;
        
        % Calcul du L_FEM
        [~,~, ~, L_FEM, ~, Model,ddlLibres] = calcul_FEM(Model,listDDLbloque);
    

% On stock les valeurs importantes

vect_L1(i) = L1;
vect_rapport(i) = L1/L0;
vect_L_FEM(i) = L_FEM;
vect_sum(i) = Lambda_sum;
e(i) = (L_FEM - Lambda_sum)/L_FEM * 100;
kO(:,:,i) = K0;



end





%% Tracer le graphique

% Calcul de l'erreur en pourcentage entre les deux courbes
err_pct = abs(vect_sum - vect_L_FEM) ./ vect_L_FEM * 100;

% Recherche de l'indice correspondant à l'erreur maximale
[~, idx] = max(err_pct);


figure('Position', [100 100 600 400]);
semilogx(K_ressort, vect_sum, 'b-', 'LineWidth', 1.5, 'MarkerSize', 8);
hold on;
semilogx(K_ressort, vect_L_FEM, 'ro', 'MarkerFaceColor', 'r', 'MarkerSize', 8);
grid on;
legend('$\lambda_{approx}$', '$\lambda_{FEM}$', 'Interpreter', 'latex', 'Location', 'southeast', 'FontSize', 12);
xlabel('Constante de raideur du ressort (Nm)', 'Interpreter', 'latex', 'FontSize', 12);
ylabel('Multiplicateur critique $\lambda_{cr}$', 'Interpreter', 'latex', 'FontSize', 12);
% title('Relation entre le multiplicateur critique et la constante de raideur du ressort', 'FontSize', 14);
set(gca, 'FontSize', 12);
box on;
ylim([2 5]);

% Ajout des valeurs de l'erreur en pourcentage pour chaque point
for i = 1:length(K_ressort)
    text(K_ressort(i), max(vect_sum(i), vect_L_FEM(i))+0.2*(min(vect_sum(1), vect_L_FEM(1))-max(vect_sum(1), vect_L_FEM(1))), sprintf('%.2f %%', err_pct(i)), 'HorizontalAlignment', 'center', 'FontSize', 9, 'Color', 'black');
end

% Ajout de la ligne et de la valeur de l'erreur maximale
text(K_ressort(idx)+1, min(vect_sum(idx), vect_L_FEM(idx))+0.1*(max(vect_sum(idx), vect_L_FEM(idx))-min(vect_sum(idx), vect_L_FEM(idx))), sprintf('Erreur max : %.2f %%', err_pct(idx)));
