@@ -58,10 +58,126 @@ function get_WorldObject3D(assembly::Modia3D.AbstractAssembly)::Object3D
5858end
5959
6060
61+ """
62+ realScalar = getFlangeVariable(assembly::Modia3D.AbstractAssembly, name::String)
63+
64+ Return the reference of a Revolute or Prismatic flange variable, given the top-level `assembly`
65+ and the full path `name` of the flange variable. If one of the following flange variable names
66+ is provided, a reference to the respective RealScalar is returned:
67+ ```
68+ flange_b.phi
69+ flange_b.s
70+ flange_b.tau
71+ flange_b.f
72+ der(<full-name>.flange_b.phi)
73+ der(<full-name>.flange_b.s)
74+ ```
75+
76+ If one of the following flange names is provided, `nothing` is returned:
77+ ```
78+ flange_a.phi
79+ flange_a.s
80+ flange_a.tau
81+ flange_a.f
82+ der(<full-name>.flange_a.phi)
83+ der(<full-name>.flange_a.s)
84+ ```
85+ """
86+ function getFlangeVariable (assembly:: Modia3D.AbstractAssembly , name:: String ):: Union{ModiaMath.RealScalar,Nothing}
87+ # Handle der(..)
88+ lenName = length (name)
89+ if lenName >= 4 && SubString (name,1 ,4 ) == " der("
90+ if SubString (name,lenName,lenName) != " )" || lenName < 6
91+ error (" Wrong name = \" " , name, " \" " )
92+ end
93+ name2 = SubString (name,5 ,lenName- 1 )
94+ der = true
95+ else
96+ name2 = name
97+ der = false
98+ end
99+
100+ field = assembly
101+ while true
102+ # println("... before. name2 = ", name2)
103+ i = findnext (" ." , name2, 1 )
104+ # println("... after.")
105+ if i== nothing || length (name2) <= i[1 ] || i[1 ] <= 1
106+ error (" Name not found: \" " , name, " \" " )
107+ end
108+ fieldName = Symbol (SubString (name2,1 ,i[1 ]- 1 ))
109+ name2 = SubString (name2,i[1 ]+ 1 )
110+ if ! isdefined (field, fieldName)
111+ error (" Name not found: \" " , name, " \" " )
112+ end
113+ field = getfield (field, fieldName)
114+
115+ # Handle the names "flange_a" and "flange_b"
116+ # println("... field name = ", fieldName, ", typeof(field) = ", typeof(field))
117+ if name2== " flange_a.phi"
118+ if typeof (field) == Modia3D. Composition. TreeJointRevolute
119+ return nothing
120+ else
121+ error (" Name = \" " , name, " \" is no flange variable of a Revolute joint" )
122+ end
123+ elseif name2== " flange_a.tau"
124+ if typeof (field) == Modia3D. Composition. TreeJointRevolute
125+ return nothing
126+ else
127+ error (" Name = \" " , name, " \" is no flange variable of a Revolute joint" )
128+ end
129+ elseif name2== " flange_a.s"
130+ if typeof (field) == Modia3D. Composition. TreeJointPrismatic
131+ return nothing
132+ else
133+ error (" Name = \" " , name, " \" is no flange variable of a Prismatic joint" )
134+ end
135+ elseif name2== " flange_a.f"
136+ if typeof (field) == Modia3D. Composition. TreeJointPrismatic
137+ return nothing
138+ else
139+ error (" Name = \" " , name, " \" is no flange variable of a Prismatic joint" )
140+ end
141+ elseif name2== " flange_b.phi"
142+ if typeof (field) == Modia3D. Composition. TreeJointRevolute
143+ return der ? getfield (field,:w ) : getfield (field,:phi )
144+ else
145+ error (" Name = \" " , name, " \" is no flange variable of a Revolute joint" )
146+ end
147+ elseif name2== " flange_b.tau"
148+ if typeof (field) == Modia3D. Composition. TreeJointRevolute
149+ if der
150+ error (" Name = \" " , name, " \" is no flange variable of a Revolute joint" )
151+ end
152+ return getfield (field,:tau )
153+ else
154+ error (" Name = \" " , name, " \" is no flange variable of a Revolute joint" )
155+ end
156+ elseif name2== " flange_b.s"
157+ if typeof (field) == Modia3D. Composition. TreeJointPrismatic
158+ return der ? getfield (field,:v ) : getfield (field,:s )
159+ else
160+ error (" Name = \" " , name, " \" is no flange variable of a Prismatic joint" )
161+ end
162+ elseif name2== " flange_b.f"
163+ if typeof (field) == Modia3D. Composition. TreeJointPrismatic
164+ if der
165+ error (" Name = \" " , name, " \" is no flange variable of a Prismatic joint" )
166+ end
167+ return getfield (field,:f )
168+ else
169+ error (" Name = \" " , name, " \" is no flange variable of a Prismatic joint" )
170+ end
171+ end
172+ end
173+ end
174+
61175
62176"""
63177 model = Modia3D.Model(assembly::Modia3D.AbstractAssembly;
64- analysis::ModiaMath.AnalysisType=ModiaMath.DynamicAnalysis)
178+ analysis::ModiaMath.AnalysisType=ModiaMath.DynamicAnalysis,
179+ potentialNames::Vector{String} = fill("",0),
180+ flowNames::Vector{String} = fill("",0))
65181
66182Generate a `Modia3D.Model` from an `assembly` generated with macro [`Modia3D.@assembly`](@ref)
67183and the type of `analysis` to be carried out on the `assembly`.
@@ -77,8 +193,14 @@ struct Model
77193 x_nominal:: Vector{Float64}
78194 is_constraint:: Vector{Bool}
79195
196+ # For connection with Modia
197+ potentials:: Vector{Union{ModiaMath.RealScalar,Nothing}}
198+ flows:: Vector{Union{ModiaMath.RealScalar,Nothing}}
199+
80200 function Model (assembly:: Modia3D.AbstractAssembly ;
81- analysis:: ModiaMath.AnalysisType = ModiaMath. DynamicAnalysis)
201+ analysis:: ModiaMath.AnalysisType = ModiaMath. DynamicAnalysis,
202+ potentialNames:: Vector{String} = fill (" " ,0 ),
203+ flowNames:: Vector{String} = fill (" " ,0 ))
82204
83205 name = Modia3D. trailingPartOfName ( string ( typeof (assembly) ) )
84206 world = get_WorldObject3D (assembly)
@@ -147,17 +269,28 @@ struct Model
147269 build_SignalObject3DConnections! (assembly)
148270 scene. initAnalysis = true
149271
272+ # Generate potentials and flows
273+ potentials = Vector {Union{ModiaMath.RealScalar,Nothing}} (nothing , length (potentialNames))
274+ flows = Vector {Union{ModiaMath.RealScalar,Nothing}} (nothing , length (flowNames))
275+ for i = 1 : length (potentialNames)
276+ potentials[i] = getFlangeVariable (assembly, potentialNames[i])
277+ # println("... potentials[", i, "] = ", potentials[i]==nothing ? "nothing" : ModiaMath.instanceName(potentials[i]))
278+ end
279+ for i = 1 : length (flowNames)
280+ flows[i] = getFlangeVariable (assembly, flowNames[i])
281+ # println("... flows[", i, "] = ", flows[i]==nothing ? "nothing" : ModiaMath.instanceName(flows[i]))
282+ end
283+
150284 # Generate Model object
151- new (name, nz, assembly, var, analysis, x_start, x_fixed, x_nominal, is_constraint)
285+ new (name, nz, assembly, var, analysis, x_start, x_fixed, x_nominal, is_constraint, potentials, flows )
152286 end
153287end
154288
155289
156290
157-
158291"""
159292 simModel = SimulationModel(assembly::Modia3D.AbstractAssembly;
160- analysis::ModiaMath.AnalysisType =ModiaMath.DynamicAnalysis,
293+ analysis::ModiaMath.dAnalysisType =ModiaMath.DynamicAnalysis,
161294 startTime = 0.0, stopTime = 1.0, tolerance = 1e-4,
162295 interval = (stopTime-startTime)/500.0,
163296 maxStepSize = NaN, maxNumberOfSteps=missing)
@@ -186,7 +319,7 @@ struct SimulationModel <: ModiaMath.AbstractSimulationModel
186319 hev = 1e-8 ,
187320 scaleConstraintsAtEvents:: Bool = true )
188321 model = Model (assembly; analysis= analysis)
189- simulationState = ModiaMath. SimulationState (model. name, getSimulationModelResidues !, model. x_start, ModiaMath. Variables. getVariableName;
322+ simulationState = ModiaMath. SimulationState (model. name, getModelResidues !, model. x_start, ModiaMath. Variables. getVariableName;
190323 x_fixed = model. x_fixed,
191324 x_nominal = model. x_nominal,
192325 is_constraint = model. is_constraint,
@@ -239,6 +372,9 @@ struct SimulationModel <: ModiaMath.AbstractSimulationModel
239372 end
240373end
241374
375+ ModiaMath. print_ModelVariables (model:: Model ) = ModiaMath. print_ModelVariables (model. var)
376+ print_ModelVariables ( model:: Model ) = ModiaMath. print_ModelVariables (model. var)
377+
242378ModiaMath. print_ModelVariables (simModel:: SimulationModel ) = ModiaMath. print_ModelVariables (simModel. model. var)
243379print_ModelVariables ( simModel:: SimulationModel ) = ModiaMath. print_ModelVariables (simModel. model. var)
244380
@@ -295,13 +431,91 @@ function ModiaMath.getVariableAndResidueValues(simModel::SimulationModel)
295431end
296432
297433
434+
435+
436+ # Only temporarily here. Shall be moved to ModiaMath
437+ """
438+ copy_x_to_variables!(x::Vector{Float64}, vars::ModelVariables)
439+
440+ Copy `x` of the integrator interface to the model variables `vars`.
441+ """
442+ function copy_x_to_variables! (x:: Vector{Float64} , m:: ModiaMath.ModelVariables ):: Nothing
443+ @assert (length (x) == m. nx)
444+
445+ for v in m. x_var
446+ # println("... typeof(", fullName(v), ") = ", typeof(v), ", isimmutable(v) = ", isimmutable(v))
447+ if ModiaMath. isScalar (v)
448+ v. value = x[ v. ivar ]
449+ elseif isimmutable (v. value)
450+ # v is an immutable array (e.g. SVector{3,Float64})
451+ v. value = x[ v. ivar: v. ivar + length (v. value) - 1 ]
452+ else
453+ vv = v. value
454+ for j in 1 : length (vv)
455+ vv[j] = x[ v. ivar + j - 1 ]
456+ end
457+ end
458+ end
459+ return nothing
460+ end
461+
462+
463+ """
464+ copy_derx_to_variables!(time::Float64, derx::Vector{Float64}, vars::ModelVariables)
465+
466+ Copy `time` and `derx` of the integrator interface to the model variables `vars`.
467+ """
468+ function copy_derx_to_variables! (time:: Float64 , derx:: Vector{Float64} , m:: ModiaMath.ModelVariables ):: Nothing
469+ @assert (length (derx) == m. nx)
470+
471+ m. var[1 ]. value = time
472+ for v in m. derx_var
473+ if ModiaMath. isScalar (v)
474+ v. value = derx[ v. ivar ]
475+ elseif isimmutable (v. value)
476+ # v is an immutable array (e.g. SVector{3,Float64})
477+ v. value = derx[ v. ivar: v. ivar + length (v. value) - 1 ]
478+ else
479+ vv = v. value
480+ for j in 1 : length (vv)
481+ vv[j] = derx[ v. ivar + j - 1 ]
482+ end
483+ end
484+ end
485+
486+ return nothing
487+ end
488+
489+
490+
491+ """
492+ modelf1!(model, x, potentials)
493+
494+ Copy the potential variables defined for `model::Modia3D.Model` from `x` to vector `potentials`,
495+ """
496+ function model_f1! (model:: Model , x:: Vector{Float64} , potentials:: Vector{Float64} ):: Nothing
497+ @assert ( length (model. potentials) == length (potentials) )
498+
499+ # Copy (time,x) to model variables
500+ copy_x_to_variables! (x, model. var)
501+
502+ # Copy selected potential variables from model to output argument potentials
503+ for i = 1 : length (potentials)
504+ potentials[i] = model. potentials[i] == nothing ? 0.0 : model. potentials[i]. value
505+ end
506+ return nothing
507+ end
508+
509+
298510const str_DUMMY = " dummyDistance(nothing,nothing)"
511+ const zeroVector = Vector {Float64} ()
299512
300- getSimulationModelResidues ! (simModel:: SimulationModel , time:: Float64 , _x:: Vector{Float64} , _derx:: Vector{Float64} , _r:: Vector{Float64} , _w:: Vector{Float64} ) =
301- getModelResidues ! (simModel. model, simModel. simulationState, time, _x, _derx, _r, _w)
513+ getModelResidues ! (simModel:: SimulationModel , time:: Float64 , _x:: Vector{Float64} , _derx:: Vector{Float64} , _r:: Vector{Float64} , _w:: Vector{Float64} ) =
514+ model_f2 ! (simModel. model, simModel. simulationState, time, _x, _derx, zeroVector , _r, _w)
302515
303- function getModelResidues! (m:: Model , sim:: ModiaMath.SimulationState ,
304- time:: Float64 , _x:: Vector{Float64} , _derx:: Vector{Float64} , _r:: Vector{Float64} , _w:: Vector{Float64} )
516+ function model_f2! (m:: Model , sim:: ModiaMath.SimulationState ,
517+ time:: Float64 , _x:: Vector{Float64} , _derx:: Vector{Float64} , _flows:: Vector{Float64} ,
518+ _r:: Vector{Float64} , _w:: Vector{Float64} )
305519 # println("... time = ", time, ", x = ", _x, ", derx = ", _derx)
306520 world = m. assembly. _internal. referenceObject3D
307521 scene = m. assembly. _internal. scene
@@ -351,6 +565,7 @@ function getModelResidues!(m::Model, sim::ModiaMath.SimulationState,
351565 @assert (length (_derx) == var. nx)
352566 @assert (length (_r) == var. nx)
353567 @assert (length (_w) == 0 )
568+ @assert (length (_flows) == length (m. flows))
354569
355570 storeResults = ModiaMath. isStoreResult (sim) && (scene. visualize || var. nwr > 0 || var. nwc > 0 )
356571
@@ -360,14 +575,25 @@ function getModelResidues!(m::Model, sim::ModiaMath.SimulationState,
360575 end
361576
362577 # Copy x and derx to variables
363- ModiaMath. copy_x_and_derx_to_variables! (time, _x, _derx, var)
578+ if length (m. potentials) == 0
579+ ModiaMath. copy_x_and_derx_to_variables! (time, _x, _derx, var)
580+ else
581+ copy_derx_to_variables! (time, _derx, var)
582+ end
364583
365584 # Compute signals
366585 initializeFlowVariables (scene)
367586 computationSignals (scene, sim)
368587 setPotentialVariables (scene)
369588 setFlowVariables (scene)
370589
590+ # Copy flows to model variables
591+ for i = 1 : length (_flows)
592+ if m. flows[i] != nothing
593+ m. flows[i]. value = _flows[i]
594+ end
595+ end
596+
371597 # Initialize force/torque of world-frame
372598 world. dynamics. f = ModiaMath. ZeroVector3D
373599 world. dynamics. t = ModiaMath. ZeroVector3D
0 commit comments