// // // calculates expressions stored in a parse Tree // // int evaluateOpFunc(opNode* exp, tree& symbolTable, tree& localVar, funcS& funcTable){ int rights; int lefts ; String s = exp->stringOp(); if(s == "NONE"){ return exp->val(); }else if(isValidVarName(s)){// if s is not an operation if(s == "call"){ exp = exp->leftNode(); String funcName = exp->stringOp();// gets function name param* parameter; if(funcTable.isMember(funcName)){ parameter = funcTable.getParameters(funcName);// passing arguments }else{ printf("WARNING: Function %s is not declared \n", funcName.c_str()); return 0; } int i = 0; opNode* params = exp->leftNode(); if(params->stringOp() != "Ecall"){ while(params->stringOp() != "Ecall"){ parameter->op[i].value = evaluateOpFunc(params->rightNode(), symbolTable, localVar, funcTable); params = params->leftNode(); i += 1; } } tree* newTree = new tree; for(int j =0; j < i ; j+=1){ newTree->insert(parameter->op[j].para, parameter->op[j].value); } if(funcTable.isMember(funcName)){ funcTable.addLocalVar(funcName, newTree); evaluateFunc(funcName, symbolTable, funcTable); return funcTable.getVal(funcName); }else{ printf("Warning: function %s is not declared \n", funcName.c_str()); } } if(localVar.isMember(s)){ return localVar.getVal(s); }else if(symbolTable.isMember(s)){ return symbolTable.getVal(s); } } if(exp->leftNode()){ lefts = evaluateOpFunc(exp->leftNode(), symbolTable, localVar, funcTable); if(s == "~" || s == "!"){return result(s, lefts, rights);} } if(exp->rightNode()){ rights = evaluateOpFunc(exp->rightNode(), symbolTable, localVar, funcTable); } return result(s,lefts,rights); }
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; }
scalar surfaceOptimizer::optimiseDivideAndConquer(const scalar tol) { point& pOpt = pts_[trias_[0][0]]; pOpt = 0.5 * (pMax_ + pMin_); point currCentre = pOpt; scalar dx = (pMax_.x() - pMin_.x()) / 2.0; scalar dy = (pMax_.y() - pMin_.y()) / 2.0; label iter(0); //- find the value of the functional in the centre of the bnd box scalar K = evaluateStabilisationFactor(); scalar funcBefore, funcAfter(evaluateFunc(K)); do { funcBefore = funcAfter; funcAfter = VGREAT; point minCentre(vector::zero); for(label i=0;i<4;++i) { pOpt.x() = currCentre.x() + 0.5 * dirVecs[i].x() * dx; pOpt.y() = currCentre.y() + 0.5 * dirVecs[i].y() * dy; K = evaluateStabilisationFactor(); const scalar func = evaluateFunc(K); if( func < funcAfter ) { minCentre = pOpt; funcAfter = func; } } //- set the centre with the minimum value //- as the centre for future search currCentre = minCentre; pOpt = minCentre; //- halve the search range dx *= 0.5; dy *= 0.5; //- calculate the tolerence const scalar t = mag(funcAfter - funcBefore) / funcAfter; # ifdef DEBUGSmooth Info << "Point position " << pOpt << endl; Info << "Func before " << funcBefore << endl; Info << "Func after " << funcAfter << endl; Info << "Normalised difference " << t << endl; # endif if( t < tol ) break; } while( ++iter < 100 ); return funcAfter; }
scalar volumeOptimizer::optimiseSteepestDescent(const scalar tol) { label iter(0); point& p = points_[pointI_]; # ifdef DEBUGSmooth Info << nl << "Smoothing point " << pointI_ << " with coordinates " << p << endl; scalar Vmina(VGREAT); forAll(tets_, tetI) Vmina = Foam::min(Vmina, tets_[tetI].mag(points_)); Info << "Vmin before " << Vmina << endl; # endif vector gradF; vector disp(vector::zero); tensor gradGradF; point pOrig; scalar funcBefore, funcAfter(evaluateFunc()); bool finished; do { finished = false; pOrig = p; funcBefore = funcAfter; evaluateGradientsExact(gradF, gradGradF); const scalar determinant = Foam::det(gradGradF); if( determinant > SMALL ) { disp = (inv(gradGradF, determinant) & gradF); p -= disp; funcAfter = evaluateFunc(); # ifdef DEBUGSmooth Info << nl << "gradF " << gradF << endl; Info << "gradGradF " << gradGradF << endl; Info << "det(gradGradF) " << determinant << endl; Info << "disp " << disp << endl; Info << "Func before " << funcBefore << endl; Info << "Func after " << funcAfter << endl; # endif scalar relax(0.8); label nLoops(0); while( funcAfter > funcBefore ) { p = pOrig - relax * disp; relax *= 0.5; funcAfter = evaluateFunc(); if( funcAfter < funcBefore ) continue; if( ++nLoops == 5 ) { //- it seems that this direction is wrong, stop the loop p = pOrig; disp = vector::zero; finished = true; funcAfter = funcBefore; } } if( mag(funcBefore - funcAfter) / funcBefore < tol ) finished = true; } else { //- move in random direction //- this is usually needed to move the point off the zero volume disp = vector::zero; forAll(tets_, tetI) { const partTet& tet = tets_[tetI]; const scalar Vtri = tet.mag(points_); if( Vtri < SMALL ) { triangle<point, point> tri ( points_[tet.a()], points_[tet.b()], points_[tet.c()] ); vector n = tri.normal(); const scalar d = mag(n); if( d > VSMALL ) disp += 0.01 * (n / d); } } p += disp; funcAfter = evaluateFunc(); } } while( (++iter < 100) && !finished ); # ifdef DEBUGSmooth scalar Vmin(VGREAT); forAll(tets_, tetI) Vmin = Foam::min(Vmin, tets_[tetI].mag(points_)); Info << nl << "New coordinates for point " << pointI_ << " are " << p << endl; Info << "Num iterations " << iter << " gradient " << gradF << endl; Info << "Vmin " << Vmin << endl; # endif return funcAfter; }