#include #include #include "PosICNewtonRaphson.h" #include "SingularMatrixError.h" #include "SystemSolver.h" #include "Part.h" #include "Constraint.h" #include "CREATE.h" #include "GESpMatParPvPrecise.h" #include "GESpMatFullPvPosIC.h" using namespace MbD; void MbD::PosICNewtonRaphson::run() { while (true) { try { VectorNewtonRaphson::run(); break; } catch (SingularMatrixError ex) { auto redundantEqnNos = ex.getRedundantEqnNos(); system->partsJointsMotionsDo([&](std::shared_ptr item) { item->removeRedundantConstraints(redundantEqnNos); }); system->partsJointsMotionsDo([&](std::shared_ptr item) { item->constraintsReport(); }); system->partsJointsMotionsDo([&](std::shared_ptr item) { item->setqsu(qsuOld); }); } } } void MbD::PosICNewtonRaphson::preRun() { std::string str("MbD: Assembling system. "); system->logString(str); PosNewtonRaphson::preRun(); } void MbD::PosICNewtonRaphson::assignEquationNumbers() { auto parts = system->parts(); //auto contactEndFrames = system->contactEndFrames(); //auto uHolders = system->uHolders(); auto essentialConstraints = system->essentialConstraints2(); auto displacementConstraints = system->displacementConstraints(); auto perpendicularConstraints = system->perpendicularConstraints(); int eqnNo = 0; for (auto& part : *parts) { part->iqX(eqnNo); eqnNo = eqnNo + 3; part->iqE(eqnNo); eqnNo = eqnNo + 4; } //for (auto& endFrm : *contactEndFrames) { // endFrm->is(eqnNo); // eqnNo = eqnNo + endFrm->sSize(); //} //for (auto& uHolder : *uHolders) { // uHolder->iu(eqnNo); // eqnNo += 1; //} auto nEqns = eqnNo; //C++ uses index 0. nqsu = nEqns; for (auto& con : *essentialConstraints) { con->iG = eqnNo; eqnNo += 1; } auto lastEssenConEqnNo = eqnNo - 1; for (auto& con : *displacementConstraints) { con->iG = eqnNo; eqnNo += 1; } auto lastDispConEqnNo = eqnNo - 1; for (auto& con : *perpendicularConstraints) { con->iG = eqnNo; eqnNo += 1; } auto lastEqnNo = eqnNo - 1; nEqns = eqnNo; //C++ uses index 0. n = nEqns; auto rangelimits = { lastEssenConEqnNo + 1, lastDispConEqnNo + 1, lastEqnNo + 1 }; pivotRowLimits = std::make_shared>(rangelimits); } bool MbD::PosICNewtonRaphson::isConverged() { return this->isConvergedToNumericalLimit(); } void MbD::PosICNewtonRaphson::handleSingularMatrix() { nSingularMatrixError++; if (nSingularMatrixError = 1){ this->lookForRedundantConstraints(); matrixSolver = this->matrixSolverClassNew(); } else { std::string str = typeid(*matrixSolver).name(); if (str == "class MbD::GESpMatParPvMarkoFast") { matrixSolver = CREATE::With(); this->solveEquations(); } else { str = typeid(*matrixSolver).name(); if (str == "class MbD::GESpMatParPvPrecise") { this->lookForRedundantConstraints(); matrixSolver = this->matrixSolverClassNew(); } else { assert(false); } } } } void MbD::PosICNewtonRaphson::lookForRedundantConstraints() { std::string str("MbD: Checking for redundant constraints."); system->logString(str); auto posICsolver = CREATE::With(); posICsolver->system = this; dx = posICsolver->solvewithsaveOriginal(pypx, y->negated(), false); }