There can be many other ways to solve your problem, but here is one approach that you may use ...
Since performance varies from machine to machine, it is somewhat hard to predict beforehand how long it may take to complete. So hard-coding the time estimate into the codes may not be the best option. What you can do is that for each class, you can set up a variable that stores the average processing time per item in the array. This variable gets updated from time to time.
For instance, in the class 'calc', everytime the rainfall method is called, you can store the number of item in the array argument and the starting time. When rainfall method is about to finish its job, you get the time it finishes, compute the average processing time per item ((finish-start)/no_of_item), and store this average time for future use. The next time rainfall method is called, you can use this average time to estimate the time it will take (no_of_item * avg_time) to complete the job, and further refine the average time with the new data everytime the method is used. Of course this method will incur some processing time penalty as you now have addional stuffs to process.
Alternatively, you can do a test-run yourself and hard-code the average time per array item into your codes.