1 /*! 2 * 3 * JSBeams : Numerical solution of beam structures in JavaScript 4 * version 0.5.1 (2011-10-15) 5 * 6 * Copyright (C) 2011 Jan Stransky 7 * 8 * Czech Technical University, Faculty of Civil Engineering, 9 * Department of Structural Mechanics, 166 29 Prague, Czech Republic 10 * 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 /** 27 * @fileOverview JavaScript implementation of numerical solution (direct stiffness methos) of beam structures. Modeled structures consists of nodes and beams. Nodes have only geometrical meaning and contains only coordinates, dofs and their values are stored in beams. Different static schemes and methods (clamped vs. pin ends, rigid arms, master x slave nodes etc.) can be modeled by special using of beam DOFs. Requires <a href="http://mech.fsv.cvut.cz/~stransky/software/jsmatrix/">jsmatrix.js</a> loaded before loading this file. For more information see <a href="http://mech.fsv.cvut.cz/~stransky/software/jsbeams/">project homepage</a>. 28 <br /><br/>JSBeams is a free software distributed under <a href='http://www.gnu.org/licenses/gpl.html'>GNU GPL license</a>. 29 * @author <a href="http://mech.fsv.cvut.cz/~stransky">Jan Stránský</a> 30 * @version 0.5.1 (2011-10-15) 31 */ 32 33 // constants for easier manipulation 34 /**constant*/ var JSB2D_CLAMPED_CLAMPED = 0; // should be 0 35 /**constant*/ var JSB2D_CC = 0; 36 /**constant*/ var JSB2D_CLAMPED_HINGE = 1; 37 /**constant*/ var JSB2D_CH = 1; 38 /**constant*/ var JSB2D_HINGE_CLAMPED = 2; 39 /**constant*/ var JSB2D_HC = 2; 40 /**constant*/ var JSB2D_HINGE_HINGE = 3; 41 /**constant*/ var JSB2D_HH = 3; 42 /**constant*/ var JSB2D_TRUSS = 3; 43 44 45 /** Returns elements of a that are not in b (Matlab-like function), ret = a - b 46 * @param {Array} a 47 * @param {Array} b 48 * @returns {Array} array of elements of a that are not in b 49 * @example a = [1,2,3,4,5,6]; 50 * b = [2,5,1,99,54]; 51 * c = setdiff(a,b) // c = [3,4,6]*/ 52 setdiff = function(A,B) { 53 var ret = []; 54 for (a=0; a<A.length; a++) { 55 var noMatch = 1; 56 for (var b=0; b<B.length; b++) { 57 if (A[a] == B[b]) { noMatch = 0; break; } 58 } 59 if (noMatch) { ret.push(A[a]); } 60 } 61 return ret; 62 } 63 64 65 /** 2d xz plane node implementation. The meaning of current implementation is only geometric, because DOFs itself are stored in beams (for both computational and graphic postprocessing part) 66 * @class represents nodes in 2d zx plane 67 * @param {float} x x coordinate of node 68 * @param {float} y y coordinate of node 69 * @param {float} z z coordinate of node 70 * @property {float} x x coordinate 71 * @property {float} y y coordinate 72 * @property {float} z z coordinate*/ 73 Node = function(x,y,z) { 74 this.x = x || 0.; 75 this.y = y || 0.; 76 this.z = z || 0.; 77 } 78 /**#@+ 79 * @function 80 * @memberOf Node# 81 */ 82 Node.prototype = { 83 /** String representation 84 * @returns {String} string representation*/ 85 toString: function() { 86 return "Node ( "+this.x+", "+this.y+", "+this.z+" )"; 87 }, 88 89 /** Sets new position to receiver 90 * @param {float} x x coordinate of new position 91 * @param {float} y y coordinate of new position 92 * @param {float} z z coordinate of new position*/ 93 setXYZ: function(x,y,z) { 94 this.x = x; this.y = y; this.z = z; 95 }, 96 97 /** Sets new position to receiver 98 * @param {float} x x coordinate of new position 99 * @param {float} z z coordinate of new position*/ 100 setXZ: function(x,z) { 101 this.x = x; this.z = z; 102 }, 103 104 /** Sets new position to receiver 105 * @param {float} y y coordinate of new position 106 * @param {float} z z coordinate of new position*/ 107 setYZ: function(y,z) { 108 this.y = y; this.z = z; 109 }, 110 111 /** Set new x coordinate to receiver 112 * @param x x coordinate of new position*/ 113 setX: function(x) { 114 this.x = x; 115 }, 116 117 /** Set new x coordinate to receiver 118 * @param y y coordinate of new position*/ 119 setY: function(y) { 120 this.y = y; 121 }, 122 123 /** Set new z coordinate to receiver 124 * @param z z coordinate of new position*/ 125 setZ: function(z) { 126 this.z = z; 127 }, 128 129 /** Change position of receiver by given values 130 * @param {float} dx length of translation in x direction 131 * @param {float} dy length of translation in y direction 132 * @param {float} dz length of translation in z direction*/ 133 translate: function(dx,dy,dz) { 134 this.x += dx; 135 this.y += dy; 136 this.z += dz; 137 }, 138 139 /** Change position of receiver by given values 140 * @param {float} dx length of translation in x direction 141 * @param {float} dz length of translation in z direction*/ 142 translateXZ: function(dx,dz) { 143 this.x += dx; 144 this.z += dz; 145 }, 146 147 /** Change position of receiver by given values 148 * @param {float} dy length of translation in y direction 149 * @param {float} dz length of translation in z direction*/ 150 translateYZ: function(dy,dz) { 151 this.y += dy; 152 this.z += dz; 153 }, 154 155 /** Change horizontal position of receiver by given values 156 * @param {float} dx length of translation in x direction*/ 157 translateX: function(dx) { 158 this.x += dx; 159 }, 160 161 /** Change horizontal position of receiver by given values 162 * @param {float} dy length of translation in y direction*/ 163 translateY: function(dy) { 164 this.y += dy; 165 }, 166 167 /** Change vertical position of receiver by given values 168 * @param {float} dz length of translation in z direction*/ 169 translateZ: function(dz) { 170 this.z += dz; 171 }, 172 173 /** Returns difference between receiver and given node 174 * @param {Node} n node to be substracted 175 * @returns {Node} difference this-node*/ 176 sub: function(n) { 177 return new Node(this.x-n.x,this.y-n.y,this.z-n.z); 178 }, 179 180 /** Returns sum of receiver and given node 181 * @param {Node} n node to be substracted 182 * @returns {Node} difference this+node*/ 183 add: function(n) { 184 return new Node(this.x+n.x,this.y+x.y,this.z+n.z); 185 }, 186 187 /** Returns receiver multiplied by given number 188 * @param {float} f multiplicator 189 * @returns {Node} product of multiplication f*this*/ 190 mulf: function(f) { 191 return new Node(f*this.x,f*this.y,f*this.z); 192 }, 193 194 /** Returns cross product of receiver and given node 195 * @param {Node} n node to be crossed 196 * @returns {Node} cross product this x node*/ 197 cross: function(n) { 198 return new Node(this.y*n.z-this.z*n.y, this.z*n.x-this.x*n.z, this.x*n.y-this.y*n.x); 199 }, 200 201 /** Returns dot product of receiver and given node 202 * @param {Node} n node to be crossed 203 * @returns {float} dot product this . node*/ 204 dot: function(n) { 205 return this.x*n.x + this.y*n.y + this.z*n.z; 206 }, 207 208 /** Returns square norm of receiver this.dot(this) 209 * @returns {float} squared norm of receiver*/ 210 squaredNorm: function() { 211 return this.dot(this); 212 }, 213 214 /** Returns (Eucleidian) norm of receiver sqrt(this.dit(this)) 215 * @returns {float} norm of receiver*/ 216 norm: function() { 217 return Math.sqrt(this.dot(this)); 218 }, 219 /**#@-*/ 220 } 221 /** Constructor, see {@link Node} for input parameters description 222 * @returns {Node} new Node object*/ 223 Node.create = function(x,y,z) { 224 return new Node(x,y,z); 225 } 226 227 228 229 230 /** 2d beam implementation 231 * @class represents structural 2d beam with 3 degrees of freedom in each node 232 * @param {Node} node1 1st node 233 * @param {Node} node2 2nd node 234 * @param {Object} [params={}] object of parameters in format {param1:val1,param2:val2}, i.e. beam=Beam2d(n1,n2,{dofs:[1,2,3,4],ea:4}); 235 * @param {int} [params.type=JSB2D_CC] type of beam. JSB2D_CC for both ends clamped, JSB2D_HC for hinge-clamped, JSB2D_CH for clamped-hinge, JSB2D_HH for hinge-hinge (truss) 236 * @param {[ints]} [params.dofs=[0,1,2,3,4,5]] degrees of freedom on both ends. number (6,5,4) should correscpond to this.type 237 * @param {float} [params.ei=1.] bending stiffness [Nm2] 238 * @param {float} [params.ea=1.] normal stiffness [N] 239 * @param {bool} [params.hasBodyLoad=false] if some body (continuous force or temperature) load is present 240 * @param {float} [params.fzloc=0.] constant continuous load parallel to local z coordinate [N/m] 241 * @param {float} [params.fxloc=0.] constant continuous load parallel to local x coordinate [N/m] 242 * @param {float} [params.mu=1.] length mass [kg/m] 243 * @param {float} [params.dT=0.] positiv temperature change (=warming) of beam center line [K] 244 * @param {float} [params.dTh=0.] (temperature of bottom fibers - temperature of top fibers)/height ((Tb-Tt)/h) [K/m] 245 * @param {float} [params.alpha=12e-6] thermal dillatation coefficient [K-1] 246 * @property {Node} node1 1st node 247 * @property {Node} node2 2nd node 248 * @property {[ints]} dofs degrees of freedom on both ends 249 * @property {bool} hasBodyLoad if some body (continuous force or temperature) load is present 250 * @property {float} ei bending stiffness [Nm2] 251 * @property {float} ea normal stiffness [N] 252 * @property {float} fzloc constant continuous load parallel to local z coordinate [N/m] 253 * @property {float} fxloc constant continuous load parallel to local x coordinate [N/m] 254 * @property {float} mu length mass [kg/m] 255 * @property {float} dT positive temperature change (=warming) of beam center line [K] 256 * @property {float} dTh (temperature of bottom fibers - temperature of top fibers)/height ((Tb-Tt)/h) [K/m] 257 * @property {float} alpha thermal dillatation coefficient [K-1] 258 * @property {Matrix} kloc stiffness matrix in local coordinate system, computed by setStiffAndTrsfMats method 259 * @property {Matrix} t transformation matrix (from global to local), computed by setStiffAndTrsfMats method 260 * @property {Matrix} tt transposed transformation matrix (from local to global), computed by setStiffAndTrsfMats method 261 * @property {Matrix} mloc mass matrix in local coordinate system, computed by setMassMats method 262 * @property {Matrix} m mass matrix in global coordinate system, computed by setMassMats method 263 * @property {Vector} load vector of end forces 264 * @property {Vector} dspl vector of end displacements 265 * @property {[Vectors]} eigShapes array of eigenshapes 266 * @property {float} len length of the beam 267 * @property {float} sin sin of node1->node2 vector 268 * @property {float} cos cos of node1->node2 vector*/ 269 // example? 270 Beam2d = function(node1,node2,params) { 271 var params = params==undefined? {} : params; 272 this.node1 = node1 || null; 273 this.node2 = node2 || null; 274 this.type = params.type || JSB2D_CC; 275 this.dofs = params.dofs || [0,1,2,3,4,5]; 276 this.ei = params.ei || 1.; 277 this.ea = params.ea || 1.; 278 this.hasBodyLoad = params.hasBodyLoad || false; 279 this.fzloc = params.fzloc || 0.; 280 this.fxloc = params.fxloc || 0.; 281 this.mu = params.mu || 1.; 282 this.dT = params.dT || 0.; 283 this.dTh = params.dTh || 0.; 284 this.alpha = params.alpha || 12e-6; 285 this.kloc = null; 286 this.a = null; 287 this.b = null; 288 this.kaa = null; 289 this.kab = null; 290 this.kba = null; 291 this.kbb = null; 292 this.t = new Matrix(); 293 this.tt = new Matrix(); 294 this.mloc = new Matrix(); 295 this.m = new Matrix(); 296 this.load = Vector.Zeros(6); 297 this.loadCC = Vector.Zeros(6); 298 this.dspl = Vector.Zeros(6); 299 this.eigShapes = []; 300 this.len = null; 301 this.sin = null; 302 this.cos = null; 303 304 this.setGeom(); 305 } 306 /**#@+ 307 * @function 308 * @memberOf Beam2d# 309 */ 310 Beam2d.prototype = { 311 /** Sets geometric parameters of received according to node positions*/ 312 setGeom: function() { 313 var dx = (this.node2.x - this.node1.x); 314 var dz = (this.node2.z - this.node1.z); 315 this.len = Math.sqrt(dx*dx + dz*dz); 316 this.cos = dx/this.len; 317 this.sin = dz/this.len; 318 }, 319 320 /** Sets stiffness matrices in local and global coordinate system according to stored material and crossection parameters and transformation matrix and its transposition according to stored geometry*/ 321 setStiffAndTrsfMats: function() { 322 var l = this.len; 323 var eal = this.ea/l; 324 var eil = this.ei/l; 325 var eil2 = eil/l; 326 var eil3 = eil2/l; 327 var s = this.sin; 328 var c = this.cos; 329 // T - from gloal to local, TT - from local to global 330 switch (this.type) { 331 case JSB2D_HC: 332 this.t.fromArray([[c,s,0,0,0],[-s,c,0,0,0],[0,0,c,s,0],[0,0,-s,c,0],[0,0,0,0,1]]); 333 this.tt.fromArray([[c,-s,0,0,0],[s,c,0,0,0],[0,0,c,-s,0],[0,0,s,c,0],[0,0,0,0,1]]); 334 break; 335 case JSB2D_CH: 336 this.t.fromArray([[c,s,0,0,0],[-s,c,0,0,0],[0,0,1,0,0],[0,0,0,c,s],[0,0,0,-s,c]]); 337 this.tt.fromArray([[c,-s,0,0,0],[s,c,0,0,0],[0,0,1,0,0],[0,0,0,c,-s],[0,0,0,s,c]]); 338 break; 339 case JSB2D_HH: 340 this.t.fromArray([[c,s,0,0],[-s,c,0,0],[0,0,c,s],[0,0,-s,c]]); 341 this.tt.fromArray([[c,-s,0,0],[s,c,0,0],[0,0,c,-s],[0,0,s,c]]); 342 break; 343 default: // c-c 344 this.t.fromArray([[c,s,0,0,0,0],[-s,c,0,0,0,0],[0,0,1,0,0,0],[0,0,0,c,s,0],[0,0,0,-s,c,0],[0,0,0,0,0,1]]); 345 this.tt.fromArray([[c,-s,0,0,0,0],[s,c,0,0,0,0],[0,0,1,0,0,0],[0,0,0,c,-s,0],[0,0,0,s,c,0],[0,0,0,0,0,1]]); 346 } 347 var k = Matrix.create([ 348 [ eal, 0 , 0 , -eal, 0 , 0 ], 349 [ 0 , 12*eil3, -6*eil2, 0 , -12*eil3, -6*eil2], 350 [ 0 , - 6*eil2, 4*eil , 0 , 6*eil2, 2*eil ], 351 [-eal, 0 , 0 , eal, 0 , 0 ], 352 [ 0 , -12*eil3, 6*eil2, 0 , 12*eil3, 6*eil2], 353 [ 0 , - 6*eil2, 2*eil , 0 , 6*eil2, 4*eil ]]); 354 if (this.type) { // type is not c-c 355 switch (this.type) { 356 case JSB2D_HC: // hinged-clamped 357 this.a = [0,1,3,4,5]; 358 this.b = [2]; 359 break; 360 case JSB2D_CH: // clamped hinge 361 this.a = [0,1,2,3,4]; 362 this.b = [5]; 363 break; 364 case JSB2D_HH: // truss 365 this.a = [0,1,3,4]; 366 this.b = [2,5]; 367 break; 368 } 369 this.kaa = k.getsm(this.a,this.a); 370 this.kab = k.getsm(this.a,this.b); 371 this.kba = k.getsm(this.b,this.a); 372 this.kbbinv = k.getsm(this.b,this.b).inv(); 373 this.kloc = this.kaa.sub(this.kab.mulm(this.kbbinv).mulm(this.kba)) 374 } 375 else { this.kloc = k; } 376 }, 377 378 /** Computes stiffness matrix in global coordinates system 379 * @return Matrix stiffness matrix and corresponding dofs*/ 380 computeGlobStiffMatrix: function() { 381 return this.tt.mulm(this.kloc).mulm(this.t); 382 }, 383 384 /** Sets mass matrices in local and gloal coordinate system from stored material and geometric parameters*/ 385 setMassMats: function() { 386 var l = this.len; 387 var mu = this.mu; 388 var a = mu*l/420; 389 var s = this.sin; 390 var c = this.cos; 391 this.Mloc.fromArray([ 392 [ 140*a, 0 , 0 , 70*a , 0 , 0 ], 393 [ 0 , 156*a ,-22*l*a , 0 , 54*a , 13*a*l ], 394 [ 0 ,-22*l*a, 4*a*l*l, 0 ,-13*a*l,-3*a*l*l], 395 [ 70*a , 0 , 0 , 140*a, 0 , 0 ], 396 [ 0 , 54*a ,-13*a*l , 0 , 156*a , 22*a*l ], 397 [ 0 , 13*a*l,-3*a*l*l, 0 , 22*a*l, 4*a*l*l]]); 398 /*this.M.fromArray([ 399 [ 140*a*c*c + 156*a*s*s, 16*a*c*s, -22*a*l*s, 70*a*c*c + 54*a*s*s, -16*a*c*s, 13*a*l*s], 400 [ 16*a*c*s, 156*a*c*c + 140*a*s*s, -22*a*c*l, -16*a*c*s, 54*a*c*c + 70*a*s*s, 13*a*c*l], 401 [ -22*a*l*s, -22*a*c*l, 4*a*l*l, -13*a*l*s, -13*a*c*l, -3*a*l*l], 402 [ 70*a*c*c + 54*a*s*s, -16*a*c*s, -13*a*l*s, 140*a*c*c + 156*a*s*s, 16*a*c*s, 22*a*l*s], 403 [ -16*a*c*s, 54*a*c*c + 70*a*s*s, -13*a*c*l, 16*a*c*s, 156*a*c*c + 140*a*s*s, 22*a*c*l], 404 [ 13*a*l*s, 13*a*c*l, -3*a*l*l, 22*a*l*s, 22*a*c*l, 4*a*l*l]]);*/ 405 }, 406 407 /** Sets geometry, stiffness matrices and "beam" load (end forces induced by continuous load and temperature load)*/ 408 linearStaticPreproc: function() { 409 this.setGeom(); 410 this.setStiffAndTrsfMats(); 411 this.load.zero(); 412 if (this.hasBodyLoad) { 413 this.loadCC.fromArray([ 414 this.ea*this.alpha*this.dT - 0.5*this.fxloc*this.len , 415 -.5*this.fzloc*this.len , 416 this.fzloc*this.len*this.len/12. + this.ei*this.alpha*this.dTh, 417 -this.ea*this.alpha*this.dT , 418 -.5*this.fzloc*this.len - 0.5*this.fxloc*this.len , 419 -this.fzloc*this.len*this.len/12. - this.ei*this.alpha*this.dTh ]); 420 if (this.type) { 421 this.load.zero(); 422 this.load.setsv(this.a,this.loadCC.getsv(this.a).sub(this.kab.mulm(this.kbbinv).mulv(this.loadCC.getsv(this.b)))) 423 } 424 else { 425 this.load = this.loadCC; 426 } 427 } 428 }, 429 430 /** Computes end displacement in local coordinate system from given global components and respective end local end forces 431 * @param {Vector} dspl vector of beam displacement in globalComponents (if global param is true) or local (if globalComponents param is false) coordinate system 432 * @param {bool} [globalComponents=true] if true, dspl is considered in global coordinate system. If false, dspl is considered in local coordinate system*/ 433 linearStaticPostpro: function(dspl,globalComponents) { 434 var globalComponents = globalComponents || true; 435 var dspl = globalComponents? this.t.mulv(dspl) : dspl; 436 if (this.type) { 437 this.dspl.zero(); 438 this.dspl.setsv(this.a,dspl); 439 this.dspl.setsv(this.b,this.kbbinv.mulv(this.loadCC.getsv(this.b).add(this.kba.mulv(dspl))).negated()); 440 this.load.zero(); 441 this.load.setsv(this.a,this.kloc.mulv(dspl).add(this.loadCC.getsv(this.a).sub(this.kab.mulm(this.kbbinv).mulv(this.loadCC.getsv(this.b))))) 442 } 443 else { 444 this.dspl = dspl; 445 this.load = this.kloc.mulv(this.dspl).add(this.loadCC); 446 } 447 }, 448 449 /** Sets geometry and stiffness and mass matrices*/ 450 eigenvalueDynamicPreproc: function() { 451 this.setGeom(); 452 this.setStiffAndTrsfMats(); 453 this.setMassMats(); 454 }, 455 456 /** Compute local components of given eigenshape 457 * @param {int} eigMode number of assumed eigenshape - numbering from 0 458 * @param {Vector} eigShape eigMode-th eigenshape in global coordinate system*/ 459 eigenvalueDynamicPostpro: function(eigMode,eigShape) { 460 this.eigShapes[eigMode] = this.TT.mulv(eigShape); 461 }, 462 463 /** Returns middle deflection of receiver due to continuous load (clamped ends are assumed) 464 * @returns {float} middle deflection from continuous load*/ 465 giveMidDeflFromLoad: function() { // local z deflection in the middle of doble-clamped beam from fzloc 466 return this.fzloc*this.len*this.len*this.len*this.len / (384*this.ei); 467 }, 468 469 /** Returns middle deflection of receiver due to end displacement (no load is assumed) 470 * @returns {float} middle deflection from end displacement*/ 471 giveMidDeflFromDspl: function() { // local z deflection in the middle of the beam form nodal dspl and fzloc=0 472 return .5*(this.dspl.get(1) + this.dspl.get(4)) + this.len/8*( -this.dspl.get(2) + this.dspl.get(5)); 473 }, 474 475 /** Returns middle deflection of receiver 476 * @returns {float} middle deflection*/ 477 giveMidDefl: function() { 478 return this.giveMidDeflFromDspl() + this.giveMidDeflFromLoad(); 479 }, 480 481 /** Returns middle deflection of receiver of eigMode-th eigenshape 482 * @param {int} eigMode number of asumed eigenshape - numbering from 0 483 * @returns {float} middle deflection of eigMode-th eigenshape*/ 484 giveMidDeflOfEigShape: function(eigMode) { // local z deflection in the middle of the beam of eigMode-th eigenShape 485 var s = this.eigShapes[eigMode]; 486 return .5*(s.get(1) + s.get(4)) + this.len/8*( -s.get(2) + s.get(5)); 487 }, 488 489 /** Returns middle bending of receiver 490 * @returns {float} middle deflection*/ 491 giveMidMoment: function() { // bending moment in the middle of the beam 492 return -this.load.get(2) - this.load.get(1)*this.len*.5 - this.fzloc*this.len*this.len*.125; 493 }, 494 /**#@-*/ 495 } 496 497 /** Constructor, see {@link Beam2d} for input parameters description 498 * @returns {Beam2d} new Beam2d object*/ 499 Beam2d.create = function(node1,node2,params) { 500 return new Beam2d(node1,node2,params); 501 } 502 503 504 505 /** Linear static solver implementation 506 * @class represents linear static solver 507 * @param {[Beams]} beams array of beams to include 508 * @param {[ints]} u array of unsupported dofs 509 * @param {[ints]} p array of supported dofs 510 * @param {Vector} nodalLoad vector of external load in nodes (load from beams, i.e. linear load, temperature etc. will be added separately from beams) 511 * @param {bool} [withPrescribedDspl=true] if there is some nonzero prescribed displacement of support 512 * @param {bool} [computeReactions=false] compute global reactions or not 513 * @property {[Beams]} beams array of beams to include 514 * @property {[ints]} u array of unsupported dofs 515 * @property {[ints]} p array of supported dofs 516 * @property {int} nDofs total number of degrees of freedom of solved structure 517 * @property {Vector} nodalLoad vector of external load in nodes (load from beams, i.e. linear load, temperature etc. will be added separately from beams) 518 * @property {bool} [withPrescribedDspl=false] if there is some nonzero prescribed displacement of support 519 * @property {Matrix} K global stiffnesss matrix of whole structure 520 * @property {Vector} dspl displacement vector 521 * @property {Vector} beamLoad vector of "beam loads", i.e. end forces from beam continuous load and temperature load 522 * @property {Vector} load total load (sum od nodalLoad and beamLoad) 523 * @example TODO*/ 524 LinearStaticSolver = function(beams,u,p,dspl,nodalLoad,withPrescribedDspl,computeReactions) { 525 this.beams = beams; 526 this.u = u; 527 this.p = p; 528 this.nDofs = this.u.length + this.p.length; 529 this.nodalLoad = nodalLoad==undefined? Vector.Zeros(this.nDofs) : nodalLoad; 530 this.withPrescribedDspl = withPrescribedDspl==undefined? false : withPrescribedDspl; 531 this.computeReactions = computeReactions==undefined? false : computeReactions; 532 this.k = Matrix.Zeros(this.nDofs,this.nDofs); 533 this.dspl = dspl==undefined? Vector.Zeros(this.nDofs) : dspl; 534 this.beamLoad = Vector.Zeros(this.nDofs); 535 this.load = Vector.Zeros(this.nDofs); 536 } 537 /**#@+ 538 * @function 539 * @memberOf LinearStaticSolver# 540 */ 541 LinearStaticSolver.prototype = { 542 543 /** Assembles global stiffness matrix of whole structure from stiffness matrices of particular beams*/ 544 assembly: function() { 545 this.k.zero(); 546 for (var beamNum=0; beamNum<this.beams.length; beamNum++) { 547 var beam = this.beams[beamNum]; 548 var dofs = beam.dofs; 549 this.k.incrsm(dofs,dofs,beam.computeGlobStiffMatrix()); 550 } 551 }, 552 553 /** Solves unknown displacements and forces*/ 554 solve: function() { 555 this.load = this.nodalLoad.add(this.beamLoad); 556 var kuu = this.k.getsm(this.u,this.u); 557 var kpu = this.k.getsm(this.p,this.u); 558 var fu = this.load.getsv(this.u); 559 if (this.withPrescribedDspl) { 560 var kup = this.k.getsm(this.u,this.p); 561 var kpp = this.k.getsm(this.p,this.p); 562 var rp = this.dspl.getsv(this.p); 563 this.dspl.setsv(this.u,kuu.solveForRhs(fu.sub(kup.mulv(rp)))); 564 if (this.computeReactions) { this.load.setsv(this.p,kpu.mulv(this.dspl.getsv(this.u)).add(kpp.mulv(rp))); } 565 } 566 else { 567 this.dspl.setsv(this.u,kuu.solveForRhs(fu)); 568 if (this.computeReactions) { this.load.setsv(this.p,kpu.mulv(this.dspl.getsv(this.u))); } 569 } 570 }, 571 572 /** Preprocesses all beams (sets their "beam load" and assemble it to global load vecor, set their geometric parameters and stiffness matrices*/ 573 preprocBeams: function() { 574 this.beamLoad.zero() 575 for (var beamNum=0; beamNum<this.beams.length; beamNum++) { 576 var beam = this.beams[beamNum]; 577 beam.linearStaticPreproc(); 578 if (beam.type) { 579 this.beamLoad.decrsv(beam.dofs,beam.tt.mulv(beam.load.getsv(beam.a))); 580 } else { 581 this.beamLoad.decrsv(beam.dofs,beam.tt.mulv(beam.load)); 582 } 583 } 584 }, 585 586 /** Postprocesses all beams (sets appropriate displacements to them)*/ 587 updateBeams: function() { 588 for (var beamNum=0; beamNum<this.beams.length; beamNum++) { 589 var beam = this.beams[beamNum]; 590 beam.linearStaticPostpro(this.dspl.getsv(beam.dofs)); 591 } 592 }, 593 594 /** Gloal function for whole simulation process*/ 595 up: function(preprocBeams,updateBeams) { 596 var preprocBeams = preprocBeams==undefined? true : preprocBeams; 597 var updateBeams = updateBeams==undefined? true : updateBeams; 598 if (preprocBeams) { this.preprocBeams(); } 599 this.assembly(); 600 this.solve(); 601 if (updateBeams) { this.updateBeams(); } 602 }, 603 /**#@-*/ 604 } 605 /** Constructor, see {@link LinearStaticSolver} for input parameters description 606 * @returns {LinearStaticSolver} new LinearStaticSolver object*/ 607 LinearStaticSolver.create = function(beams,u,p,dspl,nodalLoad,withPrescribedDspl) { 608 return new LinearStaticSolver(beams,u,p,dspl,nodalLoad,withPrescribedDspl); 609 } 610 611 612 613 614 /** Eigenvalue dynamic solver implementation 615 * @class represents eigenvalue dynamic solver 616 * @param {[Beams]} beams array of beams to include 617 * @param {[ints]} u array of unsupported dofs 618 * @param {[ints]} p array of supported dofs 619 * @param {int} [nEigModes=1] number of first eigenvalues and eigenvectors to be solved 620 * @param {Vector} [concMass=Vector.Zeros] Vector of concentrated mass for each Dof (default zero Vector) 621 * @property {[Beams]} beams array of beams to include 622 * @property {[ints]} u array of unsupported dofs 623 * @property {[ints]} p array of supported dofs 624 * @property {int} nDofs total number of degrees of freedom of solved structure 625 * @property {int} [nEigModes=1] number of first eigenvalues and eigenvectors to be solved 626 * @property {Vector} [concMass=Vector.Zeros] Vector of concentrated mass for each Dof (default zero Vector) 627 * @property {Matrix} K global stiffness matrix 628 * @property {Matrix} M global mass matrix 629 * @property {[floats]} eigFreqs computed eigenfrequencies 630 * @property {[Vectors]} eigShapes computed eigenshapes 631 * @example TODO*/ 632 EigenValueDynamicSolver = function(beams,u,p,nEigModes,concMass) { 633 this.beams = beams; 634 this.u = u; 635 this.p = p; 636 this.nDofs = this.u.length + this.p.length; 637 this.nEigModes = nEigModes==undefined? 1 : nEigModes; 638 this.concMass = concMass==undefined? Vector.Zeros(this.nDofs) : concMass; 639 this.K = Matrix.Zeros(this.nDofs,this.nDofs); 640 this.M = Matrix.Zeros(this.nDofs,this.nDofs); 641 this.eigFreqs = []; 642 for (var eigMode=0; eigMode<this.nEigModes; eigMode++) { this.eigFreqs[eigMode] = 0.; } 643 this.eigShapes = []; 644 for (var eigMode=0; eigMode<this.nEigModes; eigMode++) { this.eigShapes[eigMode] = Vector.Zeros(this.nDofs); } 645 } 646 /**#@+ 647 * @function 648 * @memberOf EigenValueDynamicSolver# 649 */ 650 EigenValueDynamicSolver.prototype = { 651 652 /** Assembles global stiffness and mass matrix of whole structure from stiffness and mass matrices of particular beams and concMass attribute*/ 653 assembly: function() { 654 this.K.zero(); 655 this.M.zero() 656 for (var beamNum=0; beamNum<this.beams.length; beamNum++) { 657 var beam = this.beams[beamNum]; 658 var dofs = beam.dofs; 659 this.K.incrsm(dofs,dofs,beam.K); 660 this.M.incrsm(dofs,dofs,beam.M); 661 } 662 for (var i=0; i<this.nDofs; i++) { this.M.incr(i,i,this.concMass.get(i)); } 663 }, 664 665 /** Solves unknown eigenfrequencies and eigenshapes*/ 666 solve: function() { 667 var kuu = this.k.getsm(this.u,this.u); 668 var kuu = this.m.getsm(this.u,this.u); 669 var results = eigSolve(Kuu,Muu,this.nEigModes); 670 for (var eigMode=0; eigMode<this.nEigModes; eigMode++) { 671 this.eigFreqs[eigMode] = results[0][eigMode]; 672 this.eigShapes[eigMode].setsv(this.u,results[1][eigMode]); 673 } 674 }, 675 676 /** Preprocesses all beams (sets their "beam load" and assemble it to global load vecor, set their geometric parameters and stiffness matrices*/ 677 preprocBeams: function() { 678 for (var beamNum = 0; beamNum<this.beams.length; beamNum++) { this.beams[beamNum].eigenvalueDynamicPreproc(); } 679 }, 680 681 /** Postprocesses all beams (from computed eigenshapes sets appropriate displacements to them)*/ 682 updateBeams: function() { 683 for (var eigMode = 0; eigMode<this.nEigModes; eigMode++) { 684 for (var beamNum=0; beamNum<this.beams.length; beamNum++) { 685 var beam = this.beams[beamNum]; 686 beam.eigenvalueDynamicPostpro(eigMode,this.eigShapes[eigMode].getsv(beam.dofs)); 687 } 688 } 689 }, 690 691 /** Global function for whole simulation process*/ 692 up: function(preprocBeams,updateBeams) { 693 var preprocBeams = preprocBeams==undefined? true : preprocBeams; 694 var updateBeams = updateBeams==undefined? true : updateBeams; 695 if (preprocBeams) { this.preprocBeams(); } 696 this.assembly(); 697 this.solve(); 698 if (updateBeams) { this.updateBeams(); } 699 }, 700 /**#@-*/ 701 } 702 /** Constructor, see {@link EigenValueDynamicSolver} for input parameters description 703 * @returns {EigenValueDynamicSolver} new EigenValueDynamicSolver object*/ 704 EigenValueDynamicSolver.create = function(beams,u,p,nEigModes,concMass) { 705 return new EigenValueDynamicSolver(beams,u,p,nEigModes,concMass); 706 } 707 708 709 710 711 712 713 714 715 716 717 /** Cross section implementation 718 * @class represents (so far polygonal only) cross section 719 * @param {[Nodes]} nodes array of nodes to create yz (!!) polygon in anti-clockwise (!!) order 720 * @param {[[Nodes]]} [holes=[[]]] array of arrays of nodes representing holes in polygon created by nodes 721 * @property {[Nodes]} nodes array of polygon nodes in yz plane ( this.nodes[0]==this.nodes[this.nodes.length-1] ) 722 * @property {float} [a=null] area 723 * @property {float} [sy=null] static moment (first moment of mass) with respect to y coordinate (global) 724 * @property {float} [sz=null] static moment (first moment of mass) with respect to z coordinate (global) 725 * @property {float} [cy=null] y coordinate of center of mass 726 * @property {float} [cz=null] z coordinate of center of mass 727 * @property {float} [iy=null] moment of inertia (second moment of area) with respect to y coordinate (local) 728 * @property {float} [iz=null] moment of inertia (second moment of area) with respect to z coordinate (local) 729 * @property {float} [dyz=null] deviation (product) moment of inertia with respect to yz coordinate system 730 * @property {float} [i1=null] first principal value of moment of inertia (i1>i2) 731 * @property {float} [i2=null] second principal value of moment of inertia (i1>i2) 732 * @property {float} [beta=null] angle from global axes to principal inertia orientation 733 * @property {[Nodes]} [core=null] core of cross section 734 * @example TODO*/ 735 CrossSection = function(nodes,holes) { 736 this.nodes = nodes; 737 if (this.nodes[this.nodes.length-1] != this.nodes[0]) { this.nodes.push(this.nodes[0]); } 738 this.holes = holes || [[]]; 739 this.a = null; 740 this.sy = null; 741 this.sz = null; 742 this.cy = null; 743 this.cz = null; 744 this.iy = null; 745 this.iz = null; 746 this.dyz = null; 747 this.i1 = null; 748 this.i2 = null; 749 this.beta = null; 750 this.core = null; 751 } 752 /**#@+ 753 * @function 754 * @memberOf CrossSection# 755 */ 756 CrossSection.prototype = { 757 /** Reset receiver (sets all values to null)*/ 758 reset: function() { 759 this.a = null; 760 this.sy = null; 761 this.sz = null; 762 this.cy = null; 763 this.cz = null; 764 this.iy = null; 765 this.iz = null; 766 this.dyz = null; 767 this.i1 = null; 768 this.i2 = null; 769 this.beta = null; 770 this.convexHull = null; 771 this.core = null; 772 }, 773 774 /** Computes area of receiver 775 * @returns {float} area of receiver*/ 776 computeA: function() { 777 var ret = 0.; 778 var n0, nL; 779 for (var i=0; i<this.nodes.length-1; i++) { 780 n0 = this.nodes[i]; 781 nL = this.nodes[i+1]; 782 ret += n0.y*nL.z - nL.y*n0.z; 783 } 784 return .5*ret; 785 }, 786 787 /** Computes static moment (first order moment of mass) of receiver with respect to y coordinate axis 788 * @param {bool} [local=false] if computed with respect to this.cy center of mass or global yz coordinates 789 * @returns {float} Sy of receiver*/ 790 computeSy: function(local) { 791 var local = local==undefined? false : local; 792 var zc = 0.; 793 if (local) { 794 if (this.cz==null) { return null; } 795 zc = this.cz; 796 } 797 var ret = 0.; 798 var n0, nL, y0, yL, z0, zL; 799 for (var i=0; i<this.nodes.length-1; i++) { 800 n0 = this.nodes[i]; 801 nL = this.nodes[i+1]; 802 y0 = n0.y; yL = nL.y; 803 z0 = n0.z-zc; zL = nL.z-zc; 804 ret += (zL+z0)*(y0*zL-yL*z0); 805 } 806 return 1/6.*ret; 807 }, 808 809 /** Computes static moment (first order moment of mass) of receiver with respect to z coordinate axis 810 * @param {bool} [local=false] if computed with respect to this.cz center of mass or global yz coordinates 811 * @returns {float} Sz of receiver*/ 812 computeSz: function(local) { 813 var local = local==undefined? false : local; 814 var yc = 0.; 815 if (local) { 816 if (this.cy==null) { return null; } 817 yc = this.cy; 818 } 819 var ret = 0.; 820 var n0, nL, y0, yL, z0, zL; 821 for (var i=0; i<this.nodes.length-1; i++) { 822 n0 = this.nodes[i]; 823 nL = this.nodes[i+1]; 824 y0 = n0.y-yc; yL = nL.y-yc; 825 z0 = n0.z; zL = nL.z; 826 ret += (y0+yL)*(y0*zL-yL*z0); 827 } 828 return 1/6.*ret; 829 }, 830 831 /** Computes y coordinate of center of mass of receiver 832 * @returns {float} Cy of receiver*/ 833 computeCy: function() { 834 var a = this.a==null? this.computeA() : this.a; 835 var sz = this.sz==null? this.computeSz() : this.sz; 836 return sz/a; 837 }, 838 839 /** Computes z coordinate of center of mass of receiver 840 * @returns {float} Cz of receiver*/ 841 computeCz: function() { 842 var a = this.a==null? this.computeA() : this.a; 843 var sy = this.sy==null? this.computeSy() : this.sy; 844 return sy/a; 845 }, 846 847 /** Computes moment of inertia (second moment of area) of receiver with respect to y coordinate axis 848 * @param {bool} [local=true] if computed with respect to this.cy center of mass or global yz coordinates 849 * @returns {float} moment of inertia (y) of receiver*/ 850 computeIy: function(local) { 851 var local = local==undefined? true : local; 852 var zc = 0.; 853 if (local) { 854 if (this.cz==null) { return null; } 855 zc = this.cz; 856 } 857 var ret = 0.; 858 var n0, nL, y0, yL, z0, zL; 859 for (var i=0; i<this.nodes.length-1; i++) { 860 n0 = this.nodes[i]; 861 nL = this.nodes[i+1]; 862 y0 = n0.y; yL = nL.y; 863 z0 = n0.z-zc; zL = nL.z-zc; 864 ret += (z0*z0+z0*zL+zL*zL)*(y0*zL-yL*z0); 865 } 866 return 1/12.*ret; 867 }, 868 869 /** Computes moment of inertia (second moment of area) of receiver with respect to z coordinate axis 870 * @param {bool} [local=true] if computed with respect to this.cz center of mass or global yz coordinates 871 * @returns {float} moment of inertia (z) of receiver*/ 872 computeIz: function(local) { 873 var local = local==undefined? true : local; 874 var yc = 0.; 875 if (local) { 876 if (this.cy==null) { return null; } 877 yc = this.cy; 878 } 879 var ret = 0.; 880 var n0, nL, y0, yL, z0, zL; 881 for (var i=0; i<this.nodes.length-1; i++) { 882 n0 = this.nodes[i]; 883 nL = this.nodes[i+1]; 884 y0 = n0.y-yc; yL = nL.y-yc; 885 z0 = n0.z; zL = nL.z; 886 ret += (y0*y0+y0*yL+yL*yL)*(y0*zL-yL*z0); 887 } 888 return 1/12.*ret; 889 }, 890 891 /** Computes deviation (prodict) moment of inertia of receiver with respect to yz coordinates 892 * @param {bool} [local=true] if computed with respect to this.cy and this.cz (center of mass) or global yz coordinates 893 * @returns {float} deviation (product) moment of inertia (yz) of receiver*/ 894 computeDyz: function(local) { 895 var local = local==undefined? true : local; 896 var yc = 0.; 897 var zc = 0.; 898 if (local) { 899 if (this.cy==null) { return null; } 900 yc = this.cy; 901 if (this.cz==null) { return null; } 902 zc = this.cz; 903 } 904 var ret = 0.; 905 var n0, nL, y0, yL, z0, zL; 906 for (var i=0; i<this.nodes.length-1; i++) { 907 n0 = this.nodes[i]; 908 nL = this.nodes[i+1]; 909 y0 = n0.y-yc; yL = nL.y-yc; 910 z0 = n0.z-zc; zL = nL.z-zc; 911 ret += (y0*zL+2*y0*z0+2*yL*zL+yL*z0)*(y0*zL-yL*z0); 912 } 913 return 1/24.*ret; 914 }, 915 916 /** Computes polar moment of inertia of receiver with respect to yz coordinate axis 917 * @returns {float polar} moment of inertia (yz) of receiver*/ 918 computeI0: function() { 919 var iy = this.iy==null? this.computeIy() : this.iy; 920 var iz = this.iz==null? this.computeIz() : this.iz; 921 return iy+iz; 922 }, 923 924 /** Computes moment of inertia tensor of receiver (i.e. [[Iy,-Dyz],[-Dyz,Iz]] ) 925 * @returns {[[float,float],[float,float]]} moment of inertia tensor (yz) of receiver*/ 926 computeInertiaTensor: function() { 927 var iy = this.iy==null? this.computeIy() : this.iy; 928 var iz = this.iz==null? this.computeIz() : this.iz; 929 var dyz = this.dyz==null? this.computeDyz() : this.dyz; 930 return [[iy,-dyz],[-dyz,iz]]; 931 }, 932 933 /** Computes principal inertia values and angle from global axes to principal inertia orientation 934 * @returns {[float,float,float]} principal values and angle of principal direction [I1,I2,angle], I1 > I2 */ 935 computePrincipalValues: function() { 936 var iy = this.iy==null? this.computeIy() : this.iy; 937 var iz = this.iz==null? this.computeIz() : this.iz; 938 var dyz = this.dyz==null? this.computeDyz() : this.dyz; 939 if (iy==iz) { return [iy,iz,0.]; } 940 if (dyz == 0.) { 941 if (iy>iz) { return [iy,iz,0.]; } 942 else { return [iz,iy,.5*Math.PI]; } 943 } 944 var beta = 0.5*Math.atan(2*dyz/(iz-iy)); 945 var c = Math.cos(beta) 946 var s = Math.sin(beta) 947 var i1 = c*c*iy + s*s*iz - 2*c*s*dyz; 948 var i2 = s*s*iy + c*c*iz + 2*c*s*dyz; 949 if (i1>i2) { return [i1,i2,beta]; } 950 else { return [i2,i1,beta+0.5*Math.PI]; } 951 }, 952 953 /** Computes normal stress at certain point with coordinates x and y 954 * @param {float} y y coordinate of desired point 955 * @param {float} z z coordinate of desired point 956 * @param {float} N normal force 957 * @param {float} My moment y 958 * @param {float} Mz moment z 959 * @param {bool} [local=false] if y z are local coordinates or not 960 * @returns {float} stress at [x,z] caused by N,My,Mz*/ 961 computeStress: function(y,z,N,My,Mz,local) { 962 var local = local || false; 963 var a = this.a==null? this.computeA() : this.a; 964 var iy = this.iy==null? this.computeIy() : this.iy; 965 var iz = this.iz==null? this.computeIz() : this.iz; 966 var dyz = this.dyz==null? this.computeDyz() : this.dyz; 967 if (local) { var y=y; var z=z; } 968 else { 969 var y = y - (this.cy==null? this.computeCy() : this.cy); 970 var z = z - (this.cz==null? this.computeCz() : this.cz); 971 } 972 return N/a + (My*iz+Mz*dyz)/(iy*iz-dyz*dyz)*z - (Mz*iy+My*dyz)/(iy*iz-dyz*dyz)*y; 973 }, 974 975 /** Computes normal stress at certain polygon node 976 * @param {Node} node polygon node 977 * @param {float} N normal force 978 * @param {float} My moment y 979 * @param {float} Mz moment z 980 * @returns {float} stress at node caused by N,My,Mz*/ 981 computeStressInNode: function(node,N,My,Mz) { 982 return this.computeStress(node.y,node.z,N,My,Mz); 983 }, 984 985 /** Computes neutral axis 986 * @param {float} N normal force 987 * @param {float} My moment y 988 * @param {float} Mz moment z 989 * @param {bool} [local=false] if returned equation is in local coordinates or not 990 * @returns {[float,float,float]} [a,b,c] as ay+bz+c=0;*/ 991 computeNeutralAxis: function(N,My,Mz,local) { 992 var local = local || false; 993 var a = this.a==null? this.computeA() : this.a; 994 var iy = this.iy==null? this.computeIy() : this.iy; 995 var iz = this.iz==null? this.computeIz() : this.iz; 996 var dyz = this.dyz==null? this.computeDyz() : this.dyz; 997 var aa = -(Mz*iy+My*dyz)/(iy*iz-dyz*dyz); 998 var bb = (My*iz+Mz*dyz)/(iy*iz-dyz*dyz); 999 var cc = N/a; 1000 if (local) { 1001 var yc = this.cy==null? this.computeCy() : this.cy; 1002 var zc = this.cz==null? this.computeCz() : this.cz; 1003 cc += aa*yc+bb*zc; 1004 } 1005 return [aa,bb,cc]; 1006 }, 1007 1008 /** Returns those nodes of receiver that forms the convex hull 1009 * @returns {[Nodes]} those nodes that forms convex hull (ret[0]==ret[ret.length-1])*/ 1010 giveConvexHull: function() { 1011 if (this.nodes.length <= 4) { return this.nodes.slice(); } 1012 // choose two nodes (most lower-left and upper-right) that for sure forms a convex part 1013 var c1 = this.nodes[0]; 1014 var c2 = this.nodes[0]; 1015 var i1 = 0; 1016 var i2 = 0; 1017 for (var i=1; i<this.nodes.length; i++) { 1018 if (this.nodes[i].z < c1.z) { c1 = this.nodes[i]; i1 = i; continue; } 1019 if (this.nodes[i].z > c2.z) { c2 = this.nodes[i]; i2 = i; continue; } 1020 if (this.nodes[i].z == c1.z && this.nodes[i].y < c1.y) { c1 = this.nodes[i]; i1 = i; } 1021 if (this.nodes[i].z == c2.z && this.nodes[i].y > c2.y) { c2 = this.nodes[i]; i2 = i; } 1022 } 1023 1024 n = this.nodes.slice(0,this.nodes.length-1) 1025 var nodes12 = i1<i2? n.slice(i1,i2) : n.slice(i1).concat(n.slice(0,i2)); 1026 var nodes21 = i2<i1? n.slice(i2,i1) : n.slice(i2).concat(n.slice(0,i1)); 1027 nodes12.push(c2); nodes21.push(c1); 1028 1029 var v, c, s, cMin, iCur, cCur, vCur, l12 = nodes12.length, l21 = nodes21.length; 1030 var ret12 = [] 1031 iCur = 0; 1032 if (l12 > 2) { 1033 do { 1034 ret12.push(nodes12[iCur]); 1035 cCur = nodes12[iCur] 1036 v = c2.sub(cCur) 1037 cMin = 1e20; 1038 for (var i=iCur+1; i<l12; i++) { 1039 vCur = nodes12[i].sub(cCur) 1040 c = vCur.dot(v)/(vCur.norm()*v.norm()) 1041 if (c <= cMin) { if (vCur.cross(v).x >= 0.) { iCur = i; cMin=c; } } 1042 } 1043 } while (iCur<l12-1) 1044 } else { ret12 = [c1]; } 1045 1046 var ret21 = []; 1047 iCur = 0; 1048 if (l21 > 2) { 1049 do { 1050 ret21.push(nodes21[iCur]); 1051 cCur = nodes21[iCur] 1052 v = c1.sub(cCur) 1053 cMin = 1e20; 1054 for (var i=iCur+1; i<l21; i++) { 1055 vCur = nodes21[i].sub(cCur) 1056 c = vCur.dot(v)/(vCur.norm()*v.norm()) 1057 if (c <= cMin) { if (vCur.cross(v).x >= 0.) { iCur = i; cMin=c; } } 1058 } 1059 } while (iCur<l21-1) 1060 } else { ret21 = [c2]; } 1061 return ret12.concat(ret21).concat(c1) 1062 }, 1063 1064 /** Computes core (area, where applied force in x direction causes no tension) 1065 * @param {bool} [local=false] if computed with respect to this.cx center of mass or global yz coordinates 1066 * @returns {[Nodes]} array of nodes creating core polygon*/ 1067 computeCore: function(local) { 1068 var core = []; 1069 var nodes = this.convexHull==null? this.giveConvexHull() : this.convexHull; 1070 var local = local || false; 1071 var a = this.a==null? this.computeA() : this.a; 1072 var iy = this.iy==null? this.computeIy() : this.iy; 1073 var iz = this.iz==null? this.computeIz() : this.iz; 1074 var dyz = this.dyz==null? this.computeDyz() : this.dyz; 1075 var yc = this.cy==null? this.computeCy() : this.cy; 1076 var zc = this.cz==null? this.computeCz() : this.cz; 1077 var y,z,n1,n2,y1,y2,z1,z2,cc; 1078 for (var i=0; i<nodes.length-1; i++) { 1079 n1 = nodes[i]; 1080 n2 = nodes[i+1]; 1081 y1 = n1.y - yc; 1082 y2 = n2.y - yc; 1083 z1 = n1.z - zc; 1084 z2 = n2.z - zc; 1085 //y = iz2*(z1-z2)/(y1*z2-y2*z1); 1086 //z = iy2*(y2-y1)/(y1*z2-y2*z1); 1087 cc = a*(y1*z2-y2*z1); 1088 y = (dyz*(y2-y1)+iz*(z1-z2))/cc; 1089 z = (dyz*(z1-z2)+iy*(y2-y1))/cc; 1090 core[i] = local? new Node(0.,y,z) : new Node(0.,y+yc,z+zc); 1091 } 1092 return core; 1093 }, 1094 1095 /** computes all values (a,sy,sz,cy,cz,iy,iz,dyz,i1,i2,beta,core) within one function call*/ 1096 up: function() { 1097 this.a = this.computeA(); 1098 this.sy = this.computeSy(); 1099 this.sz = this.computeSz(); 1100 this.cy = this.computeCy(); 1101 this.cz = this.computeCz(); 1102 this.iy = this.computeIy(); 1103 this.iz = this.computeIz(); 1104 this.dyz = this.computeDyz(); 1105 var princ = this.computePrincipalValues(); 1106 this.i1 = princ[0]; 1107 this.i2 = princ[1]; 1108 this.beta = princ[2]; 1109 this.convexHull = this.giveConvexHull(); 1110 this.core = this.computeCore(); 1111 }, 1112 /**#@-*/ 1113 } 1114 /** Constructor, see {@link CrossSection} for input parameters description 1115 * @returns {CrossSection} new CrossSection object*/ 1116 CrossSection.create = function(nodes,holes) { 1117 return new CrossSection(nodes,holes); 1118 } 1119