Try to re-solve groups that fail rank test.

Sometimes, after a large change in a sketch, constraints that are
geometrically fine may still cause the rank test to fail. One way
this can happen is VectorsParallel() pivoting wrong due to the big
move, converging anyways but ending up singular. It would then
re-pivot correctly on the new solution when you re-solve, making
this a transient error. This is visible when dragging the arm in
the jansen-asm.slvs example.

After this commit, if the rank test fails, equations are regenerated
the Jacobian is rewritten, and the rank test is retried, which
prevents these transient errors from interfering with dragging.

The problem described above was invisible before c011444, as rank
test was only performed before solving.
This commit is contained in:
EvilSpirit 2016-10-13 20:51:11 +07:00 committed by whitequark
parent bc43365eff
commit 05d9c0fab9
2 changed files with 19 additions and 7 deletions

View File

@ -308,7 +308,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB
// The group falls inside the range, so really solve it,
// and then regenerate the mesh based on the solved stuff.
if(genForBBox) {
SolveGroup(g->h, andFindFree);
SolveGroupAndReport(g->h, andFindFree);
} else {
g->GenerateLoops();
g->GenerateShellAndMesh();
@ -491,6 +491,23 @@ void SolveSpaceUI::MarkDraggedParams(void) {
}
}
void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) {
SolveGroup(hg, andFindFree);
Group *g = SK.GetGroup(hg);
if(g->solved.how == System::REDUNDANT_OKAY) {
// Solve again, in case we lost a degree of freedom because of a numeric error.
SolveGroup(hg, andFindFree);
}
bool isOkay = g->solved.how == System::SOLVED_OKAY ||
(g->allowRedundant && g->solved.how == System::REDUNDANT_OKAY);
if(!isOkay || (isOkay && !g->IsSolvedOkay())) {
TextWindow::ReportHowGroupSolved(g->h);
}
}
void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
int i;
// Clear out the system to be solved.
@ -518,12 +535,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
g->solved.remove.Clear();
int how = sys.Solve(g, &(g->solved.dof),
&(g->solved.remove), true, andFindFree);
bool isOkay = how == System::SOLVED_OKAY ||
(g->allowRedundant && how == System::REDUNDANT_OKAY);
if(!isOkay || (isOkay && !g->IsSolvedOkay()))
{
TextWindow::ReportHowGroupSolved(g->h);
}
g->solved.how = how;
FreeAllTemporary();
}

View File

@ -912,6 +912,7 @@ public:
void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false,
bool genForBBox = false);
void SolveGroup(hGroup hg, bool andFindFree);
void SolveGroupAndReport(hGroup hg, bool andFindFree);
void MarkDraggedParams(void);
void ForceReferences(void);