/*************************************************************************** * Copyright (c) 2023 Ondsel, Inc. * * * * This file is part of OndselSolver. * * * * See LICENSE file for details about copyright. * ***************************************************************************/ #include "EulerConstraint.h" #include "Item.h" #include "PartFrame.h" using namespace MbD; EulerConstraint::EulerConstraint() { } EulerConstraint::EulerConstraint(const std::string& str) : Constraint(str) { } void EulerConstraint::initialize() { Constraint::initialize(); pGpE = std::make_shared>(4); } void EulerConstraint::calcPostDynCorrectorIteration() { auto& qE = static_cast(owner)->qE; aG = qE->sumOfSquares() - 1.0; for (size_t i = 0; i < 4; i++) { pGpE->at(i) = 2.0 * qE->at(i); } } void EulerConstraint::useEquationNumbers() { iqE = static_cast(owner)->iqE; } void EulerConstraint::fillPosICError(FColDsptr col) { Constraint::fillPosICError(col); col->atiplusFullVectortimes(iqE, pGpE, lam); } void EulerConstraint::fillPosICJacob(SpMatDsptr mat) { //"ppGpEpE is a diag(2,2,2,2)." mat->atijplusFullRow(iG, iqE, pGpE); mat->atijplusFullColumn(iqE, iG, pGpE->transpose()); auto twolam = 2.0 * lam; for (size_t i = 0; i < 4; i++) { auto ii = iqE + i; mat->atijplusNumber(ii, ii, twolam); } } void EulerConstraint::fillPosKineJacob(SpMatDsptr mat) { mat->atijplusFullRow(iG, iqE, pGpE); } void EulerConstraint::fillVelICJacob(SpMatDsptr mat) { mat->atijplusFullRow(iG, iqE, pGpE); mat->atijplusFullColumn(iqE, iG, pGpE->transpose()); } void EulerConstraint::fillAccICIterError(FColDsptr col) { //"qdotT[ppGpqpq]*qdot." //"qdotT[2 2 2 2 diag]*qdot." col->atiplusFullVectortimes(iqE, pGpE, lam); auto partFrame = static_cast(owner); double sum = pGpE->timesFullColumn(partFrame->qEddot); sum += 2.0 * partFrame->qEdot->sumOfSquares(); col->atiplusNumber(iG, sum); } std::string MbD::EulerConstraint::constraintSpec() { return "EulerConstraint"; }