Exemplo n.º 1
0
void initialize_diamondSquareSurface(KMCSolver * solver, const Setting & root)
{

    const Setting & initCFG  = getSurfaceSetting(root, "Initialization");

    double H                 = getSurfaceSetting<double>(initCFG, "H");

    double sigma             = getSurfaceSetting<double>(initCFG, "sigma");

    uint clearing            = getSurfaceSetting<uint>  (initCFG, "clearing");

    uint maxSpan             = getSurfaceSetting<uint>  (initCFG, "maxSpan");

    double occupancyTreshold = getSurfaceSetting<double>(initCFG, "treshold");


    uint NX = solver->NX();

    uint NY = solver->NY();


    //Hack to support non quadratic lattices
    if (NX > NY)
    {
        NY = NX;
    }
    else
    {
        NX = NY;
    }


    int power2 = ceil(std::log2(NX - 1));

    double rf = 1/std::sqrt(2);

    //fsund Diamond Square code:
    DiamondSquare BottomGenerator(power2, RNG::Uniform, Seed::initialSeed);
    DiamondSquare TopGenerator   (power2, RNG::Uniform, Seed::initialSeed+power2);

    auto _Bottom = BottomGenerator.generate(H,              //Hurst Exponent
                                            {},             //Random Corners
                                            sigma,          //Deviation of random displacements
                                            rf,             //RandomFactor: What the f**k is this?
                                            false,          //Addition: Some weird shit I don't understand!
                                            true);          //Periodic Boundary Conditions

    auto _Top    = TopGenerator.generate(1-H,
                                        {},
                                        sigma,
                                        rf,
                                        false,
                                        true);

    //Don't want to learn how to do this with std::min(f****d up shit)

    double bottomMin = INFINITY;
    double topMin    = INFINITY;

    double bottomMax = 0;
    double topMax = 0;

    for (uint i = 0; i < solver->NX(); ++i)
    {
        for (uint j = 0; j < solver->NY(); ++j)
        {

            double bottomVal = _Bottom.at(i).at(j);
            double topVal    = _Top.at(i).at(j);

            if (topVal < topMin)
            {
                topMin = topVal;
            }

            if (topVal > topMax)
            {
                topMax = topVal;
            }

            if (bottomVal < bottomMin)
            {
                bottomMin = bottomVal;
            }

            if (bottomVal > bottomMax)
            {
                bottomMax = bottomVal;
            }

        }
    }


    //Normalize generated boundary to [0 - maxSpan] and rid the std::vectors
    //Translate from continuous to discrete surface points.

    double bottomSpan = bottomMax - bottomMin;
    double topSpan = topMax - topMin;

    umat Bottom(NX, NY);
    umat Top(NX, NY);

    for (uint i = 0; i < solver->NX(); ++i)
    {
        for (uint j = 0; j < solver->NY(); ++j)
        {

            Bottom(i, j) = std::round((_Bottom.at(i).at(j) - bottomMin)/bottomSpan*maxSpan);
            Top(i, j)    = std::round((_Top.at(i).at(j) - topMin)/topSpan*maxSpan);


        }
    }

    _Bottom.clear();
    _Top.clear();


    //calculate how many percent of the total z = z' surface is populated

    vec occupancyBottom(maxSpan, fill::zeros);
    vec occupancyTop   (maxSpan, fill::zeros);

    for (uint i = 0; i < solver->NX(); ++i)
    {
        for (uint j = 0; j < solver->NY(); ++j)
        {

            for (uint z = 0; z < Bottom(i, j); ++z)
            {
                occupancyBottom(z)++;
            }

            for (uint z = 0; z < Top(i, j); ++z)
            {
                occupancyTop(z)++;
            }

        }
    }

    uint area = solver->NX()*solver->NY();

    occupancyBottom /= area;
    occupancyTop    /= area;


    //Going from top to bottom, ending when the population is lower than
    //the given treshold.

    uint bottomCutoff = 0;
    while (occupancyTop(bottomCutoff) > occupancyTreshold)
    {
        bottomCutoff++;
    }

    uint topCutoff = 0;
    while (occupancyTop(topCutoff) > occupancyTreshold)
    {
        topCutoff++;
    }


    //calculate the new box height

    uint newNZ = 2*maxSpan - (topCutoff + bottomCutoff) + clearing;

    solver->setBoxSize({NX, NY, newNZ});


    Site * currentSite;

    for (uint x = 0; x < solver->NX(); ++x)
    {
        for (uint y = 0; y < solver->NY(); ++y)
        {

            uint bottomEnd = Bottom(x, y);
            uint topEnd    = Top(x, y);

            //Points below the cutoff are filtered out. Avoiding uints going to negative values (overflow)
            uint bottomSurface = (bottomEnd > bottomCutoff) ? (     (bottomEnd - bottomCutoff)) : 0;
            uint topSurface    =    (topEnd > topCutoff)    ? (newNZ - (topEnd - topCutoff)) : newNZ;

            for (uint z = 1; z < newNZ - 1; ++z)
            {
                currentSite = solver->getSite(x, y, z);

                //Fill in crystals below the bottom and above the top surface
                if ((z < bottomSurface) || (z >= topSurface))
                {
                    currentSite->spawnAsCrystal();
                }

                //Fill the cavity with solution
                else if (currentSite->isLegalToSpawn())
                {
                    if (KMC_RNG_UNIFORM() < solver->targetSaturation())
                    {
                        currentSite->activate();
                    }
                }

            }
        }

    }
}