|
ActiveField Technology
|
Step 4: Building a geometric model.First let us declare some variables that we use working with the geometric model:
Sub BuildGeometry() Than we create a new empty model document and just save it. For saved document we use the filename that the problem refers to. So, just after saving QuickField establishes the link between problem and model documents. The benefit of establishing the link early is that the problem setting for coordinates and length unit will be applied to the model automatically.
Sub BuildGeometry() Now we are ready to start building the edges constituting our model. The AddEgde method we will use belongs to the Shapes collection, so it seems convenient to place all these commands to the With..End With brackets:
Sub BuildGeometry() The comments (in green) put into the With block outline our next work with several parts of model geometry. When finish with building the model we will get the model picture to show it on the main screen (see discussion later) and save the model document again, this time by simple Save method. Now consider building of the steel yoke block. We use here the geometric dimension variables, declared at the global level and set by user in the MainDialog form (see Declarations section) With mdl.Shapes ' The Yoke Set shp = .AddEdge(QF.PointXY(-yokeWidth / 2, 0), _ QF.PointXY(yokeWidth / 2, 0)) .AddEdge QF.PointXY(yokeWidth / 2, 0), _ QF.PointXY(yokeWidth / 2, yokeHeight) .AddEdge QF.PointXY(yokeWidth / 2, yokeHeight), _ QF.PointXY(-yokeWidth / 2, yokeHeight) .AddEdge QF.PointXY(-yokeWidth / 2, yokeHeight), _ QF.PointXY(-yokeWidth / 2, 0) shp.Left.Label = "Steel" .......... There is the sequence of four AddEgde command builds a rectangular block. Please note the way used to assign label to the block: we remember an edge (generally speaking, group of edges) built by the first command in a shp variable. When the block is completely built, we can refer to it as a block, located from the left side of the shp edge by the shp.Left property. The Label property is used to assigning label to the block. All other rectangular blocks are built in a similar way. Please note that the left magnet block is build in such a way that it located from the right (not left) side of the edge. ' The Yoke .............. ' Right Magnet Set shp = .AddEdge(QF.PointXY(yokeWidth / 2, yokeHeight), _ QF.PointXY(yokeWidth / 2, yokeHeight + magnetHeight)) .AddEdge QF.PointXY(yokeWidth / 2, yokeHeight + magnetHeight), _ QF.PointXY(yokeWidth / 2 - maghetWidth, yokeHeight + magnetHeight) .AddEdge QF.PointXY(yokeWidth / 2 - maghetWidth, yokeHeight + magnetHeight), _ QF.PointXY(yokeWidth / 2 - maghetWidth, yokeHeight) shp.Left.Label = "ALNICO down" ' Left Magnet Set shp = .AddEdge(QF.PointXY(-yokeWidth / 2, yokeHeight), _ QF.PointXY(-yokeWidth / 2, yokeHeight + magnetHeight)) .AddEdge QF.PointXY(-yokeWidth / 2, yokeHeight + magnetHeight), _ QF.PointXY(-yokeWidth / 2 + maghetWidth, yokeHeight + magnetHeight) .AddEdge QF.PointXY(-yokeWidth / 2 + maghetWidth, yokeHeight + magnetHeight), _ QF.PointXY(-yokeWidth / 2 + maghetWidth, yokeHeight) shp.Right.Label = "ALNICO up" ' Steel Keeper yBase = yokeHeight + magnetHeight + airGap Set shp = .AddEdge(QF.PointXY(-keeperWidth / 2, yBase), _ QF.PointXY(keeperWidth / 2, yBase)) .AddEdge QF.PointXY(keeperWidth / 2, yBase), _ QF.PointXY(keeperWidth / 2, yBase + keeperHeight) .AddEdge QF.PointXY(keeperWidth / 2, yBase + keeperHeight), _ QF.PointXY(-keeperWidth / 2, yBase + keeperHeight) .AddEdge QF.PointXY(-keeperWidth / 2, yBase + keeperHeight), _ QF.PointXY(-keeperWidth / 2, yBase) shp.Left.Label = "Steel Keeper" ' Surrounding air yBase = yokeHeight + magnetHeight + airGap + keeperHeight xBase = (yokeWidth + keeperWidth) * 1.5 Set shp = .AddEdge(QF.PointXY(-xBase, -yBase), QF.PointXY(xBase, -yBase)) .AddEdge QF.PointXY(xBase, -yBase), QF.PointXY(xBase, 2 * yBase) .AddEdge QF.PointXY(xBase, 2 * yBase), QF.PointXY(-xBase, 2 * yBase) .AddEdge QF.PointXY(-xBase, 2 * yBase), QF.PointXY(-xBase, -yBase) shp.Left.Label = "Air" .Boundary(qfOuterOnly).Label = "Zero" Please note the last line of code for the surrounding air block. It refers to edges constitute the outer border of the area by Boundary property of the Shapes object. We need to assign them a Zero label. Our next step is to set the mesh spacing values to some vertices and that build the mesh. For simplicity sake we employ a straightforward strategy: assign a small spacing value to all corners of the steel parts and a big spacing (four times bigger than small one) to the outer corners. The auxiliary function fMin returns the smaller of its argument. When the mesh spacing is set the mesh itself is generated by a single command: BuildMesh method of the Shapes object.
With mdl.Shapes Now we have to do only the auxiliary task: store a picture of the geometric model to show it later in the picture box on the MainDialog form. To do it we get a ModelWindow object (win variable) represents the MDI window shows the geometric model. Then we try to make it form close to a square, because our target picture box control is of square form. It is rather hard to do that exactly because we need to know the size of window client area, whereas Width and Height properties of the ModelWindow object returns the size of the whole window. The Zoom method of the ModelWindow with no parameters sets the scale to view the whole model. Than we can use the GetPicture method that puts the picture to the Windows clipboard like the Edit->Copy command does. The next line of code gets a picture from the clipboard and stores it in the geomPicture object (declared as StdPicture)
.......... Now the geometric model is ready for further using. Step 5: Working with data labels.Our current task is to set appropriate physical values to all the labels we have defined in the model. First have a look at the whole procedure below, and than we discuss some important points.
Sub SetData() To look through the block labels defining in the model we employ the Visual Basic For Each loop. There are several way to get the label collection: from the Problem object or from the DataDoc object, represents the QuickField data document (as you remember, with a problem can be associated up to two data documents). In our case, the data document is now empty, and the only way to get the collection of labels is the Labels property of the Problem object. It is used with parameter of QfShapes type denoted which of three collection we want to iterate. Please not that VB requires the loop variable elem in the For Each construction being of Variant type. So, after receiving the next element from the collection we cast it to the Label type by assigning it to the lab variable. All operations with the content of an individual label we do with an object, accessible by the Content property of the Label object. Exact type of that object depends upon problem and label types as described in the DataDoc topic. When finished with the Content, we must put it back to the parent Label by assigning it to the Label's Content property.
Dim lab As QuickField.Label Now consider the parameter setting for each individual labels. The most simple looks code for linear media, like Air label:
Case "Air" Here we have to assign the relative magnetic permeability value to both components of the permeability tensor. An optional parameter of the Kxx (and Kyy) property allows to deal also with absolute values of permeability. Working with a label describing the saturated media, we have to create and define a Spline object.
Case "Steel", "Steel Keeper" The label is empty now, so we have to first create a new spline by the CreateBHCurve method. Than we add each spline node individually by the Add method and finally assign the spline to the label's content. With a non-linear permanent magnet we should also set the coercive force value. On the code fragment below we first set the coercive force value and then add the spline nodes. In this case we must subtract the coercive force from the magnetic field value to put the curve into the second quadrant. It is possible first to define the curve, located in the first quadrant, and then set the coercive force.
Case "ALNICO up", "ALNICO down" It is possible first to define the curve, located in the first quadrant, and then set the coercive force. With edge label we do not need to look through the edge labels collection because we have only one edge label. The following code puts zero Dirichlet condition to the "Zero" label:
' The only edge label The Dirichlet property set and returns Dirichlet boundary condition that do not depends upon coordinates. If you nee to set Dirichlet condition as a linear function of coordinates, please you the DirichletLinear property. The last line of the SetData procedure saves the modified data document. It has its file name assigned when the problem was created, so we only need a Save method. Step 6: Analyzing the solutionWhen the model and data are ready, we are able to solve a problem and start to analyze result:
Sub Solve() The AnalyzeResults method loads the solution for analyzing and creates the first FieldWindow object, represents a field picture window. After that we can get the Result object, which gives access to analyzing capabilities. In our program we have to do two tasks with the problem solution: get the field picture and calculate the force acting to the steel keeper. We get the field picture in a very similar way that we have used for the geometric model picture:
Sub ViewResults() To calculate the mechanical force we have to create a contour surrounding the keeper's body. Each FieldWindow object always possesses only one the Contour, even an empty one. We get the Contour object from our FieldWindow object called win and use its AddLineTo method to add lines to the contour. The last AddLineTo call with no parameters builds a line, connecting the last contour point with its starting point. When the closed contour oriented counter clockwise is ready, we can use the GetIntegral method of the Result object to calculate desired integral value. The force value is really a vector quantities, so being interested only in its absolute value we use its Abs property.
Function CalculateForce() As Double What's MoreThis very simple application can be considered as an prototype for more developed custom project intended to automate analyzing of some parameterized model. To do it more realistic we obviously have to develop some code for validation user's input. Probably it will be useful to allow the customer to build his or her model from some parameterized "building blocks", implement some methods for optimization an much more. |
|||