示例#1
0
文件: d8.cpp 项目: kornholi/TauDEM
// Sets only flowDir only where there is a positive slope
// Returns number of cells which are flat
int setPosDir(linearpart<float>& elevDEM, linearpart<short>& flowDir)
{
    double dxA = elevDEM.getdxA();
    double dyA = elevDEM.getdyA();
    int nx = elevDEM.getnx();
    int ny = elevDEM.getny();
    int numFlat = 0;

    double tempdxc, tempdyc;

    fact = new double*[ny]; // initialize 2d array by Nazmus 2/16

    for(int m = 0; m<ny; m++)
        fact[m] = new double[9];

    for (int m = 0; m<ny; m++) {
        for (int k = 1; k <= 8; k++) {
            elevDEM.getdxdyc(m, tempdxc, tempdyc);
            fact[m][k] = (double) (1./sqrt(d1[k]*d1[k]*tempdxc*tempdxc + d2[k]*d2[k]*tempdyc*tempdyc));
        }
    }

    for (int j = 0; j < ny; j++) {
        for (int i=0; i < nx; i++) {
            //FlowDir is nodata if it is on the border OR elevDEM has no data
            if (elevDEM.isNodata(i,j) || !elevDEM.hasAccess(i-1,j) || !elevDEM.hasAccess(i+1,j) ||
                    !elevDEM.hasAccess(i,j-1) || !elevDEM.hasAccess(i,j+1)) {
                //do nothing
                continue;
            }

            //Check if cell is "contaminated" (neighbors have no data)
            //  set flowDir to noData if contaminated
            bool contaminated = false;
            for (int k=1; k<=8; k++) {
                int in=i+d1[k];
                int jn=j+d2[k];

                if (elevDEM.isNodata(in,jn)) {
                    contaminated = true;
                    break;
                }
            }

            if (contaminated) {
                flowDir.setToNodata(i,j);
            } else {
                // If cell is not contaminated,
                flowDir.setData(i, j, 0);
                setFlow(i,j, flowDir, elevDEM);

                if (flowDir.getData(i,j) == 0) {
                    numFlat++;
                }
            }
        }
    }

    return numFlat;
}
long setPosDirDinf(linearpart<float>& elevDEM, linearpart<float>& flowDir, linearpart<float>& slope, int useflowfile) {
    double dxA = elevDEM.getdxA();
    double dyA = elevDEM.getdyA();
    long nx = elevDEM.getnx();
    long ny = elevDEM.getny();
    float tempFloat;
    double tempdxc, tempdyc;
    int i, j, k, in, jn, con;
    long numFlat = 0;

    tempFloat = 0;
    for (j = 0; j < ny; j++) {
        for (i = 0; i < nx; i++) {


            //FlowDir is nodata if it is on the border OR elevDEM has no data
            if (elevDEM.isNodata(i, j) || !elevDEM.hasAccess(i - 1, j) || !elevDEM.hasAccess(i + 1, j) ||
                    !elevDEM.hasAccess(i, j - 1) || !elevDEM.hasAccess(i, j + 1)) {
                //do nothing			
            } else {
                //Check if cell is "contaminated" (neighbors have no data)
                //  set flowDir to noData if contaminated
                con = 0;
                for (k = 1; k <= 8 && con != -1; k++) {
                    in = i + d1[k];
                    jn = j + d2[k];
                    if (elevDEM.isNodata(in, jn)) con = -1;
                }
                if (con == -1) 
                    flowDir.setToNodata(i, j);
                    //If cell is not contaminated,
                else {
                    tempFloat = -1.;
                    flowDir.setData(i, j, tempFloat); //set to -1
                    elevDEM.getdxdyc(j, tempdxc, tempdyc);


                    float DXX[3] = {0, tempdxc, tempdyc}; //tardemlib.cpp ln 1291
                    float DD = sqrt(tempdxc * tempdxc + tempdyc * tempdyc); //tardemlib.cpp ln 1293
                    SET2(j, i, DXX, DD, elevDEM, flowDir, slope); //i=y in function form old code j is x switched on purpose
                    //  Use SET2 from serial code here modified to get what it has as felevg.d from elevDEM partition
                    //  Modify to return 0 if there is a 0 slope.  Modify SET2 to output flowDIR as no data (do nothing 
                    //  if verified initialization to nodata) and 
                    //  slope as 0 if a positive slope is not found

                    //setFlow( i,j, flowDir, elevDEM, area, useflowfile);
                    if (flowDir.getData(i, j, tempFloat) == -1)
                        numFlat++;
                }
            }
        }
    }
    return numFlat;
}
long resolveFlats_parallel(T& elev, SparsePartition<short>& inc, linearpart<float>& flowDir, std::vector<std::vector<node>>&islands, linearpart<float>& orelevDir) 
{
    long nx = flowDir.getnx();
    long ny = flowDir.getny();

    int rank;
    MPI_Comm_rank(MCW, &rank);

    int numFlatsChanged = 0, totalNumFlatsChanged = 0;

    flowTowardsLower(elev, flowDir, islands, inc);

    do {
        inc.share();
        numFlatsChanged = propagateBorderIncrements(flowDir, inc);

        MPI_Allreduce(&numFlatsChanged, &totalNumFlatsChanged, 1, MPI_INT, MPI_SUM, MCW);

        if (rank == 0) {
            printf("PRL: Lower gradient processed %d flats this iteration\n", totalNumFlatsChanged);
        }
    } while(totalNumFlatsChanged > 0);

    // Not all grid cells were resolved - pits remain
    // Remaining grid cells are unresolvable pits
    markPits(elev, flowDir, islands, inc);

    // Drain flats away from higher adjacent terrain
    SparsePartition<short> higherGradient(nx, ny, 0);
   
    flowFromHigher(elev, flowDir, islands, higherGradient);

    do {
        higherGradient.share();
        numFlatsChanged = propagateBorderIncrements(flowDir, higherGradient);

        MPI_Allreduce(&numFlatsChanged, &totalNumFlatsChanged, 1, MPI_INT, MPI_SUM, MCW);

        if (rank == 0) {
            printf("PRL: Higher gradient processed %d flats this iteration\n", totalNumFlatsChanged);
        }
    } while(totalNumFlatsChanged > 0);

    // High flow must be inverted before it is combined
    //
    // higherFlowMax has to be greater than all of the increments
    // higherFlowMax can be maximum value of the data type (e.g. 65535) but it will cause overflow problems if more than one iteration is needed
    short higherFlowMax = 0;

    for (auto& island : islands) {
        for (auto& flat : island) {
            short val = higherGradient.getData(flat.x, flat.y);
        
            if (val > higherFlowMax)
                higherFlowMax = val;
        }
    }

    // FIXME: Is this needed? would it affect directions at the border?
    short globalHigherFlowmax = 0;
    MPI_Allreduce(&higherFlowMax, &globalHigherFlowmax, 1, MPI_SHORT, MPI_MAX, MCW);

    for (auto& island : islands) {
        for (auto flat : island) {
            inc.addToData(flat.x, flat.y, globalHigherFlowmax - higherGradient.getData(flat.x, flat.y));
        }
    }

    inc.share();

    if (rank==0) {
        fprintf(stderr,"\nPRL: Setting directions\n");
        fflush(stderr);
    }

    uint64_t localFlatsRemaining = 0, globalFlatsRemaining = 0;
    double tempdxc, tempdyc;
    
    for (auto& island : islands) {
        for (node flat : island) {
            //setFlow2(flat.x, flat.y, flowDir, elev, inc);
            orelevDir.getdxdyc(flat.y, tempdxc, tempdyc);
            float DXX[3] = {0, tempdxc, tempdyc}; //tardemlib.cpp ln 1291
            float DD = sqrt(tempdxc * tempdxc + tempdyc * tempdyc); //tardemlib.cpp ln 1293

            SET2(flat.y, flat.x, DXX, DD, elev, inc, flowDir);
            
            if (flowDir.getData(flat.x, flat.y) == -1) {
                localFlatsRemaining++;
            }
        }
    }

    flowDir.share();
    MPI_Allreduce(&localFlatsRemaining, &globalFlatsRemaining, 1, MPI_UINT64_T, MPI_SUM, MCW);

    auto hasFlowDirection = [&](const node& n) { return flowDir.getData(n.x, n.y) != -1; };
    auto isEmpty = [&](const std::vector<node>& i) { return i.empty(); };
    
    // Remove flats which have flow direction set
    for (auto& island : islands) {
        island.erase(std::remove_if(island.begin(), island.end(), hasFlowDirection), island.end());
    }

    // Remove empty islands
    islands.erase(std::remove_if(islands.begin(), islands.end(), isEmpty), islands.end());

    return globalFlatsRemaining;
}
long resolveFlats(T& elevDEM, SparsePartition<short>& inc, linearpart<float>& flowDir, std::vector<std::vector<node>>&islands, linearpart<float>& orelevDir) 
{
    long nx = flowDir.getnx();
    long ny = flowDir.getny();

    int rank;
    MPI_Comm_rank(MCW, &rank);
    
    if (rank==0) {
        fprintf(stderr,"Resolving flats\n");
        fflush(stderr);
    }

    flowTowardsLower(elevDEM, flowDir, islands, inc);

    // Drain flats away from higher adjacent terrain
    SparsePartition<short> s(nx, ny, 0);
    
    flowFromHigher(elevDEM, flowDir, islands, s);

    // High flow must be inverted before it is combined
    //
    // higherFlowMax has to be greater than all of the increments
    // higherFlowMax can be maximum value of the data type but it will cause overflow problems if more than one iteration is needed
    short higherFlowMax = 0;

    for (auto& island : islands) {
        for (node flat : island) {    
            short val = s.getData(flat.x, flat.y);

            if (val > higherFlowMax)
                higherFlowMax = val;
        }
    }

    for (auto& island : islands) {
        for (auto flat : island) {
            inc.addToData(flat.x, flat.y, higherFlowMax - s.getData(flat.x, flat.y));
        }
    }

    if (rank==0) {
        fprintf(stderr,"Setting directions\n");
        fflush(stderr);
    }

    long flatsRemaining = 0;
    double tempdxc, tempdyc;
    for (auto& island : islands) {
        for (node flat : island) {
            //setFlow2(flat.x, flat.y, flowDir, elevDEM, inc);
            orelevDir.getdxdyc(flat.y, tempdxc, tempdyc);
            float DXX[3] = {0, tempdxc, tempdyc}; //tardemlib.cpp ln 1291
            float DD = sqrt(tempdxc * tempdxc + tempdyc * tempdyc); //tardemlib.cpp ln 1293

            SET2(flat.y, flat.x, DXX, DD, elevDEM, inc, flowDir);

            if (flowDir.getData(flat.x, flat.y) == -1) {
                flatsRemaining++;
            }
        }
    }

    auto hasFlowDirection = [&](const node& n) { return flowDir.getData(n.x, n.y) != -1; };
    auto isEmpty = [&](const std::vector<node>& i) { return i.empty(); };
    
    // Remove flats which have flow direction set
    for (auto& island : islands) {
        island.erase(std::remove_if(island.begin(), island.end(), hasFlowDirection), island.end());
    }

    // Remove empty islands
    islands.erase(std::remove_if(islands.begin(), islands.end(), isEmpty), islands.end());

    return flatsRemaining;
}