[pyfr] 49/88: Replace @chop with a more powerful @clean decorator.

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Nov 16 12:05:29 UTC 2016


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch master
in repository pyfr.

commit f562ed7a7069e50f54b9afc274391db426d072ae
Author: Freddie Witherden <freddie at witherden.org>
Date:   Tue Jun 7 10:08:05 2016 -0700

    Replace @chop with a more powerful @clean decorator.
    
    Clean uses a similar approach to GiMMiK that also works to
    coalesce similar values in a matrix in addition to just truncating
    small values.
---
 pyfr/nputil.py | 36 ++++++++++++++++++++++++++++--------
 pyfr/polys.py  | 10 +++++-----
 pyfr/shapes.py | 12 ++++++------
 3 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/pyfr/nputil.py b/pyfr/nputil.py
index 66e3146..64cbefd 100644
--- a/pyfr/nputil.py
+++ b/pyfr/nputil.py
@@ -21,16 +21,36 @@ def block_diag(arrs):
     return out
 
 
-def chop(fn):
-    @ft.wraps(fn)
-    def newfn(*args, **kwargs):
-        arr = fn(*args, **kwargs)
+def clean(origfn=None, tol=1e-10):
+    def cleanfn(fn):
+        @ft.wraps(fn)
+        def newfn(*args, **kwargs):
+            arr = fn(*args, **kwargs).copy()
 
-        # Determine a tolerance and flush
-        arr[abs(arr) < 10*np.finfo(arr.dtype).resolution] = 0
+            # Flush small elements to zero
+            arr[np.abs(arr) < tol] = 0
 
-        return arr
-    return newfn
+            # Coalesce similar elements
+            amfl = np.abs(arr.flat)
+            amix = np.argsort(amfl)
+
+            i, ix = 0, amix[0]
+            for j, jx in enumerate(amix[1:], start=1):
+                if amfl[jx] - amfl[ix] >= tol:
+                    if j - i > 1:
+                        amfl[amix[i:j]] = np.median(amfl[amix[i:j]])
+                    i, ix = j, jx
+
+            if i != j:
+                amfl[amix[i:]] = np.median(amfl[amix[i:]])
+
+            # Fix up the signs and assign
+            arr.flat = np.copysign(amfl, arr.flat)
+
+            return arr
+        return newfn
+
+    return cleanfn(origfn) if origfn else cleanfn
 
 
 _npeval_syms = {
diff --git a/pyfr/polys.py b/pyfr/polys.py
index 2f2b6b0..a08b8b6 100644
--- a/pyfr/polys.py
+++ b/pyfr/polys.py
@@ -5,7 +5,7 @@ from math import sqrt
 
 import numpy as np
 
-from pyfr.nputil import chop
+from pyfr.nputil import clean
 from pyfr.util import lazyprop, subclass_where
 
 
@@ -52,14 +52,14 @@ class BasePolyBasis(object):
         self.order = order
         self.pts = pts
 
-    @chop
+    @clean
     def ortho_basis_at(self, pts):
         if len(pts) and not isinstance(pts[0], Iterable):
             pts = [(p,) for p in pts]
 
         return np.array([self.ortho_basis_at_py(*p) for p in pts]).T
 
-    @chop
+    @clean
     def jac_ortho_basis_at(self, pts):
         if len(pts) and not isinstance(pts[0], Iterable):
             pts = [(p,) for p in pts]
@@ -68,11 +68,11 @@ class BasePolyBasis(object):
 
         return np.array(J).swapaxes(0, 2)
 
-    @chop
+    @clean
     def nodal_basis_at(self, epts):
         return np.linalg.solve(self.vdm, self.ortho_basis_at(epts)).T
 
-    @chop
+    @clean
     def jac_nodal_basis_at(self, epts):
         return np.linalg.solve(self.vdm, self.jac_ortho_basis_at(epts))
 
diff --git a/pyfr/shapes.py b/pyfr/shapes.py
index 0c8013b..77f8b48 100644
--- a/pyfr/shapes.py
+++ b/pyfr/shapes.py
@@ -6,7 +6,7 @@ import re
 
 import numpy as np
 
-from pyfr.nputil import block_diag, chop
+from pyfr.nputil import block_diag, clean
 from pyfr.polys import get_polybasis
 from pyfr.quadrules import get_quadrule
 from pyfr.util import lazyprop
@@ -17,7 +17,7 @@ def _proj_pts(projector, pts):
     return np.vstack(np.broadcast_arrays(*projector(*pts))).T
 
 
- at chop
+ at clean
 def _proj_l2(qrule, basis):
     return np.dot(basis.vdm.T, qrule.wts*basis.ortho_basis_at(qrule.pts))
 
@@ -78,7 +78,7 @@ class BaseShape(object):
         else:
             raise ValueError('Invalid number of shape points')
 
-    @chop
+    @clean
     def opmat(self, expr):
         if not re.match(r'[M0-9\-+*() ]+$', expr):
             raise ValueError('Invalid operator matrix expression')
@@ -142,7 +142,7 @@ class BaseShape(object):
         return block_diag([self.m9]*self.ndims)
 
     @lazyprop
-    @chop
+    @clean
     def m11(self):
         ub = self.ubasis
 
@@ -259,7 +259,7 @@ class BaseShape(object):
 
         return np.vstack(coeffs)
 
-    @chop
+    @clean
     def gbasis_at(self, pts):
         return np.dot(self.gbasis_coeffs, self.ubasis.ortho_basis_at(pts)).T
 
@@ -311,7 +311,7 @@ class BaseShape(object):
     @lazyprop
     def mpts(self):
         return self.std_ele(self.order)
-    
+
     @lazyprop
     def nmpts(self):
         return len(self.mpts)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pyfr.git



More information about the debian-science-commits mailing list