def test_100(self): x, w = herme.hermegauss(100) # test orthogonality. Note that the results need to be normalized, # otherwise the huge values that can arise from fast growing # functions like Laguerre can be very confusing. v = herme.hermevander(x, 99) vv = np.dot(v.T * w, v) vd = 1 / np.sqrt(vv.diagonal()) vv = vd[:, None] * vv * vd assert_almost_equal(vv, np.eye(100)) # check that the integral of 1 is correct tgt = np.sqrt(2 * np.pi) assert_almost_equal(w.sum(), tgt)
def test_100(self): x, w = herme.hermegauss(100) # test orthogonality. Note that the results need to be normalized, # otherwise the huge values that can arise from fast growing # functions like Laguerre can be very confusing. v = herme.hermevander(x, 99) vv = np.dot(v.T * w, v) vd = 1/np.sqrt(vv.diagonal()) vv = vd[:,None] * vv * vd assert_almost_equal(vv, np.eye(100)) # check that the integral of 1 is correct tgt = np.sqrt(2*np.pi) assert_almost_equal(w.sum(), tgt)
def eval_hermite(deg, x, analytic=True): if analytic: # Use pre-computed polynomials if deg == 0: return 1. elif deg == 1.: return x elif deg == 2: return x*x - 1. elif deg == 3: return x*x*x - 3.*x elif deg == 4: return x*x*x*x - 6.*x*x + 3. # If not returned, assume we should make the call to the numerical orthogonalizer roots = hermite_e.hermegauss(deg)[0] if deg > 1 else np.array([0, ]) poly = np.poly1d(roots, r=True) return poly(x)
def update_points(self, mean, scale, have_sqrt=False): """Updates the quadrature points given some initial point and scale. Parameters ---------- mean : N x 1 numpy array Point to represent by quadrature points. scale : N x N numpy array Covariance or square root of the covariance matrix of the given point. have_sqrt : bool Optional flag indicating if the square root of the matrix was supplied. The default is False. Returns ------- None. """ def create_combos(points_per_ax, num_ax, tot_points): combos = np.meshgrid( *itertools.repeat(range(points_per_ax), num_ax)) return np.array(combos).reshape((num_ax, tot_points)).T self.num_axes = mean.size sqrt_cov = self._factor_scale_matrix(scale, have_sqrt) self.points = np.nan * np.ones((self.num_points, self.num_axes)) self.weights = np.nan * np.ones(self.num_points) # get standard values for 1 axis case, use "Probabilist's" Hermite polynomials quad_points, weights = herm_e.hermegauss(self.points_per_axis) ind_combos = create_combos(self.points_per_axis, self.num_axes, self.num_points) for ii, inds in enumerate(ind_combos): point = quad_points[inds].reshape((inds.size, 1)) self.points[ii, :] = (mean + sqrt_cov @ point).ravel() self.weights[ii] = np.prod(weights[inds]) self.weights = self.weights / np.sum(self.weights)
def unit_sigma_points(dim, degree=3): """ Unit Gauss-Hermite sigma-points of given degree. Parameters ---------- dim : int Dimension of the input random variable. degree : int, optional Degree of the integration rule. Returns ------- : (dim, num_points) ndarray GH sigma-points. """ # 1D sigma-points (x) and weights (w) x, w = hermegauss(degree) # nD sigma-points by cartesian product return cartesian([x] * dim).T # column/sigma-point
def weights(dim, degree=3): """ Gauss-Hermite quadrature weights. Parameters ---------- dim : int Dimension of the input random variable. degree : int, optional Degree of the integration rule. Returns ------- : (num_points, ) ndarray GH quadrature weights of given degree. """ # 1D sigma-points (x) and weights (w) x, w = hermegauss(degree) # hermegauss() provides weights that cause posdef errors w = factorial(degree) / (degree**2 * hermeval(x, [0] * (degree - 1) + [1])**2) return np.prod(cartesian([w] * dim), axis=1)
def inner3_herm(P,i,j,l): #compute <\Phi_i\Phi_j\Phi_l> #Set up Gauss-Hermite quadrature, weighting function is exp^{-x^2} m=(P+1)**2 x, w=H.hermegauss(m) inner=sum([product3_herm(i,j,l)(x[idx]) * w[idx] for idx in range(m)]) return inner/np.sqrt(2*np.pi) #because of the weight
def Compute_Q(proc_num, proc_max, mu1=0, mu2=0, sigma1=0.1, sigma2=0.1, gridx=50, gridy=50, p=1): num_quad = 20 lambda1 = H.hermegauss(num_quad)[0] lambda2 = H.hermegauss(num_quad)[0] # Create the characteristic function class used to define the QoI class AvgCharFunc(fn.UserExpression): def __init__(self, region, **kwargs): self.a = region[0] self.b = region[1] self.c = region[2] self.d = region[3] super().__init__(**kwargs) def eval(self, v, x): v[0] = 0 if (x[0] >= self.a) & (x[0] <= self.b) & (x[1] >= self.c) & (x[1] <= self.d): v[0] = 1./( (self.b-self.a) * (self.d-self.c) ) return v def value_shape(self): return () def QoI_FEM(lam1,lam2,pointa,pointb,gridx,gridy,p): aa = pointa[0] bb = pointb[0] cc = pointa[1] dd = pointb[1] mesh = fn.UnitSquareMesh(gridx, gridy) V = fn.FunctionSpace(mesh, "Lagrange", p) # Define diffusion tensor (here, just a scalar function) and parameters A = fn.Expression((('exp(lam1)','a'), ('a','exp(lam2)')), a = fn.Constant(0.0), lam1 = lam1, lam2 = lam2, degree=3) u_exact = fn.Expression("sin(lam1*pi*x[0])*cos(lam2*pi*x[1])", lam1 = lam1, lam2 = lam2, degree=2+p) # Define the mix of Neumann and Dirichlet BCs class LeftBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[0] < fn.DOLFIN_EPS) class RightBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[0] > 1.0 - fn.DOLFIN_EPS) class TopBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[1] > 1.0 - fn.DOLFIN_EPS) class BottomBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[1] < fn.DOLFIN_EPS) # Create a mesh function (mf) assigning an unsigned integer ('uint') # to each edge (which is a "Facet" in 2D) mf = fn.MeshFunction('size_t', mesh, 1) mf.set_all(0) # initialize the function to be zero # Setup the boundary classes that use Neumann boundary conditions NTB = TopBoundary() # instatiate NTB.mark(mf, 1) # set all values of the mf to be 1 on this boundary NBB = BottomBoundary() NBB.mark(mf, 2) # set all values of the mf to be 2 on this boundary NRB = RightBoundary() NRB.mark(mf, 3) # Define Dirichlet boundary conditions Gamma_0 = fn.DirichletBC(V, u_exact, LeftBoundary()) bcs = [Gamma_0] # Define data necessary to approximate exact solution f = ( fn.exp(lam1)*(lam1*fn.pi)**2 + fn.exp(lam2)*(lam2*fn.pi)**2 ) * u_exact #g1:#pointing outward unit normal vector, pointing upaward (0,1) g1 = fn.Expression("-exp(lam2)*lam2*pi*sin(lam1*pi*x[0])*sin(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) #g2:pointing downward (0,1) g2 = fn.Expression("exp(lam2)*lam2*pi*sin(lam1*pi*x[0])*sin(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) g3 = fn.Expression("exp(lam1)*lam1*pi*cos(lam1*pi*x[0])*cos(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) fn.ds = fn.ds(subdomain_data=mf) # Define variational problem u = fn.TrialFunction(V) v = fn.TestFunction(V) a = fn.inner(A*fn.grad(u), fn.grad(v))*fn.dx L = f*v*fn.dx + g1*v*fn.ds(1) + g2*v*fn.ds(2) + g3*v*fn.ds(3) #note the 1, 2 and 3 correspond to the mf # Compute solution u = fn.Function(V) fn.solve(a == L, u, bcs) psi = AvgCharFunc([aa, bb, cc, dd], degree=0) Q = fn.assemble(fn.project(psi * u, V) * fn.dx) return Q Q_FEM = np.zeros(400) num_Q_per_proc = 400//proc_max if proc_num != proc_size -1: for i in range(proc_num*num_Q_per_proc, (proc_num+1)*num_Q_per_proc): Q_FEM[i] = QoI_FEM(mu1+sigma1*lambda1[i%num_quad],mu2+sigma2*lambda2[i//num_quad],[0.4,0.4],[0.6,0.6],gridx,gridy,p) else: for i in range(proc_num*num_Q_per_proc,400): Q_FEM[i] = QoI_FEM(mu1+sigma1*lambda1[i%num_quad],mu2+sigma2*lambda2[i//num_quad],[0.4,0.4],[0.6,0.6],gridx,gridy,p) filename = os.path.join(os.getcwd(), "Data", "Q_FEM_quad_") + str(proc_num) + ".mat" data_dict = {'Q_FEM': Q_FEM} sio.savemat(filename, data_dict) return
def q(i,j): x, w=H.hermegauss(20) Q=sum([w[ldx]*sum([w[kdx] * Q_FEM_quad[ldx*20+kdx] * H.hermeval(x[kdx],Phi(i)) for kdx in range(20)])*H.hermeval(x[ldx],Phi(j)) for ldx in range(20)]) q= Q/(2*np.pi*factorial(i)*factorial(j)) return q
def quadrature(self, points): xi, w = hermite_e.hermegauss(points) w /= np.sqrt(2*np.pi) return xi, w
def unit_sigma_points(dim, degree): # 1D sigma-points (x) and weights (w) x, w = hermegauss(degree) # nD sigma-points by cartesian product return cartesian([x] * dim).T # column/sigma-point
def weights(dim, degree): # 1D sigma-points (x) and weights (w) x, w = hermegauss(degree) # hermegauss() provides weights that cause posdef errors w = factorial(degree) / (degree ** 2 * hermeval(x, [0] * (degree - 1) + [1]) ** 2) return np.prod(cartesian([w] * dim), axis=1)