Exemple #1
0
// 
//
//  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;
}