IT Tips – Is SP1 for Windows 7 Going to Slow Down my Machine?

ANSYS R13 Lemans CPU Wall Clock Benchmark Results Before and After a Windows 7 64-bit SP1 Update

I was curious what sort of impact the Windows 7 SP1 upgrade would have on a new install of ANSYS R13. Would the Service Pack upgrade have a positive or negative impact on the ANSYS R13 and additionally the Lemans benchmarks?  Here is what we found:

  • Hardware test machine: Single socket 6 core AMD C32 running 2.6GHz, 8GB of RAM, 2 x 160GB Intel SSD drives in RAID0, Windows 7 Professional
  • Benchmarks completed by Clinton Smith, Consulting Mechanical Engineer CFD and Thermal Analysis at PADT, Inc.

Results:

  • The benchmark results appear approximately the same before and after the install of the Service Pack.
  • No apparent issues or crashes with ANSYS R13 after installing the Windows 7 Service Pack 1 update
  • Six core benchmarks and one core benchmarks are slightly faster after SP1 upgrade.
  • Four core and two core benchmarks are slightly slower after SP1 upgrade:

ANSYS Le Mans Model, 1,864,025 Nodes

Cores

Wall Time (s)
Pre SP1

Wall Time (s)
With SP1

Diff

% Diff

1

7,220

7,190

-30

-0.4%

2

3,970

3,980

10

0.3%

4

2,300

2,320

20

0.9%

6

1,850

1,840

10

-0.5%

Conclusion:

It appears that overall the impact of the upgrade is a positive. No system stability or ANSYS R13 issues related to the upgrade.

FE Modeler Part 3: Morphing Meshes

Morph-lady-catIn the first two parts of this series we talked about how to use FE Modeler to translate meshes and how to create geometry from meshes.  The third “big” thing that this tool does is allow you to morph a mesh to a new shape.  There are a few less important things that FE Modeler does, and we will cover those in the last article of this series.

First, let’s take a good long look at the picture to the left.  Mesh morphing is nothing like what the image shows, but it is pretty creepy to look at so I thought I’d throw it up there.

Mesh morphing in FE Modeler works by taking the faceted surface geometry you can create, covered in the previous article, and allowing the user to apply transformations or a projection to that geometry.  You would use this if you want to change your geometry while keeping the same basic mesh.  This is because when you are doing optimization or parametric study and changing the CAD geometry, you force a remesh every time and sometimes the change in mesh is large enough to effect your study.  You would also need to use this method if all you had was an FE mesh.

Basic Process

Let’s start with a very simple example to show how it is done. 

Figure 1 shows a piece of example geometry.  It has some nice features that we will do more complex morphs on.

f1_geometry
Figure 1: Simple Example Geometry, Itching to be Morphed

To start off we do the same geometry (covered in detail in Part 2 of this series):

  1. Read in geometry
  2. Select Geometry Synthesis in the tree and make sure Use Node components is Yes
  3. Click on the Initial Geometry Icon
  4. If everything works you should have a solid that you can now work with

Now you need to define how you want to modify the faceted geometry.  Do this by selecting Initial Geometry in the tree and then clicking on the “New Target Configuration” Icon.  See Figure 2.

 

f2_MakeTargetConfigurationFigure 2: Creating the Target Configuration

When you do this the program will go out and configure some things internally and then add two new things to the tree: 1) a “Target Configuration” that is a child of Initial Geometry and 2) a Parameterized configuration branch. Figure 3 shows the result in the tree.

 

f3_Tree_After_Target_ConfigFigure 3: Model Tree After Creation of Target Configuration

So, at this point you might be trying to figure out why there are branches and children where they are. The way I think about it is that the Geometry Synthesis listing is not a branch and is not a child of something.  It is it’s own “tree”  So everything on the first level under it, its children, are different things you can do with Geometry Synthesis:  Find skins, define working Geometry,  Set up mesh Morphing (Initial Geometry), and view what the current mesh looks like based on the current parameters (Parameterized Configuration).  I feel that the Initial Geometry branch is mislabeled and should say Mesh Morphing, but it is too late to change the name now.

Back to morphing meshes…  The way you specify what you want morphed is to define Design Points that have some sort of translation or projection.  Then you specify how far to translate with a parameter that you control in the Project Schematic.  For our first run through, we are going to offset a surface. 

Do this by clicking on Design Point and then on the Transformation Icon and Select “Face Offset” (or RMB –>Insert->Face Offset) and fill out the details view.  For this example I used the end face and set the maximum offset value to 30 mm.  Note, even though it doesn’t say it in the GUI, the help points out that you should put in your maximum value that you might use.  the program then scales from the original to this value as you change the offset parameter.  Figure 4 shows the setup for this example.

f4_Offset_face
Figure 4: Specifying the Face Offset, Before Generation

Click on Generate the Design Point to see what the offset looks like:

f5_Offset_Face_2
Figure 5: The Offset Face after Generation

Here is where it gets a little tricky.  All you did was define a potential geometry change.  That change is not applied to the model until you actually set parameters and apply them.   And, the parameter is controlled at the Project Schematic level, not within FE Modeler.  The value you put in under Design Point, that is simply a maximum value that the program uses to figure out how to do the Morphing.  The actual morphing uses the parameter as defined in the Project Schematic.

To see this click on Parameterized Configuration and you will see that there is 1 parameter, it is called Mesh.Morpher.1, and its value is 0.  (Figure 6).

f6_ParamValues
Figure 6: Configuration Information after Offset is Defined

Therefore, your next step is to go to the project schematic and change the offset value to some new value you want to morph the mesh to (remember, the value we put in for the Design Point is our guess at the maximum value, we can use any value we want for the parameter value).  To change the value in the Project Schematic, bring up the schematic and click on the parameter bar.  You should now see the parameter in the Outline view. For this example, I changed it to 17.354.  Now exit back to the parameter manager and click on Update Project.  Go back to your FE Modeler window, click on Parameterized Mesh, and you should see the morphed mesh:

f7_morphed_mesh
Figure 7: Morphed Mesh

Figure 8 shows an animation from an offset of 0 to 30: 

SimpleMorph1

Figure 8: Mesh Morphing from an Offset of 0mm to 30mm

To get the mesh out and usable in your model you have one more step.  If you click on Write Solver File now you will get your original geometry.  You need to click on Parameterized Mesh then click on the Update FE Modeler Mesh icon.  Now set your Target System and chose Write Solver file.  Or, if you are staying in workbench, drag a new system onto the Model in the Project Schematic.  The cool thing about this is that you now have a parametric model that is linked to an analysis in Workbench. It is therefore easy to do design studies, optimization, and the rest of the cool things Workbench is great at, and without CAD geometry!  Figure 9 shows an example of using the mesh for a modal analysis.

f9_Use_Morphed_MeshFigure 9: Using the Morphed Mesh in a Modal Analysis

Getting More Complicated

Although the process is the same, you can get a lot more complicated.  The program allows for five different translations, offsets or projections, and some of them have multiple options within. They are all kind of self explanatory.

  f10_tranlation_options
Figure 10: Morphing Options

Here is the description from the help as a reference:

  • Translation (of vertices, edges, surfaces, or parts): A translation is given in the global Cartesian coordinate system or by the definition of a translation vector between two points.
  • Rotation (of vertices, edges, surfaces, or parts): You must define a rotation axis between two points or a point and a vector and then give a rotation angle in degrees or radians.
  • Face (Surface) Offset – a Face Offset can be:
    • Uniform – Enter a negative or positive Offset Value to move the face inward or outward.
    • Non Uniform – Enter a negative or positive Offset Value to move the face inward or outward. With this transformation, you can offset a surface with a nonlinear curve. In addition, a Non Uniform surface offset includes the following options:
      • Distance to the edges – Define the distance from the edges to the maximum displacement of the transformed face.
      • Function type – Select a function type based on the shape you want to obtain, options include: Linear, Double Tangent, Linear-tangent, Tangent-linear.
      • Immobile edges – By default, all of the edges for the target surface are selected. You can de-select edges if desired.
  • Edge Offset: An offset of one edge along a face by a specified distance; always with a given sign depending on the edge normal.
  • Projection: a projection of a face, an edge, or a vertex onto a face, edge, or vertex or a group of faces or a group of edges. The Projection transformation works in tandem with the Working Geometries feature. Using an imported Working Geometry, you can project the entities of a Target Configuration onto the entities of the imported (Working) geometry.

For this example I added a rotation for the block sticking up, a translation for the top circle face of the cylinder, and an edge offset for the lower right edge.  the result is shown in Figure 11. 

 f11_Morphed-Unmorphed
Figure 11: Part with Offset, Rotation, Translation and Edge Offset Applied. Overlaid on Original Mesh

f12_Morphed_With_labels

Figure 12: Part with Offset, Rotation, Translation and Edge Offset Applied. Labeled. 

Mesh_Morph2

Figure 13: Animation of Morphing

Whew, that is a lot of material, and we are out of time to get this article back.  Look for a Part 3.5 in the near future filling in some missing pieces and a few more examples.

If you want to try this yourself, ask you sales professional for  temp Key of the ANSYS Mesh Morpher. And as always, start simple and work your way to more complex parts.

Mapped Face Meshing in ANSYS Workbench

In the era of automatic tetrahedral meshing, many have lost their way.  Wondering analysts simply read in their geometry, specify a few sizing controls, hit a mesh button and get a mesh.  But in the end, they receive a mesh that is not ideal, especially on the surface.  What these meandering meshers need is a map… a mapped mesh. 

OK, that is a pretty lame introduction, but I’ve run out of Monty Python references and I don’t have Doug’s B movie knowledge. 

Bad intro aside, many users are not aware of the strong capabilities available in Workbench meshing for creating really nice mapped meshes on surfaces.  Once created, these mapped meshes can be used to mesh 2D and shell models as well as to extrude a mesh (sweep method) for a 3D Hex mesh or a ‘seed’ mesh for a tetrahedral mesh (patch conforming algorithm).  By using a controlled mapped mesh, users can ‘find’ their way to a better mesh.

Mapped Mesh Method

The Mapped Mesh Method has been an Mesh Control that has been in ANSYS for a while.  It is found in the Mesh Control menu item when you are in the Mesh part of the tree, or by RMB->Insert->Mapped Face Meshing.  For simple geometry, and some not so simple, you simply slap that control on a face or faces and let ANSYS figure out the best way to make a mapped mesh.

F1-Add_MethodFigure 1: Insert Mapped Face Meshing

In the past, the area had to be a pretty “square” topology – four easily identified edges.  But over the last couple of releases more intelligence has been added to recognize complex geometries as mapable. Figure 2 shows several different topologies and how the mesher does a nice job of mapping them with no user modification.

F2-MapExamplesFigure 2: Automatic Meshing of Complex Topologies with Mapped Meshes

Note that the last topology did not map mesh.  We will come back to that.  But the other five all meshed with a nice looking mapped mesh. So how does ANSYS figure out how to do this? 

What they do is take geometry and break it up into 4 sided chunks.  They call this making Submaps.  But to do this they need to identify the outside edges in terms of squarish topology. The secret to doing this is identifying the vertices (points where edges connect) as either a corner, a side or an edge.  Figure 3 (stolen from the user manual) shows an example of each:

F3-Vertex_Types
Figure 3: Vertex Types

The algorithm identifies the vertex type by looking at the inside (mesh side) angle formed by the two edges attached to the vertex using based on the following table:

Vertex Type

Angle Range

Number of Elements Connected

Image

End

0°-135°

1

T1-EndVertex

Side

136°-224°

2

T2-SideVertex

Corner

225°-314°

3

T3-CornerVertex

You can get a feel for the algorithm (but not the actual one, it is much more complex) by stepping through breaking up the geometry in Figure 3 and follow the following steps in your head:

  1. Mesh the edges creating nodes on the edges based on local and global meshing settings
  2. March around the edges making virtual edges that combine by combining any edges linked by Side vertices (the only one is F-G-A in this example).
  3. Go to the first corner you encountered.  Shoot a line along the vector from B-C until you intersect with an edge. Find F-E.
  4. Count number of nodes from A-B, call it N. Then count N nodes from F toward E and make the Nth node a virtual vertex H.
  5. Draw a virtual edge from C-H. Note, B-C-H is now one virtual edge because in B-C-H, C is now a Side vertex.
  6. Keep marching around from H till you get back to A.  You end up with 4 corners so now you have a sub map.
  7. Go back to where you broke off, C, and march around to C (remember H-C is now an edge and C looks like an End in this topology) until you get another corner.  You now have the second sub map.

Pretty cool, huh. I wish I would have thought of that.  The actual method is of course much more complex and has allsorts of checks and “if this, than do that” stuff in it.  

Helping the Algorithm Out

Sometimes the angles just don’t work out so you need to go in and tell the mesher what is a corner, side, or end.  You do this in the Details view for the Mapped Face Meshing method you attach to the face.

F4-DetailsArea
Figure 4: Details View for Mapped Face Meshing Method

You basically click on the cell for Sides, Corners and Ends and then identify the vertices for each.  The last example in figure three has rounded corners so the algorithm identifies the vertices on the rounds as Sides because they are 180° apart. The result is the free mesh shown in Figure 5. If you want a mapped mesh, you need to specify the vertices on the rounds. Figure 6 shows the result. Well, maybe sometimes the free mesh is better.

F5_RoundedCornerFreeMesh
Figure 5: Resulting Free Mesh with Automatic Identification of Vertices

f6-RoundedCornerMapMeshed
Figure 6: Mapped Mesh after Manual Identification of Vertices

The other option on really nasty geometry is to take it into DesignModeler and imprint the surfaces to create your own sub maps.

Conclusions

In most cases, just putting a Mapped Face Meshing control on a surface will give you a nice mapped mesh.  The mapped mesh is usually more uniform, has less distorted elements, no triangles, and usually has less nodes. But a mapped mesh is not always better, you need to use your engineering judgment to decide which is best in each application.  I like to use this control on fillets and on blocky parts.

So, when you are not liking the look of the default surface mesh, even if you are not hex meshing your model, turn off the autopilot, and try a Mapped Face Meshing control. 

Mid-side nodes: Do they really help?

Do those pesky mid-side nodes really do anything other than increase my node count and runtime?  Over the years, I have heard that question over and over. “Do I really need them?”  If you are using tetra elements, then the answer is absolutely, “Yes!”  They even do more than just give you nice curvature to follow your geometry.  For tetras, the midside nodes are necessary to predict proper stresses.  Lower ordered tetras are overly stiff and will under predict deflection and stresses.  Let’s look at the underlying equations that make up the shape functions in both element types.

image

Yeah, the equations for tetras are a little more complicated than that, but I really didn’t think you  wanted to go down that road. But I will remind you that low-order elements have linear shape functions, while high-order elements have quadratic shape functions. So let’s look at an example, instead, to show that lower-order tetras will give unconservative results.

For the example, I made a simply-supported, rectangular-cross-section plank.  It’s 100 inches long, by 10 inches wide, by 1 inch thick, with a 1 psi pressure load. I set the mesh size at 1 inch and solved with low-order tetras, high-order tetras, and also with low and high-order hex elements.  The results are tabulated below along with the hand-calculated solution from the 7th Edition of Roark’s Formulas for Stress and Strain, Table 8.1, case 2e.

image

image

  Deflection Def. % Diff Stress Stress  % Diff Nodes Elements
Roark’s -0.53864   7500.0 psi      
20-Node Hex -0.54159 0.55% 7527.0 psi 0.36% 7553 1,000
8-Node Hex -0.54142 0.52% 7529.5 psi 0.39% 2222 1,000
10-Node Tetra -0.54158 0.55% 7525.9 psi 0.35% 20661 11,998
4-Node Tetra* -0.27151 49.6% 2249.3 psi  –70.0% 3222 11,999

As you can see, the hex elements along with the 10-node tetras get close to the solution and provide conservative results.  The 4-node tetras, however, which are actually degenerate 8-node hex elements because ANSYS removed their 4-node tetra elements along time ago, show only half the deflection under the same load.   The extra stiffness also causes the modal frequencies to be higher. In this case, the frequencies of the low-order tetras were about 40% higher than the high-order tetras.  When you’re looking at operating ranges, this could also lead to unconservative conclusions.

Of course this is a pretty coarse mesh with only one element through the thickness. So how do the results change as the mesh is refined? We should only need to cut the element size by half to get the extra nodes and the same results, right? 

    Deflection Def. % Diff Stress Stress  % Diff Nodes Elements
Roark’s -0.53864”   7500.0 psi      
1”  -0.27151”

–49.6%

2249.3 psi

-70.0%

3,222 11,999
0.5” -0.39768”

-26.2%

4879.1 psi

-34.9%

17,624 77,612
0.3” -0.47582”

-11.7%

6069.5 psi

-19.1%

69,040 334,433
0.2” -0.51023”

-5.3%

6760.9 psi

-9.8%

213,122 1,105,641
0.1” -0.53345”

-0.96%

7309.6 psi

-2.5%

1,599,327 8,877,326

As you can see the answer is, “No.”  Because  the high-order elements have quadratic shape functions , it takes far more linear elements to make up the difference. Here is a little animation to show why. You can see the error left by each set of linear elements when try to match a quadratic function.JoeAnim1

For another example, I made a long square-cross-section bar with holes in it.  It is cantilevered with a shear load at the other end.  I set the Physics preference to Mechanical and the Relevance Center to ‘Fine’ and I got the mesh that you see below. (I’d say its not too bad for 15 seconds of works. )image

   imageimage

Just to make sure that my mesh was the same in both cases, I told Mechanical to Drop the midside nodes and then I added a Command Object in the high-order  case to convert the elements to Solid 187 tetras during the run. Since no geometry is sent from Mechanical, the midside nodes were added and the edges were kept straight, so no further curvature was picked up.  Here’s the command object to try out yourself.

imageimage

 

By scoping the results to just the hole closest to the fixed end we can see the difference in the stress values for the two runs.  The low-order tetras yield results that are 12% lower for deflection and over 19% lower for stress than the same mesh with midside nodes.  (But look, Boss! I saved 4 seconds on the solve time!!!)

  Elements Nodes Total
Deflection
SEQV Solver Runtime
Low-order 18383 4854 0.28744” 177.51 Ksi 6.677 Sec.
High-order 18383 31332 0.32633” 219.46 Ksi 10.951 Sec.

 

imageimage

imageimage

So how many low-order tetras are needed to get the same accuracy this time?   I used the Convergence Tool in Workbench to find out this time. The Convergence tool refines the mesh only for the scoped region of the results plot.  So the resultant mesh looks like this.

image

imageimage

 

clip_image001[6]

  Elements Nodes SEQV Solver Runtime
Low-order

1,271,619

234,484

21.951 Ksi

349.785 Sec.

High-order

18,383

31,332

21.946 Ksi

10.951 Sec.

The last pass took just under 6 minutes to run (349.8 sec). The stress finally gets as high as it is with the high-order elements, but the deflection results are still incorrect because the model was only refined at the hole.  And say it with me, “If the deflection is wrong, then the stress ain’t gonna be right!!!”  So basically I’ve wasted a half an hour getting the wrong solution so that you won’t have to do the same. Just remember, mid-side nodes are your friends. And just like any good friend, take advantage of them when you can!

Using the Solar Load Model in Fluent

One of the useful features in ANSYS Fluent is the solar load model. This capability can be used to calculate the effective radiation load based on the position on the earth’s surface (latitude and longitude), the model orientation with respect to North, the time of day, the season, and established conditions for clear or cloudy weather. The applications are widespread, but readily apparent are calculations of radiative heating on automotive cabins and buildings.

Two options are available for the solar load model; solar ray tracing or discrete ordinates. Solar ray tracing is coupled to Fluent by computing heat fluxes from incident solar radiation using a ray tracing and shading algorithm, and then applies the calculated heat flux on element faces of semi-transparent walls. Solar ray tracing presents less computational overhead than discrete ordinates, as it calculates the solar loads once at the beginning of a steady-state simulation. However, it uses some simplifying assumptions to do so (another example of the accuracy/solution time tradeoff that simulation analysts often encounter). It does not calculate the emission from surfaces, and the reflecting component of the incident load is distributed uniformly across all participating surfaces rather than retained locally at the surfaces reflected to. However, solar ray tracing can be coupled with one of the supported radiation models (P-1, Rosseland, Surface-to-Surface) if surface emission effects are important.

The discrete ordinates method is coupled to Fluent by calculating radiation heat fluxes on semi-transparent walls. The discrete ordinates approach directly calculates the irradiation flux as a boundary condition for the solution of the radiative transfer equation.

A key part of the Solar Load Model in Fluent is the Solar Calculator, which calculates the solar beam direction and irradiation for a known time and position. The Solar Calculator inputs are displayed in Figure 1, followed by an explanation of each.

Solar_calc_GUI

Figure 1 – Solar Calculator Panel for Fluent’s Solar Load Model

The inputs for the Solar Calculator are:

· Global position (latitude, longitude, and time zone). The time zone is measured as a plus or minus from Greenwich Mean Time (GMT).

· Starting date and time

· Orientation of the model with respect to North/East

· Solar irradiation method

· Sunshine factor

There are two choices for the irradiation method; Fair Weather Conditions (ASHRAE) and Theoretical Maximum (NREL). These methods are similar, but the Fair Weather Conditions method applies greater attenuation on the radiative load. The sunshine factor is simply a linear multiplier that allows the incident load to be reduced in order to account for cloud cover. Once the irradiation and solar beam direction are known, they are applied as inputs to the solar ray tracing algorithm or the discrete ordinates method.

After selecting the appropriate input conditions for the Flatiron Solar Calculator, you can click “Apply” to generate the irradiation and solar beam direction information. This information is printed to the Fluent TUI (text user interface) window, and typically looks something like:

Theoretical Maximum:

Sun Direction Vector: X: -0.0722563, Y: 0.799654, Z: -0.596097

Sunshine Fraction: 1

Direct Normal Solar Irradiation (at Earth’s surface) [W/m^2]: 1327.15

Diffuse Solar Irradiation – vertical surface: [W/m^2]: 105.195

Diffuse Solar Irradiation – horizontal surface [W/m^2]: 113.693

Ground Reflected Solar Irradiation – vertical surface [W/m^2]: 117.495

Figure 2 – Printed result in the Fluent interface after applying the Solar Calculator

This information is printed so that it can be used in the specification of boundary conditions. The Solar Load Model (for both Ray Tracing and Discrete Ordinates) applies a calculated solar flux on semi-transparent surfaces only, so if there are opaque surfaces in the model, the solar load will have to be applied as a boundary condition on the opaque surfaces explicitly.

The explicit application of the solar load to the opaque surfaces in the model requires the calculation of the heat flux on that surface. The solar load is a vector quantity applied to the model along the “Sun Direction Vector” (Figure 2). The incident solar load on a particular surface will be the component of this vector projected into the direction of the local surface normal vector. The result of the projection is then multiplied by the “Direct Normal Solar Irradiation” shown in the printed output in Figure 2. This value represents the heat flux which must be applied as a boundary condition on the opaque surfaces of the model. Intuitively, if the result of the dot product between the “Sun Direction Vector” and the unit normal on the surface is a negative scalar, then the surface in question is not irradiated by the sun.

The Solar Load Model is applied to calculate the load on a simple model of two solid aluminum blocks subjected to solar heating in Phoenix on a summer day at 1 pm with an ambient temperature of 100 degrees Fahrenheit (see Figure 3). The view in Figure 3 is from the South (positive y direction).

fluent01

Figure 3 – Simple geometry for coupled thermal and fluid solution with solar loading

The grid contains ~200e3 cells, and uses hex elements to resolve the interior of the blocks and tetra elements to resolve the air volume of the surroundings. Inflation layers are used at the interfaces between the air volume and the solids. The solar loads on each surface and contributions from natural convection (in the form of heat transfer coefficients) are applied as heat flux conditions on the walls of the aluminum blocks. In this case, the Solar Calculator is used to get the sun direction vector and applied load, which are applied as individual boundary conditions. The Solar ray tracing and the coupling of the Solar Load model with the radiation models is not utilized in this example, primarily because the boundaries on which the solar loads are applied are all opaque, and the re-radiation of energy is not accounted for. The coupled solver with pseudo-transient relaxation is applied for the solution of the momentum, energy, and turbulence equations. A few representative plots are shown in Figure 4 a-c.

 

fluent03fluent04fluent06

(a)                                                                (b)                                                              (c)

Figure 4 – Simulation results: (a) Temperature contours on aluminum blocks; (b) Temperature contours in a plane; (c) Vertical velocity contours in a plane

In summary, the Solar Load Model in Fluent presents a way to easily calculate details about the solar heat flux conditions given a certain geographical location, season, and time of day. Furthermore, Fluent’s Solar Load model has the capability to resolve the physics associated with solar heating of transparent media and re-radiation problems.

FE Modeler Part 2: Converting a Mesh to Geometry

HolyGrailofFEA_thumb1One of the “Holy Grails” of simulation is the ability to take a Finite Element mesh and convert it into geometry that you can then use to create a new mesh or import it into a CAD system as CAD geometry.  What most users do not know is that ANSYS, Inc. has a product that can do this -  FE Modeler.  With the addition of a very affordable Mesh Morpher License users have access to a straightforward process to convert a mesh into geometry.

People usually want to do such a conversion for one of two reasons.  The first is the “legacy mesh.”  They have a FEA mesh from the past that has no geometry associated with it and they want to make a new mesh or use it to create a mesh around it for CFD.  This can also be an STL file from somewhere.  The second is that they want to do an analysis or get a CAD part of a part that is distorted in some way by a load.  They may want to do a metal forming simulation and get the final shape for their assembly model or they may need to do a flow analysis on a piece of geometry that gets highly distorted.

The Basics:Mesh_Witch_thumb

If you have ever tried to take a mesh to geometry yourself using other tools or a CAD tool, you know it is very hard to do unless you are working with a part made out of nothing but flat planes.  This is because the way a tool like this must work is to:

  1. Take a 3D FEA model and finds only external faces.
  2. Find edges between faces that can be considered an edge.  This is done by looking at the angle between the normals of the faces and if they are above a certain criteria, they are tagged as an edge.
  3. Gather the edges into loops and find all the element faces enclosed by those loops.
  4. Fit a cylinder, plane, cone, or NURB surface to the faces and bound them with the edge loops.

If you have a simple, blocky part where all the faces meet at right angles, no problem. But add a few fillets and boom, the tools can never sort out the loops. So what to do?

You need to help the algorithm out by splitting up your faces into components (or Named Selections in Workbench speak) and make sure that those components define a chunk of external element faces that are fairly easy for the program to work with. Figures 1-4 show this for some simple blocks.

Block 1 has right angle corners so the algorithm makes quick work of it and finds six surface and 12 edges.  Unfortunately, real parts rarely have all right angles.

Block 2 has fillets and a fine enough mesh such that the algorithm can’t find any edges.  It tries to turn the entire outer surface of the mesh into one big surface, and fails.  No closed loops, bummer.

Block 3 is the same as 2, except that the top surface patch is defined by a nodal component.  This gives the algorithm enough information to create two loops and therefore a valid solid. But maybe not what you want because the larger surface kind of wraps around most of the block, and when you try to turn that into a Parasolid it usually fails, as shown in Figure 4.

The 4th block has a component defined for each surface in the original CAD model.  The algorithm loves this and makes each patch into a nice surface that then converts to usable CAD geometry.  This is fairly easy (if a bit tedious) to do if you are starting with CAD geometry, meshing it, and using the deformed shape to create a new mesh.  But if you have just a mesh you will need to be a bit of a Mechanical APDL selection guru to make it happen, but more on that below.

p2_f1_Mesh_thumb

Figure 1: Mesh from *.CDB File

p2_f2_NodalComponents_thumb

Figure 2: Nodal Components

p2_f3_Surfaces_thumb

Figure 3: Surfaces After Detection

p2_f4_CAD_Geometry_thumb

Figure 4: CAD Surfaces

The Process:

To illustrate the process, we will assume we have a real world problem:  You have a piece of tubing as shown in Figure 5 that you want to install into place, but to do so you really have to distort it (Figure 6 is the stress analysis results in the installed shape).  As you can see, there is significant ovalization and you need to figure out what the flow will be in this distorted shape.

p2_f5_TubeCADGeometry_thumb

p2_f6_TubeDeflectedShape_thumb

Figure 5: CAD Geometry

Figure 6: Installed Shape

p2_f7_SystemSchematic_thumb
Figure 7: Project Schematic of Stress and Fluid Runs

So the first step is really in the CAD area.  You need to use ANSYS DesignModeler to split your geometry up into surfaces that can be easily found and refit by FE Modeler.  One thing that always helps is to split any cylinders in half.  Break up long, nasty surfaces and merge together any small and complex ones.  You can create your components (Named Selections) here or in ANSYS Mechanical, your call.  But either way every surface that is not a plane needs to be given an individual name.  If your CAD systems supports it, you can do it in the CAD system as well before you slice and prep in ANSYS DesignModeler.

While I was writing this article Matt Sutton was doing Part 3 of his Mechanical Scripting HOWTO.  I asked him if he could make an example script that would automatically create a Named Selection for each surface in a part.  You can find it here:

http://www.padtinc.com/blog/post/2011/01/05/An-ANSYS-Mechanical-Scripting-Example.aspx

If you have complex geometry, this script is highly recommended.

Next, move into ANSYS mechanical and set up your analysis like you normally would.  If you didn’t bring over Named Selections, define them now.  Now you need to insert a simple code snippet into the  Solution Branch with two commands:

      upcoord, 1
      cdwrite

p2_f8_command_snippet_thumb2
Figure 8: Command Snippet

The UPCOORD command tells MAPDL to take the current solution (by default the last load step. If you want a different point in the solution, you need to add a SET command first) and move the nodes to the deflected shape that has been calculated. After this command your nodes are in your deformed shape. The CDWRITE command simply writes the model to a text file, and because your nodes are in the deflected position, that file will contain your distorted geometry.  Run your analysis and when it is done, the snippet is executed and the *.cdb file is written.  If you already have a solution and do not want to rerun, just go into ANSYS MAPDL and type the commands into /POST1.

Now that you have the distorted mesh, you need to get it into FE modeler.  Create a new standalone FE Modeler system and RMB on Model and choose Add Input Mesh…  Your *.cdb file is going to be in your project directory in the dp0/sys/Mech directory (of course, this assumes that you only have the one model in your project.  Use the appropriate dp* and sys* to identify your file if you are using something other than the first model in your project).

If you are not using SI units you will need to set the properties for the FE Modeler system and for the file in the Project Schematic or things will get all messed up. To do this RMB on the Model cell and choose properties.  Set the units for FE Modeler here.  Then RMB again on the cell and choose Manage Input Meshes.  This shows the file in the outline view and when you click on it, you can change the Unit System property.

Up2_f8p5_SettingUnits_thumb

Figure 8.5: Setting Units on FE Modeler and on your input mesh file

Launch FE modeler and make sure your mesh came in without any problems.  Check the Bodies and the Element types, etc…  Then look at your components in the tree.  Note that it not only captured the surface components you defined, any nodal constraint or load that you defined will show up as well.  You may need to delete some components. You can also use the selection capabilities in FE Modeler to make new components.

Once you are happy with that, it is time to let the program find faces.  Select Geometry Synthesis in the tree and then in the Details make sure that “Use Node Components” is set to Yes!  This is very important and the most common mistake users make. 

p2_f9_components_in_FEM_thumb

Figure 9: Nodal Components in FE Modeler

Now click on the Initial Geometry icon and it will go do its thing.

If you get bad surfaces, you need to go back and add more components and break things up a bit.  but if it works you should see a solid of your part.  You are not done yet.  These are not “CAD” surfaces but rather faceted (a bunch of triangles) surfaces. 

p2_f10_InitialGeometry_thumb

Figure 10: Deformed Faceted Surface

Select Initial Geometry in the tree and you should see a “Convert to Parasolid” icon on the ribbon bar.  Click that and it will use the Parasolid modeling kernal to try and fit your surfaces.  This can take a while on a complex part.  If you split things up well enough and your mesh was fine enough, you should now have a surface model of your geometry! 

p2_f11_ParasolidSurfaces_thumb

Figure 11: Parasolid Surface Geometry in FE Modeler

If you geometry is simple, it will even sew it into a solid.  But if the little icon next to your part in the tree is a surface and not a block, you still need to sew things together.  Do this by choosing the Add a Sew Tool icon or RMB-> Add a Sew Tool.  Select the surfaces you want to sew, using the tree being the easiest way to select all of them.  Then hit the generate button and see what you get.  If it does not make a solid, make the tolerance number a bit bigger.  If that still does not work, you may need to export the surfaces to a CAD tool with good surfacing and sew it there. 

To export your distorted geometry, select Parasolid Geometry in the tree and choose Export to a Parasolid File or RMB-> Export to a Parasolid File.

You have done it, you have real CAD geometry of your deformed shape!

p2_f12_SolidWorksDistortedModel_thum

Figure 12: The Holy Grail: You Distorted Geometry in Your CAD System

Getting the distorted shape into CAD is pretty critical, at least now your drawings are realistic instead of some guess at the installed shape.  But if you need to do more analysis, that proceeds like any other simulation.  You read in your CAD geometry (CAD geometry you made from distorted nodes, yea, that is what I’m talking about! Hoooo haaaa!) and set it up for your analysis and run it.  In our example we took the Parasolid file into DM and created a fluid volume inside the pipe (which is way easy to do in DM) and then did a CFD run.

p2_f13_CFD_Solution_thumb1

All in ANSYS products, all within the Workbench Environment. 

Starting with a Legacy Mesh or STL file:

The reason why the above method worked so well is that we had original CAD geometry that we could make components for.  When you start with just a legacy mesh without components you need to get in there an make nodal components on the surface.  FE Modeler has some basic node picking capabilities that you can use, but for real parts you really need to get into ANSYS Mechanical APDL and use the following method:

    1. Use ESURF with MESH200 elements to create a surface mesh from your solid mesh. 
    2. Delete the solid mesh
    3. Use picking, selection commands and such to break those elements into surfaceable chunks.
    4. When you have things split up fairly well, CDWRITE to make a CDB file for FE Modeler.

This can be pretty tedious, but a bit of up-front work will result in nicer surfaces, or determine if you even get a solid model.

Comments:

The guts of this product have been around for many release with a couple of different names, Paramesh being the most common.  At R13 we have really found that it is robust and usable for simple to moderately complex geometry. The key are the nodal components.  Set those up right and it should work out.

We have also found that working with a refined mesh is much better than a coarse one.  So if you are running an analysis to get a distorted shape, you may want more refinement than the analysis actually requires, in order to get good surfaces for a distorted solid model.

It should be noted, that although this is a pretty amazing tool, it can not do miracles.  Really complex, distorted or coarse meshes just will not work.  But do not give up.  Get what surface you can into your CAD system and patch it up there.  Bring_me_a_Shrubbery_thumb

You can download the project that has the blocks and the distorted tube and take a look at this yourself, or try it with your own geometry.  You will need to ask your ANSYS sales professional for a temp key of ANSYS Mesh Morpher to use this tool.  Play with it, get a feel for it.

So, next time your boss says “Bring me…. a…… CAD file of a Deflected Shrubbery!”  you know what to do.

Direct Modeling with SpaceClaim

Those keeping up with ANSYS, Inc. update presentations may have seen mention of a new product called ANSYS SpaceClaim Direct Modeler.  ANSYS SpaceClaim Direct Modeler is a  slightly modified version of the CAD package SpaceClaim (from the SpaceClaim Corporation).  It is sold by ANSYS, Inc. and can operate either as a stand-alone application or integrated into the Workbench environment.  It’s a nice combination of a slick CAD tool for use in a high-powered FEA program.

scdm

In case you’re keeping count, SpaceClaim brings the total number of geometry processing modules ANSYS offers up to 3:

The very first one is /prep7, available within ANSYS MAPDL.  If you’re using this for serious CAD work, you have way too much time on your hands.  It’s good at doing basic modifications (surface imprints, solid gluing, surface stitching) but not much else.  The nice thing about it is that you can harness APDL to create batch jobs.  I’ve seen this used heavily in board and package level semiconductor analyses for creating BGAs and all the other small parts that need to be considered.

The next module is DesignModeler.  This is the default CAD creation/manipulation/repair module within ANSYS Workbench (requires additional license).  DesignModeler (or DM as the cool kids call it) does everything except create detailed drawings.  It’s extremely useful for creating fluid domains, gluing bodies for conformal meshes in Workbench, repairing/modifying geometry, and is overall an indispensable tool for creating efficient models within Workbench. 

As I mentioned at the top, there is a new module called ANSYS SpaceClaim Direct Modeler (still waiting for confirmation that the cool kids call it SCDM, as the product is fairly new) which is an alternate CAD module within Workbench.  So what’s the difference between DesignModeler and SpaceClaim?  Glad you asked!  Here’s a 30k-ft top-level view:

 

DesignModeler SpaceClaim
History-Based CAD Creation Direct (Explicit) CAD Creation
Uses CAD Plug-Ins to Import Geometry Uses CAD Translators to Import Geometry
Assembling Multiple Parts is ‘Character Building’ Assembling Multiple Parts is Easy

So let’s dig in to these differences.

History vs Direct CAD Creation:

Regardless of how you create geometry, underneath the hood there’s some fairly complicated math going on to build NURB surfaces.  The overall shape of the geometry is defined by the order, control points, and knot vector in addition to all the continuity conditions that are enforced.  Now that I’ve lost your attention, the difference between history and direct CAD modeling is in how all these controls are defined.  A history-based modeler has (as you guessed) a history, typically in the form of a tree.  This means you need to have some design intent in place to have downstream features created relative to existing objects.  Long story short, this makes it easier to tweak designs while still maintaining the design intent as well as aide in any CNC machining operations (hopefully your history matches what would be performed by the machinist).

Direct modeling, on the other hand, doesn’t have a history.  It just is.  So unlike history-based modeling, you won’t run into an issue of deleting a fillet/chamfer and have downstream operations fail.  You don’t have to worry about implied datums or anything else like that.  Where the wheels fall off the direct modeling method are if you need to repeat a bunch of downstream operations.  For example, I had just completed a major defeaturing effort on a sheet-metal riveted nightmare.  The analysis showed that the current design was inadequate, so more rivets were added.  Using SpaceClaim, I can’t just go back to an upstream import and redefine a few downstream operations.  I wound up repeating the same defeaturing operations on the negative margin portion of the model, then slapped it into the existing model.  Direct modeling really shines if you’re trying to tweak the shape of a part by just pulling/pushing certain faces together, if you were using a history-based modeler you would have to base all of your operations on existing objects, which can be extremely tedious and/or impossible.  An example is shown below, where a tiny step is removed by drafting (through a ‘Pull’ operation) a face to an existing edge:

example1

Long story short, history-based offers a good ‘turn the crank’ capabilities to recreate entire assemblies based off of a few minor tweaks.  Direct modeling skips the hassle of accidental datums and other parent/child relationships.  Direct modeling may feel like CAD without a safety net, I prefer to view it as more of a Buddhist-esque CAD system.  Stop grasping after the history tree and you’ll find enlightenment (for most situations).

CAD Plug-ins vs Translators:

This one is simple.  Plug-ins require the CAD system to be installed locally on the machine.  Translators do not.  Both SC and DM will import SolidWorks, Pro/E, and all your other favorite CAD systems.  The difference is that if you’re using DM, you’ll need to have the source-CAD tool installed as well.  If you’re using SC you can free up that disk space. 

Creating Assemblies:

 

For anyone who’s ever used DM to assemble multiple parts together, I feel your pain.  It essentially uses the same methodology of /prep7’s VTRAN command to translate a selected part from one coordinate system into another.  Starting at R12, you could specify translations and rotations, but you still had to know how far to move the part to place it properly.  Once you get the hang of it, it’s not hard (just tedious).  Throw in the frozen vs active (aka unfrozen) behavior, and it can make for some choice words after hitting ‘Generate’

Oh, how I’ve wished that there was a way to specify a mate/align/insert constraint.  In comes SpaceClaim, like a knight in shining armor (or like Will Ferrell as a lumberjack in Stepbrothers…I’ll let you look it up on youtube).  Super easy to assign constraints and assemble your parts.  Like most other operations in SC, it’s intuitive.  Pick two cylindrical faces and hit ‘align’ and BAM, you’ve got a coaxial constraint.  Pick to faces and hit ‘align’, KAPOW, you’ve got an align/mate constraint. 

 


 

On top of these things, here’s a quick list of other features.

Cross-Section Mode Easy to create cross-section views

Changes made to cross-section view propagates through entire solid (awesomely awesome if you ask me)

Keyboard Shortcuts Basic keyboard shortcuts for most common operations
Midsurfacing (DM) Extract midsurface representation and thickness for use in shell meshing
Shared Topology (DM) Ability to define multi-body parts for conformal mesh
Interference Detection Find (and fix) overlapping regions in an assembly
Multiple Tabs Ability to open a single part in its own tab.  Changes made on separate tab propagate back to assembly

(DM) represents existing features currently within DesignModeler

So, now that you’re tripping over yourself to get your hands on this new tool, where do you go to learn more?  SpaceClaim has some excellent (and free) video tutorials complete with input files.  You can access these by going to:

www.spaceclaim.com

Then go to Support > Tutorials, and start downloading.

Finally, in an effort to leave you ‘wanting more’, here’s a sneak peak at what I’ll be doing during the Webinar:

example

Caps and Limits on Hardware Resources in Microsoft Windows

Sometime around 3am last October I found myself beating my head up against a server rack. I was frustrated with trying to figure out what was limiting my server hardware. I was aware of a couple limits that Microsoft had placed into its OS software. However, I had no idea how far reaching the limits were. I figured it would be best if I had a better understanding of these hardware limits. So I researched the caps that are placed on the hardware by two of the most popular Operating Systems on the planet: Microsoft Windows 7, Windows Server 2008 R2 editions and REHL.

I have compiled this easy to read superlative analysis of my facts and findings. Read on, I know you are curious to find out what I’ve uncovered.

Enjoy!


“They capped and limited US!"

Microsoft Windows Operating Systems

·        Windows 7

a.     Professional / Enterprise / Ultimate

                                                              i.      Processor: 2 Socket limit (many cores)

1.     Core limits:

a.     64-bit: 256 max quantity of cores in 1 physical processor

b.     32-bit: 32 cores max quantity of cores in 1 physical processor

                                                            ii.      RAM: 192 GB limit to amount of accessible

b.     Home Premium

                                                              i.      RAM: 16GB

c.      Home Basic

                                                              i.      RAM: 8GB

d.     Starter Edition

                                                              i.      RAM: 2 GB


 

·        Windows Server 2008

a.      Standard & R2

                                                              i.      Processor: 4 socket limit – (many cores)

1.      (4 – Parts x 12core) = 48 cores

                                                            ii.      RAM: 32 GB

·        Windows Server 2008 R2 Foundation  (R2 releases are 64-bit only)

                                                          iii.      RAM: 128 GB

·        HPC Edition 2008 R2 (R2 releases are 64-bit only)

                                                         iv.      RAM: 128 GB

·        Windows Server 2008 R2 Datacenter (R2 releases are 64-bit only)

a.     Processor: 8 socket limit

b.     RAM: 2TB

·        Windows Server 2008 R2 Enterprise (R2 releases are 64-bit only)

a.     Processor: 8 socket limit

b.     RAM: 2TB

Red Hat Enterprise Linux – 64-bit

·         Red Hat defines a logical CPU as any schedulable entity. So every core/thread in a multi-core/thread processor is a logical CPU

·         This information is by Product default.  Not the maximums of a fully licensed/subscribed REHL product.

a.     Desktop

                                                              i.      Processor: 1-2 CPU

                                                            ii.      RAM: 64 GB

b.     Basic

                                                              i.      Processor: 1-2 CPU

                                                            ii.      RAM: 16 GB

c.      Enterprise

                                                              i.      Processor: 1-8 CPU

1.     RAM: 64 GB

d.     *** Red Hat Enterprise Linux: Red Hat would be happy to create custom subscriptions with yearly fees for other configurations to fit your specific environment. Please contact Red Hat to check on costs.

References

http://msdn.microsoft.com/en-us/library/aa366778(VS.85).aspx#memory_limits

http://www.microsoft.com/hpc/en/us/default.aspx

http://www.redhat.com/rhel/compare/

AMD Opteron Magny-Cours Processor Wins InfoWorld Best CPU (Parallel Processing)

It was nice to see that the chip PADT has been using to build very inexpensive compute clusters just got recognition from an industry leading magazine:

Read the InfoWorld article here.

When we talk about these systems some folks look at us like we are a bit insane, “AMD can’t be a better solution than Intel”  It is good to see that some experts are agreeing with us.  Makes us feel less lonely out there waving the Opteron flag.

ANSYS CFX: Going 2D in CFX

If you have had the chance to work with CFX, most likely you have been working only with three-dimensional models. You usually receive a CAD model or create your own geometry and then use one of the many meshing tools available in ANSYS to mesh your 3D geometry. However, what if you are tasked to solve a simple two-dimensional model? Without thinking twice about it you create a 2D planar or axisymmetric geometry and generate a mesh. Unfortunately, when you try to read this simple 2D mesh into CFX you get an error while trying to load it. Unlike FLUENT, CFX does not have a separate 2D and 3D solver and doesn’t read in simple 2D meshes. This may first appear as a big problem but the work-around is rather simple. This article will give you the information needed to solve “2D” problems in CFX.

Since CFX is naturally a 3D solver, using a planar or axisymmetric 2D mesh is not possible. Instead, you will need to create a thin 3D volume or a thin 3D wedge, respectively. You can call these thin geometries “quasi-2D.” For example, consider the 2D planar geometry shown in Fig. 1 that represents a channel with flow entering through the boundary on the left and exiting on the right boundary. The upper and lower boundaries are no-slip walls. To solve this type of problem in CFX, you need to give the planar geometry some thickness in the 3rd dimension.

clip_image002

Figure 1: Simple 2D planar geometry representing a channel.

The first question is how thick or thin should you make the volume. You need to consider the quality of the cells so creating a thin volume usually works well. For a 2D planar geometry, a thickness of approximately 1/100th the length of the largest dimension in the model generally provides a nice mesh with good quality cells. Depending on possible smaller features in the geometry, this rule-of-thumb value can be adjusted. Thus, when you create your geometry, you can build a volume with the proper thickness or simply extrude an existing 2D planar model.

Figure 2 shows the channel geometry from Fig. 1 extruded in the 3rd dimension using the rule-of-thumb value from above. Note that if you create an extremely thin volume it may be difficult to select and to see the thin side areas for naming the boundaries. A very thin model is also not necessary and may affect the quality of the cells. The CFX solver is very robust so the thickness can vary quite a bit without any problems; however, it is best to stay consistent and using the suggestions outlined in this article are recommended.

clip_image004

Figure 2: Quasi-2D thin volume representing a channel.

Since the model is a 2D representation, you can just use a single cell thickness in the 3rd dimension. You can mesh the 2D face the same way you would mesh a regular 2D planar model. Once meshed and loaded into CFX, you can easily apply your inlet boundary, outlet boundary and upper and lower wall boundaries. The question now is what to do with the faces in the 3rd dimension. In the example above and with any geometry that represents a 2D planar model you will need to use symmetry boundaries.

Creating a “quasi-2D” model for a simple 2D planar geometry is easy enough. What about creating a model for a 2D axisymmetric geometry? In this case, we need to extrude a wedge. Again, the question is how many degrees should the wedge be extruded.

clip_image006

Figure 3: Quasi-2D thin wedge representing an axisymmetric pipe.

For a 2D axisymmetric geometry, a wedge having a thickness of about 5 degrees works just fine. An example of a 5 degree extrusion for an axisymmetric geometry representing a pipe is shown in Fig. 3. Once again, you only need a single cell in the 3rd dimension. There is no need for any special meshing near the axis. You can mesh the planar face just as you would a normal 2D geometry and take into consideration the need to resolve gradients and other important features in the flow. After loading the mesh into CFX, you apply your inlet boundary, outlet boundary and the outer wall boundary. There is no need to apply any boundary at the axis. There are now two options for the boundary condition on the faces of the 3rd dimension. If there is no flow in the 3rd direction, then you apply a symmetry boundary just as is done in the 2D planar case. If you are trying to model an axisymmetric problem with swirl, then you will need to apply a periodic boundary condition on the faces. Remember to use a periodic boundary only if you have swirling flow.

 

Summary

This article shows that solving a “2D” model in CFX is relatively straightforward. Except for the step of having to create a thin volume or wedge and applying the extra boundary conditions (symmetry or periodic) as specified in the article, setting up these types of models is the same as any other 2D solver and the results are basically identical. A helpful hint that may prove useful is as follows. The CFX solver requires that symmetry boundaries be planar to within a certain tolerance and sometimes a symmetry boundary mesh fails to meet this tolerance. This will require that you go back and remesh the model and ensure that the symmetry planes are essentially flat. However, if the solver continues to complain, you can change the offending symmetry boundary to a wall with a slip condition. The resulting solution will be the same as using a symmetry boundary.

Questions, comments and suggestions for future thermal/CFD FOCUS articles can be sent to J. Luis Rosales at the following email address: luis.rosales@padtinc.com.

IT Tips: Setting Up FreeNX for Remote Access to Linux Machines from Windows

How To Install FreeNX with Key-based authentication on CentOS 5.5 in a Windows Platform Environment

 

In this article I will show you how to install and configured one of our more popular remote access programs here at PADT, Inc.  The software that I will be showing you how to install is called FreeNX.  FreeNX is the opensource version of a product distributed by the company called NOMACHINE, http://www.nomachine.com/.  Another program that the Analysts have struggled with over the years and still is a favorite with some of the Analysts here at PADT, Inc. is a program called CYGWIN http://www.cygwin.com/. However, the analysts seem to prefer the fast interface and overall robustness of the FREENX server.

Within this guide I will attempt to break the install down into two components so that Network Administrators and IT Managers are able to have this up and running in 30 minutes. For my installation I used the How To install NX Server using FreeNX guide freely provided by the CentOS wiki site as a reference. http://wiki.centos.org/HowTos/FreeNX

Of course it’s okay to install NX server on FreeNX using the graphical user interface

STEP 1 – SERVER: NOMACHINE FREENX SERVER INSTALLATION USING GRAPHICAL INTERFACE

1.       Install FREENX on your CentOS 5.5 server. My test NX server is a DELL Poweredge 1950 server, that has an install of CentOS 5.5 64-bit edition.

a.       Console installation

                                                               i.      Login as root console

                                                             ii.      Click Applications à Add/Remove Software

                                                            iii.      You will see the following dialogue box.

                                                           iv.      clip_image002[3]_thumb[2]

                                                             v.      On The left had side scroll down the list until you see CentOS extras. On the right window select FreeNX and NX. Then select Apply. A screen shot is shown below.

                                                           vi.      clip_image004[3]_thumb[1]

                                                          vii.      Allow the dependencies check to run. When you see the image that looks like the one below prompting to Cancel or Continue. Select Continue

                                                        viii.      clip_image006[3]_thumb[1]

                                                           ix.      Next, Allow the system to download and install the packages.

                                                             x.      clip_image008[3]_thumb[1]

                                                           xi.      When it has completed the checkmark on FreeNX and NX will be selected and you can now close out the package manager.

STEP 2  – SERVER: Terminal Session command line changes for FreeNX Key-based authentication

1.       You may have thought you could get away with a GUI only installation of FreeNX but not this time.

2.       Click Applications à Accessories à Terminal

a.       clip_image010[3]_thumb[1]

3.       For my server example I choose to use vi as my text editor. However you may choose to use whatever text editor you may like. I guarantee any Linux user will immediately be impressed if you open up a terminal session and start editing the file using vi.

First lets go over of my most used vi commands: vi basics for Windows Network Administrators

                                                                           i.      i = insert text

                                                                         ii.      d = delete text

                                                                        iii.      d[space bar] = please delete the one piece of text to the right.

                                                                       iv.      dd = opps did I just delete the entire line?

                                                                         v.      :q! = Eek! get me out of here now I screwed up the file really bad. No I don’t want to save the file right now!

                                                                       vi.       :wq! = Yes save the file right now

                                                                      vii.      For further research and light reading please go here: http://www.uic.edu/depts/accc/software/unixgeneral/vi101.html

Editing the sshd_config file using vi

b.      Within your open terminal window type:

c.       cd /etc/ssh/

clip_image012[3]_thumb[1]

d.      Login as root. Because you are the Network Administrator or IT Manager. Hopefully you are already logged in as root

e.      Next type, vi sshd_config (reference or print out David’s most used vi commands first!)

f.        clip_image014[3]_thumb[1]

4.       Now don’t panic…using your down-arrow key tap down until you get to the area that reads Password Authentication. Remove the # mark by pressing (gently) d then the space bar. This will remove the # (remark) comment.

5.       Per the documentation modify if you have disallowed ssh password cleartext tunneled passwords. You will need to make the PasswordAuthentication  line to look like the above highlighted text.

6.       Next, add the following line below the text PasswordAuthetication yes

                                                                          i.      Within vi press i  

1.       This will put you into INSERT mode.

2.       Add the text AllowUsers nx

3.       Add any additional users similar to how I have it above.

a.       :ie.  AllowUsers nx userid1 userid2 Ansys, Inc.

4.       Now that you have that text added you have the vi basics for Windows Network Administrators command lists from above press. :wq!

Configure the NX database to allow passthrough authentication.

Editing the node.conf file using vi

7.       Next, we need to edit the node.conf file within the /etc/nxserver/ folder

a.       You should be back to your terminal session

b.      Within your open terminal window type:

c.       cd /etc/nxserver/

                                                                           i.      clip_image016[3]_thumb[1]

                                                                         ii.      vi node.conf

1.       With your vi editing session open tap down to the place in the file that reads  ## Authentication / Security directives

a.       clip_image018[3]_thumb[1]

b.      Un-remark # the ENABLE_PASSDB_ AUTHENTICATION =”0” and modified to read as the one highlighted above.

                                                                                                                                                   i.      ENABLE_PASSDB_AUTHENTICATION=”1”

Add your nx users to the NX Database

Add yourself to the nxserver database.

Suppose your username is ansys

·         [root@ben1]# nxserver –adduser ansys

·         NX> 100 NXSERVER – Version 1.5.0-60 OS (GPL)

·         NX> 1000 NXNODE – Version 1.5.0-60 OS (GPL)

·         NX> 716 Public key added to: /home/ ansys /.ssh/authorized_keys2

·         NX> 1001 Bye.

·         NX> 999 Bye

Assign a password for the userid’s.

Add your nx server password to the NX Database

·         [root@ben1]# nxserver –passwd ansys

·         NX> 100 NXSERVER – Version 1.5.0-60 OS (GPL)

·         New password:

·         Password changed.

·         NX> 999 Bye

Verify that you have added userid1on the AllowUsers line in the /etc/ssh/sshd_config file: and then reload sshd:

·         In your Terminal session type:

·         service sshd reload

 

·         clip_image020[3]_thumb[1]

 

STEP 3 – CLIENT INSTALLATION

·         You can download FreeNX windows client from here and install. Follow the instructions.

Key points to remember on your Windows Client Installation:

 

·         Follow the excellent instructions provided by NOMACHINE – However.

·         I suggest that you change Desktop to GNOME,

o    Ansys, Inc., Inc. installations prefers the GNOME desktop. Also increase your bandwidth slider to you current network connection.

·         I choose:

o   Host: your NX Server

o    LAN

o   Display of 1024×768 (or all available)

·         clip_image022[3]_thumb clip_image024[3]_thumb

 

The critical piece to finish the installation is to copy and paste the client key from the nxserver into your Windows Client install.

·         Located under the GENERAL tab (see image above) Click Key… and delete the key within your client installation.

o   Paste in the key from your new nx server install

o   Next, click Save.

·         To locate your nxserver key copy the text out of the file located in the directory:

o   /etc/nxserver/

§  vi client.id_dsa.key

§  copy the text out

o   client.id_dsa.key – Copy all of the text from this file and paste it into the Key.. file on your Windows Client installation.

§  As root user – highlight the text and Copy then paste into your Client

§  Again the location of the client.id_dsa.key is below

o   clip_image026[3]_thumb[1]

 

 

 

               

 

New Year, New Articles, And New Features on The Focus Blog

Sorry about the multiple posts of the customization articles.  We are still figuring out the most efficient way to post things to this blog.  LiveWriter seems the best, but we have trouble editing a post or publishing with formating.  Still learning.

We also upgraded to BlogEngine V2.0.  Things seem more stable and a bit faster.  

And lastly, we hooked the blog up to Disqus.com.  This is a community sight for blog comments that does spam filtering and controls access a bit.  We hope it will keep the offers for a very special private video chat from Amber, a bored student, to a minimum.  

The article buffer is filling up.  Look for information on a nice tool for logging on to Linux machines from Windows (NX), more information on using FE Modeler, and some useful CFD hints and tips in the comming weeks.

ANSYS Mechanical Scripting: HOWTO Part 3

Where We Left Off Last Time…

In the second part of this series I left you with a recipe for discovering ANSYS Mechanical functionality by using entities in the GUI itself to help guide your search through the ANSYS source code that is shipped with every ANSYS Mechanical installation.  This technique is the first tool in our toolbox.  In this blog post, I’ll introduce you to a couple of the internal ANSYS Mechanical data structures that are associated with geometry in particular.  I’ll simply be introducing them in this blog without any discussion of how one might determine additional functionality associated with these structures.  In a future blog post, I’ll step you through the use of the most powerful tool available in our toolbox: the Visual Studio Script Debugger.

Introducing the ANSYS Mechanical Geometry Selection Manager and B-Rep Geometry Data Structure

CAD geometry is represented inside a computer using a Boundary Representation (B-Rep) data structure.  This data structure falls into a category of data structures computer scientists like to call graphs.   In general, a graph is a structure comprised of nodes connected to each other with arcs.  A road map is a type of graph where cities represent nodes and the roads connecting them represent arcs.  Sites like facebook and linkedin are giant graphs where people are represented as nodes and friendships or acquaintances are represented as arcs.   As you can see, graphs are pretty general and you can represent lots of structured relationships with them.

In CAD geometry, the nodes in our graph are comprised of various topological entities like vertices, edges, faces, shells and bodies.  The arcs are the incident relationships that exist between these entities.  So, for example, an edge will have a start vertex and an end vertex.  These relationships can be represented by links between the particular edge and its start vertex or end vertex.  Likewise, however, the particular start vertex of one edge may be the end vertex of another edge.  So, this relationship can be represented by links between a given vertex and all of the edges to which it is attached.  There are similar relationships between edges and faces.  A series of edges will form the boundary for a given face and a series of faces might share a common edge.  Shells represent a volume that is defined by a set of connected faces. (i.e faces that share common edges)  A body is comprised of one or more shells.  Why isn’t a body the same as a shell?  Well, it turns out that bodies with internal holes are more conveniently represented as comprising of two or more shells.  One shell represents the outermost envelope and the other shells represent the internal voids.   How, then, does one know if they are inside or outside of a body?  Well, the faces that comprise a shell each have an associated outward normal vector that points to the “outside” of the body in question.  The normal vector sense is defined using an ordering on the bounding edges of a given face.  Typically as you traverse the list of edges comprising the boundary of a given face, you are actually walking counter-clockwise around the face.  Using this assumption, one can determine an outward normal.

Lets discuss some of the specifics of the ANSYS Mechanical B-Rep.  First, an individual B-Rep structure is associated with each part in a Mechanical session.  So, if you have 15 parts you will have 15 different B-Rep structures.  Second, each entity (vertex, edge, face, body) within a given B-Rep has an associated unique ID. (This ID is called the TopoID, or Topological ID)  This ID is just an unsigned integer value, with one small twist.  The top two bits of the ID encode the entity’s topological type.  That is, if you stripped off the top two bits, you would get one of the following four combinations:

Top Two Bits

Decimal Value

Topological Type

00 0 Vertex
01 1 Edge
10 2 Face
11 3 Body

The lower 30 bits actually encode the unique id for a given vertex, edge, face or body.  So, what that means is that ANSYS Mechanical is limited to geometry with fewer than roughly one billion vertices, edges, etc… If you have a model with more than that, perhaps a bit of geometry simplification is in order.

To access a given topological entity within a B-Rep object, one uses the following type of function call (Note, I haven’t introduced where the brep_object below comes from…  Bear with me, we’ll get to it soon.)

var topo_object = brep_object.Cell(topo_id);

The Cell function accepts a valid topoID and returns the associated object.  The returned object is a rich object and has numerous fields that obviously differ depending on the topological type.  So, for example, an edge object will have a StartVertex and EndVertex field that contains references to its start and end vertices in particular.  However, all topological objects have one field in common.  They all contain an ID field.  So the following code would supply the topolD of the start vertex associated with a given edge:

var brep_object = /*Get B-Rep from somewhere */
var edge_id = /* Get Edge ID from somewhere*/
var edge = brep_object.Cell(edge_id);
var start_vertex_id = edge.StartVertex.Id;

You might gather that one can get the actual start vertex object with a subsequent line like:

var start_vertex = brep_object.Cell(start_vertex_id);

Now, each vertex object is going to contain a list of edges that are attached to this vertex.  So, if we needed all the edges attached to the original edge for some reason, we could use this technique with the start vertex and the end vertex. 

Walking the B-Rep data structure is perhaps interesting at best, but it currently doesn’t do anything for us.  What we need is to be able to select some piece of geometry, or pieces of geometry.  Enter the ANSYS Mechanical Selection Manager.  This object is closely associated with the B-Rep data structures.  Before we discuss this object in some detail, consider starting each and every one of your scripts with the following code:

//  The script code object is a reference to the javascript engine embedded
//  inside the mechanical application.  This object has all of the functions
//  that are defined in the ANSYS mechanical javascript files
var SC = DS.Script;

//  The selection manager object is a reference to the ANSYS mechanical 
//  geometry selection tool.  This is a complex object that contains 
//  references to the currently selected set of geometric entities.  More
//  importantly, it contains back pointers to entity ids within the 
//  Mechanical BREP structure.
var SM = SC.sm;

This code introduces two global variables into your script.  The first object contains a reference to the actual javascript engine embedded in the Mechanical application.  This object is derived from the DS object, which represents the fundamental Mechanical application object.  You can think of the DS object as the mother of all objects.  The ScriptCode or SC object stores all of the javascript code that ships with the ANSYS mechanical product.  So, if you use the technique described in Part 2 of this series and find a particular function call, you would actually call it against this object.  So, for example, we found the function doPrototypeInsertCommandEditor() in Part 2.  If we were to actually call that function in our script, it would look like:

SC.doPrototypeInsertCommandEditor();

The second global variable shown above is the selection manager, or SM.  You can see that this object is a child of the script code object.   This object has numerous functions and properties and in a later post I hope to document as many as I can.  However, a great deal of mileage can be gained by understanding the following two function calls, and the following few properties.  I list them below in code form so you can see how they would typically be called inside a script:

/*  F U N C T I O N S   O F   T H E    S E L E C T I O N    M A N A G E R */
// Clear()  
// This function resets the selection manager so that no geometry is currently 
// selected.
SM.Clear();

// AddToSelection(partID, topoID, bShouldDraw)
// This function adds a particular topological entity (vertex, edge, face, body) 
// to the currently selected set. The first argument specifies the particular
// part this entity is associated with.  You can think of this as referencing the
// particular BRep structure.  The second argument specifies the topological
// entities specific ID.  The final argument is a boolean specifying whether or
// not the selection manager should highlight the selected geometry in green.
SM.AddToSelection(partID, topoID, bShouldDraw);

/*  P R O P E R T I E S   O F   T H E    S E L E C T I O N    M A N A G E R */
// Vertices
// The number of currently selected vertices
var num_selected_vertices = SM.Vertices;

// Edges
// The number of currently selected edges.
var num_selected_edges = SM.Edges;

// Faces
// The number of currently selected faces.
var num_selected_faces = SM.Faces

// Parts
// The number of currently selected (bodies*)
// Note: I think this is where the SM and the BRep use different
// terms for a body.  However, I may be wrong.
var num_selected_bodies = SM.Parts

// SelectedCount
// The total number of selected entities.  (Sum of the above)
var num_selected = SM.SelectedCount;

// SelectedEntityTopoID(i)
// The ith selected entity's topological id.  Note you can use the
// top two bits of this id to determine the type of this selected
// object.  i goes from 1 to SelectedCount.
var selected_topoid = SM.SelectedEntityTopoID(i);

// SelectedPartID(i)
// The part id for the ith selected entity. For models with numerous
// parts this will tell you which part the currently selected entity is
// associated with.  You use this to reference the proper BRep structure.
// i goes from 1 to SelectedCount.
var selected_partid = SM.SelectedPartID(i);

// PartMgr
// The Part Manager (PartMgr) object is a child of the selection manager.
// It also has numerous methods and properties, however, the one
// property that I have found most useful is the PartById(id).
// PartMgr.PartById(id)
// This returns the particular part object associated with a given part id
var part = SM.PartMgr.PartById(partID);

// The part object returned by the PartMgr.PartById(partID) call has 
// associated with it a given BRep data structure.  Referencing this brep
// structure is how you get from the selection manager's selected entity
// id to a given piece of topology.  So for example, assume the user
// has selected one face in the model.  This is one way we can get to that
// face object.
var topo_id = SM.SelectedEntityTopoID(1);
var part_id = SM.SelectedPartID(1);
var part = SM.PartMgr.PartById(part_id);
var brep = part.BRep;
var face = brep.Cell(topo_id);

The above code represents a small portion of the interface of the ANSYS Mechanical selection manager and also the geometry B-Rep structure.  As you can see, the two structures are coupled through the notion of a part id, which selects a given B-Rep structure, and a selected entity id, which represents a piece of topology within the specified B-Rep structure.   Once a given topological entity is identified and retrieved from the B-Rep structure, one can navigate the connectivity information contained in the B-Rep to find other topological entities nearby.  By using a combination of the Clear() function and the AddToSelection(…) function associated with the selection manager, one can programmatically control which topological entities are currently selected. 

You can see this technique in action by perusing the Example in the previous posting.

An ANSYS Mechanical Scripting Example

Creating Unique Named Selections for Every Face in A Body.

I’ve put together a simple example of creating a unique named selection for each face associated with a selected set of bodies.  This example demonstrates the some of the techniques described in Part 3 of this series.  I recommend you read that post first to get a feel for the selection manager and ANSYS B-Rep data structures before returning to this post.

The unique name for each face is built up from a base name with the part ID and face ID appended to this name.  The function call used to create the named selection was taken directly from the ANSYS source code.  I used the technique described in Part 2 to find this function.  That is, I searched first for the string “Create Named Selection” and then for the string “ID_ComponentAdd” which led me to this XML code in dstoolbar.xml

   1:  <contextToolbar handle="NamedSelections">
   2:      <display id="2500">
   3:        <entry type="button" tipid="ID_ComponentAdd" icon="addselectiontolist">
   4:          <visibilityFilter name="idMeshing"/>
   5:          <visibilityFilter name="idMeshingAlbionSimAddin"/>
   6:          <visibilityFilter name="idAlbionSimAddin"/>
   7:          <actionCallback objectId="1" methodName="doAddComponent"/>
   8:          <visibilityCallback objectId="11" methodName="CanAddComponent"/>
   9:        </entry>

Which, as you can see on line 7, there is a method call named doAddComponent().  If we look into the call for this function, we see that it calls a function called addNamedSelection(bDialogFlag, specifiedName, criteria).  We can use this function to create a named selection with a programmatically generated name.

The flow of the example code is as follows:

  1. Check to see that at least one body is selected, if not, warn the user and quit.
  2. If one or more bodies are selected, build up a list of face ids and part ids associated with each body.
  3. Clear the selection manager so that nothing is selected.
  4. Iterate over the structure of part ids and face ids constructed in step 2 .
  5. For each face, create a unique name that is comprised of the part id and the face id concatenated to a base string.
  6. When finished, clear the selection manager so that nothing is selected.  This is sort of a clean up operation.  One enhancement might be to remember the bodies that were selected and clear out the faces from the selection manager and reselect these bodies so that the program is in the same state after this macro as it was when the macro was invoked.

Here is the code.  You can copy and paste this into a text file and save it somewhere on your hard drive.  The, select a body and choose Tools->Run Macro and navigate to the text file to see it work.

/****************************************************************************
 *                                                      Phoenix Analysis And
 *                                                       Design Technologies
 ****************************************************************************
 *  This script is designed to be run from the Tools->Run Macro menu from
 *  within ANSYS Mechanical.  The purpose of the script is to create a named
 *  selection for each individual face within the currently selected body.  
 *  This script makes use of the addNamedSelection() ANSYS Mechanical function 
 *  to actually create the component once the selection has been made.
 ***************************************************************************/

//  NOTE: The base name below is used as the first part of each named
//  selection name.  Change this to something more appropriate if you desire.
var basename = 'faces';

//  Here are a series of global variables that hold references to some
//  of the main objects in the mechanical application.

//  NOTE: The DS object is defined by the script engine ahead of time.  This
//  object references the main ANSYS Mechanical application

//  The script code object is a reference to the javascript engine embedded
//  inside the mechanical application.  This object has all of the functions
//  that are defined in the ANSYS mechanical javascript files
var SC = DS.Script;

//  The selection manager object is a reference to the ANSYS mechanical 
//  geometry selection tool.  This is a complex object that contains 
//  references to the currently selected set of geometric entities.  More
//  importantly, it contains back pointers to entity ids within the 
//  Mechanical BREP structure.
var SM = SC.sm;

//  NOTE:  The ANSYS Mechanical BREP structure is a classical topological
//  data structure that defines the connectivity of the geometry within
//  the currently opened model.  This structure consists of lists of
//  vertices, edges, faces, shells, bodies and parts.  More importantly,
//  the connectivity between these entities is represented in the data
//  structure as "use" lists.  For example, a vertex contains a list
//  of edges to which it is attached.  Likewise, an edge contains a list
//  of faces to which it is attached, as well as a pointer to the start
//  and end vertices of the edge.  With this information, one can "walk"
//  the topology of the part by iterating over the various use lists.
//  For this macro, we will grab all of the faces attached to a given
//  body using the BREP structure as a guide.

//  These type constants are encoded into the top two bits of a given
//  brep entity id.
var BODY_TOPO_TYPE = 3;
var FACE_TOPO_TYPE = 2;
var EDGE_TOPO_TYPE = 1;
var VERT_TOPO_TYPE = 0;

//  There is no concept of "main" in javascript, but it makes it easy to
//  find the entry point to the script.  There is a call to this function at
//  the bottom of this script
function main() {
    // First, see if we have a body selected.  If not, report to 
    // the user that a body must be selected first.
    if (SM.Parts > 0) {
        // Do the real work
        create_faces_ns_from_body();
    } else {
        SC.WBScript.Out('You must select a body before running the \
FacesFromBody.js macro.  Please select a body and re-run this \
macro.', true);
    }
}

// This function simply picks off the top two bits of a given topo id
// and returns the decimal value [0, 1, 2 or 3]  This corresponds to
// the topological types:
//      BODY_TOPO_TYPE = 3
//      FACE_TOPO_TYPE = 2
//      EDGE_TOPO_TYPE = 1
//      VERT_TOPO_TYPE = 0
function classify_entity_type(topo_id) {
    // The top two bits store the topological entity type within the topo
    // id value
    var type = topo_id >>> 30;
    return type;
}



// This function creates a named selection of all the faces associated with
// the currently selected body(s).  
// Pre Condition:   At least one body must be selected.
// Post Condition:  The selection manager will be cleared and a new named
//                  selection will exist for each face in the body.  The
//                  named selection will be of the form:
//                  basename_partid_faceid
function create_faces_ns_from_body() {
    // See structure definition below.
    var face_id_map = new Array(SM.Parts);

    // First we want to iterate over the selected parts and create
    // a list of all of the face ids for each selected part
    for (var i = 1; i <= SM.SelectedCount; i++) {
        var topo_id = SM.SelectedEntityTopoID(i);
        var part_id = SM.SelectedPartID(i);

        // Make sure this is a body.  If not, just continue around
        if (classify_entity_type(topo_id) != BODY_TOPO_TYPE) {
            continue;
        }
        var part = SM.PartMgr.PartById(part_id);
        var brep = part.BRep;
        // Pull the body object out of the BRep structure.  The call
        // for this is the Cell function with the topological id for
        // the body of interest
        body = brep.Cell(topo_id);
                
        // This array will be used to hold a list of face ids for a given
        // body.
        var face_ids = new Array();
        // These are the actual face objects associated with this body
        var faces = body.Faces;
        // Now store all of the face ids in our face id list
        for (var f = 1; f <= faces.Count; f++) {
            face_ids.push(faces(f).Id);
        }
        // Now that we have the face ids, put them into an array of structures
        // that each look like the following:
        // |-------|
        // |   0   |-> Part ID
        // |-------|
        // |-------|
        // |   1   |-> List of face ids for this part ID
        // |-------|
        face_id_map[i - 1] = new Array(2);
        face_id_map[i - 1][0] = part_id;
        face_id_map[i - 1][1] =
            face_ids.slice(0, face_ids.length); // Slice creates a copy of the array

    }
    // Now that we've built up our datastructure of face ids, we need to select them all
    SM.Clear();
    var name = null;
    for (var i = 0; i < face_id_map.length; i++) {
        var part_id = face_id_map[i][0];
        var face_ids = face_id_map[i][1];
        for (var j = 0; j < face_ids.length; j++) {
            SM.Clear();
            // Create a unique name based on the part id and face id
            name = basename + '_' + part_id.toString() + '_' + face_ids[j].toString();
            SM.AddToSelection(part_id, face_ids[j], false);
            // Create the component
            SC.addNamedSelection(false, name, SC.id_NS_UnknownMultiCriterion);           
        }
    }
    // Clear out the selection manager
    SM.Clear();
}

// Make it happen...
main();

Happy Holidays From PADT to the ANSYS Community

aa1aa2aa3aa4

Well, another year is coming to an end and we are about to enter the Holiday Season.  It is a difficult time for many of us, leaving our computers at work, not being allowed to  log in from home, and being forced to interact with our families.  But after  a long and challenging year, even CAE elves need a break.

We want to take some time to offer a special thanks to all of you out there who read The Focus.  You have stuck with us through the transition from Newsletter to Blog, through all the bad puns, and most of all the ‘B’ movie references.  We do appreciate all the kinds words and comments that we receive.

We hope that all of you have a a fantastic holiday we wish you safe and prosperous simulation in the new year.

SnowManCFD1