Constraint::SphereOnSphereContact::SphereOnSphereContact
   (MobilizedBody&      mobod_F, 
    const Vec3&         defaultCenter_F, 
    Real                defaultRadius_F, 
    MobilizedBody&      mobod_B, 
    const Vec3&         defaultCenter_B,
    Real                defaultRadius_B,
    bool                enforceRolling)
:   Constraint(new SphereOnSphereContactImpl(enforceRolling))
{
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSubsystem() && mobod_B.isInSubsystem(),
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "Both mobilized bodies must already be in a SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSameSubsystem(mobod_B),
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "The two mobilized bodies to be connected must be in the same "
        "SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK2_ALWAYS(defaultRadius_F > 0 && defaultRadius_B > 0,
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "The sphere radii must be greater than zero; they were %g and %g.",
        defaultRadius_F, defaultRadius_B);

    mobod_F.updMatterSubsystem().adoptConstraint(*this);

    updImpl().m_mobod_F         = updImpl().addConstrainedBody(mobod_F);
    updImpl().m_mobod_B         = updImpl().addConstrainedBody(mobod_B);
    updImpl().m_def_p_FSf       = defaultCenter_F;
    updImpl().m_def_radius_F    = defaultRadius_F;
    updImpl().m_def_p_BSb       = defaultCenter_B;
    updImpl().m_def_radius_B    = defaultRadius_B;
}
예제 #2
0
void Differentiator::calcJacobian
   (const Vector& y0, const Vector& fy0, Matrix& dfdy,
   Differentiator::Method m) const 
{
    rep->nDifferentiations++;
    rep->nDifferentiationFailures++; // assume the worst

    SimTK_APIARGCHECK2_ALWAYS(y0.size()==rep->NParameters, "Differentiator", "calcJacobian",
        "Expecting %d elements in the parameter (state) vector but got %d", 
        rep->NParameters, (int)y0.size());

    SimTK_APIARGCHECK2_ALWAYS(fy0.size()==rep->NFunctions, "Differentiator", "calcJacobian",
        "Expecting %d elements in the unperturbed function value but got %d", 
        rep->NFunctions, (int)fy0.size());

    rep->frep.calcJacobian(*rep,m,y0,&fy0,dfdy);

    rep->nDifferentiationFailures--;
}
예제 #3
0
void FactorQTZRep<T>::solve(  const Matrix_<T>& b, Matrix_<T>& x ) const {
    SimTK_APIARGCHECK_ALWAYS(isFactored ,"FactorQTZ","solve",
       "No matrix was passed to FactorQTZ. \n"  );

    SimTK_APIARGCHECK2_ALWAYS(b.nrow()==nRow,"FactorQTZ","solve",
       "number of rows in right hand side=%d does not match number of rows in original matrix=%d \n",
        b.nrow(), nRow );

    x.resize(nCol, b.ncol() );
    Matrix_<T> tb;
    tb.resize(maxmn, b.ncol() );
    for(int j=0;j<b.ncol();j++) for(int i=0;i<b.nrow();i++) tb(i,j) = b(i,j);
    doSolve(tb, x);
}
예제 #4
0
// The slow version
Matrix Differentiator::calcJacobian
   (const Vector& y0, Differentiator::Method m) const 
{
    rep->nDifferentiations++;
    rep->nDifferentiationFailures++; // assume the worst

    SimTK_APIARGCHECK2_ALWAYS(y0.size()==rep->NParameters, "Differentiator", "calcJacobian",
        "Expecting %d elements in the parameter (state) vector but got %d", 
        rep->NParameters, (int)y0.size());

    Matrix dfdy(rep->NFunctions, rep->NParameters); 
    rep->frep.calcJacobian(*rep,m,y0,0,dfdy);

    rep->nDifferentiationFailures--;
    return dfdy;
}
예제 #5
0
// The slow version
Vector Differentiator::calcGradient
   (const Vector& y0, Differentiator::Method m) const 
{
    rep->nDifferentiations++;
    rep->nDifferentiationFailures++; // assume the worst

    SimTK_APIARGCHECK2_ALWAYS(y0.size()==rep->NParameters, "Differentiator", "calcGradient",
        "Supplied number of parameters (state length) was %ld but should have been %d", 
        y0.size(), rep->NParameters);

    Vector grad(rep->NParameters); 
    rep->frep.calcGradient(*rep,m,y0,0,grad);

    rep->nDifferentiationFailures--;
    return grad; // TODO: use DeadVector to avoid copy
}
예제 #6
0
void FactorQTZRep<T>::solve( const Vector_<T>& b, Vector_<T> &x ) const {

    SimTK_APIARGCHECK_ALWAYS(isFactored ,"FactorQTZ","solve",
       "No matrix was passed to FactorQTZ. \n"  );

    SimTK_APIARGCHECK2_ALWAYS(b.size()==nRow,"FactorQTZ","solve",
       "number of rows in right hand side=%d does not match number of rows in original matrix=%d \n",
        b.size(), nRow );


    Matrix_<T> m(maxmn,1);

    for(int i=0;i<b.size();i++) {
        m(i,0) = b(i);
    }
    Matrix_<T> r(nCol, 1 );
    doSolve( m, r );
    x.copyAssign(r);
}
예제 #7
0
void FactorQTZRep<T>::factor(const Matrix_<ELT>&mat )  {
    SimTK_APIARGCHECK2_ALWAYS(mat.nelt() > 0,"FactorQTZ","factor",
       "Can't factor a matrix that has a zero dimension -- got %d X %d.",
       (int)mat.nrow(), (int)mat.ncol());


    // allocate and initialize the matrix we pass to LAPACK
    // converts (negated,conjugated etc.) to LAPACK format
    LapackConvert::convertMatrixToLapack( qtz.data, mat );

    int info;
    const int smallestSingularValue = 2;
    const int largestSingularValue = 1;
    typedef typename CNT<T>::TReal  RealType;
    RealType smlnum, bignum, smin, smax;

    if (mat.nelt() == 0) return;


    // Compute optimal size for work space for dtzrzf and dgepq3. The
    // arguments here should match the calls below, although we'll use maxRank
    // rather than rank since we don't know the rank yet.
    T workSz;
    const int maxRank = std::min(nRow, nCol);
    LapackInterface::tzrzf<T>(maxRank, nCol, 0, nRow, 0, &workSz, -1, info);
    const int lwork1 = (int)NTraits<T>::real(workSz);

    LapackInterface::geqp3<T>(nRow, nCol, 0, nRow, 0, 0, &workSz, -1, info);
    const int lwork2 = (int)NTraits<T>::real(workSz);

    TypedWorkSpace<T> work(std::max(lwork1, lwork2));

    LapackInterface::getMachinePrecision<RealType>( smlnum, bignum);

    // scale the input system of equations
    anrm = (RealType)LapackInterface::lange<T>('M', nRow, nCol, qtz.data, nRow);

    if (anrm > 0 && anrm < smlnum) {
        scaleLinSys = true;
        linSysScaleF = smlnum;
    } else if( anrm > bignum )  {
        scaleLinSys = true;
        linSysScaleF = bignum;
    }
    if (anrm == 0) { // matrix all zeros
        rank = 0;
    } else {
        if (scaleLinSys) {
           LapackInterface::lascl<T>('G', 0, 0, anrm, linSysScaleF, nRow, nCol,
                                     qtz.data, nRow, info );
        }

        // compute QR factorization with column pivoting: A = Q * R
        // Q * R is returned in qtz.data
        LapackInterface::geqp3<T>(nRow, nCol, qtz.data, nRow, pivots.data,
                                  tauGEQP3.data, work.data, work.size, info );

        // compute Rank

        smax = CNT<T>::abs( qtz.data[0] );
        smin = smax;
        if( CNT<T>::abs(qtz.data[0]) == 0 ) {
            rank = 0;
            actualRCond = 0;
        } else {
            T s1,s2,c1,c2;
            RealType smaxpr,sminpr;

            // Determine rank using incremental condition estimate
            Array_<T> xSmall(mn), xLarge(mn); // temporaries
            xSmall[0] = xLarge[0] = 1;
            for (rank=1,smaxpr=0.0,sminpr=1.0;
                 rank<mn && smaxpr*rcond < sminpr; )
            {
                LapackInterface::laic1<T>(smallestSingularValue, rank,
                    xSmall.begin(), smin, &qtz.data[rank*nRow],
                    qtz.data[(rank*nRow)+rank], sminpr, s1, c1);

                LapackInterface::laic1<T>(largestSingularValue, rank,
                    xLarge.begin(), smax, &qtz.data[rank*nRow],
                    qtz.data[(rank*nRow)+rank], smaxpr, s2, c2);

                if (smaxpr*rcond < sminpr) {
                    for(int i=0; i<rank; i++) {
                         xSmall[i] *= s1;
                         xLarge[i] *= s2;
                    }
                    xSmall[rank] = c1;
                    xLarge[rank] = c2;
                    smin = sminpr;
                    smax = smaxpr;
                    actualRCond = (double)(smin/smax);
                    rank++;
                }
            }

            // R => T * Z
            // Matrix is rank deficient so complete the orthogonalization by
            // applying orthogonal transformations from the right to
            // factor R from an upper trapezoidal to an upper triangular matrix
            // T is returned in qtz.data and Z is returned in tauORMQR.data
            if (rank < nCol) {
                LapackInterface::tzrzf<T>(rank, nCol, qtz.data, nRow,
                                          tauORMQR.data, work.data,
                                          work.size, info);
            }
        }
    }
}