diff --git a/python/Tutorials/Simple_Patch_Antenna.py b/python/Tutorials/Simple_Patch_Antenna.py index 173d454..cd80f78 100644 --- a/python/Tutorials/Simple_Patch_Antenna.py +++ b/python/Tutorials/Simple_Patch_Antenna.py @@ -58,7 +58,7 @@ mesh_res = C0/(f0+fc)/1e-3/20 ### Generate properties, primitives and mesh-grid #initialize the mesh with the "air-box" dimensions -mesh.AddLine('x', [-SimBox[0]/2, feed_pos, SimBox[0]/2]) +mesh.AddLine('x', [-SimBox[0]/2, SimBox[0]/2]) mesh.AddLine('y', [-SimBox[1]/2, SimBox[1]/2] ) mesh.AddLine('z', [-SimBox[2]/3, SimBox[2]*2/3] ) @@ -66,14 +66,14 @@ mesh.AddLine('z', [-SimBox[2]/3, SimBox[2]*2/3] ) patch = CSX.AddMetal( 'patch' ) # create a perfect electric conductor (PEC) start = [-patch_width/2, -patch_length/2, substrate_thickness] stop = [ patch_width/2 , patch_length/2, substrate_thickness] -pb=patch.AddBox(priority=10, start=start, stop=stop) # add a box-primitive to the metal property 'patch' -pb.AddEdges2Grid('xy', metal_edge_res=mesh_res/2) +patch.AddBox(priority=10, start=start, stop=stop) # add a box-primitive to the metal property 'patch' +FDTD.AddEdges2Grid(dirs='xy', properties=patch, metal_edge_res=mesh_res/2) # create substrate substrate = CSX.AddMaterial( 'substrate', epsilon=substrate_epsR, kappa=substrate_kappa) start = [-substrate_width/2, -substrate_length/2, 0] stop = [ substrate_width/2, substrate_length/2, substrate_thickness] -sb=substrate.AddBox( priority=0, start=start, stop=stop ) +substrate.AddBox( priority=0, start=start, stop=stop ) # add extra cells to discretize the substrate thickness mesh.AddLine('z', linspace(0,substrate_thickness,substrate_cells+1)) @@ -82,12 +82,14 @@ mesh.AddLine('z', linspace(0,substrate_thickness,substrate_cells+1)) gnd = CSX.AddMetal( 'gnd' ) # create a perfect electric conductor (PEC) start[2]=0 stop[2] =0 -gb=gnd.AddBox(start, stop, priority=10, edges2grid='all') +gnd.AddBox(start, stop, priority=10) + +FDTD.AddEdges2Grid(dirs='xy', properties=gnd) # apply the excitation & resist as a current source start = [feed_pos, 0, 0] stop = [feed_pos, 0, substrate_thickness] -port = FDTD.AddLumpedPort(1 ,feed_R, start, stop, 'z', 1.0, priority=5, edges2grid='all') +port = FDTD.AddLumpedPort(1, feed_R, start, stop, 'z', 1.0, priority=5, edges2grid='xy') mesh.SmoothMeshLines('all', mesh_res, 1.4) diff --git a/python/openEMS/automesh.py b/python/openEMS/automesh.py new file mode 100644 index 0000000..93472fa --- /dev/null +++ b/python/openEMS/automesh.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +""" +Created on Sun Feb 19 20:29:25 2017 + +@author: thorsten +""" + +import sys +import numpy as np + +from CSXCAD import CSPrimitives +from CSXCAD.Utilities import CheckNyDir, GetMultiDirs + +def mesh_hint_from_primitive(primitive, dirs, **kw): + if primitive.GetType() is CSPrimitives.POINT: + return mesh_hint_from_point(primitive, dirs, **kw) + if primitive.GetType() is CSPrimitives.BOX: + return mesh_hint_from_box(primitive, dirs, **kw) + else: + return None + +def mesh_hint_from_point(point, dirs, **kw): + """ mesh_hint_from_point(point, dirs) + + Get a grid hint for the coordinates of the point. + + :param dirs: str -- 'x','y','z' or 'xy', 'yz' or 'xyz' or 'all' + :returns: (3,) list of mesh hints + """ + hint = [None, None, None] + coord = point.GetCoord() + for ny in GetMultiDirs(dirs): + hint[ny] = [coord[ny],] + return hint + +def mesh_hint_from_box(box, dirs, **kw): + """ mesh_hint_from_box(box, dirs, metal_edge_res=None, **kw) + + Get a grid hint for the edges of the given box with an an optional 2D metal + edge resolution. + + :param dirs: str -- 'x','y','z' or 'xy', 'yz' or 'xyz' or 'all' + :param metal_edge_res: float -- 2D flat edge resolution + :returns: (3,) list of mesh hints + """ + metal_edge_res = kw.get('metal_edge_res', None) + up_dir = kw.get('up_dir' , True) + down_dir = kw.get('down_dir', True) + + if metal_edge_res is None: + mer = 0 + else: + mer = np.array([-1.0, 2.0])/3 * metal_edge_res + if box.HasTransform(): + sys.stderr.write('FDTD::automesh: Warning, cannot add edges to grid with transformations enabled\n') + return + hint = [None, None, None] + start = np.fmin(box.GetStart(), box.GetStop()) + stop = np.fmax(box.GetStart(), box.GetStop()) + for ny in GetMultiDirs(dirs): + hint[ny] = [] + if metal_edge_res is not None and stop[ny]-start[ny]>metal_edge_res: + if down_dir: + hint[ny].append(start[ny]-mer[0]) + hint[ny].append(start[ny]-mer[1]) + if up_dir: + hint[ny].append(stop[ny]+mer[0]) + hint[ny].append(stop[ny]+mer[1]) + elif stop[ny]-start[ny]: + if down_dir: + hint[ny].append(start[ny]) + if up_dir: + hint[ny].append(stop[ny]) + else: + hint[ny].append(start[ny]) + return hint + diff --git a/python/openEMS/openEMS.pyx b/python/openEMS/openEMS.pyx index 973ed87..60abbbb 100644 --- a/python/openEMS/openEMS.pyx +++ b/python/openEMS/openEMS.pyx @@ -19,7 +19,9 @@ import os, sys, shutil import numpy as np cimport openEMS -from . import ports, nf2ff +from . import ports, nf2ff, automesh + +from CSXCAD.Utilities import GetMultiDirs cdef class openEMS: """ openEMS @@ -267,7 +269,15 @@ cdef class openEMS: openEMS.ports.LumpedPort """ assert self.__CSX is not None, 'AddLumpedPort: CSX is not set!' - return ports.LumpedPort(self.__CSX, port_nr, R, start, stop, p_dir, excite, **kw) + port = ports.LumpedPort(self.__CSX, port_nr, R, start, stop, p_dir, excite, **kw) + edges2grid = kw.get('edges2grid', None) + if edges2grid is not None: + grid = self.__CSX.GetGrid() + for n in GetMultiDirs(edges2grid): + grid.AddLine(n, start[n]) + if start[n] != stop[n]: + grid.AddLine(n, stop[n]) + return port def AddWaveGuidePort(self, port_nr, start, stop, p_dir, E_func, H_func, kc, excite=0, **kw): """ AddWaveGuidePort(self, port_nr, start, stop, p_dir, E_func, H_func, kc, excite=0, **kw) @@ -364,6 +374,42 @@ cdef class openEMS: self.__CSX = CSX self.thisptr.SetCSX(CSX.thisptr) + def GetCSX(self): + return self.__CSX + + def AddEdges2Grid(self, dirs, primitives=None, properties=None, **kw): + """ AddEdges2Grid(primitives, dirs, **kw) + + Add the edges of the given primitives to the FDTD grid. + + :param dirs: primitives -- one or more primitives + :param dirs: str -- 'x','y','z' or 'xy', 'yz' or 'xyz' or 'all' + """ + csx = self.GetCSX() + if csx is None: + raise Exception('AddEdges2Grid: Unable to access CSX!') + prim_list = [] + if primitives is not None and type(primitives) is not list: + prim_list.append(primitives) + elif primitives is not None: + prim_list += primitives + + if properties is not None and type(properties) is not list: + prim_list += properties.GetAllPrimitives() + elif primitives is not None: + for prop in properties: + prim_list += prop.GetAllPrimitives() + + grid = csx.GetGrid() + for prim in prim_list: + hint = automesh.mesh_hint_from_primitive(prim, dirs, **kw) + if hint is None: + continue + for n in range(3): + if hint[n] is None: + continue + grid.AddLine(n, hint[n]) + def Run(self, sim_path, cleanup=False, setup_only=False, verbose=None): """ Run(sim_path, cleanup=False, setup_only=False, verbose=None) diff --git a/python/openEMS/ports.py b/python/openEMS/ports.py index 6b2764b..1f0ea2a 100644 --- a/python/openEMS/ports.py +++ b/python/openEMS/ports.py @@ -158,7 +158,7 @@ class LumpedPort(Port): elif self.R==0: lumped_R = CSX.AddMetal(self.lbl_temp.format('resist')) - lumped_R.AddBox(self.start, self.stop, priority=self.priority, edges2grid=kw.get('edges2grid', None)) + lumped_R.AddBox(self.start, self.stop, priority=self.priority) if excite!=0: exc_vec = np.zeros(3)