Esempio di soluzione di una struttura reticolare

Questo script illustra la soluzione matriciale di una struttura reticolare, nel caso generale D-dimensionale. Il codice è valido per D >= 1; viene presentato un esempio per D == 2

Contents

Definizione della struttura

Costanti

dimensioni della struttura:

geometria e topologia

% problema piano 2D
D = 2;
% due nodi per elemento
nnodel = 2;

% struttura con quattro nodi
N = 4;

% struttura con cinque aste
M = 5;

% coordinate nodali (mm)
XY = [ 0.0, 10.0,  0.0, 10.0;
       0.0,  0.0, 10.0, 10.0 ];

% incidenze
INC = [1, 2, 3, 2, 4;
       2, 3, 1, 4, 3];

% rigidezze (N/mm)
kel = [10, 10, 10, 10, 10];

% verifico la coerenza delle dimensioni delle strutture dati
assert(all(size(XY) == [D, N]), 'matrice XY: errore dim');
assert(all(size(INC) == [nnodel, M]), 'matrice INC: errore dim');
assert(length(kel) == M, 'matrice kel: errore dim');

% verifico che in INC ci siano tutti e soli gli interi 1:N
assert(all(unique(INC) == (1:N)'), 'errore matrice INC')

Vincoli e carichi

vincoli

carichi

% spostamenti imposti (mm)
vinc = [ 1, 1, 0.0;
         1, 2, 0.0;
         2, 2, 0.0 ];

% forze nodali (N)
forc = [ 4, 1, 100.
         4, 2, 100. ];

% controlli sulle dimensioni delle matrici
assert(size(vinc, 2) == 3);
assert(size(forc, 2) == 3);

% controlli sugli elementi delle matrici
assert(all(ismember(vinc(:, 1),1:N)))
assert(all(ismember(forc(:, 1),1:N)))
assert(all(ismember(vinc(:, 2),1:D)))
assert(all(ismember(forc(:, 2),1:D)))

output dati di input

disp '************'
disp 'Dati di input'
disp ' '

disp 'coordinate nodali:'
disp(XY)

disp 'incidenze e rigidezze'
disp(vertcat(INC, kel))

disp 'vincoli'
disp(vinc)

disp('forze nodali')
disp(forc)
************
Dati di input
 
coordinate nodali:
     0    10     0    10
     0     0    10    10

incidenze e rigidezze
     1     2     3     2     4
     2     3     1     4     3
    10    10    10    10    10

vincoli
     1     1     0
     1     2     0
     2     2     0

forze nodali
     4     1   100
     4     2   100

Matrici ausiliarie

% gradi di libertà per nodo
gdln = D;
% gradi di libertà totali
gdl = gdln*N;
% gradi di libertà per elemento
gdle = gdln*nnodel;

% mappa da (componente, nodo) -> gdl
maptogdl = reshape(1:gdl,D,N);

Assemblaggio della matrice di rigidezza globale

ciclo sugli elementi per assemblare la matrice di rigidezza globale

% preparo matrice di zeri delle dimensioni opportune
K = zeros(gdl,gdl);
eyegdle = eye(gdle, gdle);
% ciclo sugli elementi
for i=1:M
    % matrice di rigidezza dell'elemento
    ki = kbar(XY(:,INC(:,i)),kel(i));
    % creo la matrice di assemblaggio
    L = zeros(gdle,gdl);
    jj = maptogdl(:,INC(:,i));
    jj = jj(:);
    L(:, jj) = eyegdle;
    % assemblo la matrice di rigidezza
    K = K + L'*ki*L;
end

% matrice di rigidezza assemblata
% disp(K)

% verifiche finali matrice assemblata
% tol è una tolleranza relativa, definita rispetto all'epsilon macchina
tol = 1000 * eps;
% vettore che conterrà i moti rigidi del sistema
urig = zeros(gdl, D*(D+1)/2);
% calcolo traslazioni rigide
for i = 1:D
    % spostamento unitario in direzione i
    urig(maptogdl(i,:),i) = 1;
end
% calcolo rotazioni rigide
soD = rots(D);
for i = 1:size(soD, 3)
    rot = soD(:,:,i)*XY;
    urig(:,D+i) = rot(:);
end
assert(size(urig,2) == D+size(soD,3))
assert(rank(urig) == min(size(urig)))

% (K * urig) è sufficientemente piccolo?
assert(norm(K*urig,inf) < tol*norm(urig,inf)*norm(K,inf))
% è giusto il rango della matrice?
assert(rank(K) <= gdl - size(urig, 2))

Imposizione dei vincoli e dei carichi nodali

i vincoli vengono imposti mediante decomposizione a blocchi della matrice di rigidezza

% calcolo gdl vincolati
gdv = (vinc(:,1)-1)*gdln + vinc(:,2);
% uv sono gli spostamenti imposti
u_V = vinc(:, 3);

% verifico che non ci siano ripetizioni
assert(length(gdv) == length(unique(gdv)));

% calcolo gdl incogniti
gdi = setdiff(1:gdl, gdv);

% assemblo il vettore delle forze nodali
f = zeros(gdl, 1);
for i = 1:size(forc,1)
    j = maptogdl(forc(i, 2), forc(i, 1));
    f(j) = f(j) + forc(i, 3);
end

% procedo alla decomposizione a blocchi della matrice

K_II = K(gdi,gdi);
K_IV = K(gdi,gdv);
K_VV = K(gdv,gdv);
f_I = f(gdi);
f_V = f(gdv);

Calcolo di spostamenti e reazioni vincolari

si risolve il sistema ridotto e si calcolano le reazioni vincolari

% calcolo spostamenti nodali e reazioni vincolari
u_I = K_II\(f_I-K_IV*u_V);
r_V = K_IV'*u_I + K_VV*u_V - f_V;

% ricostruisco il vettore completo degli spostamenti
u = zeros(gdl,1);
u(gdi) = u_I;
u(gdv) = u_V;
r = zeros(gdl,1);
r(gdv) = r_V;

output dei risultati

disp '************'
disp 'Risultati'
disp ' '

disp 'spostamenti:'
disp(reshape(u,D,N))

disp 'forze nodali:'
disp(reshape(f,D,N))

disp 'reazioni vincolari:'
disp(reshape(r,D,N))
************
Risultati
 
spostamenti:
         0   10.0000   40.0000   50.0000
         0         0   10.0000   10.0000

forze nodali:
     0     0     0   100
     0     0     0   100

reazioni vincolari:
 -100.0000         0         0         0
 -100.0000   -0.0000         0         0

verifiche finali

verifico che le equazioni di equilibrio siano soddisfatte

assert(norm(f + r - K*u,inf) < tol*norm(f,inf))