def gen_3dbeam(maxh, nref, comm, lens=[10, 1, 1]): b = csg.OrthoBrick(csg.Pnt(-1, 0, 0), csg.Pnt(lens[0], lens[1], lens[2])).bc("other") p = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(-1, 0, 0)).bc("left") geo = csg.CSGeometry() geo.Add(b * p) return gen_ref_mesh(geo, maxh, nref, comm)
def __init__(self, pointa, pointb, *, eps=csg_eps): eps *= numpy.linalg.norm(numpy.array(pointb) - numpy.array(pointa)) super().__init__( netgen_csg.OrthoBrick(netgen_csg.Pnt(*pointa), netgen_csg.Pnt(*pointb)), csg_boundaries=[ dolfin.CompiledSubDomain('on_boundary && near(x[0], xx, eps)', xx=pointa[0], eps=eps), dolfin.CompiledSubDomain('on_boundary && near(x[0], xx, eps)', xx=pointb[0], eps=eps), dolfin.CompiledSubDomain('on_boundary && near(x[1], xx, eps)', xx=pointa[1], eps=eps), dolfin.CompiledSubDomain('on_boundary && near(x[1], xx, eps)', xx=pointb[1], eps=eps), dolfin.CompiledSubDomain('on_boundary && near(x[2], xx, eps)', xx=pointa[2], eps=eps), dolfin.CompiledSubDomain('on_boundary && near(x[2], xx, eps)', xx=pointb[2], eps=eps) ])
def test_pickle_mesh(): import netgen.csg as csg geo = csg.CSGeometry() brick = csg.OrthoBrick(csg.Pnt(-3, -3, -3), csg.Pnt(3, 3, 3)) mesh = geo.GenerateMesh(maxh=0.2) assert geo == mesh.GetGeometry() dump = pickle.dumps([geo, mesh]) geo2, mesh2 = pickle.loads(dump) assert geo2 == mesh2.GetGeometry() mesh.Save("msh1.vol.gz") mesh2.Save("msh2.vol.gz") import filecmp, os assert filecmp.cmp("msh1.vol.gz", "msh2.vol.gz") os.remove("msh1.vol.gz") os.remove("msh2.vol.gz")
def cube_geo(): origin = csg.Pnt(0, 0, 0) side = 1 box = csg.OrthoBrick(origin, csg.Pnt(side, 2 * side, side)).bc('cube_outer') normal_vec = csg.Vec(0, 1, 0) topplane = csg.Plane(csg.Pnt(0, 1, 0), normal_vec).bc('dirichlet') cube = (box * topplane).mat('cube_mat') cube_geom = csg.CSGeometry() cube_geom.Add(cube) return cube_geom
def test_pickle_surface_fespaces(): import netgen.meshing as meshing import netgen.csg as csg geo = csg.CSGeometry() bottom = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(0, 0, 1)) surface = csg.SplineSurface(bottom) pts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)] geopts = [surface.AddPoint(*p) for p in pts] for p1, p2, bc in [(0, 1, "left"), (1, 2, "top"), (2, 3, "right"), (3, 0, "bottom")]: surface.AddSegment(geopts[p1], geopts[p2], bc) geo.AddSplineSurface(surface) mesh = Mesh( geo.GenerateMesh(maxh=0.3, perfstepsend=meshing.MeshingStep.MESHSURFACE)) spaces = [ HDivDivSurface(mesh, order=3, dirichlet=[1, 2, 3, 4]), FacetSurface(mesh, order=3, dirichlet=[1, 2, 3, 4]), HDivSurface(mesh, order=3, dirichlet=[1, 2, 3, 4]) ] for space in spaces: with io.BytesIO() as f: pickler = pickle.Pickler(f) pickler.dump(space) data = f.getvalue() with io.BytesIO(data) as f: unpickler = pickle.Unpickler(f) space2 = unpickler.load() assert space.ndof == space2.ndof
def test_SurfaceGetFE(quads=False): # 2d surface in 3d tests import netgen.meshing as meshing import netgen.csg as csg geo = csg.CSGeometry() bottom = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(0, 0, 1)) surface = csg.SplineSurface(bottom) pts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)] geopts = [surface.AddPoint(*p) for p in pts] for p1, p2, bc in [(0, 1, "left"), (1, 2, "top"), (2, 3, "right"), (3, 0, "bottom")]: surface.AddSegment(geopts[p1], geopts[p2], bc) geo.AddSplineSurface(surface) mesh = Mesh( geo.GenerateMesh(perfstepsend=meshing.MeshingStep.MESHSURFACE, quad=quads)) for spacename in surfacespaces.keys(): if quads and spaces2d[spacename]["quad"]: for order in surfacespaces[spacename]["order"]: space = FESpace(type=spacename, mesh=mesh, order=order) for vb in surfacespaces[spacename]["vorb"]: for el in space.Elements(vb): assert space.GetFE(el).ndof == len( space.GetDofNrs(el)), [spacename, vb, order] return
def __init__(self, pointa, pointb, radius, *, eps=csg_eps): unit = 1. * numpy.array(pointb) - numpy.array(pointa) unit /= numpy.linalg.norm(unit) eps *= radius super().__init__( netgen_csg.Cylinder(netgen_csg.Pnt(*pointa), netgen_csg.Pnt(*pointb), radius), csg_boundaries=[ dolfin.CompiledSubDomain( 'on_boundary && near((x[0]-p0)*(x[0]-p0) + (x[1]-p1)*(x[1]-p1) + (x[2]-p2)*(x[2]-p2) - ((x[0]-p0)*u0 + (x[1]-p1)*u1 + (x[2]-p2)*u2)*((x[0]-p0)*u0 + (x[1]-p1)*u1 + (x[2]-p2)*u2), rr, eps)', u0=unit[0], u1=unit[1], u2=unit[2], p0=pointa[0], p1=pointa[1], p2=pointa[2], rr=radius * radius, eps=eps) ])
def __init__(self, center, radius, *, eps=csg_eps): eps *= radius super().__init__( netgen_csg.Sphere(netgen_csg.Pnt(*center), radius), csg_boundaries=[ dolfin.CompiledSubDomain( 'on_boundary && near((x[0]-c0)*(x[0]-c0) + (x[1]-c1)*(x[1]-c1) + (x[2]-c2)*(x[2]-c2), rr, eps)', c0=center[0], c1=center[1], c2=center[2], rr=radius * radius, eps=eps) ])
def __init__(self, zero, normal, *, eps=csg_eps): value = numpy.array(zero).dot(numpy.array(normal)) super().__init__( netgen_csg.Plane(netgen_csg.Pnt(*zero), netgen_csg.Vec(*normal)), csg_boundaries=[ dolfin.CompiledSubDomain( 'on_boundary && near(x[0]*n0 + x[1]*n1 + x[2]*n2, value, eps)', n0=normal[0], n1=normal[1], n2=normal[2], value=value, eps=eps) ])
def save(cls, network, phases=[], filename='', maxsize='auto', fileformat='STL Format', logger_level=0): r""" Saves (transient/steady-state) data from the given objects into the specified file. Parameters ---------- network : OpenPNM Network Object. The network containing the desired data. phases : list of OpenPNM Phase Objects (place holder, default is none). filename : string (optional). The name of the file containing the data to export. maxsize : a float or a string "auto" (optional). The maximum size of the mesh elements allowed. "auto" corresponds to an automatic determination based on pores and throats sizes. Any float value will be used as a maximum size. Small values result in finner meshes, but slower mesh calculations. fileformat : string (optional). Default is "STL Format" which corresponds to STL format. Other formats such as Gmsh and Fluent are supported (see ngsolve.org). logger_level : integer between 0 and 7 (optional). Default is 0. The logger level set in netgen package. Notes ----- This method only saves the geometry of the network, not any of the pore-scale models or other attributes. To save an actual OpenPNM Project use the ``Workspace`` object. """ try: import netgen.csg as csg except ModuleNotFoundError: logger.error('Module "netgen.csg" not found.') try: from netgen.meshing import SetMessageImportance as log log(logger_level) except ModuleNotFoundError: logger.warning('Module "netgen.meshing" not found. ' + 'The "logger_level" ignored.') project, network, phases = cls._parse_args(network=network, phases=phases) network = network[0] if filename == '': filename = project.name path = cls._parse_filename(filename=filename, ext='stl') # Path is a pathlib object, so slice it up as needed fname_stl = path.name # correct connections where 'pore.diameter' = 'throat.diameter' dt = network['throat.diameter'].copy() dp = network['pore.diameter'][network['throat.conns']] dt[dp[:, 0] == dt] *= 0.99 dt[dp[:, 1] == dt] *= 0.99 scale = max(network['pore.diameter'].max(), dt.max(), network['throat.length'].max()) if maxsize == 'auto': maxsize = min(network['pore.diameter'].min(), dt.min(), network['throat.length'].min()) geo = csg.CSGeometry() # define pores geometry = csg.Sphere( csg.Pnt(network['pore.coords'][0, 0] / scale, network['pore.coords'][0, 1] / scale, network['pore.coords'][0, 2] / scale), network['pore.diameter'][0] / scale / 2) for p in range(1, network.Np): pore = csg.Sphere( csg.Pnt(network['pore.coords'][p, 0] / scale, network['pore.coords'][p, 1] / scale, network['pore.coords'][p, 2] / scale), network['pore.diameter'][p] / scale / 2) geometry += pore # define throats for t in range(network.Nt): A = network['throat.endpoints.tail'][t, :] / scale B = network['throat.endpoints.head'][t, :] / scale V = (B - A) / _np.linalg.norm(B - A) plane1 = csg.Plane(csg.Pnt(A[0], A[1], A[2]), csg.Vec(-V[0], -V[1], -V[2])) plane2 = csg.Plane(csg.Pnt(B[0], B[1], B[2]), csg.Vec(V[0], V[1], V[2])) cylinder = csg.Cylinder(csg.Pnt(A[0], A[1], A[2]), csg.Pnt(B[0], B[1], B[2]), dt[t] / scale / 2) throat = cylinder * plane1 * plane2 geometry += throat # add pore and throats to geometry, build mesh, rescale, and export geo.Add(geometry) mesh = geo.GenerateMesh(maxh=maxsize / scale) mesh.Scale(scale) mesh.Export(filename=fname_stl, format=fileformat)
def test_pickle_csg(): import netgen.csg as csg geo = csg.CSGeometry() geo.Add(csg.Sphere(csg.Pnt(0, 0, 0), 2).bc("sphere")) brick = csg.OrthoBrick(csg.Pnt(-3, -3, -3), csg.Pnt(3, 3, 3)) geo.Add(csg.Cylinder(csg.Pnt(0, 0, 0), csg.Pnt(1, 0, 0), 0.5) * brick) geo.Add( csg.Ellipsoid(csg.Pnt(0, 0, 0), csg.Vec(1, 0, 0), csg.Vec(0, 1, 0), csg.Vec(0, 0, 0.5))) geo.Add(csg.Cone(csg.Pnt(0, 0, 0), csg.Pnt(3, 0, 0), 1, 0.5) * brick) geo.Add( csg.EllipticCone(csg.Pnt(0, 0, 0), csg.Vec(2, 0, 0), csg.Vec(0, 1, 0), 3, 0.5) * brick) geo.Add(csg.Torus(csg.Pnt(0, 0, 0), csg.Vec(0, 1, 0), 0.3, 0.05)) pts2d = [[1, 1], [1, -1], [-1, -1], [-1, 1]] segs = [[0, 1], [1, 2], [2, 3], [3, 0]] curve = csg.SplineCurve2d() pnrs = [curve.AddPoint(*p) for p in pts2d] for s in segs: curve.AddSegment(pnrs[s[0]], pnrs[s[1]]) geo.Add(csg.Revolution(csg.Pnt(0, 0, 0), csg.Pnt(1, 0, 0), curve)) path = csg.SplineCurve3d() pnts = [(0, 0, 0), (2, 0, 0), (2, 2, 0)] segs = [(0, 1, 2)] for pnt in pnts: path.AddPoint(*pnt) for seg in segs: path.AddSegment(*seg) geo.Add(csg.Extrusion(path, curve, csg.Vec(0, 0, 1))) geo_dump = pickle.dumps(geo) geo2 = pickle.loads(geo_dump) vd1 = geo._visualizationData() vd2 = geo2._visualizationData() for val1, val2 in zip(vd1.values(), vd2.values()): assert numpy.array_equal(val1, val2)
def get_Netgen_nonconformal(N, scale, offset, dim=2): """ Generate a structured quadrilateral/hexahedral NGSolve mesh over a prescribed square/cubic domain. Args: N (list): Number of mesh elements in each direction (N+1 nodes). scale (list): Extent of the meshed domain in each direction ([-2,2] square -> scale=[4,4]). offset (list): Centers the meshed domain in each direction ([-2,2] square -> offset=[2,2]). dim (int): Dimension of the domain (must be 2 or 3). Returns: mesh (Netgen mesh): Structured quadrilateral/hexahedral Netgen mesh. """ # Construct a Netgen mesh. ngmesh = ngmsh.Mesh() if dim == 2: ngmesh.SetGeometry(unit_square) ngmesh.dim = 2 # Set evenly spaced mesh nodes. points = [] for i in range(N[1] + 1): for j in range(N[0] + 1): x = -offset[0] + scale[0] * j / N[0] y = -offset[1] + scale[1] * i / N[1] z = 0 points.append(ngmesh.Add(ngmsh.MeshPoint(ngmsh.Pnt(x, y, z)))) # TODO: Should the user be able to set their own BC names? idx_dom = ngmesh.AddRegion('dom', dim=2) idx_bottom = ngmesh.AddRegion('bottom', dim=1) idx_right = ngmesh.AddRegion('right', dim=1) idx_top = ngmesh.AddRegion('top', dim=1) idx_left = ngmesh.AddRegion('left', dim=1) # Generate mesh faces. for i in range(N[1]): for j in range(N[0]): p1 = i * (N[0] + 1) + j p2 = i * (N[0] + 1) + j + 1 p3 = i * (N[0] + 1) + j + 2 + N[0] p4 = i * (N[0] + 1) + j + 1 + N[0] ngmesh.Add(ngmsh.Element2D(idx_dom, [points[p1], points[p2], points[p3], points[p4]])) # Assign each edge of the domain to the same boundary. for i in range(N[1]): ngmesh.Add(ngmsh.Element1D([points[N[0] + i * (N[0] + 1)], points[N[0] + (i + 1) * (N[0] + 1)]], index=idx_right)) ngmesh.Add(ngmsh.Element1D([points[(i + 1) * (N[0] + 1)], points[i * (N[0] + 1)]], index=idx_left)) for i in range(N[0]): ngmesh.Add(ngmsh.Element1D([points[i], points[i + 1]], index=idx_bottom)) ngmesh.Add(ngmsh.Element1D([points[1 + i + N[1] * (N[0] + 1)], points[i + N[1] * (N[0] + 1)]], index=idx_top)) elif dim == 3: ngmesh.dim = 3 p1 = (0, 0, 0) p2 = (1, 1, 1) cube = ngcsg.OrthoBrick(ngcsg.Pnt(p1[0], p1[1], p1[2]), ngcsg.Pnt(p2[0], p2[1], p2[2])).bc(1) geo = ngcsg.CSGeometry() geo.Add(cube) ngmesh.SetGeometry(geo) # Set evenly spaced mesh nodes. points = [] for i in range(N[0] + 1): for j in range(N[1] + 1): for k in range(N[2] + 1): x = -offset[0] + scale[0] * i / N[0] y = -offset[1] + scale[1] * j / N[1] z = -offset[2] + scale[2] * k / N[2] points.append(ngmesh.Add(ngmsh.MeshPoint(ngmsh.Pnt(x, y, z)))) # Generate mesh cells. for i in range(N[0]): for j in range(N[1]): for k in range(N[2]): base = i * (N[1] + 1) * (N[2] + 1) + j * (N[2] + 1) + k baseup = base + (N[1] + 1) * (N[2] + 1) p1 = base p2 = base + 1 p3 = base + (N[2] + 1) + 1 p4 = base + (N[2] + 1) p5 = baseup p6 = baseup + 1 p7 = baseup + (N[2] + 1) + 1 p8 = baseup + (N[2] + 1) idx = 1 ngmesh.Add(ngmsh.Element3D(idx, [points[p1], points[p2], points[p3], points[p4], points[p5], points[p6], points[p7], points[p8]])) def add_bc(p, d, N, deta, neta, facenr): def add_seg(i, j, os): base = p + i * d + j * deta p1 = base p2 = base + os ngmesh.Add(ngmsh.Element1D([points[p1], points[p2]], index=facenr)) return for i in range(N): for j in [0, neta]: add_seg(i, j, d) for i in [0, N]: for j in range(neta): add_seg(i, j, deta) for i in range(N): for j in range(neta): base = p + i * d + j * deta p1 = base p2 = base + d p3 = base + d + deta p4 = base + deta ngmesh.Add(ngmsh.Element2D(facenr, [points[p1], points[p2], points[p3], points[p4]])) return # Order is important! ngmesh.Add(ngmsh.FaceDescriptor(surfnr=4, domin=1, bc=1)) ngmesh.Add(ngmsh.FaceDescriptor(surfnr=2, domin=1, bc=2)) ngmesh.Add(ngmsh.FaceDescriptor(surfnr=5, domin=1, bc=3)) ngmesh.Add(ngmsh.FaceDescriptor(surfnr=3, domin=1, bc=4)) ngmesh.Add(ngmsh.FaceDescriptor(surfnr=0, domin=1, bc=5)) ngmesh.Add(ngmsh.FaceDescriptor(surfnr=1, domin=1, bc=6)) # Assign each exterior face of the domain to its respective boundary. add_bc(0, 1, N[2], N[2] + 1, N[1], 1) add_bc(0, (N[1] + 1) * (N[2] + 1), N[0], 1, N[2], 2) add_bc((N[0] + 1) * (N[1] + 1) * (N[2] + 1) - 1, -(N[2] + 1), N[1], -1, N[2], 3) add_bc((N[0] + 1) * (N[1] + 1) * (N[2] + 1) - 1, -1, N[2], -(N[1] + 1) * (N[2] + 1), N[0], 4) add_bc(0, N[2] + 1, N[1], (N[1] + 1) * (N[2] + 1), N[0], 5) add_bc((N[0] + 1) * (N[1] + 1) * (N[2] + 1) - 1, -(N[1] + 1) * (N[2] + 1), N[0], -(N[2] + 1), N[1], 6) # TODO: Should the user be able to specify their own bc names? bc_names = {0: 'back', 1: 'left', 2: 'front', 3: 'right', 4: 'bottom', 5: 'top'} for key, val in bc_names.items(): ngmesh.SetBCName(key, val) else: raise ValueError('Only works with 2D or 3D meshes.') return ngmesh
def hinges_3d(N=4, touch=True): geo = csg.CSGeometry() plane_left = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(-1, 0, 0)).bc("left") plane_right = csg.Plane(csg.Pnt(1, 0, 0), csg.Vec(1, 0, 0)).bc("outer") plane_bot = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(0, -1, 0)).bc("outer") plane_top = csg.Plane(csg.Pnt(0, 1, 0), csg.Vec(0, 1, 0)).bc("outer") plane_back = csg.Plane(csg.Pnt(0, 0, 0), csg.Vec(0, 0, -1)).bc("outer") plane_front = csg.Plane(csg.Pnt(0, 0, 1), csg.Vec(0, 0, 1)).bc("outer") box = csg.OrthoBrick(csg.Pnt(-0.1, -0.1, -0.1), csg.Pnt(1, 1, 1)).mat("mat_a").bc("outer") # N hinges, so N+1 boxes, or N+2 if we do not want to touch diri h = 1 / (N + 1) hinges = list() if touch: h0 = csg.OrthoBrick(csg.Pnt(-0.1, -0.1, -0.1), csg.Pnt(h, h, 1.1)).mat("mat_b").bc("inner") hinges.append(h0) rmin = 1 rmax = N hinges = hinges + [ csg.OrthoBrick(csg.Pnt(k * h, k * h, -0.1), csg.Pnt((k + 1) * h, (k + 1) * h, 1.1)).mat("mat_b").bc("inner") for k in range(rmin, rmax) ] hl = csg.OrthoBrick(csg.Pnt(N * h, N * h, -0.1), csg.Pnt(1.1, 1.1, 1.1)).mat("mat_b").bc("inner") hinges.append(hl) bmh = box - hinges[0] hs = hinges[0] for h in hinges[1:]: hs = hs + h bmh = bmh - h geo.Add(bmh * plane_left * plane_right * plane_bot * plane_top * plane_back * plane_front) geo.Add(hs * plane_left * plane_right * plane_bot * plane_top * plane_back * plane_front) return geo