scalar surfaceOptimizer::optimiseSteepestDescent(const scalar tol) { point& pOpt = pts_[trias_[0][0]]; //- find the bounding box const scalar avgEdge = Foam::mag(pMax_ - pMin_); //- find the minimum value on the 5 x 5 raster scalar K = evaluateStabilisationFactor(); scalar funcBefore, funcAfter(evaluateFunc(K)); //- start with steepest descent optimisation vector gradF; tensor gradGradF; vector disp; disp.z() = 0.0; direction nIterations(0); do { funcBefore = funcAfter; evaluateGradients(K, gradF, gradGradF); //- store data into a matrix matrix2D mat; mat[0][0] = gradGradF.xx(); mat[0][1] = gradGradF.xy(); mat[1][0] = gradGradF.yx(); mat[1][1] = gradGradF.yy(); FixedList<scalar, 2> source; source[0] = gradF.x(); source[1] = gradF.y(); //- calculate the determinant const scalar det = mat.determinant(); if( mag(det) < VSMALL ) { disp = vector::zero; } else { disp.x() = mat.solveFirst(source); disp.y() = mat.solveSecond(source); if( mag(disp) > 0.2 * avgEdge ) { vector dir = disp / mag(disp); disp = dir * 0.2 * avgEdge; } } # ifdef DEBUGSmooth Info << "Second gradient " << gradGradF << endl; Info << "Gradient " << gradF << endl; Info << "Displacement " << disp << endl; Info << "K = " << K << endl; # endif pOpt -= disp; K = evaluateStabilisationFactor(); funcAfter = evaluateFunc(K); if( mag(funcAfter - funcBefore) / funcBefore < tol ) break; #ifdef DEBUGSmooth Info << "New coordinates " << pOpt << endl; # endif } while( ++nIterations < 100 ); return funcAfter; }
// Implementation of knupp metric untangling void knuppMetric::optimizeNodePosition(const scalar tolObsolete) { if( !bb_.contains(p_) ) p_ = 0.5 * (bb_.min() + bb_.max()); const scalar tol = Foam::sqr(2.0 * SMALL) * magSqr(bb_.min() - bb_.max()); label iterI, outerIter(0); vector gradF, disp; tensor gradGradF; scalar func, lastFunc; # ifdef DEBUGSmooth forAll(normals_, nI) { const scalar fx = normals_[nI] & (p_ - centres_[nI]); Info << "Tet " << nI << " has distance " << fx << " func " << Foam::sqr(mag(fx) - fx) << endl; } Info << "BoundBox size " << (bb_.max() - bb_.min()) << endl; Info << "Tolerance " << tol << endl; # endif bool finished; do { finished = true; lastFunc = evaluateMetric(); iterI = 0; do { # ifdef DEBUGSmooth Info << "Iteration " << iterI << endl; Info << "Initial metric value " << lastFunc << endl; # endif //- store previous value const point pOrig = p_; //- evaluate gradients evaluateGradients(gradF, gradGradF); //- calculate displacement const scalar determinant = det(gradGradF); if( determinant > SMALL ) { disp = (inv(gradGradF, determinant) & gradF); for(direction i=0;i<vector::nComponents;++i) { const scalar& val = disp[i]; if( (val != val) || ((val - val) != (val - val)) ) { disp = vector::zero; break; } } p_ -= disp; func = evaluateMetric(); # ifdef DEBUGSmooth Info << "Second grad " << gradGradF << endl; Info << "inv(gradGradF, determinant) " << inv(gradGradF, determinant) << endl; Info << "Gradient " << gradF << endl; Info << "Determinant " << determinant << endl; Info << "Displacement " << disp << endl; Info << "New metric value " << func << endl; # endif scalar relax(0.8); label nLoops(0); while( func > lastFunc ) { p_ = pOrig - relax * disp; relax *= 0.5; func = evaluateMetric(); if( func < lastFunc ) continue; //- it seems that this direction is wrong if( ++nLoops == 5 ) { p_ = pOrig; disp = vector::zero; func = 0.0; } } lastFunc = func; } else { disp = vector::zero; } } while( (magSqr(disp) > tol) && (++iterI < 10) ); if( (lastFunc < VSMALL) && (evaluateMetricNoBeta() > VSMALL) ) { beta_ /= 2.0; finished = false; } } while( !finished && (++outerIter < 5) ); # ifdef DEBUGSmooth Info << "Last value " << lastFunc << endl; Info << "Beta " << beta_ << endl; Info << "Metric with no beta " << evaluateMetricNoBeta() << endl; forAll(normals_, nI) { const scalar fx = normals_[nI] & (p_ - centres_[nI]); Info << "Tet " << nI << " has distance " << fx << " func " << Foam::sqr(mag(fx) - fx) << endl; } //::exit(1); # endif }