1
+
2
+ import cmf
3
+ import numpy as np
4
+ from datetime import datetime ,timedelta
5
+ from collections import Counter
6
+ import time
7
+ import timeit
8
+ import argparse
9
+
10
+ def test (d , withsubstance = False , threads = 1 ):
11
+ """
12
+ creates a set of river segments with and without substance. the solver
13
+ can be set up with a varying nu,ber of threads as well as separated for
14
+ water and substance fluxes.
15
+ """
16
+ cmf .set_parallel_threads (threads )
17
+
18
+ if withsubstance :
19
+ p = cmf .project ("X" )
20
+ X , = p .solutes
21
+ else :
22
+ p = cmf .project ()
23
+ X = None
24
+ # Create a triangular reach crosssection for 10 m long reaches with a bankslope of 2
25
+ shape = cmf .TriangularReach (10. ,2. )
26
+ # Create a 1km river with 100 reaches along the x axis and a constant slope of 1%
27
+ reaches = [p .NewReach (i ,0 ,i * .01 ,shape ,False ) for i in range (0 ,1000 ,d )]
28
+ for r_lower , r_upper in zip (reaches [:- 1 ],reaches [1 :]):
29
+ r_upper .set_downstream (r_lower )
30
+ for i , r in enumerate (reaches ):
31
+ r .Name = 'R{}' .format (i + 1 )
32
+
33
+ # Initial condition: 10 cmf of water in the most upper reach
34
+ for r in reaches :
35
+ r .depth = 0.1
36
+ if withsubstance :
37
+ r .conc (X , 1.0 )
38
+
39
+ # Template for the water solver
40
+ wsolver = cmf .CVodeIntegrator (1e-9 )
41
+ # Template for the solute solver
42
+ ssolver = cmf .HeunIntegrator ()
43
+ # Creating the SWI, the storage objects of the project are internally assigned to the correct solver
44
+ solver = cmf .SoluteWaterIntegrator (p .solutes , wsolver , ssolver , p )
45
+ # solver = cmf.CVodeIntegrator(p,1e-6)
46
+ assert solver .size () == len (reaches ) * (len (p .solutes ) + 1 )
47
+
48
+ # We store the results in this list
49
+ depth = [[r .depth for r in reaches ]]
50
+
51
+ start = time .time ()
52
+ c = Counter ()
53
+ for t in solver .run (datetime (2012 ,1 ,1 ),datetime (2012 ,1 ,2 ), cmf .min * 10 ):
54
+ # c.update([solver.get_error().argmax()])
55
+ print ('{:10.3} sec, {}, {}, {}, {:0.4g}'
56
+ .format (time .time ()- start , t ,
57
+ solver .dt ,0 ,0 #solver.get_rhsevals(),
58
+ #np.abs(solver.get_error()).max()
59
+ ))
60
+ depth .append ([r .depth for r in reaches ])
61
+
62
+ time_elapsed = time .time () - start
63
+
64
+ for state_id , count in sorted (c .items ()):
65
+ state = reaches [state_id // (len (p .solutes ) + 1 )]
66
+ solute_id = state_id % (len (p .solutes ) + 1 )
67
+ if solute_id :
68
+ solute = p .solutes [solute_id - 1 ]
69
+ state_name = str (state ) + '.' + str (solute )
70
+ # state_val = state.Solute(solute).state
71
+ else :
72
+ state_name = str (state )
73
+ # state_val = state.
74
+ print ('{:>20}: {}x greatest error' .format (state_name , count ))
75
+
76
+ return time_elapsed , depth , solver , c
77
+
78
+ if __name__ == '__main__' :
79
+
80
+ parser = argparse .ArgumentParser ()
81
+ parser .add_argument ('segment_length' , type = int , help = 'Length of river segments in m' )
82
+ parser .add_argument ('-X' ,'--tracer' , action = 'store_true' , help = 'Use -x to create a tracer' )
83
+ parser .add_argument ('-t' ,'--threads' , action = 'store' , default = 1 , type = int , help = 'Number of threads' )
84
+ args = parser .parse_args ()
85
+
86
+ def run ():
87
+ return test (args .segment_length , args .tracer , args .threads )
88
+
89
+ t = timeit .Timer (run )
90
+
91
+ print ('l={args.segment_length:4} m, X={args.tracer}, t={args.threads}: {t:0.5g}s' .format (args = args , t = t .timeit (1 )))
92
+
0 commit comments