Still stuck with the simulation system, is there any good pseudocode for the multiple flow direction (MFD) algorithm? I read a pseudocode example and implemented it, however the simulation was linear: that is the first cell gets the highest amount of rainfall and the last cell does not get any water. I'm resorting to sorting the elevation of the cells from highest to lowest so that the water would spread out properly. I don't want to use r.terraflow or TOPMODEL since this is an independent project and I don't want to use existing simulation systems.
Any ideas as to how to implement MFD or correct my algorithm would be very appreciated.
BTW, null values were set to -500 by the DEM reader. The code is implemented in C# and is not yet optimized, I just want a correct MFD simulation at the moment.
static void rainfallAlgo() {
double total, percentage, transfer;
double[] tile = new double[10];
for (int i = 0; i != Convert.ToInt32(totalRow); i++){
for (int j = 0; j != Convert.ToInt32(totalCol); j++){
if ((elev[i, j] != -500)&&(elevrain[i,j]>=elev[i,j])){
Console.WriteLine();
total = 0;
for (int k = 1; k <= 9; k++){
if (k != 5){
tile[k] = compare(i, j, k);
total += tile[k];
}
}
for (int k = 1; k <= 9; k++){
if (total == 0){
Console.WriteLine("I am ZERO");
total = 1;
}
if (k != 5){
percentage = tile[k] / total;
Console.Write(k+ ":");
Console.WriteLine(percentage);
transfer = percentage * (elevrain[i,j]-elev[i,j]);
if (k == 1)
elevrain[i - 1, j - 1] += transfer;
else if (k == 2)
elevrain[i - 1, j] += transfer;
else if (k == 3)
elevrain[i - 1, j + 1] += transfer;
else if (k == 4)
elevrain[i, j - 1] += transfer;
else if (k == 6)
elevrain[i, j + 1] += transfer;
else if (k == 7)
elevrain[i + 1, j - 1] += transfer;
else if (k == 8)
elevrain[i + 1, j] += transfer;
else if (k == 9)
elevrain[i + 1, j + 1] += transfer;
}
}
if(total!=1)
elevrain[i, j] = elev[i, j];
Console.WriteLine(elevrain[i,j]);
}
}
}
}
static void addRain(){
rainfall = new double[Convert.ToInt32(totalRow), Convert.ToInt32(totalCol)];
elevrain = new double[Convert.ToInt32(totalRow), Convert.ToInt32(totalCol)];
int i = 0, j = 0;
while (i != Convert.ToInt32(totalRow)){
while (j != Convert.ToInt32(totalCol)){
rainfall[i, j] = 2;
elevrain[i, j] = elev[i, j] + rainfall[i,j];
j++;
}
i++;
j = 0;
}
}
static double compare(int i, int j, int k){
double total=0;
if( k==1 ) {
if ( (elevrain[i, j] > elevrain[i - 1, j - 1] ) && (elev[i-1, j-1]!=-500.0) )
total = (elevrain[i, j] - elevrain[i - 1, j - 1]) / 1.414213562373095;
else
total = 0;
} else if( k==2 ) {
if ( (elevrain[i, j] > elevrain[i - 1, j]) && (elev[i - 1, j] != -500.0))
total = elevrain[i, j] - elevrain[i - 1, j];
else
total = 0;
} else if( k==3 ) {
if ( (elevrain[i, j] > elevrain[i - 1, j + 1]) && (elev[i - 1, j + 1] != -500.0) )
total = (elevrain[i, j] - elevrain[i - 1, j + 1]) / 1.414213562373095;
else
total = 0;
} else if( k==4 ) {
if ((elevrain[i, j] > elevrain[i, j - 1]) && (elev[i, j - 1] != -500.0) )
total = elevrain[i, j] - elevrain[i, j - 1];
else
total = 0;
} else if( k== 6 ) {
if ( (elevrain[i, j] > elevrain[i, j + 1]) && (elev[i, j + 1] != -500.0) )
total = elevrain[i, j] - elevrain[i, j + 1];
else
total = 0;
} else if( k== 7 ) {
if ( (elevrain[i, j] > elevrain[i + 1, j - 1]) && (elev[i + 1, j-1] != -500.0) )
total = (elevrain[i, j] - elevrain[i + 1, j - 1]) / 1.414213562373095;
else
total = 0;
} else if ( k== 8 ) {
if ((elevrain[i, j] > elevrain[i + 1, j]) && (elev[i + 1, j] != -500.0) )
total = elevrain[i, j] - elevrain[i + 1, j];
else
total = 0;
} else if ( k== 9) {
if ( (elevrain[i, j] > elevrain[i + 1, j + 1]) && (elev[i + 1, j +1] != -500.0) )
total = (elevrain[i, j] - elevrain[i + 1, j + 1]) / 1.414213562373095;
else
total = 0;
}
return total;
}
Best Answer
Your question is poorly stated. It as at once general, as it asks if anyone has ideas about how to implement MFDs, and specific, as it seems to ask what is wrong with you code. I'll try to answer this second conceptualization of your question here.
You claim that the code you've posted is not optimized. I have rewritten the code below as I think you should have written it. The changes I have introduced include making good use of loops and offset arrays. These changes are not optimizations, they are helpful abstractions that allow you to work with the code and review it in meaningful ways. Without such abstractions you are not coding, you are producing functional gibberish.
With the introduction of the arrays
di
anddj
it becomes more reasonable to analyze your code.I am left wondering why you have chosen to label your central cell as
5
as this makes your loops much more painful. It is better to use0
as the central label so that you can loop sequentially over all of the neighbouring cells.I have also used an array
dr
to store the offset distances between the centers of the central cell and its neighbours.I think you will find that the judicious use of arrays such as those I've introduced here will lead to better code and that better code will lead you more quickly to the solutions you seek.
You can also wrap your grids into classes which provide meaningful accessor names to help you follow what's going on. You can take a look at some of my code here and here to get ideas.
Happy coding.