Logics of Reaction Assignment - mkraska/meclib GitHub Wiki

How do we detect which force or moment matches what support or connection?

In Meclib, a proximity check is made for active forces (start and end point) and active moments (center point).

In general, the function hasPoint() is used to check the proximity between an object and a point. For unidirectional objects, also the distance to the centerline is evaluated using JXG.Math.Geometry.distPointLine([1, point.X(), point.Y()], line.stdform) and a narrow tolerance is applied as to not accept misplaced reactions.

For isolated supports, this is sufficient for matchmaking.

Ambiguities arise in the case that multiple supports apply to a single point, e.g. the nodes of a truss or multiple ropes or bars.

The ambiguity can be reduced by

  • checking for parallelity condition (this won't help in a truss with parallel bars at the same node)
  • name checking (is the name of the support part of the reaction name? Is the number of a bar or rope equal to the index of a force?). This would require appropriate naming schemes, which would not be an artificial requirement)
  • one could demand both points of a force being on the element to be replaced (artificial limitation, specific to Meclib)

Implementation by:

  • Maxima function matchByName()
  • Maxima function matchByParallel()

These functions would reduce the force index lists in the names response.

matchByParallel()

Takes the objects and names list and returns a reduced names list. The list is reduced such that indices are removed for loads which are not parallel to the item they replace. Loads of items, where parallelity can't be established, are kept.

matchByParallel(o,n):=block([res, llist],res: [],
    /* for all objects */
    for i:1 thru length(o) do (
        /* if names entry is not a list, copy it to result */
        if (not listp(n[i])) then res: endcons(n[i], res) else (
            /* either a nondirectional item or parallel to the force */
            llist: sublist(n[i], 
                lambda([x], 
                    member(o[i][1], [ "fix12, fix123", "circle"]) or
                    parallelp(o[i], o[x] )
                )
            ),
            res: endcons(llist, res)
        )
    ),
    return(res)
);

Feedback functions

unidir(objects, names, index, description)

Provides feedback for reactions at unidirectional supports.

  • index Index of the support object
  • description Textual description of the support (like "Loslager A", "Stab BC", "Seil")

Returns [text, isOK]

  • text Text to be used in the PRT (both branches of the top level node, use {@text@})
  • isOK Flag indicating correct reaction. Use answer test ATAlgEquiv(isOK, true)
unidir(o, n, i, description):=block(
    [txt, R], txt: sconcat("<br>",description,": "),
    /* Is object i an unidirectional support? */
    if not member(o[i][1], ["bar", "dashpot", "springt", "springc", "fix1", "rope"]) 
    then return ([sconcat(txt, "object ", string(i), "(",o[i][1],") is not an unidirectional support."), false]),
    /* Is object i de-activated */ 
    if ( last(o[i]) # "hide") then return ([sconcat(txt, " ist nicht deaktiviert."), false]),
    /* Any reactions found at i? */
    if not listp(n[i]) or n[i]=[] then return([sconcat(txt, "Keine Reaktion gefunden."), false]),
    /* Exactly 1 reaction found? */
    if (length(n[i]) > 1) then return( [sconcat(txt, "Mehr als eine Reaktion gefunden."), false]),
    /* Is the reaction a force? */
    if ( o[n[i][1]][1] # "force" ) then return ([sconcat(txt, "Die Reaktion muss eine Kraft sein."),false]),
    R: o[n[i][1]], 
    /* Is the force normal to the support? */
    if not parallelp(R, o[i]) then return ([sconcat(txt, "Die Reaktion \\(", R[2], "\\) hat nicht die richtige Richtung."),false]),
    /* everything should be ok here */
    return([sconcat(txt, "Reaktion \\(", R[2], "\\) gefunden."),true])
);
);

Helper functions

direction()

parallelp()