Drv (Driver) Class
This is a class in the Object Oriented Programming (OOP) paradigm that defines an analysis driver object in the LESM (Linear Elements Structure Model) program..
The analysis driver object object can be interpreted as an object that represents the structural model as a whole. The properties of a driver object are the main global variables of a typical structural analysis program. The methods of a driver object are the general steps of the direct stiffness method that do not depend on the analysis model or element type. Therefore, an analysis driver object is responsible for running the functions that drives the structural analysis. Only one driver object is created during the analysis process.
Contents
Class definition
Definition of super-class Drv as a handle class.
classdef Drv < handle
Public attributes
properties (SetAccess = public, GetAccess = public) anm = []; % handle to an object of the Anm class materials = []; % vector of handles to objects of the Material class sections = []; % vector of handles to objects of the Section class nodes = []; % vector of handles to objects of the Node class elems = []; % vector of handles to objects of the Elem class K = []; % global stiffness matrix F = []; % global forcing vector D = []; % global displacement vector ID = []; % global d.o.f. numbering matrix nmat = 0; % number of materials nsec = 0; % number of cross-sections nnp = 0; % number of nodes nel = 0; % number of elements neq = 0; % number of equations neqfree = 0; % number of equations of free d.o.f. neqfixed = 0; % number of equations of fixed d.o.f. end
Constructor method
methods %------------------------------------------------------------------ function drv = Drv(anm,mat,sec,nodes,elems,K,F,D,ID,nmat,nsec,nnp,nel,neq,neqfr,neqfx) if (nargin > 0) drv.anm = anm; drv.materials = mat; drv.sections = sec; drv.nodes = nodes; drv.elems = elems; drv.K = K; drv.F = F; drv.D = D; drv.ID = ID; drv.nmat = nmat; drv.nsec = nsec; drv.nnp = nnp; drv.nel = nel; drv.neq = neq; drv.neqfree = neqfr; drv.neqfixed = neqfx; end end end
Public methods
methods %------------------------------------------------------------------ % Creates or removes fictitious rotation constraints on nodes where % all incident elements are hinged, to force global stability % during the analysis process by avoiding a singular stifness matrix. % Input arguments: % fict: flag to check if constraints must be created or removed function fictRotConstraint(drv,fict) include_constants; for n = 1:drv.nnp % Create fictitious rotation constraints (before analysis process) if fict == 1 % Calculate total number of incident elements and hinged % elements on current node [tot,hng] = drv.nodes(n).elemsIncidence(drv); % Check if all incident elements are hinged if tot == hng % Insert ficticious constraint % on free rotation d.o.f.'s. if drv.nodes(n).ebc(4) == FREE_DOF drv.nodes(n).ebc(4) = FICTFIXED_DOF; end if drv.nodes(n).ebc(5) == FREE_DOF drv.nodes(n).ebc(5) = FICTFIXED_DOF; end if drv.nodes(n).ebc(6) == FREE_DOF drv.nodes(n).ebc(6) = FICTFIXED_DOF; end end % Remove fictitious rotation constraints (after analysis process) elseif fict == 0 if drv.nodes(n).ebc(4) == FICTFIXED_DOF drv.nodes(n).ebc(4) = FREE_DOF; end if drv.nodes(n).ebc(5) == FICTFIXED_DOF drv.nodes(n).ebc(5) = FREE_DOF; end if drv.nodes(n).ebc(6) == FICTFIXED_DOF drv.nodes(n).ebc(6) = FREE_DOF; end end end end %------------------------------------------------------------------ % Dimensions and initializes global stiffness matrix, global forcing % vector and global displacement vector. function dimKFD(drv) drv.K = zeros(drv.neq,drv.neq); drv.F = zeros(drv.neq,1); drv.D = zeros(drv.neq,1); end %------------------------------------------------------------------ % Assembles global d.o.f (degree of freedom) numbering ID matrix: % ID(k,n) = equation number of d.o.f. k of node n % Free d.o.f.'s have the initial numbering. % countF --> counts free d.o.f.'s. (numbered first) % countS --> counts fixed d.o.f.'s. (numbered later) function assembleDOFNum(drv) % Initialize equation numbers for free and fixed d.o.f.'s. countF = 0; countS = drv.neqfree; % Check if each d.o.f. is free or fixed to increment eqn. % number and store it in the ID matrix. for n = 1:drv.nnp for k = 1:drv.anm.ndof if drv.ID(k,n) == 0 countF = countF + 1; drv.ID(k,n) = countF; else countS = countS + 1; drv.ID(k,n) = countS; end end end end %------------------------------------------------------------------ % Assembles element gather vector (gle) that stores element d.o.f.'s % equation numbers. function assembleGle(drv) for e = 1:drv.nel % Initialize element gather vector drv.elems(e).gle = zeros(drv.elems(e).nen * drv.anm.ndof, 1); i = 0; % Assemble d.o.f.'s of initial node to element gather vector for j = 1:drv.anm.ndof i = i + 1; drv.elems(e).gle(i) = drv.ID(j,drv.elems(e).nodes(1).id); end % Assemble d.o.f.'s of final node to element gather vector for j = 1:drv.anm.ndof i = i + 1; drv.elems(e).gle(i) = drv.ID(j,drv.elems(e).nodes(2).id); end end end %------------------------------------------------------------------ % Assembles global stiffness matrix by adding the contribution of % the stiffness matrices of all elements. function gblMtx(drv) for e = 1:drv.nel % Compute element stiffness matrix in global system keg = drv.elems(e).gblStiffMtx(); % Assemble element stiffness matrix to global matrix drv.assembleElemMtx(keg,e); end end %------------------------------------------------------------------ % Assembles element stiffness matrix coefficients (in global system) % to the correct positions of the global stiffness matrix. % Input arguments: % keg: element stiffness matrix in global system % e: element identification number function assembleElemMtx(drv,keg,e) % Extract element gather vector gle = drv.elems(e).gle; % Add contribution of element stifness matrix to % global stiffness matrix. drv.K(gle,gle) = drv.K(gle,gle) + keg; % This command is a vector indexing, equivalent to: % ndof = drv.anm.ndof; % nen = drv.elems(e).nen; % % for il = 1:nen*ndof % ig = gle(il); % for jl = 1:nen*ndof % jg = gle(jl); % drv.K(ig,jg) = drv.K(ig,jg) + keg(il,jl); % end % end % % Where: % il is the local (element) row equation number % jl is the local (element) column equation number % ig is the global row equation number % jg is the global column equation number end %------------------------------------------------------------------ % Adds element equivalent nodal loads (ENL), from distributed loads % and thermal loads, to global forcing vector. function elemLoads(drv) for e = 1:drv.nel % Add distributed load as ENL to global forcing vector feg = drv.elems(e).load.gblDistribLoadENL(); drv.assembleENL(feg,e); % Add thermal load as ENL to global forcing vector feg = drv.elems(e).load.gblThermalLoadENL(); drv.assembleENL(feg,e); end end %------------------------------------------------------------------ % Assembles element equivalent nodal load vector (in global system) % to any term of the global forcing vector, including the terms that % correspond to constrained d.o.f.'s. % Input arguments: % feg: element equivalent nodal load vector in global system % e: element identification number function assembleENL(drv,feg,e) % Extract element gather vector gle = drv.elems(e).gle; % Add contribution of element equivalent nodal load vector to % global forcing vector drv.F(gle) = drv.F(gle) + feg; % This command is a vector indexing, equivalent to: % ndof = drv.anm.ndof; % nen = drv.elems(e)nen; % % for il = 1:nen*ndof % ig = gle(il); % drv.F(ig) = drv.F(ig) + feg(il); % end % % Where: % il is the local (element) row equation number % ig is the global row equation number end %------------------------------------------------------------------ % Partitions and solves the system of equilibrium equations. % Partitions the coefficient matrix K, forcing vector F and unknown % vector D: % f -> free d.o.f.'s (numbered first) - natural B.C. (unknown) % s -> constrainted by support d.o.f.'s (numbered later) - essential B.C. (known) % % Partitioned equilibrium system: % [ Kff Kfs ] * [ Df ] = [ Ff ] % [ Ksf Kss ] [ Ds ] = [ Fs ] % % Output: % status: flag for stable free-free global matrix (0 = unstable, 1 = stable) function status = solveEqnSystem(drv) % Assemble free-free global matrix Kff = drv.K(1:drv.neqfree,1:drv.neqfree); % Check for stable free-free global matrix by verifying its % reciprocal condition number (a very low reciprocal condition % number indicates that the matrix is badly conditioned and % may be singular) status = 1; if (rcond(Kff) < 10e-12) status = 0; return; end % Partition system of equations Kfs = drv.K(1:drv.neqfree,drv.neqfree+1:drv.neq); Ksf = drv.K(drv.neqfree+1:drv.neq,1:drv.neqfree); Kss = drv.K(drv.neqfree+1:drv.neq,drv.neqfree+1:drv.neq); Ff = drv.F(1:drv.neqfree); Ds = drv.D(drv.neqfree+1:drv.neq); Fs = drv.F(drv.neqfree+1:drv.neq); % Solve for Df Df = Kff \ (Ff - Kfs * Ds); % Reconstruct the global unknown vector D drv.D = [ Df Ds ]; % Recover forcing unknown values (reactions) at essential B.C. % It is assumed that the Fs vector currently stores combined % nodal loads applied directly to fixed d.o.f's. % Superimpose computed reaction values to combined nodal loads, % with inversed direction, that were applied directly to fixed % d.o.f.'s. Fs = -Fs + Ksf * Df + Kss * Ds; % Reconstruct the global forcing vector drv.F = [ Ff Fs ]; end %------------------------------------------------------------------ % Computes element internal forces on element ends. function elemIntForce(drv) for e = 1:drv.nel % Initialize element internal force arrays with null values drv.anm.initIntForce(drv.elems(e)); % Compute element internal forces from global analysis % (from nodal displacements and rotations) fel_gblAnl = drv.elems(e).gblAnlIntForce(drv); % Get element internal forces from local analysis % (fixed end forces of distributed loads and thermal loads) fel_lclAnl = drv.elems(e).fel_distribLoad + drv.elems(e).fel_thermalLoad; % Add contribution of element internal forces from global % analysis and from local analysis fel = fel_gblAnl + fel_lclAnl; % Assemble element internal force arrays drv.anm.assembleIntForce(drv.elems(e),fel); end end %------------------------------------------------------------------ % Computes element internal displacements in several cross-section % positions. function elemIntDispl(drv) for e = 1:drv.nel % Initialize element internal displacements array with % null values drv.anm.initIntDispl(drv.elems(e)); % Compute displacements in several cross-section positions L = drv.elems(e).length; step = L / (size(drv.elems(e).intDispl,2) - 1); j = 1; for x = 0:step:L % Compute element internal displacements from global % analysis (from nodal displacements and rotations) del_gblAnl = drv.elems(e).gblAnlIntDispl(drv,x); % Compute element internal displacements from local % analysis (internal displacements from distributed % loads and thermal loads) del_lclAnl = drv.anm.lclAnlIntDispl(drv.elems(e),x); % Add contribution of element internal displacements % from global analysis and from local analysis del = del_gblAnl + del_lclAnl; % Assemble element internal displacements array drv.elems(e).intDispl(:,j) = del; j = j + 1; end end end %------------------------------------------------------------------ % Processes current model data according to the direct stiffness % method, i.e., assembles global equilibrium system of equations, % calculates nodal displacements and rotations, and computes % support reactions and elements internal forces. % This method also prints the processing stages and results in % the default output (MATLAB command window). % Output: % status: flag for stable free-free global matrix (0 = unstable, 1 = stable) function status = process(drv) fprintf(1,'Preparing analysis data...\n'); % Dimension and initialize global matrix and vectors drv.dimKFD(); % Generate global d.o.f. numbering matrix drv.anm.setupDOFNum(drv); % Assemble global d.o.f. numbering matrix drv.assembleDOFNum(); % Assemble element gather vectors drv.assembleGle(); % Store prescribed displacements in global displacement vector drv.anm.setupPrescDispl(drv); % Assemble global stiffness matrix fprintf(1,'Assembling stiffness matrix...\n'); drv.gblMtx(); % Assemble global forcing vector fprintf(1,'Assembling forcing vector...\n'); drv.anm.nodalLoads(drv); % Initialize forcing vector with nodal loads drv.elemLoads(); % Add element equivalent nodal loads to forcing vector % Partition and solve the system of equations fprintf(1,'Solving system of equations...\n'); status = drv.solveEqnSystem(); % Check structural model stability if (status == 1) % Compute elements internal forces fprintf(1,'Computing element internal forces...\n'); drv.elemIntForce(); % Compute elements internal displacements fprintf(1,'Computing element internal displacements...\n'); drv.elemIntDispl(); else fprintf(1,'Unstable structure or invalid input data...\n'); end end %------------------------------------------------------------------ % Cleans data structure of the entire model. function clean(drv) % Clean data structure of the Anm object if drv.anm ~= 0 drv.anm.clean(); end % Clean data structure of all Material objects for m = 1:drv.nmat drv.materials(m).clean(); end % Clean data structure of all Section objects for s = 1:drv.nsec drv.sections(s).clean(); end % Clean data structure of all Node objects for n = 1:drv.nnp drv.nodes(n).clean(); end % Clean data structure of all Element objects and Lelem objects for e = 1:drv.nel drv.elems(e).load.clean(); drv.elems(e).clean(); end % Clean data structure of the Drv object drv.anm = []; drv.materials = []; drv.sections = []; drv.nodes = []; drv.elems = []; drv.K = []; drv.F = []; drv.D = []; drv.ID = []; drv.nmat = 0; drv.nsec = 0; drv.nnp = 0; drv.nel = 0; drv.neq = 0; drv.neqfree = 0; drv.neqfixed = 0; end end
end