On Wednesday, May 28, 2014 8:42:34 PM UTC-5, moorepants wrote: > > > > > Jason > moorepants.info > +01 530-601-9791 > > > On Wed, May 28, 2014 at 12:06 PM, James Crist <cris...@umn.edu<javascript:> > > wrote: > >> I'm working on methods to linearize the equations of motion (EOM) >> generated in sympy.physics.mechanics. The goal is to have a function >> `linearize` that can take in a `KanesMethod`, `LagrangesMethod`, or any >> other system of equations (and ideally a matrix of equations, I think that >> can work too), and spit out the linearized system. Here are my thoughts on >> the interface: >> >> *1.) A `Linearizer` Class:* >> >> This will hold the generalized form of the nonlinear equations. All >> systems should be describable by the Kinematic Differential Equations, >> Dynamic Differential Equations, and Configuration, Motion, and Acceleration >> Constraint equations. Or lack of these. Once in this form, a method >> `linearize` or `linearize_about`, or something else (see below) will >> actually perform the calculation. >> > > Do you have an idea yet if constrained EoMS from different methods can all > be massaged into the same set of equations listed above? >
I'm pretty sure they can? I haven't sat down to work this out yet, but my dim recollection of Lagrange's method makes me think we can treat the multipliers as dependent coordinates, and everything else should work out the same. If not, then the design of this will have to be redone. I'll make a priority of figuring this out today. > > >> >> *2.) A `linearize` function:* >> >> This will wrap the creation and use of the `Linearizer` class. Will sub >> out to various methods to put to the system into the generalized form in >> `Linearizer`, have it perform the linearization, and return the results. >> > > Will you retain a `linearize` method with each `*Method` class or will you > do something like Linearizer(KanesMethod(...), equilibrium_point)? > > Will the code that massage's the nonlinear EoMs belong in each Method > class? > Ideally either linearize(*Method, ...) or *Method.linearize(...) should work. The code for putting in the general form will belong to each class. Then when a new class is implemented, all that needs to be added is the to_linearizer method, and everything should work. > > >> >> *3.) Class methods for KanesMethod and LagrangesMethod that wrap the >> `Linearizer` class and do the same as above.* >> >> ***Questions:*** >> >> *1.)* In general the linearized EOM are only valid if the point they are >> linearized about satisfies all the constraints. Should we check for that? I >> think we should, but it gets kind of tricky if symbolic linearization is >> performed. >> >> For example, suppose we have a constrained system with 5 generalized >> coordinates (qs) and 4 generalized speeds (u). The system only has 2 DOF, >> so it has constraint equations that relate the dependent (q3, q4, q5, u3, >> u4) to the independent (q1, q2, u1, u2). Thus, any point is "fixed" by >> choosing q1, q2, u1, u2; the remainder are solved for by the constraint >> equations. If linearization is purely symbolic, the dependent variables >> must satisfy these equations, even if they're not expressly stated in the >> final form. Possible solutions: >> >> *a)* Have 'linearize' take the trim condition (point of linearization) >> and validate it against the constraint equations. Notify the user if it is >> over specified (5 values given, only 4 are free). Then perform the >> linearization. This issue with doing it this way is that checking >> symbolically may be difficult at times, and users may also wish to solve >> for the linearized system in a completely generalized way (i.e. sub in a >> point after the fact). The benefit of subbing beforehand though is that >> with fewer symbols, the computations will go faster. >> >> *b)* Always perform completely symbolic. No checking. Provide composed >> function in output to validate before subbing in. Use would be: >> >> linearized_eom, validator = linearize(eom, ...) >> trim_conditions = something >> if validator(trim_conditions): >> linearized_eom.subs(trim_conditions) >> >> Benefits of doing it this way are that the linearization is done only >> once, and values are substituted in later. However, the initial >> linearization will be more time consuming than if values were presubbed. >> >> *c)* Similiar to b), but return an object `LinearizedEom`, with an >> `about` method, that validates, and then subs in values if they pass. >> Issues with this are the linearized system isn't in matrix form (although a >> `to_matrices` method could be provided). Same issues as b) as well. >> > > Most of the package is design now to not baby the user. It follows the > garbage in, garbage out philosophy to some degree. If it is easier to not > validate constraints, I think we can push that onto the user's plate to > ensure. We can likely implement it later if it becomes a necessity, but I > don't think it will. > I'll leave it unchecked for now. You're right, this can be added later if desired. > > >> >> *2.)* Using the same example as above, suppose the user knows they want >> to linearize about q1 = 2, q2 = b (some constant), u1 = u2 = 0, and the >> derivatives all to be 0 (equilibrium condition). This would constrain the >> remaining generalized coordinates and speeds to some value. One thought >> would be to have this specified in a dictionary, and try to solve for any >> terms that weren't submitted. If solve can find the missing ones, then >> proceed with the linearization/validation/substitution (depends on decision >> from above). Otherwise through an error that the trim condition was >> over/under specified. Or would it be better for the user to have to solve >> for a complete trim condition? This would be simpler, and may be less >> surprising. If it did solve for the condition, the result would have to be >> made available to the user so they knew what it was linearized about. >> >> > I'm not sure I follow this. Can you make a simple example or some psuedo > code that demonstrates the question? > Suppose you had a system of equations: q1*u1 + q2 = 0 q2 + u1 = 0 Specifying q1 = 0 fully solves the system as q1 = 0, u1 = 0, q2 = 0. Specifying just q1 then gives a valid linearization point. The question was whether allowing a dictionary of {q1: 0} rather than the fully solved {q1: 0, q2: 0, u1: 0} would be valid. However, as we're not verifying this is no longer relevant. > > >> ------- >> >> Let me know what your thoughts are on these, and if you have any >> questions or suggestions for improvements. >> >> -Jim >> >> -- >> You received this message because you are subscribed to the Google Groups >> "PyDy" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to pydy+uns...@googlegroups.com <javascript:>. >> To post to this group, send email to py...@googlegroups.com <javascript:> >> . >> Visit this group at http://groups.google.com/group/pydy. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscr...@googlegroups.com. To post to this group, send email to sympy@googlegroups.com. Visit this group at http://groups.google.com/group/sympy. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/9a831372-2a0c-4759-b2e9-bb4105ba9a29%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.