def laplacian(k): ''' Calculate the laplacian matrix for the Dubiner basis. Returns L where \nabla^2 u = u . L for any vandermonde matrix u N.B. would be easy to generalise this to any polynomial basis (indeed, the calculation of the mass matrix is currently superfluous as the Dubiner basis is orthonomal) THIS IS NOT USED - see p.c.b.reference.py for the alternative implemenation ''' tp, tw = puq.trianglequadrature(k+1) dt = DubinerTriangle(k,tp) vtp = dt.values() dtp = dt.derivs() mass = np.tensordot(vtp * tw, vtp, (0,0)) stiffness = -np.tensordot(dtp * tw, dtp, ((0,1),(0,1))) ex, ew = puq.legendrequadrature(k+1) # Now do the boundary integrals ew = ew.reshape(-1,1) ep1 = np.hstack((ex, np.zeros_like(ex))) ep2 = np.hstack((np.zeros_like(ex),ex)) ep3 = np.hstack((ex,1-ex)) for p, n in ((ep1,[0,-1]),(ep2,[-1,0]), (ep3, [1,1])): dt = DubinerTriangle(k, p) vn = np.tensordot(dt.derivs(), np.array(n), (0,0)) stiffness+=np.tensordot(dt.values() * ew, vn, (0,0)) return np.linalg.solve(mass, stiffness)
def testTriangle(self): for n in range(1, 10): x, w = puq.trianglequadrature(n) # test integration of constants self.assertAlmostEqual(sum(w), 0.5) # integrate x self.assertAlmostEqual(np.dot(x[:, 0], w), 1.0 / 6) # integrate y self.assertAlmostEqual(np.dot(x[:, 1], w), 1.0 / 6)
def testOrthonormal(self): ''' Test that the Dubiner polynomials are L^2-orthonormal over the reference triangle''' N = 8 for k in range(0, N): x,w = puq.trianglequadrature(k+1) dt = pup.DubinerTriangle(k,x) dtV = dt.values() l2 = np.dot(dtV.T, w * dtV) np.testing.assert_almost_equal(l2, np.eye(dtV.shape[1],dtV.shape[1]))
def testValues(self): N = 5 for k in range(N): x,w = puq.trianglequadrature(k+1) dt = pup.DubinerTriangle(k, x) V = dt.values() n = ((k+1)*(k+2))/2 self.assertEquals(V.shape[1], n) # test that we get the correct number of basis functions VV = np.dot(V.T, w * V) np.testing.assert_almost_equal(VV, np.eye(n)) # test that they are orthonormal
def testLaplacian(self): ''' Use finite differences to check the Lapalcian calculations''' N = 6 h = 1E-4 x,w = puq.trianglequadrature(5) for k in range(1,N): v = pup.DubinerTriangle(k, x).values() L = pup.laplacian(k) Lv = np.dot(v, L) Lhv = (sum([pup.DubinerTriangle(k, x+xh).values() for xh in ([0,h],[0,-h],[h,0],[-h,0])]) - 4*v)/(h**2) np.testing.assert_almost_equal(Lv, Lhv, decimal=3)
def testOptimalBasis2(self): """ Can we find the right direction to approximate a plane wave?""" k = 4 g = pcb.PlaneWaves(numpy.array([[3.0/5,4.0/5]]), k).values # g = pcb.FourierBessel(numpy.array([-2,-1]), numpy.array([5]),k) npw = 3 nq = 8 gen, ini = puo.pwbasisgeneration(k, npw) triquad = puq.trianglequadrature(nq) basis, (coeffs, l2err) = puo.optimalbasis2(g, gen, ini, triquad) self.assertAlmostEqual(sum(l2err),0)
def testConstrainedOptimisation(self): k = 4 g = pcb.PlaneWaves(numpy.array([[3.0/5,4.0/5]]), k).values # g = pcb.FourierBessel(numpy.array([-2,-1]), numpy.array([5]),k) npw = 3 nq = 8 ini = pcb.circleDirections(npw) triquad = puq.trianglequadrature(nq) linearopt = puo.LeastSquaresFit(g, triquad) pwpg = puo.PWPenaltyBasisGenerator(k, 1, 2) basis = puo.optimalbasis3(linearopt.optimise, pwpg.finalbasis, ini) (coeffs, l2err) = linearopt.optimise(basis) self.assertAlmostEqual(sum(l2err),0)
def testDerivs(self): N = 5 h = 1E-8 for k in range(0,N): x,w = puq.trianglequadrature(k+1) dt = pup.DubinerTriangle(k,x) dtV = dt.values() dtxh = pup.DubinerTriangle(k, x+[h,0]) dtxhV = dtxh.values() dtyh = pup.DubinerTriangle(k, x+[0,h]) dtyhV = dtyh.values() dtD = dt.derivs() dtxhD = (dtxhV - dtV)/h dtyhD = (dtyhV - dtV)/h np.testing.assert_almost_equal(dtD[0],dtxhD, decimal=4) np.testing.assert_almost_equal(dtD[1],dtyhD, decimal=4)
def raytracesoln(problem, etods, pdeg = 2, npw = 15, radius = 0.5): quadpoints = 15 k = problem.k rtpw = prb.OldRaytracedBasisRule(etods) fb = FourierBesselRule() shadow = RaytracedShadowRule(etods, fb) crt = SourceBasisRule() poly = pcbr.ReferenceBasisRule(pcbr.Dubiner(pdeg)) # unonpw = pcbu.UnionBasisRule([shadow, crt]) # polynonpw = pcb.ProductBasisRule(poly, unonpw) # basisrule = pcbu.UnionBasisRule([polynonpw,rtpw]) # unionall = pcbu.UnionBasisRule([shadow, rtpw, crt]) # polyall = pcb.ProductBasisRule(poly, unionall) # basisrule = polyall rt = pcbu.UnionBasisRule([rtpw, shadow]) polyrt = pcb.ProductBasisRule(poly, rt) basisrule = polyrt # pw = pcb.planeWaveBases(2, k, nplanewaves=npw) # basisrule = CornerMultiplexBasisRule(pw, basisrule, radius) # polyrt2 = pcbu.UnionBasisRule([rt,pcb.ProductBasisRule(poly, crt)]) # basisrule = polyrt2 basisrule = pcbred.SVDBasisReduceRule(puq.trianglequadrature(quadpoints), basisrule, threshold=1E-5) p = 1 if pdeg < 1 else pdeg h = 4.0/40 alpha = ((p*1.0)**2 ) / (k*h) beta = np.min([(k*h) / (p * 1.0),1]) computation = psc.Computation(problem, basisrule, pcp.HelmholtzSystem, quadpoints, alpha = alpha, beta = beta) solution = computation.solution(psc.DirectSolver().solve, dovolumes=True) bounds=array([[-2,2],[-2,2]],dtype='d') npoints=array([200,200]) pos.standardoutput(computation, solution, 20, bounds, npoints, mploutput = True, cmap=pom.mp.cm.get_cmap('binary'))
def testDubiner(self): # The Dubiner basis is L^2-orthogonal, so we can test that the SVN reduction doesn't do much to it # ... On reflection, this doesn't test very much. But it at least exercises the code, so leaving it in k = 10 N = 3 bounds=np.array([[0.1,0.1],[0.9,0.9]],dtype='d') npoints=np.array([20,20]) sp = pug.StructuredPoints(bounds, npoints) for n in range(1,4): mesh = tum.regularsquaremesh(n) dubrule = pcbr.ReferenceBasisRule(pcbr.Dubiner(N)) problem = psp.Problem(mesh, k, {}) dubbasis = psp.constructBasis(problem, dubrule) refquad = puq.trianglequadrature(N+1) svnrule = pcbred.SVDBasisReduceRule(refquad, dubrule) svnbasis = psp.constructBasis(problem, svnrule) # The bases should be equivalent: testEquivalentBases(dubbasis, svnbasis, mesh, sp)
from pypwdg.output.vtk_output import VTKStructuredPoints from pypwdg.output.vtk_output import VTKGrid from pypwdg.mesh.meshutils import MeshQuadratures from pypwdg.core.vandermonde import LocalVandermondes mesh_dict=gmsh_reader('../../examples/3D/scattmesh.msh') mesh=gmshMesh(mesh_dict,dim=3) boundaryentities = [82, 83] Nq = 16 Np = 3 dirs = cubeRotations(cubeDirections(Np)) quad=trianglequadrature(Nq) elttobasis = [[PlaneWaves(dirs, k)]] * mesh.nelements params={'alpha':.5, 'beta':.5,'delta':.5} l_coeffs=[-1j*k, 1] r_coeffs=[-1j*k, 1] bnddata={82:zero_impedance(k), 83:dirichlet(g) } mqs = MeshQuadratures(mesh, quad) lv = LocalVandermondes(mesh, elttobasis, mqs, usecache=False) bndvs=[] for data in bnddata.values():
def testMEQ(self): for n in range(1, 6): mesh = tum.regularsquaremesh(n) mq = pmmu.MeshElementQuadratures(mesh, puq.trianglequadrature(5)) for i in range(2 * n ** 2): self.assertAlmostEquals(sum(mq.quadweights(i)), 1.0 / (2 * n ** 2))
def test3DQuadratures(self): """ Ensure quadratures on neighbouring faces of various 3D meshes match """ self.compareQuadratures(tum.meshes3d(), puq.trianglequadrature(4))
def __init__(self, k): self.k = k self.n = ((k+1) * (k+2)) / 2 self.volume = puq.trianglequadrature(k+1) self.face = puq.legendrequadrature(k+1)
entityton ={9:1} problem=psp.VariableNProblem(entityton, mesh,k, bnddata) etods = prc.tracemesh(problem, {10:lambda x:direction}) etob = [[pcb.PlaneWaves(ds, k)] if len(ds) else [] for ds in etods] pob.vtkbasis(mesh,etob,'soundsoftrays.vtu',None) b0=pcbv.PlaneWaveVariableN(pcb.circleDirections(30)) b=pcb.PlaneWaveFromDirectionsRule(etods) origins=np.array([[-.5,-.5],[-.5,.5],[.5,-.5],[.5,.5]]) h=pcb.FourierHankelBasisRule(origins,[0]) h2=pcb.ProductBasisRule(h,pcbr.ReferenceBasisRule(pcbr.Dubiner(p))) b1=pcb.ProductBasisRule(b,pcbr.ReferenceBasisRule(pcbr.Dubiner(p))) bh=pcb.UnionBasisRule([h2,b1]) b2=pcbr.ReferenceBasisRule(pcbr.Dubiner(p)) basisrule = pcbred.SVDBasisReduceRule(puq.trianglequadrature(quadpoints), bh, threshold=1E-5) computation = psc.Computation(problem, basisrule, pcp.HelmholtzSystem, quadpoints,alpha=alpha,beta=beta,delta=delta) solution = computation.solution(psc.DirectSolver().solve, dovolumes=True) pos.standardoutput(computation, solution, quadpoints, bounds, npoints, 'soundsoft_pol', mploutput = True) print solution.getError('Dirichlet') print solution.getError('Neumann') print solution.getError('Boundary')