@@ -189,6 +189,13 @@ def _init_model(self):
189189
190190 self ._disp_inserted = False
191191
192+ # a cache for badlands information that can be reused in UW coupling.
193+ # The surface grid information from badlands is used to:
194+ # 1. designate material type, _update_material_types.
195+ # 2. used for sampling the velocity field (via help_gen_sample_point).
196+ # store this in bdl_cache
197+ self ._bdl_cache = None
198+
192199 # Transfer the initial DEM state to Underworld
193200 self ._update_material_types ()
194201 comm .Barrier ()
@@ -219,57 +226,72 @@ def _generate_dem(self):
219226 dem [:, 2 ] = coordsZ .flatten ()
220227 return dimensionalise (dem , u .meter ).magnitude
221228
222- def solve (self , dt , sigma = 0 ):
223- """
224- Execute Badlands a badlands solve in the Underworld coupling.
225- 1. Collect Badland's recGrid and broadcast to all procs.
226- 2. Inerpolate Underworld velocity field on recGrid
227- 3. Calculate overall displacement in meters by muliplying velocity (m/yr) with input dt (yr).
228- 4. Using the displacement run badlands from currect time `t` to time `t+dt`.
229- 5. Save final stratigraphic field from badlands.
230- 6. Update Underworld particles depending on Badland tin. Another interpolation.
231- """
229+ def help_gen_sample_point (self , uw_sample_style = 0 ):
230+ '''
231+ Collective routine. Return sample points.
232232
233- dt_years = np .round (dimensionalise (dt , u .years ).magnitude ,6 ) # fix pint scaling issue
233+ Return:
234+ -------
235+ np.array : shape (dim)
236+ Locations to sample UW velocity.
237+
238+ uw_sample_style : int, 0 default
239+ Style for UW velocity sampling. Possible values 0 or 1.
240+ 0 - Use dynamic elevation from Badlands' model elevation. Interpolated to grid locations to sample the UW velocity.
241+ 1 - Use OLD method to sample at Badlands' initial recGrid elevations.
242+
243+ Take locations in Badlands' recGrid find the UW velocity field.
244+ This helper function abstracts the different algorithm, based on dim.
245+ This uses cached data, _bdl_cache, from routine _update_material_types().
246+ '''
247+
248+ if uw_sample_style :
249+ # The previous LIMITED implementation.
250+ # LIMITED as it use the static recGrid data from Badlands to sample the UW velocity.
251+ np_surface = None
252+ if rank == 0 :
253+ rg = self .badlands_model .recGrid
254+ if self .Model .mesh .dim == 2 :
255+ zVals = rg .regZ .mean (axis = 1 )
256+ np_surface = np .column_stack ((rg .regX , zVals ))
234257
235- if rank == 0 and self .verbose :
236- purple = "\033 [0;35m"
237- endcol = "\033 [00m"
238- print (purple + f"Processing surface with Badlands { dt_years } :\n \t from { self .time_years } -> { self .time_years + dt_years } " + endcol )
239- sys .stdout .flush ()
258+ if self .Model .mesh .dim == 3 :
259+ np_surface = np .column_stack ((rg .rectX , rg .rectY , rg .rectZ ))
260+
261+ np_surface = comm .bcast (np_surface , root = 0 )
262+ comm .Barrier ()
263+
264+ return nd (np_surface * u .meters ) # non dimensionalise
265+
266+ ## SHOULD only get here is uw_sample_style == 0
240267
241268 fact = dimensionalise (1.0 , u .meter ).magnitude
242269 if self .Model .mesh .dim == 2 :
243270 if rank == 0 :
244- known_xy = self .badlands_model .recGrid .tinMesh ['vertices' ] / fact
245- known_z = self .badlands_model .elevation / fact
246- xs = self .badlands_model .recGrid .regX / fact
271+ xs = self .badlands_model .recGrid .regX / fact # 1D simple
247272 ys = self .badlands_model .recGrid .regY / fact
248273
249- known_xy = comm . bcast ( known_xy , root = 0 )
250- known_z = comm . bcast ( known_z , root = 0 )
274+ ( known_xy , known_z ) = ( self . _bdl_cache [ 0 ], self . _bdl_cache [ 1 ] )
275+
251276 xs = comm .bcast (xs , root = 0 )
252277 ys = comm .bcast (ys , root = 0 )
253278
254279 comm .Barrier ()
255280
256281 grid_x , grid_y = np .meshgrid (xs , ys )
257- interpolate_z = griddata (known_xy ,
258- known_z ,
259- (grid_x , grid_y ),
282+ interpolate_z = griddata (points = known_xy ,
283+ values = known_z ,
284+ xi = (grid_x , grid_y ),
260285 method = 'nearest' ).T
261286 interpolate_z = interpolate_z .mean (axis = 1 )
262- nd_coords = np .column_stack ((xs , interpolate_z ))
287+ return np .column_stack ((xs , interpolate_z ))
263288
264289 if self .Model .mesh .dim == 3 :
265290 if rank == 0 :
266- known_xy = self .badlands_model .recGrid .tinMesh ['vertices' ] / fact
267- known_z = self .badlands_model .elevation / fact
268- rect_x = self .badlands_model .recGrid .rectX / fact
291+ rect_x = self .badlands_model .recGrid .rectX / fact # 1D, every point
269292 rect_y = self .badlands_model .recGrid .rectY / fact
270293
271- known_xy = comm .bcast (known_xy , root = 0 )
272- known_z = comm .bcast (known_z , root = 0 )
294+ ( known_xy , known_z ) = (self ._bdl_cache [0 ], self ._bdl_cache [1 ])
273295 rect_x = comm .bcast (rect_x , root = 0 )
274296 rect_y = comm .bcast (rect_y , root = 0 )
275297
@@ -278,7 +300,46 @@ def solve(self, dt, sigma=0):
278300 values = known_z ,
279301 xi = (rect_x , rect_y ),
280302 method = 'nearest' )
281- nd_coords = np .column_stack ((rect_x ,rect_y , interpolate_z ))
303+ return np .column_stack ((rect_x ,rect_y , interpolate_z ))
304+
305+
306+ def solve (self , dt , sigma = 0 , uw_sample_style = 0 ):
307+ """
308+ Collective routine
309+
310+ Execute Badlands a badlands solve in the Underworld coupling.
311+
312+ Parameters
313+ ----------
314+ dt : float,
315+ Non dimensional time to advance badlands forward.
316+ sigma : float, 0 default
317+ Apply a gaussian_filter, as per scipy.ndimage.filters, to the injected velocity displacements from UW to badlands
318+ uw_sample_style : int, 0 default
319+ Style for UW velocity sampling. Possible values 0 or 1.
320+ 0 - Use dynamic elevation from Badlands' model elevation. Interpolated to grid locations to sample the UW velocity.
321+ 1 - Use OLD method to sample at Badlands' initial recGrid elevations.
322+
323+ Information of function.
324+ Execute Badlands a badlands solve in the Underworld coupling.
325+ 1. Collect Badland's recGrid and broadcast to all procs.
326+ 2. Inerpolate Underworld velocity field on recGrid
327+ 3. Calculate overall displacement in meters by muliplying velocity (m/yr) with input dt (yr).
328+ 4. Using the displacement run badlands from currect time `t` to time `t+dt`.
329+ 5. TODO: Ensure final stratigraphic field from badlands at `t+dt`.
330+ 6. Update Underworld particles depending on Badland tin. Another interpolation.
331+ """
332+
333+ dt_years = np .round (dimensionalise (dt , u .years ).magnitude ,6 ) # fix pint scaling issue
334+
335+ if rank == 0 and self .verbose :
336+ purple = "\033 [0;35m"
337+ endcol = "\033 [00m"
338+ print (purple + f"Processing surface with Badlands { dt_years } :\n \t from { self .time_years } -> { self .time_years + dt_years } " + endcol )
339+ sys .stdout .flush ()
340+
341+ # call the helper function to generate sample point for velocity evaluation
342+ nd_coords = self .help_gen_sample_point (uw_sample_style )
282343
283344 tracer_velocity = self .Model .velocityField .evaluate_global (nd_coords )
284345
@@ -301,43 +362,6 @@ def solve(self, dt, sigma=0):
301362 # Run the Badlands model to the same time point
302363 bdm .run_to_time (run_until )
303364
304- # # perform final checkpoint to syc
305- # # time_uw = time_bdm
306- # # These save are criticle for checkpoint/restart
307- # # so save them somewhere else
308- # from badlands import checkPoints
309- # checkPoints.write_checkpoints(
310- # bdm.input,
311- # bdm.recGrid,
312- # bdm.lGIDs,
313- # bdm.inIDs,
314- # bdm.tNow,
315- # bdm.FVmesh,
316- # bdm.force,
317- # bdm.flow,
318- # bdm.rain,
319- # bdm.elevation,
320- # bdm.fillH,
321- # bdm.cumdiff,
322- # bdm.cumhill,
323- # bdm.cumfail,
324- # bdm.wavediff,
325- # bdm.outputStep,
326- # bdm.prop,
327- # bdm.mapero,
328- # bdm.cumflex,
329- # )
330-
331- # # force a final stratigraphy step
332- # _ = bdm.strata.buildStrata(
333- # bdm.elevation,
334- # bdm.cumdiff,
335- # bdm.force.sealevel,
336- # bdm.recGrid.boundsPt,
337- # 1,
338- # bdm.outputStep,
339- # )
340-
341365 self .time_years += dt_years
342366
343367 # TODO: Improve the performance of this function
@@ -372,6 +396,9 @@ def _determine_particle_state_2D(self):
372396 xs = comm .bcast (xs , root = 0 )
373397 ys = comm .bcast (ys , root = 0 )
374398
399+ # all procs
400+ self ._bdl_cache = (known_xy , known_z )
401+
375402 comm .Barrier ()
376403
377404 grid_x , grid_y = np .meshgrid (xs , ys )
@@ -413,6 +440,9 @@ def _determine_particle_state(self):
413440 known_xy = comm .bcast (known_xy , root = 0 )
414441 known_z = comm .bcast (known_z , root = 0 )
415442
443+ # all procs
444+ self ._bdl_cache = (known_xy , known_z )
445+
416446 comm .Barrier ()
417447
418448 volume = self .Model .swarm .particleCoordinates .data
@@ -433,7 +463,6 @@ def _determine_particle_state(self):
433463 return flags
434464
435465 def _update_material_types (self ):
436-
437466 # What do the materials (in air/sediment terms) look like now?
438467 if self .Model .mesh .dim == 3 :
439468 under_bd_surface = self ._determine_particle_state ()
0 commit comments