(testmodels-geometricallyexactbeamrightangleframe)= # geometricallyExactBeamRightAngleFrame.py You can view and download this file on Github: [geometricallyExactBeamRightAngleFrame.py](https://github.com/jgerstmayr/EXUDYN/tree/master/python/TestModels/geometricallyExactBeamRightAngleFrame.py) ```{code-block} python :linenos: #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This is an EXUDYN example # # Details: Lateral buckling of the right-angle frame (Argyris et al. 1979; Simo and Vu-Quoc 1986) with # ObjectBeamGeometricallyExact (#1499): two arms of length 0.24 m with a thin rectangular # cross section 30 x 0.6 mm, clamped at the end of the first arm, the arms joined rigidly at # the corner, an in-plane force P at the end of the second arm, along the first arm, and a # small out-of-plane force 1e-4*P as imperfection. The frame buckles out of its plane at the # critical load 1.088 N of the literature. Measured with 16 elements per arm: the out-of-plane # displacement of the tip reaches 1 mm at P = 1.081 N, 5 mm at 1.088 N and 10 mm at 1.092 N; # 8 and 32 elements agree to 0.003 N. # # Author: Johannes Gerstmayr # Date: 2026-09-30 # # Copyright:This file is part of Exudyn. Exudyn is free software. You can redistribute it and/or modify it under the terms of the Exudyn license. See 'LICENSE.txt' for more details. # #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ import exudyn as exu from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities import numpy as np testIsActive = exu.sys.get('testIsActive', False) L = 0.24 #length of each arm w = 0.0006 #thickness, out of the plane of the frame h = 0.03 #height, in the plane of the frame E = 7.124e10; nu = 0.31; G = E/(2*(1+nu)) A = h*w; Iyy = h*w**3/12; Izz = w*h**3/12 J = h*w**3/3 #torsion of a thin rectangle nElements = 16 #per arm forceMax = 1.2 imperfection = 1e-4 SC = exu.SystemContainer() mbs = SC.AddSystem() section = exu.BeamSection() section.stiffnessMatrix = np.diag([E*A, G*A, G*A, G*J, E*Iyy, E*Izz]) section.inertia = 100*J*np.eye(3) #not used by the static solver section.massPerLength = 100*A lElement = L/nElements #first arm along x, second arm along -y rotationArm2 = RotationMatrixZ(-np.pi/2) nodesArm1 = [mbs.AddNode(NodeRigidBodyEP(referenceCoordinates=[i*lElement, 0, 0]+list(eulerParameters0))) for i in range(nElements+1)] nodesArm2 = [mbs.AddNode(NodeRigidBodyEP(referenceCoordinates=[L, -i*lElement, 0]+list(RotationMatrix2EulerParameters(rotationArm2)))) for i in range(nElements+1)] for nodes in [nodesArm1, nodesArm2]: for i in range(nElements): mbs.AddObject(ObjectBeamGeometricallyExact(nodeNumbers=[nodes[i], nodes[i+1]], length=lElement, sectionData=section)) mGround = mbs.AddMarker(MarkerNodeRigid(nodeNumber=mbs.AddNode(NodePointGround()))) mbs.AddObject(GenericJoint(markerNumbers=[mGround, mbs.AddMarker(MarkerNodeRigid(nodeNumber=nodesArm1[0]))])) mbs.AddObject(GenericJoint(markerNumbers=[mbs.AddMarker(MarkerNodeRigid(nodeNumber=nodesArm1[-1], localHT=exu.HT(rotation=rotationArm2))), mbs.AddMarker(MarkerNodeRigid(nodeNumber=nodesArm2[0]))])) def LoadTip(mbs, t, loadVector): return [forceMax*t, 0, imperfection*forceMax*t] mbs.AddLoad(LoadForceVector(markerNumber=mbs.AddMarker(MarkerNodeRigid(nodeNumber=nodesArm2[-1])), loadVector=[0, 0, 0], loadVectorUserFunction=LoadTip)) sTip = mbs.AddSensor(SensorNode(nodeNumber=nodesArm2[-1], outputVariableType=exu.OutputVariableType.Displacement, storeInternal=True, writeToFile=False)) mbs.Assemble() simulationSettings = exu.SimulationSettings() simulationSettings.linearSolver.solverType = exu.LinearSolverType.EigenSparse simulationSettings.staticSolver.useLoadFactor = False #the load follows the user function of t in [0, 1] simulationSettings.staticSolver.numberOfLoadSteps = 240 simulationSettings.staticSolver.newton.relativeTolerance = 1e-8 simulationSettings.staticSolver.newton.absoluteTolerance = 1e-7 #forces of 1 N; the default 1e-10 is below the round-off simulationSettings.solution.file.write = False simulationSettings.solution.sensors.writePeriod = 1e-4 mbs.SolveStatic(simulationSettings) data = mbs.GetSensorStoredData(sTip) force = forceMax*data[:, 0] uz = data[:, 3] testResult = 0 for displacement in [1e-3, 5e-3, 1e-2]: forceAt = np.interp(displacement, uz, force) exu.Print('out-of-plane tip displacement', displacement, 'at P =', round(forceAt, 4)) testResult += forceAt testResult += uz[-1] exu.Print('out-of-plane tip displacement at P =', forceMax, ':', round(uz[-1], 6)) exu.Print('solution of geometricallyExactBeamRightAngleFrame=', testResult) exu.sys['testResult'] = testResult if not testIsActive: mbs.PlotSensor(sensorNumbers=[np.column_stack((uz, force))], components=[0], componentsX=[-1], xLabel='out-of-plane tip displacement', yLabel='P') ```