(testmodels-genericode2matrixformatstest)= # genericODE2matrixFormatsTest.py You can view and download this file on Github: [genericODE2matrixFormatsTest.py](https://github.com/jgerstmayr/EXUDYN/tree/master/python/TestModels/genericODE2matrixFormatsTest.py) ```{code-block} python :linenos: #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This is an EXUDYN example # # Details: ObjectGenericODE2 with its mass, stiffness and damping matrices given dense and sparse, with the # dense and the sparse linear solver (#777): a chain of four masses on springs, fixed at one end and # pulled at the other, as one GenericODE2 on four 1D coordinates. All four combinations give the same # motion, and the static deflection is the one of the springs in series. # # Author: Johannes Gerstmayr # Date: 2026-10-05 # # 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) n = 4 (mass, k, d, force) = (0.5, 1e3, 2., 10.) M = mass*np.eye(n) K = np.zeros((n,n)) for i in range(n): #spring i between mass i-1 (or the wall) and mass i K[i,i] += k if i > 0: K[i-1,i-1] += k; K[i-1,i] -= k; K[i,i-1] -= k D = d/k*K def Container(matrix, sparse): container = exu.MatrixContainer() if sparse: triplets = [[i, j, matrix[i,j]] for i in range(n) for j in range(n) if matrix[i,j] != 0] container.SetWithSparseMatrix(np.array(triplets), numberOfRows=n, numberOfColumns=n, useDenseMatrix=False) else: container.SetWithDenseMatrix(matrix, useDenseMatrix=True) return container def Run(sparseMatrices, linearSolverType, static=False): SC = exu.SystemContainer() mbs = SC.AddSystem() nodes = [mbs.AddNode(Node1D(referenceCoordinates=[0])) for i in range(n)] mbs.AddObject(ObjectGenericODE2(nodeNumbers=nodes, massMatrix=Container(M, sparseMatrices), stiffnessMatrix=Container(K, sparseMatrices), dampingMatrix=Container(D, sparseMatrices), forceVector=[0]*(n-1)+[force])) mbs.Assemble() settings = exu.SimulationSettings() settings.linearSolver.solverType = linearSolverType settings.solution.file.write = False settings.timeIntegration.verboseMode = 0 settings.staticSolver.verboseMode = 0 settings.timeIntegration.numberOfSteps = 200 settings.timeIntegration.endTime = 0.5 if static: mbs.SolveStatic(settings) else: mbs.SolveDynamic(settings) return mbs.systemData.GetODE2Coordinates() results = [] for sparseMatrices in [False, True]: for linearSolverType in [exu.LinearSolverType.EXUdense, exu.LinearSolverType.EigenSparse]: results.append(Run(sparseMatrices, linearSolverType)) exu.Print('sparse matrices', sparseMatrices, ',', linearSolverType, ':', results[-1]) difference = max(np.linalg.norm(result - results[0]) for result in results) static = Run(True, exu.LinearSolverType.EigenSparse, static=True) staticExpected = force/k*np.arange(1, n+1) #springs in series: each spring carries the force exu.Print('largest difference of the combinations', difference, ', static', static, ', expected', staticExpected) u = np.sum(results[0]) + int(difference < 1e-12) + int(np.linalg.norm(static - staticExpected) < 1e-8) #within the Newton tolerance exu.Print('solution of genericODE2matrixFormatsTest=', u) exu.sys['testResult'] = u ```