symbolicUserFunctionCopyTest.py
You can view and download this file on Github: symbolicUserFunctionCopyTest.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: A model with a symbolic user function, copied through mbs.GetDictionary() and
5# mbs.SetDictionary() into a second system (#1888): the copy keeps the function symbolic
6# and computes the same motion. A mass on a spring, driven by a load whose user function
7# is symbolic; the result is the position of the copy after 1 s, which equals the original.
8#
9# Author: Johannes Gerstmayr
10# Date: 2026-09-29
11#
12# 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.
13#
14#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15
16import exudyn as exu
17from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
18
19import numpy as np
20
21testIsActive = exu.sys.get('testIsActive', False)
22esym = exu.symbolic
23
24SC = exu.SystemContainer()
25mbs = SC.AddSystem()
26
27node = mbs.AddNode(NodePoint(referenceCoordinates=[0,0,0]))
28mbs.AddObject(ObjectMassPoint(nodeNumber=node, mass=1))
29mNode = mbs.AddMarker(MarkerNodePosition(nodeNumber=node))
30nFixed = mbs.AddNode(NodePointGround())
31mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mbs.AddMarker(MarkerNodePosition(nodeNumber=nFixed)), mNode],
32 stiffness=[100,100,100], damping=[1,1,1]))
33
34def UFload(mbs, t, loadVector):
35 return [loadVector[0]*esym.sin(10*t), loadVector[1], 0]
36
37load = mbs.AddLoad(LoadForceVector(markerNumber=mNode, loadVector=[10,5,0]))
38symbolicLoad = CreateSymbolicUserFunction(mbs, UFload, 'loadVectorUserFunction', load)
39mbs.SetLoadParameter(load, 'loadVectorUserFunction', symbolicLoad)
40
41def Solve(mbs):
42 mbs.Assemble()
43 simulationSettings = exu.SimulationSettings()
44 simulationSettings.timeIntegration.numberOfSteps = 200
45 simulationSettings.timeIntegration.endTime = 1
46 simulationSettings.solution.file.write = False
47 mbs.SolveDynamic(simulationSettings)
48 return mbs.GetNodeOutput(node, exu.OutputVariableType.Position)
49
50#the copy is made before solving, from the dictionary of the model
51mbsCopy = SC.AddSystem()
52mbsCopy.SetDictionary(mbs.GetDictionary())
53isSymbolic = mbsCopy.GetLoadParameter(load, 'loadVectorUserFunction')['type'] == 'Symbolic'
54
55pOriginal = Solve(mbs)
56pCopy = Solve(mbsCopy)
57exu.Print('copy is symbolic:', isSymbolic, ', difference to the original:', np.linalg.norm(pCopy - pOriginal))
58
59testResult = sum(pCopy) + (0 if isSymbolic else 1)
60exu.Print('solution of symbolicUserFunctionCopyTest=', testResult)
61exu.sys['testResult'] = testResult