Index: trunk/anuga_core/source/anuga/operators/rate_operators.py
===================================================================
--- trunk/anuga_core/source/anuga/operators/rate_operators.py	(revision 8878)
+++ trunk/anuga_core/source/anuga/operators/rate_operators.py	(revision 8879)
@@ -22,4 +22,5 @@
 from anuga.fit_interpolate.interpolate import Modeltime_too_early, \
                                               Modeltime_too_late
+from anuga.utilities.function_utils import evaluate_temporal_function
 
 
@@ -126,33 +127,37 @@
 
 
-        if  self.rate_callable:
-            try:
-                rate = self.rate(t)
-            except Modeltime_too_early, e:
-                raise Modeltime_too_early(e)
-            except Modeltime_too_late, e:
-                if self.default_rate is None:
-                    msg = '%s: ANUGA is trying to run longer than specified data.\n' %str(e)
-                    msg += 'You can specify keyword argument default_rate in the '
-                    msg += 'rate operator to tell it what to do in the absence of time data.'
-                    raise Modeltime_too_late(msg)
-                else:
-                    # Pass control to default rate function
-                    rate = self.default_rate(t)
-
-                    if self.default_rate_invoked is False:
-                        # Issue warning the first time
-                        msg = ('\n%s'
-                           'Instead I will use the default rate: %s\n'
-                           'Note: Further warnings will be supressed'
-                           % (str(e), self.default_rate(t)))
-                        warn(msg)
-
-                        # FIXME (Ole): Replace this crude flag with
-                        # Python's ability to print warnings only once.
-                        # See http://docs.python.org/lib/warning-filter.html
-                        self.default_rate_invoked = True
-        else:
-            rate = self.rate
+        assert not self.rate_spatial
+
+
+        rate = evaluate_temporal_function(self.rate, t, default_right_value=self.default_rate)
+#        if  self.rate_callable:
+#            try:
+#                rate = self.rate(t)
+#            except Modeltime_too_early, e:
+#                raise Modeltime_too_early(e)
+#            except Modeltime_too_late, e:
+#                if self.default_rate is None:
+#                    msg = '%s: ANUGA is trying to run longer than specified data.\n' %str(e)
+#                    msg += 'You can specify keyword argument default_rate in the '
+#                    msg += 'rate operator to tell it what to do in the absence of time data.'
+#                    raise Modeltime_too_late(msg)
+#                else:
+#                    # Pass control to default rate function
+#                    rate = self.default_rate(t)
+#
+#                    if self.default_rate_invoked is False:
+#                        # Issue warning the first time
+#                        msg = ('\n%s'
+#                           'Instead I will use the default rate: %s\n'
+#                           'Note: Further warnings will be supressed'
+#                           % (str(e), self.default_rate(t)))
+#                        warn(msg)
+#
+#                        # FIXME (Ole): Replace this crude flag with
+#                        # Python's ability to print warnings only once.
+#                        # See http://docs.python.org/lib/warning-filter.html
+#                        self.default_rate_invoked = True
+#        else:
+#            rate = self.rate
 
 
@@ -191,5 +196,10 @@
         #print xy
         #print t
-        rate = self.rate(x,y,t)
+
+        #print self.rate_type, self.rate_type == 'x,y,t'
+        if self.rate_type == 'x,y,t':
+            rate = self.rate(x,y,t)
+        else:
+            rate = self.rate(x,y)
 
         return rate
@@ -197,51 +207,28 @@
 
     def set_rate(self, rate):
-        """Ability to change rate while running
-        """
-
-        #------------------------------------------
-        # Check and store rate
-        #------------------------------------------
-        msg = ('Keyword argument rate must be a'
-               'scalar, or a function of time.')
-        assert (isinstance(rate, (int, float)) or
-                callable(rate)), msg
-
-        self.rate_callable = False
-        self.rate_spatial = False
+        """Set rate (function)
+        Can change rate while running
+        """
+
+        from anuga.utilities.function_utils import determine_function_type
+
+        # Possible types are 'scalar', 't', 'x,y' and 'x,y,t'
+        self.rate_type = determine_function_type(rate)
 
         self.rate = rate
 
-        if callable(rate):
+        if self.rate_type == 'scalar':
+            self.rate_callable = False
+            self.rate_spatial = False
+        elif self.rate_type == 't':
             self.rate_callable = True
-
-            x = num.array([0.0, 1.0])
-            y = num.array([0.0, 2.0])
-            t =0.0
-
-            try:
-                self.rate(x,y,t)
-            except:
-                #print 'Problem calling with two arguments'
-                self.rate_spatial = False
-                self.rate_callable = False
-            else:
-                self.rate_spatial = True
-                self.rate_callable = True
-
-                #print self.rate_spatial , self.rate_callable
-                return
-
-            try:
-                self.rate(t)
-            except:
-                self.rate_callable = False
-                #print 'Problem calling 1 argument'
-            else:
-                self.rate_callable = True
-                self.rate_spatial = False
-
-        #print self.rate
-        #print self.rate_spatial , self.rate_callable
+            self.rate_spatial = False
+        else:
+            self.rate_callable = True
+            self.rate_spatial = True
+
+
+
+
 
 
Index: trunk/anuga_core/source/anuga/utilities/function_utils.py
===================================================================
--- trunk/anuga_core/source/anuga/utilities/function_utils.py	(revision 8879)
+++ trunk/anuga_core/source/anuga/utilities/function_utils.py	(revision 8879)
@@ -0,0 +1,92 @@
+""" Generic function utilities to test type of function
+"""
+
+import numpy as num
+from anuga.fit_interpolate.interpolate import Modeltime_too_early
+from anuga.fit_interpolate.interpolate import Modeltime_too_late
+
+def determine_function_type(function):
+    """Test type of function, either
+    - scalar
+    - function of t (scalar)
+    - function of two arrays x,y
+    - function of two arrays x,y and t (scalar)"""
+
+    #------------------------------------------
+    # Check that argument is at least a scalar
+    # or csllable
+    #------------------------------------------
+    msg = "Input argument must be a scalar, or a function"
+
+    assert (isinstance(function, (int, float)) or
+            callable(function)), msg
+
+    if callable(function):
+
+        # test if temporal
+        x = num.array([0.0, 1.0])
+        y = num.array([0.0, 2.0])
+        t =0.0
+
+        try:
+            function(x,y,t)
+        except:
+            #print 'Problem calling with three arguments'
+            try:
+                function(x,y)
+            except:
+                #print 'Problem calling with 2 array arguments'
+                try:
+                    function(t)
+                except:
+                    print 'problem calling with one scalar argument'
+                    msg = 'Input argument cannot be called as f(t), f(x,y) or f(x,y,t)'
+                    raise Exception, msg
+                else:
+                    return 't'
+            else:
+                return 'x,y'
+        else:
+            return 'x,y,t'
+
+    else:
+        return 'scalar'
+
+
+def evaluate_temporal_function(function, t, default_left_value=None, default_right_value=None):
+    
+    if  callable(function):
+        try:
+            result = function(t)
+        except Modeltime_too_early, e:
+
+            if default_left_value is None:
+                msg = '%s: Trying to evaluate function earlier than specified in the data set.\n' %str(e)
+                raise Modeltime_too_early(msg)
+            else:
+                # Pass control to default left function
+                if callable(default_left_value):
+                    result = default_left_value(t)
+                else:
+                    result = default_left_value
+
+        except Modeltime_too_late, e:
+            if default_right_value is None:
+                msg = '%s: Trying to evaluate function later than specified in the data set.\n' %str(e)
+                raise Modeltime_too_late(msg)
+            else:
+                # Pass control to default right function
+                if callable(default_right_value):
+                    result = default_right_value(t)
+                else:
+                    result = default_right_value
+    else:
+        result = function
+
+    return result
+
+
+
+
+
+
Index: trunk/anuga_core/source/anuga/utilities/test_function_utils.py
===================================================================
--- trunk/anuga_core/source/anuga/utilities/test_function_utils.py	(revision 8879)
+++ trunk/anuga_core/source/anuga/utilities/test_function_utils.py	(revision 8879)
@@ -0,0 +1,70 @@
+import unittest
+import numpy as num
+
+from anuga.utilities.function_utils import determine_function_type
+
+
+class Test_Function_Utils(unittest.TestCase):
+                
+    def test_determine_function_type_scalar(self):
+
+        type = determine_function_type(1.0)
+
+        assert type == 'scalar'
+
+
+        type = determine_function_type(1)
+
+        assert type == 'scalar'
+
+
+    def test_determine_function_type_exception(self):
+
+        try:
+            type = determine_function_type([])
+        except:
+            # We expect an exception to be raised
+            pass
+        else:
+            # Shouldn't get here
+            raise Exception
+
+
+    def test_determine_function_type_time_only(self):
+
+
+        def myfunc(t):
+             return t*2
+
+        type = determine_function_type(myfunc)
+
+        assert type == 't'
+
+
+    def test_determine_function_type_spatial_only(self):
+
+
+        def myfunc(x,y):
+             return x+y
+
+        type = determine_function_type(myfunc)
+
+        assert type == 'x,y'
+
+    def test_determine_function_type_spatial_only(self):
+
+
+        def myfunc(x,y,t):
+             return x+y+t
+
+        type = determine_function_type(myfunc)
+
+        assert type == 'x,y,t'
+
+        
+#-------------------------------------------------------------
+
+if __name__ == "__main__":
+    suite = unittest.makeSuite(Test_Function_Utils, 'test')
+    runner = unittest.TextTestRunner() #verbosity=2)
+    runner.run(suite)    
