def getP2Rules(): res = {} res[ngs.ET.SEGM] = ngs.IntegrationRule([(0, 0, 0), (1.0, 0, 0), (0.5, 0, 0)], [0.0] * 3) # for 2d elements we need to get the normal vectors at the corner vertices plus mapped coordinates of edge midpoints res[ngs.ET.TRIG] = ngs.IntegrationRule([(1, 0, 0), (0, 1, 0), (0, 0, 0), (0.5, 0.0, 0.0), (0.0, 0.5, 0.0), (0.5, 0.5, 0.0)], [0.0] * 6) res[ngs.ET.QUAD] = ngs.IntegrationRule([(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0), (0.5, 0.0, 0.0), (0.0, 0.5, 0.0), (0.5, 0.5, 0.0), (1.0, 0.5, 0.0), (0.5, 1.0, 0.0)], [0.0] * 9) # 3d elements have no normal vectors, so only evaluate at edge midpoints res[ngs.ET.TET] = ngs.IntegrationRule([(0.5, 0.0, 0.0), (0.0, 0.5, 0.0), (0.5, 0.5, 0.0), (0.5, 0.0, 0.5), (0.0, 0.5, 0.5), (0.0, 0.0, 0.5)], [0.0] * 6) # no curved hexes/prims/pyramids yet res[ngs.ET.HEX] = ngs.IntegrationRule([], []) res[ngs.ET.PRISM] = ngs.IntegrationRule([], []) res[ngs.ET.PYRAMID] = ngs.IntegrationRule([], []) # // PRISM # for (auto & ip : ir_trig.Range(3,6)) # ir_prism.Append(ip); # for (auto & ip : ir_trig.Range(0,3)) # ir_prism.Append(IntegrationPoint(ip(0), ip(1), 0.5)); # for (auto & ip : ir_trig.Range(3,6)) # ir_prism.Append(IntegrationPoint(ip(0), ip(1), 1.0)); # # // PYRAMID # for (auto & ip : ir_quad.Range(4,9)) # ir_pyramid.Append(ip); # for (auto & ip : ir_quad.Range(0,4)) # ir_pyramid.Append(IntegrationPoint(ip(0), ip(1), 0.5)); # # // HEX # for (auto & ip : ir_quad.Range(4,9)) # ir_hex.Append(ip); # for (auto x : {0.0, 0.5, 1.0}) # for (auto y : {0.0, 0.5, 1.0}) # ir_hex.Append(IntegrationPoint(x,y,0.5)); # for (auto & ip : ir_quad.Range(4,9)) # ir_hex.Append(IntegrationPoint(ip(0), ip(1), 1.0)); return res
def getReferenceRules(order, sd): n = (order) * (sd + 1) + 1 h = 1.0 / (n - 1) res = {} n2 = n * (n + 1) // 2 n3 = n * (n + 1) * (n + 2) // 6 res[ngs.ET.SEGM] = ngs.IntegrationRule([(1.0 - i * h, 0.0, 0.0) for i in range(n)], [0.0 for i in range(n)]) res[ngs.ET.TRIG] = ngs.IntegrationRule([(i * h, j * h, 0.0) for j in range(n) for i in range(n - j)], [0.0] * n2) res[ngs.ET.QUAD] = ngs.IntegrationRule([(i * h, j * h, 0.0) for j in range(n) for i in range(n)], [0.0] * (n + 1)**2) res[ngs.ET.TET] = ngs.IntegrationRule([(i * h, j * h, k * h) for k in range(n) for j in range(n - k) for i in range(n - k - j)], [0.0] * n3) res[ngs.ET.HEX] = ngs.IntegrationRule([(i * h, j * h, k * h) for k in range(n) for j in range(n) for i in range(n)], [0.0] * (n + 1)**3) res[ngs.ET.PRISM] = ngs.IntegrationRule([(i * h, j * h, k * h) for k in range(n) for j in range(n) for i in range(n - j)], [0.0] * ((n + 1) * n2)) # no subdivision or high order for pyramids n = 2 h = 1.0 / (n - 1) res[ngs.ET.PYRAMID] = ngs.IntegrationRule( [(i * h * (1.0 - 0 * h), j * h * (1.0 - 0 * h), k * h) for k in range(n) for j in range(n - k) for i in range(n - k)], [0.0] * (n * (n + 1) * (n + 2 * n + 1) // 6)) return res
def BuildRenderData(mesh, func, order=2, draw_surf=True, draw_vol=True, deformation=None): timer.Start() #TODO: handle quads and non-smooth functions #TODO: subdivision d = {} d['ngsolve_version'] = ngs.__version__ d['mesh_dim'] = mesh.dim # order = order or mesh.GetCurveOrder() if (not func) and (mesh.GetCurveOrder() == 1): order = 1 order2d = min(order, 3) order3d = min(order, 2) d['order2d'] = order2d d['order3d'] = order3d d['draw_vol'] = func and mesh.dim == 3 and draw_vol d['draw_surf'] = func and draw_surf if isinstance(deformation, bool): d['deformation'] = deformation deformation = None func2 = None if func and func.is_complex: d['is_complex'] = True func1 = func[0].real func2 = ngs.CoefficientFunction((func[0].imag, 0.0)) d['funcdim'] = 2 elif func and func.dim > 1: func1 = func[0] func2 = ngs.CoefficientFunction( tuple(func[i] if i < func.dim else 0.0 for i in range(1, 3))) # max 3-dimensional functions d['funcdim'] = func.dim elif func: func1 = func d['funcdim'] = 1 else: func1 = ngs.CoefficientFunction(0.0) d['funcdim'] = 0 func1 = ngs.CoefficientFunction((ngs.x, ngs.y, ngs.z, func1)) func0 = ngs.CoefficientFunction((ngs.x, ngs.y, ngs.z, 0.0)) if deformation is not None: func1 += ngs.CoefficientFunction((deformation, 0.0)) func0 += ngs.CoefficientFunction((deformation, 0.0)) d['show_wireframe'] = False d['show_mesh'] = False if order2d > 0: og = order2d d['show_wireframe'] = True d['show_mesh'] = True timer2.Start() timer3Bvals.Start() # transform point-values to Bernsteinbasis def Binomial(n, i): return math.factorial(n) / math.factorial(i) / math.factorial(n - i) def Bernstein(x, i, n): return Binomial(n, i) * x**i * (1 - x)**(n - i) Bvals = ngs.Matrix(og + 1, og + 1) for i in range(og + 1): for j in range(og + 1): Bvals[i, j] = Bernstein(i / og, j, og) iBvals = Bvals.I timer3Bvals.Stop() # print (Bvals) # print (iBvals) Bezier_points = [] # TODO: Quads ipts = [(i / og, 0) for i in range(og + 1)] + [ (0, i / og) for i in range(og + 1) ] + [(i / og, 1.0 - i / og) for i in range(og + 1)] ir = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) vb = [ngs.VOL, ngs.BND][mesh.dim - 2] pts = mesh.MapToAllElements(ir, vb) cf = func1 if draw_surf else func0 pmat = cf(pts) timermult.Start() pmat = pmat.reshape(-1, og + 1, 4) BezierPnts = np.tensordot(iBvals.NumPy(), pmat, axes=(1, 1)) timermult.Stop() timer2list.Start() for i in range(og + 1): Bezier_points.append(encodeData(BezierPnts[i])) timer2list.Stop() if func2 and draw_surf: pmat = func2(pts) pmat = pmat.reshape(-1, og + 1, 2) timermult.Start() BezierPnts = np.tensordot(iBvals.NumPy(), pmat, axes=(1, 1)) timermult.Stop() timer2list.Start() for i in range(og + 1): Bezier_points.append(encodeData(BezierPnts[i])) timer2list.Stop() d['Bezier_points'] = Bezier_points timer2.Stop() timer3.Start() ndtrig = int((og + 1) * (og + 2) / 2) if og in bezier_trig_trafos.keys(): iBvals_trig = bezier_trig_trafos[og] else: def BernsteinTrig(x, y, i, j, n): return math.factorial(n)/math.factorial(i)/math.factorial(j)/math.factorial(n-i-j) \ * x**i*y**j*(1-x-y)**(n-i-j) Bvals = ngs.Matrix(ndtrig, ndtrig) ii = 0 for ix in range(og + 1): for iy in range(og + 1 - ix): jj = 0 for jx in range(og + 1): for jy in range(og + 1 - jx): Bvals[ii, jj] = BernsteinTrig(ix / og, iy / og, jx, jy, og) jj += 1 ii += 1 iBvals_trig = Bvals.I bezier_trig_trafos[og] = iBvals_trig # Bezier_points = [ [] for i in range(ndtrig) ] Bezier_points = [] ir = ngs.IntegrationRule([(i / og, j / og) for j in range(og + 1) for i in range(og + 1 - j)], [ 0, ] * (ndtrig)) vb = [ngs.VOL, ngs.BND][mesh.dim - 2] pts = mesh.MapToAllElements(ir, vb) pmat = ngs.CoefficientFunction(func1 if draw_surf else func0)(pts) timer3minmax.Start() funcmin = np.min(pmat[:, 3]) funcmax = np.max(pmat[:, 3]) pmin = np.min(pmat[:, 0:3], axis=0) pmax = np.max(pmat[:, 0:3], axis=0) mesh_center = (pmin + pmax) / 2 mesh_radius = np.linalg.norm(pmax - pmin) / 2 timer3minmax.Stop() pmat = pmat.reshape(mesh.GetNE(vb), len(ir), 4) BezierPnts = np.tensordot(iBvals_trig.NumPy(), pmat, axes=(1, 1)) timer3list.Start() for i in range(ndtrig): Bezier_points.append(encodeData(BezierPnts[i])) timer3list.Stop() if func2 and draw_surf: pmat = ngs.CoefficientFunction(func2)(pts) pmat = pmat.reshape(mesh.GetNE(vb), len(ir), 2) funcmin = min(funcmin, np.min(pmat)) funcmax = max(funcmax, np.max(pmat)) BezierPnts = np.tensordot(iBvals_trig.NumPy(), pmat, axes=(1, 1)) if og == 1: for i in range(ndtrig): Bezier_points.append(encodeData(BezierPnts[i])) else: BezierPnts = BezierPnts.transpose( (1, 0, 2)).reshape(mesh.GetNE(vb), len(ir) // 2, 4).transpose((1, 0, 2)) for i in range(ndtrig // 2): Bezier_points.append(encodeData(BezierPnts[i])) d['Bezier_trig_points'] = Bezier_points d['mesh_center'] = list(mesh_center) d['mesh_radius'] = mesh_radius timer3.Stop() timer4.Start() if mesh.dim == 3 and draw_vol: p0 = [] p1 = [] p2 = [] p3 = [] values = [] tets = [] if order3d == 1: ir = ngs.IntegrationRule([(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)], [0] * 4) else: ir = ngs.IntegrationRule([(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0), (0.5, 0, 0), (0, 0.5, 0), (0, 0, 0.5), (0.5, 0.5, 0), (0.5, 0, 0.5), (0, 0.5, 0.5)], [0] * 10) pts = mesh.MapToAllElements(ir, ngs.VOL) pmat = func1(pts) if draw_vol else func0(pts) ne = mesh.GetNE(ngs.VOL) pmat = pmat.reshape(ne, len(ir), 4) funcmin = min(funcmin, np.min(pmat[:, :, 3])) funcmax = max(funcmax, np.max(pmat[:, :, 3])) points3d = [] for i in range(len(ir)): points3d.append(encodeData(pmat[:, i, :])) if func2 and draw_vol: pmat = func2(pts).reshape(ne, len(ir) // 2, 4) funcmin = min(funcmin, np.min(pmat)) funcmax = max(funcmax, np.max(pmat)) for i in range(len(ir) // 2): points3d.append(encodeData(pmat[:, i, :])) d['points3d'] = points3d if func: d['funcmin'] = funcmin d['funcmax'] = funcmax timer4.Stop() timer.Stop() return d
def BuildRenderData(mesh, func, order=2, draw_surf=True, draw_vol=True, deformation=None, region=True, objects=[]): timer.Start() if isinstance(deformation, ngs.CoefficientFunction) and deformation.dim == 2: deformation = ngs.CoefficientFunction((deformation, 0.0)) #TODO: handle quads and non-smooth functions #TODO: subdivision d = {} d['ngsolve_version'] = ngs.__version__ d['mesh_dim'] = mesh.dim # order = order or mesh.GetCurveOrder() if (not func) and (mesh.GetCurveOrder() == 1) and (mesh.nv == len( mesh.ngmesh.Points())): order = 1 order2d = min(order, 3) order3d = min(order, 2) d['order2d'] = order2d d['order3d'] = order3d d['draw_vol'] = func and mesh.dim == 3 and draw_vol and mesh.ne > 0 d['draw_surf'] = func and draw_surf d['objects'] = [] for obj in objects: if isinstance(obj, dict): d['objects'].append(obj) else: d['objects'].append(obj._GetWebguiData()) if isinstance(deformation, bool): d['deformation'] = deformation deformation = None func0 = None func2 = None if func and func.is_complex: d['is_complex'] = True func1 = func[0].real func2 = ngs.CoefficientFunction((func[0].imag, 0.0)) d['funcdim'] = 2 elif func and func.dim > 1: func1 = func[0] func2 = ngs.CoefficientFunction( tuple(func[i] if i < func.dim else 0.0 for i in range(1, 3))) # max 3-dimensional functions d['funcdim'] = func.dim elif func: func1 = func d['funcdim'] = 1 else: # no function at all -> we are just drawing a mesh, eval mesh element index instead mats = mesh.GetMaterials() bnds = mesh.GetBoundaries() bbnds = mesh.GetBBoundaries() nmats = len(mesh.GetMaterials()) nbnds = len(mesh.GetBoundaries()) n = max(nmats, nbnds, len(bbnds)) func1 = ngs.CoefficientFunction(list(range(n))) n_regions = [0, 0, nmats, nbnds] d['mesh_regions_2d'] = n_regions[mesh.dim] d['mesh_regions_3d'] = nmats if mesh.dim == 3 else 0 d['names'] = bnds if mesh.dim == 3 else mats d['edge_names'] = bbnds if mesh.dim == 3 else bnds d['funcdim'] = 0 func0 = func1 if func0 is None: func0 = ngs.CoefficientFunction(0.0) func1 = ngs.CoefficientFunction((ngs.x, ngs.y, ngs.z, func1)) func0 = ngs.CoefficientFunction((ngs.x, ngs.y, ngs.z, func0)) if deformation is not None: func1 += ngs.CoefficientFunction((deformation, 0.0)) func0 += ngs.CoefficientFunction((deformation, 0.0)) d['show_wireframe'] = False d['show_mesh'] = False if order2d > 0: og = order2d d['show_wireframe'] = True d['show_mesh'] = True timer2.Start() timer3Bvals.Start() # transform point-values to Bernsteinbasis def Binomial(n, i): return math.factorial(n) / math.factorial(i) / math.factorial(n - i) def Bernstein(x, i, n): return Binomial(n, i) * x**i * (1 - x)**(n - i) Bvals = ngs.Matrix(og + 1, og + 1) for i in range(og + 1): for j in range(og + 1): Bvals[i, j] = Bernstein(i / og, j, og) iBvals = Bvals.I timer3Bvals.Stop() # print (Bvals) # print (iBvals) Bezier_points = [] # TODO: Quads ipts = [(i / og, 0) for i in range(og + 1)] + [ (0, i / og) for i in range(og + 1) ] + [(i / og, 1.0 - i / og) for i in range(og + 1)] ir_trig = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) ipts = [(i / og, 0) for i in range(og + 1)] + [ (0, i / og) for i in range(og + 1) ] + [(i / og, 1.0) for i in range(og + 1)] + [(1.0, i / og) for i in range(og + 1)] ir_quad = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) vb = [ngs.VOL, ngs.BND][mesh.dim - 2] if region and region.VB() == vb: vb = region cf = func1 if draw_surf else func0 timer2map.Start() pts = mesh.MapToAllElements( { ngs.ET.TRIG: ir_trig, ngs.ET.QUAD: ir_quad }, vb) timer2map.Stop() pmat = cf(pts) pmima = updatePMinMax(pmat) timermult.Start() pmat = pmat.reshape(-1, og + 1, 4) if False: BezierPnts = np.tensordot(iBvals.NumPy(), pmat, axes=(1, 1)) else: BezierPnts = np.zeros((og + 1, pmat.shape[0], 4)) for i in range(4): ngsmat = ngs.Matrix(pmat[:, :, i].transpose()) BezierPnts[:, :, i] = iBvals * ngsmat timermult.Stop() timer2list.Start() for i in range(og + 1): Bezier_points.append(encodeData(BezierPnts[i])) timer2list.Stop() if func2 and draw_surf: pmat = func2(pts) pmat = pmat.reshape(-1, og + 1, 2) timermult.Start() BezierPnts = np.tensordot(iBvals.NumPy(), pmat, axes=(1, 1)) timermult.Stop() timer2list.Start() for i in range(og + 1): Bezier_points.append(encodeData(BezierPnts[i])) timer2list.Stop() d['Bezier_points'] = Bezier_points ipts = [(i / og, 0) for i in range(og + 1)] ir_seg = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) vb = [ngs.VOL, ngs.BND, ngs.BBND][mesh.dim - 1] if region and region.VB() == vb: vb = region pts = mesh.MapToAllElements(ir_seg, vb) pmat = func0(pts) pmima = updatePMinMax(pmat) pmat = pmat.reshape(-1, og + 1, 4) edge_data = np.tensordot(iBvals.NumPy(), pmat, axes=(1, 1)) edges = [] for i in range(og + 1): edges.append(encodeData(edge_data[i])) d['edges'] = edges timer2.Stop() timer3.Start() ndtrig = int((og + 1) * (og + 2) / 2) if og in bezier_trig_trafos.keys(): iBvals_trig = bezier_trig_trafos[og] else: def BernsteinTrig(x, y, i, j, n): return math.factorial(n)/math.factorial(i)/math.factorial(j)/math.factorial(n-i-j) \ * x**i*y**j*(1-x-y)**(n-i-j) Bvals = ngs.Matrix(ndtrig, ndtrig) ii = 0 for ix in range(og + 1): for iy in range(og + 1 - ix): jj = 0 for jx in range(og + 1): for jy in range(og + 1 - jx): Bvals[ii, jj] = BernsteinTrig(ix / og, iy / og, jx, jy, og) jj += 1 ii += 1 iBvals_trig = Bvals.I bezier_trig_trafos[og] = iBvals_trig # Bezier_points = [ [] for i in range(ndtrig) ] Bezier_points = [] ipts = [(i / og, j / og) for j in range(og + 1) for i in range(og + 1 - j)] ir_trig = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) ipts = ([(i / og, j / og) for j in range(og + 1) for i in range(og + 1 - j)] + [(1 - i / og, 1 - j / og) for j in range(og + 1) for i in range(og + 1 - j)]) ir_quad = ngs.IntegrationRule(ipts, [ 0, ] * len(ipts)) vb = [ngs.VOL, ngs.BND][mesh.dim - 2] if region and region.VB() == vb: vb = region pts = mesh.MapToAllElements( { ngs.ET.TRIG: ir_trig, ngs.ET.QUAD: ir_quad }, vb) pmat = ngs.CoefficientFunction(func1 if draw_surf else func0)(pts) timer3minmax.Start() pmima = updatePMinMax(pmat, pmima) funcmin, funcmax = getMinMax(pmat[:, 3]) timer3minmax.Stop() pmin, pmax = [ngs.Vector(p) for p in zip(*pmima)] mesh_center = 0.5 * (pmin + pmax) mesh_radius = np.linalg.norm(pmax - pmin) / 2 pmat = pmat.reshape(-1, len(ir_trig), 4) if False: timer3multnumpy.Start() BezierPnts = np.tensordot(iBvals_trig.NumPy(), pmat, axes=(1, 1)) timer3multnumpy.Stop() else: timer3multngs.Start() BezierPnts = np.zeros((len(ir_trig), pmat.shape[0], 4)) for i in range(4): ngsmat = ngs.Matrix(pmat[:, :, i].transpose()) BezierPnts[:, :, i] = iBvals_trig * ngsmat timer3multngs.Stop() timer3list.Start() for i in range(ndtrig): Bezier_points.append(encodeData(BezierPnts[i])) timer3list.Stop() if func2 and draw_surf: pmat = ngs.CoefficientFunction(func2)(pts) pmat = pmat.reshape(-1, len(ir_trig), 2) funcmin, funcmax = getMinMax(pmat.flatten(), funcmin, funcmax) BezierPnts = np.tensordot(iBvals_trig.NumPy(), pmat, axes=(1, 1)) if og == 1: for i in range(ndtrig): Bezier_points.append(encodeData(BezierPnts[i])) else: BezierPnts = BezierPnts.transpose( (1, 0, 2)).reshape(-1, len(ir_trig) // 2, 4).transpose( (1, 0, 2)) for i in range(ndtrig // 2): Bezier_points.append(encodeData(BezierPnts[i])) d['Bezier_trig_points'] = Bezier_points d['mesh_center'] = list(mesh_center) d['mesh_radius'] = mesh_radius timer3.Stop() timer4.Start() if d['draw_vol']: p0 = [] p1 = [] p2 = [] p3 = [] values = [] tets = [] midpoint = lambda p0, p1: tuple( (0.5 * (p0[i] + p1[i]) for i in range(3))) def makeP2Tets(p1_tets): p2_tets = [] for tet in p1_tets: tet.append(midpoint(tet[0], tet[3])) tet.append(midpoint(tet[1], tet[3])) tet.append(midpoint(tet[2], tet[3])) tet.append(midpoint(tet[0], tet[1])) tet.append(midpoint(tet[0], tet[2])) tet.append(midpoint(tet[1], tet[2])) p2_tets.append(tet) return p2_tets # divide any element into tets p1_tets = {} p1_tets[ngs.ET.TET] = [[(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)]] p1_tets[ngs.ET.PYRAMID] = [[(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)], [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0)]] p1_tets[ngs.ET.PRISM] = [[(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)], [(0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0)], [(1, 0, 1), (0, 1, 1), (1, 0, 0), (0, 0, 1)]] p1_tets[ngs.ET.HEX] = [[(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)], [(0, 1, 1), (1, 1, 1), (1, 1, 0), (1, 0, 1)], [(1, 0, 1), (0, 1, 1), (1, 0, 0), (0, 0, 1)], [(0, 1, 1), (1, 1, 0), (0, 1, 0), (1, 0, 0)], [(0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0)], [(1, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 0)]] intrules = {} for eltype in p1_tets: points = p1_tets[eltype] if order3d > 1: points = makeP2Tets(points) intrules[eltype] = ngs.IntegrationRule(sum(points, [])) pts = mesh.MapToAllElements(intrules, ngs.VOL) pmat = func1(pts) np_per_tet = len(intrules[ngs.ET.TET]) ne = mesh.GetNE(ngs.VOL) pmat = pmat.reshape(-1, np_per_tet, 4) funcmin, funcmax = getMinMax(pmat[:, :, 3].flatten(), funcmin, funcmax) points3d = [] for i in range(np_per_tet): points3d.append(encodeData(pmat[:, i, :])) if func2: pmat = func2(pts).reshape(-1, np_per_tet // 2, 4) funcmin, funcmax = getMinMax(pmat.flatten(), funcmin, funcmax) for i in range(np_per_tet // 2): points3d.append(encodeData(pmat[:, i, :])) d['points3d'] = points3d if func: d['funcmin'] = funcmin d['funcmax'] = funcmax timer4.Stop() timer.Stop() return d