def visualize(self, U, m, legend=None, separate_colorbars=True, block=True): """Visualize the provided data.""" if isinstance(U, VectorArrayInterface): U = (U, ) assert all(u in self.space for u in U) if any(len(u) != 1 for u in U): raise NotImplementedError if any(u._list[0].imag_part is not None for u in U): raise NotImplementedError if legend is None: legend = [f'VectorArray{i}' for i in range(len(U))] if isinstance(legend, str): legend = [legend] assert len(legend) == len(U) legend = [l.replace(' ', '_') for l in legend] # NGSolve GUI will fail otherwise if not separate_colorbars: raise NotImplementedError for u, name in zip(U, legend): ngs.Draw(u._list[0].real_part.impl, self.mesh, name=name)
def Draw(scene, *args, **kwargs): if _headless: scene.initGL() scene.update() return scene else: import ngsolve ngsolve.Draw(scene, *args, **kwargs) ngsolve.Redraw(blocking=True)
def _generateMesh(self, *args): from netgen.csg import CSGeometry, Sphere, Pnt from ngsolve import Mesh r = self.getRadius() geometry = CSGeometry() sphere = Sphere(Pnt(0, 0, 0), r).bc("sphere") geometry.Add(sphere) self.geometry = geometry self.mesh = Mesh(geometry.GenerateMesh(maxh=r / 5)) ngsolve.Draw(self.mesh)
def loadMeshFile(): filename, filt = QtWidgets.QFileDialog.getOpenFileName(caption = "Load Mesh", filter = "Netgen mesh file (*.vol *.vol.gz);; Neutral format (*.mesh *.emt);; Surface format (*.surf);; Universal format (*.unv);; Olaf format (*.emt);; TET format (*.tet);; STL format (*.stl *.stlb);; Pro/ENGINEER neutral format (*.fnf)") if filename: if filename.endswith(".vol") or filename.endswith(".vol.gz"): mesh = ngsolve.Mesh(filename) else: from netgen.meshing import ImportMesh mesh = ngsolve.Mesh(ImportMesh(filename)) ngsolve.Draw(mesh) if not self._flags.noConsole: self.console.pushVariables({"mesh" : mesh})
def _solveStep(self): # reset the boundary condition after every refinement self._gfu.Set(self._g, definedon=self._mesh.Boundaries(".*")) # draw the solution if the gui is open if self.show_gui: ngs.Draw(self._gfu) # assamble the bilinear form self._a.Assemble() # assamble the linear functional self._f.Assemble() # solve the boundary value problem iteratively # if the solution does not converge, this is the first place to look ngs.solvers.BVP(bf=self._a, lf=self._f, gf=self._gfu, pre=self._c) if self.show_gui: ngs.Redraw(blocking=True)
def run(): while True: val = self.to_draw.get() if val is None: break what, values = val while what == 'redraw': try: val = self.to_draw.get(False) logger.debug("throw away redraw signal") except: break what, values = val if what == "draw": index, args, kwargs = values scene = ngsolve.Draw(*args, **kwargs) self._ngs_plugin.switch_to_plugin() scene._redraw_index = index self.index_table[index] = weakref.ref(scene) elif what == "set_scene_item": index, name, val = values logger.debug("Receive set {} of scene {} to {}".format( name, index, val)) scene = self.getScene(index) if scene: setattr(scene, name, val) elif what == "call_scene_item": index, name, args, kwargs = values logger.debug( "Receive call {} of scene {} with args {} and kwargs {}" .format(name, index, args, kwargs)) scene = self.getScene(index) if scene: getattr(scene, name)(*args, **kwargs) else: assert what == "redraw" widget = G.gui.window_tabber.activeGLWindow.glWidget state = widget.blockSignals(True) for scene in widget.scenes: if hasattr(scene, "_redraw_index"): scene.update(*(values[scene._redraw_index])) widget.blockSignals(state) widget.updateGL() self.to_draw.task_done()
def loadGeometryFile(): filename, filt = QtWidgets.QFileDialog.getOpenFileName(caption = "Load Geometry", filter = "Geometry file (*.in2d *.geo *.step *.stp *.iges *.stl *.stlb)") if filename: if filename.endswith(".in2d"): import netgen.geom2d as gm geo = gm.SplineGeometry(filename) elif filename.endswith(".geo"): import netgen.csg as gm geo = gm.CSGeometry(filename) elif filename.endswith(".step") or filename.endswith(".stp") or filename.endswith(".iges"): import netgen.occ as gm geo = gm.OCCGeometry(filename) else: import netgen.stl as gm geo = gm.STLGeometry(filename) ngsolve.Draw(geo) if not self._flags.noConsole: self.console.pushVariables({"geo" : geo})
def Solve(a, f, c, ms=100): ngs.ngsglobals.msg_level = 5 gfu = ngs.GridFunction(a.space) with ngs.TaskManager(): a.Assemble() f.Assemble() ngs.ngsglobals.msg_level = 5 if c is None: c = a.mat.Inverse(V.FreeDofs()) else: c.Test() cb = None if a.space.mesh.comm.rank != 0 else lambda k, x: print( "it =", k, ", err =", x) cg = ngs.krylovspace.CGSolver(mat=a.mat, pre=c, callback=cb, maxsteps=ms, tol=1e-6) cg.Solve(sol=gfu.vec, rhs=f.vec) print("used nits = ", cg.iterations) ngsolve.Draw(mesh, deformation=ngsolve.CoefficientFunction( (gfu[0], gfu[1], 0)))
fes = ngs.H1(mesh, dirichlet=[1, 2, 3], order=1) u = fes.TrialFunction() v = fes.TestFunction() # rhs f = ngs.LinearForm(fes) f += ngs.SymbolicLFI(v) # lhs a = ngs.BilinearForm(fes, symmetric=True) a += ngs.SymbolicBFI(grad(u) * grad(v)) c = ngs.Preconditioner(a, 'h1amg', test=True) gfu = ngs.GridFunction(fes) bvp = ngs.BVP(bf=a, lf=f, gf=gfu, pre=c) while True: fes.Update() gfu.Update() a.Assemble() f.Assemble() bvp.Do() ngs.Draw(gfu, mesh, 'solution') input('Hit enter for refinement') mesh.Refine()
#"ngs_amg_max_levels" : 4, "ngs_amg_log_level": "extra", "ngs_amg_enable_sp": True, "ngs_amg_sp_max_per_row": 4, "ngs_amg_enable_redist": True, "ngs_amg_first_aaf": 0.025 } gfu = ngsolve.GridFunction(V) a.Assemble() f.Assemble() gfu.vec.data = a.mat.Inverse(V.FreeDofs()) * f.vec #ngsolve.Draw(mesh, deformation = ngsolve.CoefficientFunction((gfu[0], gfu[1], gfu[2])), name="defo") ngsolve.Draw(mesh, deformation=ngsolve.CoefficientFunction((gfu[0], gfu[1])), name="defo") ngsolve.Draw(gfu[2], mesh, name="rot") # for i in range(6): # ngsolve.Draw(gfu[i], mesh, name="comp_"+str(i)) # ngsolve.Draw(gfu, name="sol") # # c = ngsolve.Preconditioner(a, "ngs_amg.elast3d", **pc_opts) c = ngs_amg.elast_3d(a, **pc_opts) pt = 0 #100 * 1024 * 1024 with ngsolve.TaskManager(pajetrace=pt): Solve(a, f, c, ms=40) # if ngsolve.mpi_world.rank == 1: #SetNumThreads(5)
init_gfu.Set(init) init_solution = init_gfu.vec.FV().NumPy().copy() init_data = op(init_solution) setting = HilbertSpaceSetting(op=op, Hdomain=L2, Hcodomain=Sobolev) landweber = Landweber(setting, data, init_solution, stepsize=1) stoprule = (rules.CountIterations(1000) + rules.Discrepancy(setting.Hcodomain.norm, data, noiselevel=setting.Hcodomain.norm(noise), tau=1.1)) reco, reco_data = landweber.run(stoprule) ngs.Draw(exact_solution_coeff, op.fes_domain.mesh, "exact") ngs.Draw(init, op.fes_domain.mesh, "init") # Draw recondtructed solution gfu_reco = ngs.GridFunction(op.fes_domain) gfu_reco.vec.FV().NumPy()[:] = reco coeff_reco = ngs.CoefficientFunction(gfu_reco) ngs.Draw(coeff_reco, op.fes_domain.mesh, "reco") # Draw data space gfu_data = ngs.GridFunction(op.fes_codomain) gfu_reco_data = ngs.GridFunction(op.fes_codomain) gfu_data.vec.FV().NumPy()[:] = data coeff_data = ngs.CoefficientFunction(gfu_data)
mesh.Add(Element2D(1, [pnts[0]] + pnts[2:4])) mesh.Add(Element3D(1, pnts)) return mesh def Prism(): mesh = Mesh(3) mesh.AddRegion("", 2) mesh.AddRegion("", 3) pnts = [ mesh.Add(MeshPoint(Pnt(0, 0, 0))), mesh.Add(MeshPoint(Pnt(1, 0, 0))), mesh.Add(MeshPoint(Pnt(0, 1, 0))), mesh.Add(MeshPoint(Pnt(0, 0, 1))), mesh.Add(MeshPoint(Pnt(1, 0, 1))), mesh.Add(MeshPoint(Pnt(0, 1, 1))) ] mesh.Add(Element2D(1, list(reversed(pnts[:3])))) mesh.Add(Element2D(1, pnts[3:])) mesh.Add(Element2D(1, pnts[:2] + list(reversed(pnts[3:5])))) mesh.Add(Element2D(1, pnts[1:3] + list(reversed(pnts[4:6])))) mesh.Add(Element2D(1, [pnts[2], pnts[0], pnts[3], pnts[5]])) mesh.Add(Element3D(1, list(reversed(pnts[:3])) + list(reversed(pnts[3:])))) return mesh if __name__ == "__main__": mesh = Prism() import ngsolve ngsolve.Draw(ngsolve.Mesh(mesh))
def solve(self): # disable garbage collector # --------------------------------------------------------------------# gc.disable() while (gc.isenabled()): time.sleep(0.1) # --------------------------------------------------------------------# # measure how much memory is used until here process = psutil.Process() memstart = process.memory_info().vms # starts timer tstart = time.time() if self.show_gui: import netgen.gui # create mesh with initial size 0.1 self._mesh = ngs.Mesh(unit_square.GenerateMesh(maxh=0.1)) #create finite element space self._fes = ngs.H1(self._mesh, order=2, dirichlet=".*", autoupdate=True) # test and trail function u = self._fes.TrialFunction() v = self._fes.TestFunction() # create bilinear form and enable static condensation self._a = ngs.BilinearForm(self._fes, condense=True) self._a += ngs.grad(u) * ngs.grad(v) * ngs.dx # creat linear functional and apply RHS self._f = ngs.LinearForm(self._fes) self._f += (-4) * v * ngs.dx # preconditioner: multigrid - what prerequisits must the problem have? self._c = ngs.Preconditioner(self._a, "multigrid") # create grid function that holds the solution and set the boundary to 0 self._gfu = ngs.GridFunction(self._fes, autoupdate=True) # solution self._g = self._ngs_ex self._gfu.Set(self._g, definedon=self._mesh.Boundaries(".*")) # draw grid function in gui if self.show_gui: ngs.Draw(self._gfu) # create Hcurl space for flux calculation and estimate error self._space_flux = ngs.HDiv(self._mesh, order=2, autoupdate=True) self._gf_flux = ngs.GridFunction(self._space_flux, "flux", autoupdate=True) # TaskManager starts threads that (standard thread nr is numer of cores) with ngs.TaskManager(): # this is the adaptive loop while self._fes.ndof < self.max_ndof: self._solveStep() self._estimateError() self._mesh.Refine() # since the adaptive loop stopped with a mesh refinement, the gfu must be # calculated one last time self._solveStep() if self.show_gui: ngs.Draw(self._gfu) # set measured exectution time self._exec_time = time.time() - tstart # set measured used memory memstop = process.memory_info().vms - memstart self._mem_consumption = memstop # enable garbage collector # --------------------------------------------------------------------# gc.enable() gc.collect()
(0, 0), EI(bc="bottom"), # set bc for segment (0,0)-(1,0) (1, 0), EI(bc="right"), # set bc for segment (1,0)-(1,1) (1, 1), EI(bc="top"), # set bc for segment (1,1)-(0,1) (0, 1), EI(bc="left"), # set bc for segment (0,1)-(0,0) ], mat="rect") circle = Circle(center=(0.5, 0.5), radius=R, mat="mat2", bc="circle") geo.Add(rect - circle) ngmesh = geo.GenerateMesh(maxh=0.4) mesh = ng.Mesh(ngmesh) mesh.Curve(order) ng.Draw(mesh) datafile = open('TemperatureDevelopment.dat', 'w') """Let's start with some functions and parameters needed for the whole model""" T_0 = ng.CoefficientFunction(300.) T_ref = ng.CoefficientFunction(293.) V0 = ng.CoefficientFunction(.1) # set boundary value of electrode to 10 V f = ng.CoefficientFunction(0.0) rho_0 = ng.CoefficientFunction(1.754e-8) # reference resistivity C_p = ng.CoefficientFunction(340.) # heat capacity rho = ng.CoefficientFunction(8930.) # density [kg/m^3] k_iso = ng.CoefficientFunction(384.) # thermal conductivity [W/(m*K)] alpha = ng.CoefficientFunction( 3.9e-3) # coefficient for T-dependent resistivity [1/K] t_max = 2000. # time in s
return 1 / (1 + ng.exp(-x)) # vectorize the logistic function for component-wise application vσ = np.vectorize(σ) # NNet coefficient function u_net = W3.dot(vσ(W2.dot(vσ(Wx.dot(ng.x) + Wy.dot(ng.y) + b1)) + b2)) + b3 # unit square domain #mesh = Mesh(unit_square.GenerateMesh(maxh=0.2)) ngmesh = unit_square.GenerateMesh(maxh=0.2) ngmesh.Refine() #ngmesh.Refine() mesh = ng.Mesh(ngmesh) mesh.ngmesh.SetGeometry(unit_square) ng.Draw(mesh) uₕ = poisson_solve() ΔFEM = uₕ - uexact ΔNET = u_net - uexact FEM_error = ng.sqrt(ng.Integrate(ng.InnerProduct(ΔFEM, ΔFEM), mesh)) NET_error = ng.sqrt(ng.Integrate(ng.InnerProduct(ΔNET, ΔNET), mesh)) print('FEM error = ', FEM_error) print('NET_error = ', NET_error) ng.Draw(uₕ) ng.Draw(u_net, mesh, "u_net")
def _loadGeo(gui, filename): import netgen.csg as csg geo = csg.CSGeometry(filename) ngsolve.Draw(geo)
def _loadin2d(gui, filename): import netgen.geom2d as geom2d geo = geom2d.SplineGeometry(filename) ngsolve.Draw(geo)
class GenerateSphereScene(ngsgui.scenes.BaseScene): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @inmain_decorator(True) def _generateMesh(self, *args): from netgen.csg import CSGeometry, Sphere, Pnt from ngsolve import Mesh r = self.getRadius() geometry = CSGeometry() sphere = Sphere(Pnt(0, 0, 0), r).bc("sphere") geometry.Add(sphere) self.geometry = geometry self.mesh = Mesh(geometry.GenerateMesh(maxh=r / 5)) ngsolve.Draw(self.mesh) @inmain_decorator(True) def _createParameters(self): super()._createParameters() self.addParameters( "Radius", settings.ValueParameter(name="Radius", default_value=1.0)) genmesh = settings.Button(name="GenerateMesh", label="Generate mesh") genmesh.changed.connect(self._generateMesh) self.addParameters("GenerateMesh", genmesh) s = GenerateSphereScene() ngsolve.Draw(s)
print('hofrees_loc:', hofrees_loc) print('hofrees_ex:', hofrees_ex) V.FreeDofs()[10 + 15] = True #for k in hofrees_loc[0:1]: # V.FreeDofs()[k] = True import sys sys.stdout.flush() W = ngsolve.H1(mesh, order=order) gfbf = ngsolve.GridFunction(W) gfbf.vec[:] = 0 if ngsolve.mpi_world.rank == 1: gfbf.vec[10 + 15] = 1 ngsolve.Draw(mesh, name="mesh") ngsolve.Draw(gfbf, mesh, name="bf") dobft = False if dobft: while True: bf_nr = int(0) if ngsolve.mpi_world.rank == 0: bf_nr = int(input('nr ?')) print('got nr', bf_nr) bf_nr = ngsolve.mpi_world.Sum(bf_nr) if ngsolve.mpi_world.rank == 1: gfbf.vec[:] = 0 gfbf.vec[bf_nr] = 1 ngsolve.mpi_world.Barrier() ngsolve.Redraw()
y0 = 0.5 kx = 0 ky = 0 wave_packet = ngs.CoefficientFunction( exp(1j * (kx * x + ky * y)) * exp(-((x-x0)**2+(y-y0)**2)/4/delta_x**2)) gf_psi = ngs.GridFunction(fes) gf_psi.Set(wave_packet) gf_psi.vec.data = 1/ngs.Norm(gf_psi.vec) * gf_psi.vec freedofs = fes.FreeDofs() for i in range(len(gf_psi.vec)): if not freedofs[i]: gf_psi.vec[i] = 0 ngs.Draw(ngs.Norm(gf_psi), mesh, name='abs(psi)') ## Crank-Nicolson time step max_time = 1 timestep = 0.0001 t = 0 mstar = m.mat.CreateMatrix() mstar.AsVector().data = timestep / 2 * a.mat.AsVector() - m.mat.AsVector() inv = mstar.Inverse(freedofs) w = gf_psi.vec.CreateVector() du = gf_psi.vec.CreateVector() while t < max_time: t += timestep w.data = a.mat * gf_psi.vec
gf_mpi = [] middlename = 'gridfunction' for k in range(len(idx)): # Create two grid functions: One for the sequential solve, and one # for the MPI solve. sequential_name = 'sequential_' + middlename + '_{0:02d}' gf_sequential += [ ng.GridFunction(X, name=sequential_name.format(idx[k])) ] mpi_name = 'mpi_' + middlename + '_{0:02d}' gf_mpi += [ng.GridFunction(X, name=mpi_name.format(idx[k]))] # Load the grid functions from file. sequential_filename = 'outputs/' + sequential_name gf_sequential[-1].Load(sequential_filename.format(idx[k]), parallel=False) mpi_filename = 'outputs/' + mpi_name gf_mpi[-1].Load(mpi_filename.format(idx[k]), parallel=True) # Draw the grid functions. for k in range(len(idx)): ng.Draw(gf_sequential[k]) ng.Draw(gf_mpi[k]) except Exception as e: print('An error occurred:', e)
initial_potential_space = ngs.H1(mesh, order=1, dirichlet='particle|anode') phi = initial_potential_space.TrialFunction() psi = initial_potential_space.TestFunction() a_pot = ngs.BilinearForm(initial_potential_space) a_pot += ngs.SymbolicBFI(grad(phi) * grad(psi)) a_pot.Assemble() f_pot = ngs.LinearForm(initial_potential_space) # permittivity seems to be missing, but gives too high value if included f_pot += ngs.SymbolicLFI(cf_valence * cf_n0 * F * psi) f_pot.Assemble() gf_phi = ngs.GridFunction(initial_potential_space) gf_phi.Set(ngs.CoefficientFunction(cathode_init_pot), definedon=mesh.Materials('particle')) ngs.Draw(gf_phi) res = f_pot.vec.CreateVector() res.data = f_pot.vec - a_pot.mat * gf_phi.vec gf_phi.vec.data += a_pot.mat.Inverse(initial_potential_space.FreeDofs()) * res gfu.components[1].vec.data = gf_phi.vec # Visualization ngs.Draw(gfu.components[1]) input() ngs.Draw(1/normalization_concentration * gfu.components[0], mesh, name='nconcentration') visoptions.autoscale = '0' visoptions.mminval = '0' visoptions.mmaxval = '1.3' input() # Time stepping
u00 = exp(-1000 * ((x - 0.5) * (x - 0.5))) # Nonzero initial condition cwave = 1. # wave speed F = ngs.CoefficientFunction((0, 0)) # Zero source a, f, X, sep = makeforms(mesh, p, F, q_zero, mu_zero, cwave, epsil=1.e-10) euz = GridFunction(X) # Contains solution at each adaptive step q = euz.components[sep[0]] # Volume (L2) components mu = euz.components[sep[0]+1] zq = euz.components[sep[1]] # Interface components zmu = euz.components[sep[1]+1] zq.Set(u00, definedon='bottom') zmu.Set(-u00, definedon='bottom') ngs.Draw(mu, autoscale=False, # draw only one of the solution components min=-1.0, max=1.0) # ADAPTIVE LOOP: globalerr = 1 # estimated total error itcount = 0 # iteration count def solve_on_current_mesh(): # assemble the problem on current mesh: X.Update() euz.Update() euz.vec[:] = 0 zq.Set(u00, definedon='bottom')
fes = ngs.H1(mesh, order=2, dirichlet=[1,2,3,4], complex=True) u = fes.TrialFunction() v = fes.TestFunction() a = ngs.BilinearForm(fes) a += ngs.SymbolicBFI(hbar / 2 / m_e * grad(u) * grad(v)) a.Assemble() m = ngs.BilinearForm(fes) m += ngs.SymbolicBFI(u * v) m.Assemble() gf_psi = ngs.GridFunction(fes) freedofs = fes.FreeDofs() for i in range(len(gf_psi.vec)): gf_psi.vec[i] = random() if freedofs[i] else 0 inv = a.mat.Inverse(freedofs) w = gf_psi.vec.CreateVector() for i in range(100): w.data = m.mat * gf_psi.vec gf_psi.vec.data = inv * w norm = 1/ngs.Norm(gf_psi.vec) gf_psi.vec.data = norm * gf_psi.vec ngs.Draw(gf_psi)
trace_space, points[:, bem_x], k) plot_me[bem_x] += np.exp(1j * k * (points[0, bem_x] * d[0] + points[1, bem_x] * d[1] + points[2, bem_x] * d[2])) plot_me[bem_x] += dlp_pot.evaluate(dirichlet_fun).flat plot_me[bem_x] -= slp_pot.evaluate(neumann_fun).flat fem_points = points[:, np.logical_not(bem_x)].transpose() fem_val = np.zeros(len(fem_points)) for p, point in enumerate(fem_points): fem_val[p] = gfu(point[0], point[1], point[2]).real plot_me[np.logical_not(bem_x)] += fem_val plot_me = plot_me.reshape((Nx, Ny)) plot_me = plot_me.transpose()[::-1] # Plot the image from matplotlib import pyplot as plt fig = plt.figure(figsize=(10, 8)) plt.imshow(np.real(plot_me), extent=[xmin, xmax, ymin, ymax]) plt.xlabel('x') plt.ylabel('y') plt.colorbar() plt.title("FEM-BEM Coupling for Helmholtz") ngs.Draw(gfu) plt.show()
from netgen.csg import * geo = CSGeometry() #plate block = OrthoBrick(Pnt(0, -0.5 * h, -0.5 * w), Pnt(L, 0.5 * h, 0.5 * w)) geo.Add(block) mesh = ngs.Mesh(geo.GenerateMesh(maxh=meshH)) mesh.Curve(1) if False: #set this to true, if you want to visualize the mesh inside netgen/ngsolve # import netgen import netgen.gui ngs.Draw(mesh) netgen.Redraw() #%%+++++++++++++++++++++++++++++++++++++++++++++++++++++ #Use femInterface to import femInterface model and create FFRFreducedOrder object eigenModesComputed = False femInterface.ImportMeshFromNGsolve(mesh, density=rho, youngsModulus=Emodulus, poissonsRatio=nu, computeEigenmodes=eigenModesComputed, verbose=False, excludeRigidBodyModes=6, numberOfModes=nModes, maxEigensolveIterations=20)
def _loadSTL(gui, filename): import netgen.stl as stl geo = stl.LoadSTLGeometry(filename) ngsolve.Draw(geo)
# Face Z = 0 mesh.Add(FaceDescriptor(surfnr=3, domin=1, bc=3)) AddSurfEls(0, n + 1, (n + 1) * (n + 1), facenr=3) # Face X = 1 mesh.Add(FaceDescriptor(surfnr=4, domin=1, bc=4)) AddSurfEls((n + 1)**3 - 1, -(n + 1), -1, facenr=4) # Face Z = 1 mesh.Add(FaceDescriptor(surfnr=5, domin=1, bc=5)) AddSurfEls((n + 1)**3 - 1, -(n + 1) * (n + 1), -(n + 1), facenr=5) # Face Y = 1 mesh.Add(FaceDescriptor(surfnr=6, domin=1, bc=6)) AddSurfEls((n + 1)**3 - 1, -1, -(n + 1) * (n + 1), facenr=6) # Set names for the above boundary parts (0-based indexing!) mesh.SetBCName(0, 'X0') mesh.SetBCName(1, 'Y0') mesh.SetBCName(2, 'Z0') mesh.SetBCName(3, 'X1') mesh.SetBCName(4, 'Z1') mesh.SetBCName(5, 'Y1') return mesh mesh = GenerateCubeMesh(9) ngs.Draw(ngs.Mesh(mesh))