@@ -199,9 +199,11 @@ def bboxes(self):
199
199
if self ._bboxes is None :
200
200
bboxes = []
201
201
for proc in range (self .n_procs ):
202
- print (f"Calculating bboxes for processor { proc } " )
202
+ print (f"Read mesh for processor { proc } " )
203
203
mesh_state = self .read_mesh_state (proc )
204
- bbox = mesh_ops .mesh_cell_bboxes (* mesh_state )
204
+ print (f"Calculate bboxes for processor { proc } " )
205
+ # bbox = mesh_ops.mesh_cell_bboxes(*mesh_state)
206
+ bbox = mesh_ops .mesh_cell_bboxes_nb (* mesh_state )
205
207
bboxes .append (bbox )
206
208
207
209
# Appears there are no ghost cells,
@@ -434,6 +436,14 @@ def precalc_raster_info_clipping(self, fld, force=False):
434
436
raster_weights = sparse .hstack ( (raster_weights ,proc_raster_weights ) )
435
437
self .raster_precalc = raster_weights
436
438
439
+ # def get_raster_cache_fn(self,label,fld,proc=None,**kw):
440
+ # hash_input=[fld.extents,fld.F.shape,self.rot]
441
+ # hash_out = hashlib.md5(pickle.dumps(hash_input)).hexdigest()
442
+ #
443
+ # cache_dir=os.path.join(self.proc_dir(proc),"cache")
444
+ # cache_fn=os.path.join(cache_dir,
445
+ # f"raster_weights-{fld.dx:.3g}x_{fld.dy:.3g}y-{hash_out}")
446
+
437
447
def precalc_raster_weights_proc_by_faces (self ,proc ,fld ,force = False ):
438
448
hash_input = [fld .extents ,fld .F .shape ,self .rot ]
439
449
hash_out = hashlib .md5 (pickle .dumps (hash_input )).hexdigest ()
@@ -456,55 +466,71 @@ def precalc_raster_weights_proc_by_faces(self,proc,fld,force=False):
456
466
pickle .dump (raster_weights , fp , - 1 )
457
467
return raster_weights
458
468
459
- def to_raster (self , variable , timename , force_precalc = False ):
460
- if variable == 'wse' :
461
- return self .raster_wse (timename )
462
-
463
- self .read_timestep (timename )
469
+ def to_raster (self , variable , timename , force_precalc = False , cache = True ):
464
470
n_components = None
465
471
if variable == 'U' :
466
472
n_components = 3
467
473
fld = field .SimpleGrid .zeros (extents = self .raster_xxyy ,
468
474
dx = self .raster_dx ,dy = self .raster_dy ,
469
475
n_components = n_components )
476
+
477
+ if cache :
478
+ hash_input = [fld .extents ,fld .F .shape ,self .rot ]
479
+ hash_out = hashlib .md5 (pickle .dumps (hash_input )).hexdigest ()
480
+ cache_dir = os .path .join (self .sim_dir ,"cache" )
481
+ cache_fn = os .path .join (cache_dir ,
482
+ f"{ variable } -{ timename } -{ fld .dx :.3g} x_{ fld .dy :.3g} y-{ hash_out } .tif" )
483
+ if os .path .exists (cache_fn ):
484
+ return field .GdalGrid (cache_fn )
470
485
471
- if self .raster_precalc is None :
472
- self .precalc_raster_info (fld ,force = force_precalc )
473
-
474
- raster_weights = self .raster_precalc
475
-
476
- fld_x ,fld_y = fld .xy ()
486
+ if variable == 'wse' :
487
+ fld = self .raster_wse (timename )
488
+ else :
489
+ self .read_timestep (timename )
490
+
491
+ if self .raster_precalc is None :
492
+ self .precalc_raster_info (fld ,force = force_precalc )
493
+
494
+ raster_weights = self .raster_precalc
495
+
496
+ fld_x ,fld_y = fld .xy ()
497
+
498
+ # for sanity, process each component in sequence (tho memory inefficient)
499
+ for comp in range (n_components or 1 ):
500
+
501
+ if variable == 'U' :
502
+ # this
503
+ num = raster_weights .dot (self .alphas * self .vels [:,comp ])
504
+ den = raster_weights .dot (self .alphas )
505
+
506
+ # seems like division by zero should be handled by 'divide', but
507
+ # so far it trips 'invalid'
508
+ with np .errstate (divide = 'ignore' ,invalid = 'ignore' ):
509
+ u = num / den
510
+ u [ np .abs (den )< 1e-10 ] = np .nan
511
+
512
+ fld .F [:,:,comp ] = u .reshape ( (fld .F .shape [0 ],fld .F .shape [1 ]) )
513
+ elif variable == 'depth_bad' :
514
+ # this field and inv_depth_bad are not good approximations
515
+ # and left here only for comparison to other approaches.
516
+ # measure up from the bed, which is assumed flat
517
+ # This will not be a good estimate when the bed is not flat,
518
+ # non-simple, or the domain doesn't fill the pixel.
519
+ fld .F [:,:] = raster_weights .dot (self .alphas ).reshape ( fld .F .shape )
520
+ elif variable == 'inv_depth_bad' :
521
+ # More likely that the top of the domain is flat than the
522
+ # bed being flat, but still has errors when the freesurface
523
+ # intersects the walls.
524
+ fld .F [:,:] = raster_weights .dot (1.0 - self .alphas ).reshape ( fld .F .shape )
525
+ else :
526
+ raise Exception (f"Not ready for other fields like { variable } " )
527
+
528
+ if cache :
529
+ cache_dir = os .path .dirname (cache_fn )
530
+ if not os .path .exists (cache_dir ):
531
+ os .makedirs (cache_dir )
532
+ fld .write_gdal (cache_fn )
477
533
478
- # for sanity, process each component in sequence (tho memory inefficient)
479
- for comp in range (n_components or 1 ):
480
-
481
- if variable == 'U' :
482
- # this
483
- num = raster_weights .dot (self .alphas * self .vels [:,comp ])
484
- den = raster_weights .dot (self .alphas )
485
-
486
- # seems like division by zero should be handled by 'divide', but
487
- # so far it trips 'invalid'
488
- with np .errstate (divide = 'ignore' ,invalid = 'ignore' ):
489
- u = num / den
490
- u [ np .abs (den )< 1e-10 ] = np .nan
491
-
492
- fld .F [:,:,comp ] = u .reshape ( (fld .F .shape [0 ],fld .F .shape [1 ]) )
493
- elif variable == 'depth_bad' :
494
- # this field and inv_depth_bad are not good approximations
495
- # and left here only for comparison to other approaches.
496
- # measure up from the bed, which is assumed flat
497
- # This will not be a good estimate when the bed is not flat,
498
- # non-simple, or the domain doesn't fill the pixel.
499
- fld .F [:,:] = raster_weights .dot (self .alphas ).reshape ( fld .F .shape )
500
- elif variable == 'inv_depth_bad' :
501
- # More likely that the top of the domain is flat than the
502
- # bed being flat, but still has errors when the freesurface
503
- # intersects the walls.
504
- fld .F [:,:] = raster_weights .dot (1.0 - self .alphas ).reshape ( fld .F .shape )
505
- else :
506
- raise Exception (f"Not ready for other fields like { variable } " )
507
-
508
534
return fld
509
535
510
536
def rot_name (self ):
@@ -930,25 +956,44 @@ def precalc_raster_weights_proc_by_faces(fld, xyz, face_nodes, face_cells, cell_
930
956
931
957
fld_x ,fld_y = fld .xy () # I think these are pixel centers
932
958
959
+ # unclear whether numba version is sketch or not.
960
+ slicer = mesh_ops .mesh_slice_nb # mesh_slice_nb
961
+
962
+ if 0 : # debugging checks
963
+ print ("Checking cells before any operations" )
964
+ for cIdx in utils .progress (range (len (mesh_state [3 ])), func = print ):
965
+ if not mesh_ops .mesh_check_cell (cIdx ,False ,mesh_state ):
966
+ import pdb
967
+ pdb .set_trace ()
968
+ mesh_ops .mesh_check_cell (cIdx ,True ,mesh_state )
969
+
970
+ print ("Check complete" )
971
+
933
972
cell_mapping = None
934
973
for col in utils .progress (range (fld .shape [1 ])):
935
974
if col == 0 : continue
936
975
xmin = fld_x [col ]- fld .dx / 2
937
976
xmax = fld_x [col ]+ fld .dx / 2
938
- cell_mapping , mesh_state = mesh_ops . mesh_slice (np .r_ [1 ,0 ,0 ], xmin , cell_mapping , * mesh_state )
977
+ cell_mapping , mesh_state = slicer (np .r_ [1 ,0 ,0 ], xmin , cell_mapping , * mesh_state )
939
978
940
979
if 0 : # debugging checks
941
980
print ("Checking cells" )
942
981
for cIdx in utils .progress (range (len (mesh_state [3 ])), func = print ):
943
- assert mesh_ops .mesh_check_cell (cIdx ,False ,mesh_state )
982
+ if not mesh_ops .mesh_check_cell (cIdx ,False ,mesh_state ):
983
+ print (f"cIdx={ cIdx } failed check" )
984
+ mesh_ops .mesh_check_cell (cIdx ,True ,mesh_state )
985
+ raise Exception (f"cIdx={ cIdx } failed check" )
986
+
944
987
print ("Check complete" )
945
-
988
+
946
989
# Slice the mesh so all cells are in exactly one pixel
990
+ print ("Slicing by row" )
947
991
for row in utils .progress (range (fld .shape [0 ])):
992
+ print ("Row:" , row )
948
993
if row == 0 : continue
949
994
ymin = fld_y [row ]- fld .dy / 2
950
995
ymax = fld_y [row ]+ fld .dy / 2
951
- cell_mapping , mesh_state = mesh_ops . mesh_slice (np .r_ [0 ,1 ,0 ], ymin , cell_mapping , * mesh_state )
996
+ cell_mapping , mesh_state = slicer (np .r_ [0 ,1 ,0 ], ymin , cell_mapping , * mesh_state )
952
997
953
998
if 0 : # debugging checks
954
999
print ("Checking cells after all slicing" )
@@ -957,8 +1002,9 @@ def precalc_raster_weights_proc_by_faces(fld, xyz, face_nodes, face_cells, cell_
957
1002
print ("Check complete" )
958
1003
959
1004
print ("Calculate volume" )
960
- volumes ,centers = mesh_ops .mesh_cell_volume_centers (* mesh_state )
1005
+ volumes ,centers = mesh_ops .mesh_cell_volume_centers_nb (* mesh_state )
961
1006
1007
+ print ("Assemble matrix" )
962
1008
raster_weights = sparse .dok_matrix ((fld .F .shape [0 ]* fld .F .shape [1 ],
963
1009
n_cells_orig ),
964
1010
np .float64 )
0 commit comments