@@ -495,7 +495,7 @@ def select(self, indicator, ischeme='bezier2', **kwargs):
495495 return self [selected ]
496496
497497 @log .withcontext
498- def locate (self , geom , coords , * , ischeme = 'vertex' , scale = 1 , tol = None , eps = 0 , maxiter = 100 , arguments = None ):
498+ def locate (self , geom , coords , * , tol , eps = 0 , maxiter = 100 , arguments = None , weights = None , maxdist = None , ischeme = None , scale = None ):
499499 '''Create a sample based on physical coordinates.
500500
501501 In a finite element application, functions are commonly evaluated in points
@@ -526,39 +526,36 @@ def locate(self, geom, coords, *, ischeme='vertex', scale=1, tol=None, eps=0, ma
526526 Array of coordinates with ``ndims`` columns.
527527 tol : :class:`float`
528528 Maximum allowed distance between original and located coordinate.
529- ischeme : :class:`str` (default: "vertex")
530- Sample points used to determine bounding boxes.
531- scale : :class:`float` (default: 1)
532- Bounding box amplification factor, useful when element shapes are
533- distorted. Setting this to >1 can increase computational effort but is
534- otherwise harmless.
535529 eps : :class:`float` (default: 0)
536530 Epsilon radius around element within which a point is considered to be
537531 inside.
538532 maxiter : :class:`int` (default: 100)
539533 Maximum allowed number of Newton iterations.
540534 arguments : :class:`dict` (default: None)
541535 Arguments for function evaluation.
536+ weights : :class:`float` array (default: None)
537+ Optional weights, in case ``coords`` are quadrature points.
538+ maxdist : :class:`float` (default: None)
539+ Speed up failure by setting a distance between point and element
540+ centroid above which the element is rejected immediately. If all points
541+ are expected to be located then this can safely be left unspecified.
542542
543543 Returns
544544 -------
545545 located : :class:`nutils.sample.Sample`
546546 '''
547547
548- if tol is None :
549- warnings .deprecation ('locate without tol argument is deprecated, please provide an explicit tolerance' )
550- tol = 1e-12
548+ if ischeme is not None :
549+ warnings .deprecation ('the ischeme argument is deprecated and will be removed in future' )
550+ if scale is not None :
551+ warnings .deprecation ('the scale argument is deprecated and will be removed in future' )
551552 coords = numpy .asarray (coords , dtype = float )
552553 if geom .ndim == 0 :
553554 geom = geom [_ ]
554555 coords = coords [...,_ ]
555556 if not geom .shape == coords .shape [1 :] == (self .ndims ,):
556557 raise Exception ('invalid geometry or point shape for {}D topology' .format (self .ndims ))
557- bboxsample = self .sample (* element .parse_legacy_ischeme (ischeme ))
558- vertices = map (bboxsample .eval (geom , ** arguments or {}).__getitem__ , bboxsample .indexiter )
559- bboxes = numpy .array ([numpy .mean (v ,axis = 0 ) * (1 - scale ) + numpy .array ([numpy .min (v ,axis = 0 ), numpy .max (v ,axis = 0 )]) * scale
560- for v in vertices ]) # nelems x {min,max} x ndims
561- vref = element .getsimplex (0 )
558+ centroids = self .elem_mean (geom , geometry = geom , degree = 2 )
562559 ielems = parallel .shempty (len (coords ), dtype = int )
563560 xis = parallel .shempty ((len (coords ),len (geom )), dtype = float )
564561 subsamplemetas = function .SubsampleMeta (roots = self .roots , ndimsnormal = sum (root .ndims for root in self .roots )- self .ndims , ndimspoints = self .ndims ),
@@ -567,8 +564,9 @@ def locate(self, geom, coords, *, ischeme='vertex', scale=1, tol=None, eps=0, ma
567564 with parallel .ctxrange ('locating' , len (coords )) as ipoints :
568565 for ipoint in ipoints :
569566 coord = coords [ipoint ]
570- ielemcandidates , = numpy .logical_and (numpy .greater_equal (coord , bboxes [:,0 ,:]), numpy .less_equal (coord , bboxes [:,1 ,:])).all (axis = - 1 ).nonzero ()
571- for ielem in sorted (ielemcandidates , key = lambda i : numpy .linalg .norm (bboxes [i ].mean (0 )- coord )):
567+ dist = numpy .linalg .norm (centroids - coord , axis = 1 )
568+ for ielem in numpy .argsort (dist ) if maxdist is None \
569+ else sorted ((dist < maxdist ).nonzero ()[0 ], key = dist .__getitem__ ):
572570 converged = False
573571 ref = self .references [ielem ]
574572 p = ref .getpoints ('gauss' , 1 )
0 commit comments