Author |
Topic  |
|
dhimel
USA
6 Posts |
Posted - May 31 2013 : 15:54:24
|
I've built a model which contains overlapping conductor and dielectric panels. The models runs without a hitch in fastcap2, but will not run in fastercap (solution will not converge). The error message states that the problem is likely overlapping panels - is there a simple way to remedy this problem without rebuilding the entire geometry?
Thank You, Denny |
|
Enrico
548 Posts |
Posted - May 31 2013 : 16:33:10
|
The point is, you should never overlap a conductor and a dielectric panel. If your goal is to model a conductor at the interface between two different materials, and you want to do it with a conductor with no thickness, you should need another element model (what is called in FastCap2 User's Guide 'B', instead of 'D' or 'C'); but this is not implemented so far. As a matter of fact, real conductors always have a finite thickness, so in most cases you can model a thin box, with one permittivity on one side and another permittivity on the other. Take care that even if FastCap2 is not complaining about the input file and giving you a result, it cannot be trusted to be in line with your expectations.
Best Regards, Enrico
|
 |
|
dhimel
USA
6 Posts |
Posted - May 31 2013 : 19:47:17
|
Thank you for the helpful response.
So the lst files allow the user to specify the dielectric constant of the surrounding medium for a conductor. If you have a situation where there are different dielectrics surrounding a conductor, e.g. a thin box with a different dielectric medium on either side, how would you specify this when building up your model?
Thank You, Denny |
 |
|
Enrico
548 Posts |
Posted - Jun 05 2013 : 23:58:48
|
I am writing a paper on this topic that we'll publish in the 'literature' page.
To answer your specific question, unless the conductor is really, really thin (and therefore would require a B model), you can model it as a thin box, with a different dielectric constant on each side / group of sides.
You can check the sample file 'capacitor.lst'. Even if this conductor is not thin, you can leverage the structure of the file to define your own conductor.
If too thin, and you are getting convergence problems, you can tune the parameters lowering the -d value and selecting -g to use the Galerkin solution scheme.
Best Regards, Enrico
|
 |
|
Enrico
548 Posts |
Posted - Jun 11 2013 : 18:19:30
|
You can download the white paper I was speaking of from the 'literature' page.
The title is "The Treatment of Dielectrics in FasterCap"
Best Regards, Enrico
|
 |
|
dhimel
USA
6 Posts |
Posted - Jun 11 2013 : 19:30:37
|
Great - thank you! I am finding the white paper to be very helpful. |
 |
|
an1985
USA
2 Posts |
Posted - Feb 24 2015 : 20:54:21
|
Hi Enrico, I have quick followup question on the same topic.
In your white paper parallel plate example, all the parallel plates and the dielectric length and width are equal. Lets suppose instead you have a '+' like top and bottom conductor parallel plate formation. For instance as follows:
Conductor 1 (lxwxh or x,y,z) = 0.5 x 1 x 0.2 [xoffset: 0.25] Conductor 2 (lxwxh or x,y,z) = 1 x 0.5 x 0.2 [yoffset: 0.25]
And lets suppose that in between the conductors lies a dielectric layer same as the one in your whitepaper.
Dielectric 1 (x,y,z) = 1 x 1 x 0.6
Can I get away with (and still get relatively accurate capacitance) modeling the dielectric interface between the two plates as a simple 1x1x0.6 and bounding the dielectric only in the sides like in the whitepaper? Or do I have to create a top and bottom boundary that fills the gap where there is no conductor present (this process would get really tedious if there are multiple stripped i.e. '++++' pattern) ?
Regards, AJ
|
Edited by - an1985 on Feb 24 2015 21:32:53 |
 |
|
Enrico
548 Posts |
Posted - Feb 26 2015 : 20:06:00
|
You should create a dielectric interface wherever two different dielectric mediums touch.
Actually creating such a geometry manually is cumbersome, I agree with you, but using any modeling CAD application you can script eases the task a lot.
As I said in other posts, we are working on a simple interface over FreeCAD, which is a powerful and completely open-source and free multi-platform CAD. I can provide you the raw scripts to perform the export, if you are interested.
Best Regards, Enrico
|
 |
|
an1985
USA
2 Posts |
Posted - Feb 27 2015 : 18:46:12
|
You sent an export_mesh.py containing 1 export_mesh function and 1 export_faces function sometime back. Do you have any updates on this?
#***************************************************************************
#* *
#* Copyright (c) 2014 *
#* FastFieldSolvers S.R.L. ht*p://w*w.fastfieldsolvers.com *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD, Mesh, Part, MeshPart, DraftGeomUtils, os
from FreeCAD import Vector
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
else:
def translate(ctxt,txt):
return txt
__title__="FreeCAD E.M. Mesh Macros"
__author__ = "FastFieldSolvers S.R.L."
__url__ = "ht*p://w*w.fastfieldsolvers.com"
DEF_FOLDER = "."
##
def export_mesh(filename, meshobj=None, isDiel=False, showNormals=False, folder=DEF_FOLDER):
'''export mesh in FasterCap format as conductor or dielectric interface
'filename' is the name of the export file
'meshobj' must be a Mesh::Feature object
'isDiel' specifies if the mesh is a dielectric, so the function will add
a reference point to each panel to indicate which is the external side (outside)
'showNormals' will add a compound object composed by a set of arrows showing the
normal direction for each panel
'folder' is the folder in which 'filename' will be saved
Example:
mymeshGui = Gui.ActiveDocument.Mesh
mymeshObj = mymeshGui.Object
export_mesh("mymesh.txt", meshobj=mymeshObj, folder="C:/temp")
'''
# if no valid mesh was passed
if meshobj == None:
return
elif meshobj.TypeId != "Mesh::Feature":
FreeCAD.Console.PrintMessage("Error: 'meshobj' is not an object of type 'Mesh::Feature'")
return
if not os.path.isdir(folder):
os.mkdir(folder)
with open(folder + os.sep + filename, 'w') as fid:
# write the preamble
if isDiel == True:
fid.write("0 dielectric definition file for mesh '" + meshobj.Label)
else:
fid.write("0 conductor definition file for mesh '" + meshobj.Label)
fid.write("' created using FreeCAD's ElectroMagnetic workbench\n")
fid.write("* see ht*p://w*w.freecad.org and ht*p://w*w.fastfieldsolvers.com\n")
fid.write("\n")
# export facets
arrows = []
condName = meshobj.Label.replace(" ","_")
for facet in meshobj.Mesh.Facets:
if len(facet.Points) == 3:
fid.write("T " + condName)
elif len(facet.Points) == 4:
fid.write("Q " + condName)
else:
FreeCAD.Console.PrintMessage("Unforseen number of mesh facet points: " + len(facet.Points) + ", skipping facet")
continue
center = Vector(0.0, 0.0, 0.0)
avgSideLen = 0.0
for j, point in enumerate(facet.Points):
fid.write(" ")
for i in range(3):
fid.write(" " + str(point[i]))
if isDiel == True or showNormals == True:
# 'point' is a tuple, transform in vector
center = center + Vector(point)
# get side length
side = Vector(facet.Points[(j+1)%3]) - Vector(point)
avgSideLen += side.Length
if isDiel == True or showNormals == True:
# calculate the reference point
# (there should be a better way to divide a vector by a scalar..)
center.multiply(1.0 / len(facet.Points) )
# and now move along the normal, proportional to the average facet dimension
scaledNormal = Vector(facet.Normal)
scaledNormal.multiply(avgSideLen / len(facet.Points) )
refpoint = center + scaledNormal
if isDiel == True:
fid.write(" ")
for i in range(3):
fid.write(" " + str(refpoint[i]))
fid.write("\n")
if showNormals == True:
arrows.append(make_arrow(center, refpoint))
if showNormals == True:
# add the vector normals visualization to the view
# Note: could also use Part.show(normals) but in this case we could
# not give the (permanent) name to the object, only change the label afterwards
normals = Part.makeCompound(arrows)
normalobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Normals")
normalobj.Shape = normals
fid.closed
##
def make_arrow(startpoint, endpoint):
'''create an arrow
'startpoint' is a Vector specifying the start position
'endpoint' is a Vector specifying the end position
'''
line = Part.makeLine(startpoint, endpoint)
# calculate arrow head base
dir = endpoint - startpoint
len = dir.Length
base = dir
base.normalize()
base.multiply(len * 0.8)
base = startpoint + base
# radius2 is calculated for a fixed arrow head angle tan(15deg)=0.27
cone = Part.makeCone(0.2 * len * 0.27, 0.0, 0.2 * len, base, dir, 360)
# add the compound representing the arrow
arrow = Part.makeCompound([line, cone])
return arrow
##
def export_faces(filename, isDiel=False, name="", showNormals=False, folder=DEF_FOLDER):
'''export faces in FasterCap format as conductor or dielectric interface
The function operates on the selection. The selection can be a face or a compound.
'filename' is the name of the export file
'isDiel' specifies if the mesh is a dielectric, so the function will add
a reference point to each panel to indicate which is the external side (outside)
'name' is the name of the conductor created in the file. If not specified, defaults
to the label of the first element in the selection set
'showNormals' will add a compound object composed by a set of arrows showing the
normal direction for each panel
'folder' is the folder in which 'filename' will be saved
Example:
export_faces("mymesh.txt", folder="C:/temp")
'''
# get selection
sel = FreeCADGui.Selection.getSelection()
# if no valid mesh was passed
if sel == None:
return
if name == "":
condName = sel[0].Label.replace(" ","_")
else:
condName = name
# scan objects in selection and extract all faces
faces = []
facets = []
for obj in sel:
if obj.TypeId == "Mesh::Feature":
facets.extend(obj.Mesh.Facets)
else:
if obj.Shape.ShapeType == "Face":
faces.append(obj.Shape)
elif obj.Shape.ShapeType == "Compound":
faces.extend(obj.Shape.Faces)
# scan faces and find out which faces have more than 4 vertexes
# TBD warning: should mesh also curve faces
facesComplex = [x for x in faces if len(x.Vertexes) >= 5]
facesSimple = [x for x in faces if len(x.Vertexes) < 5]
# mesh complex faces
doc = FreeCAD.ActiveDocument
for face in facesComplex:
mesh = doc.addObject("Mesh::Feature","Mesh")
mesh.Mesh = MeshPart.meshFromShape(Shape=face, Fineness=0, SecondOrder=0, Optimize=1, AllowQuad=0)
facets.extend(mesh.Mesh.Facets)
# now we have faces and facets. Uniform all
panels = []
for face in facesSimple:
sortEdges = DraftGeomUtils.sortEdges(face.Edges)
# Point of a Vertex is a Vector, as well as Face.normalAt()
points = [x.Vertexes[0].Point for x in sortEdges]
panels.append( [points, face.normalAt(0,0)] )
for facet in facets:
points = [ Vector(x) for x in facet.Points]
panels.append( [points, Vector(facet.Normal)] )
if not os.path.isdir(folder):
os.mkdir(folder)
with open(folder + os.sep + filename, 'w') as fid:
# write the preamble
if isDiel == True:
fid.write("0 dielectric definition file for the following objects\n")
else:
fid.write("0 conductor definition file for the following objects\n")
for obj in sel:
fid.write("* - " + obj.Label + "\n")
fid.write("* created using FreeCAD's ElectroMagnetic workbench\n")
fid.write("* see ht*p://w*w.freecad.org and ht*p://w*w.fastfieldsolvers.com\n\n")
arrows = []
# export faces
for panel in panels:
pointsNum = len(panel[0])
if pointsNum == 3:
fid.write("T " + condName)
elif pointsNum == 4:
fid.write("Q " + condName)
else:
FreeCAD.Console.PrintMessage("Unforseen number of panel vertexes: " + pointsNum + ", skipping panel")
continue
center = Vector(0.0, 0.0, 0.0)
avgSideLen = 0.0
for j, vertex in enumerate(panel[0]):
fid.write(" ")
for i in range(3):
fid.write(" " + str(vertex[i]))
if isDiel == True or showNormals == True:
# 'point' is a tuple, transform in vector
center = center + vertex
# get side length
side = panel[0][(j+1)%3] - vertex
avgSideLen += side.Length
if isDiel == True or showNormals == True:
# calculate the reference point
# (there should be a better way to divide a vector by a scalar..)
center.multiply(1.0 / pointsNum )
# and now move along the normal, proportional to the average facet dimension
scaledNormal = panel[1]
scaledNormal.multiply(avgSideLen / pointsNum )
refpoint = center + scaledNormal
if isDiel == True:
fid.write(" ")
for i in range(3):
fid.write(" " + str(refpoint[i]))
fid.write("\n")
if showNormals == True:
arrows.append(make_arrow(center, refpoint))
fid.closed
if showNormals == True:
# add the vector normals visualization to the view
# Note: could also use Part.show(normals) but in this case we could
# not give the (permanent) name to the object, only change the label afterwards
normals = Part.makeCompound(arrows)
normalobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Normals")
normalobj.Shape = normals
AJ |
Edited by - an1985 on Feb 27 2015 18:46:31 |
 |
|
Enrico
548 Posts |
Posted - Mar 17 2015 : 18:25:32
|
To formally close the topic also on the forum, as we discussed via private email:
Yes we have something better, but however simple it is not functional yet. It is a whole workbench you can plug as an add-on to FreeCAD. The improvement, besides that, is the capability to transforma the 3D dielectric bodies into shells, so they can be cut by the conductors in contact with the dielectric.
Enrico
|
 |
|
|
Topic  |
|
|
|