Phoenix Business Journal: 6 tips for conducting a technical meeting over the Internet

pbj-phoenix-business-journal-logoOnline meeting are great.  Sharing your work in real time with others makes a huge difference. In “6 tips for conducting a technical meeting over the Internet” we share advice on how to make those online meeting even more productive.

Posted in Publications | Tagged , , , , , , | Comments Off on Phoenix Business Journal: 6 tips for conducting a technical meeting over the Internet

Keypad Shortcuts for Quick Views in Workbench

keypad1Hey, did you know that you can access predefined views in both ANSYS Mechanical and DesignModeler using your numeric keypad? You can! Assuming the front view is looking down the +Z-axis at the X-Y plane, here are the various views you can access via your numeric keypad.

For this to work, make sure you’ve clicked within the graphics window itself—not on the top window bar, or one of the tool bars, but right in the region where the model is displayed. You may need to turn off Num Lock, though it works for me on both my laptop and desktop with Num Lock on or off.

With that out of the way, here are the views:

0) Isometric view, a bit more zoomed in than the standard auto-fit isometric view. This is my preferred level of zoom while still being able to see the whole model, to be honest.

image

1) Front view (looking down the +Z-axis)

image

2) Bottom view (looking down the -Y-axis)

image

3) Right view (looking down the +X-axis)

image

4) Back up to the previous view

5) Isometric view, standard autofit (I don’t like the standard auto-fit—too much empty space. I prefer the keypad 0 level of zoom.)

image

6) Go forward to the next view in the cache

7) Left view (looking down the -X-axis)

image

8) Top view (looking down the +Y-axis)

image

9) Back view (looking down the -Z-axis)

image

Here’s a handy-dandy chart you can print out to refer to when using the numeric keypad to change views in Mechanical or DesignModeler. Share it with your friends.

image

Posted in The Focus | Tagged , , , , , , | Comments Off on Keypad Shortcuts for Quick Views in Workbench

Phoenix Business Journal: ​Finding hope at a technology open house

pbj-phoenix-business-journal-logoSometimes you hold an event as a way to educate the community, and then it comes back and educates you. This posting “​Finding hope at a technology open house” shares what we learned at our SciTech Festival open house this year.

Posted in Publications | Tagged , , , , , , | Comments Off on Phoenix Business Journal: ​Finding hope at a technology open house

Support Design and Removal for 3D Printed ULTEM-9085 (Case Study: Intake Manifold)

ULTEM-9085 is one of my favorite materials to 3D-print: one of the reasons is it is a high performance polymer that can and has been used for end part manufacturing (see my blog post about ULTEM in functional aerospace parts), but the other is because it is a demanding material to print, in ways that ABS, Polycarbonate and even Nylon are not. What makes it demanding is primarily that ULTEM supports are not soluble and need to be removed mechanically. An additional challenge comes from the fact that the support is best removed when the part is at a high temperature (175-195 C), which requires the use of gloves and reduces the user’s dexterity. For complex geometries with internal channels, this is particularly challenging and occasionally results in an inability to print a certain part in ULTEM-9085, which runs contrary to the design freedom this technology otherwise enables.

In this post, I accumulate what I have learned through working (and failing) on many an ULTEM-9085 job, as well as through discussions with other users, and share this here in terms of design and process guidelines. To demonstrate these guidelines, I use a recent geometry that we printed for the Arizona State University’s (ASU) SAE team for an engine intake manifold. These guidelines apply to the Stratasys Fortus platform (for Fused Deposition Modeling, or FDM) using the Insight software that accompanies these tools. The screen shots are from Insight 10.6, and a Fortus 400 was used to print the parts shown.

Summary of Guidelines:

  1. Orient the part to eliminate supports in regions where you cannot remove them
  2. Use the box support style
  3. Optimize parameter settings (support angle, contour width, layer thickness)
  4. Remove the supports as soon as the part comes out of the build chamber
  5. Other observations: the interface of separation

1. Part Orientation

The single most important factor in simplifying support removal is part orientation. Most users of the FDM process know that part orientation determines the amount of support material consumed and also impacts the time to build the part. When working with ULTEM-9085, the additional challenge is that it is possible to design in supports that cannot be removed and will require you to scrap the job. This is especially true of internal features. While the automatic orientation feature in Insight allows you to minimize supports, it does not account for the difficulty of removing them. Thus when you are dealing with internal features, you may need to manually orient your part such that the internal features are aligned as close to the vertical as possible, and above the support angle (to be covered later).

As shown in Figure 1, for the intake manifold, I oriented the internal pipe structure close to the vertical and had to iterate a few times and verify that I had no support in the hard-to-reach areas. While I did have supports internally, they were limited to areas that were easy to access.

Figure 1. Engine intake manifold, to be printed out of ULTEM-9085

Figure 1. Engine intake manifold, to be printed out of ULTEM-9085

Figure 2. Part orientation to avoid any internal supports

Figure 2. Part orientation to avoid any internal supports in inaccessible regions

2. Box Supports

In a recent software upgrade, Insight added the ability to create box supports. The support structures consist of adjacent boxes instead of a continuous raster, which has the effect of allowing for easier separation of the support, though does slow down the build time. In my experience this support strategy does help with removal – the one parameter to consider here is the “Perforations” setting, though the default values were used for this part. The perforation is a layer of model material that is inserted into the support to make for easier breaking off of the support material. All cleavage surfaces in Fig. 3 are at perforation edges and you can see the building like construction with each floor distinguished by a layer of model material. When you have supports in hard to access regions, consider increasing the interval height so as to ensure you get separation at the model-support interface on the part before it occurs within the support on a perforation layer.

Figure Box Supports

Figure 3. Box Supports after removal from an ULTEM-9085 part

3. Optimize Process Parameters

While orientation will have the most significant impact on the support you need, another variable to be aware of is the “Self-Support Angle” parameter. This angle is measured from the horizontal, and represents the minimum angle of the part wall that will be built without supports. As a result, to reduce support requirements, you want this number to be as low as possible so that a greater volume of the part can be self-supported. Stratasys recommends default values, but these scale as a function of the contour width, and layer thickness, as shown in Fig. 4. The values bottom out at 40 degrees for the 0.013″ layer thickness and 43 degrees for the 0.010″ layer thickness. Thus, all other things being equal, you will be able to reduce the support needed by choosing a 0.013″ layer thickness and a 0.026″ or larger contour width. Note that both of these will impact your ability to resolve thin walls and fine features, so ensure you scan through all the tool-paths to validate that the geometry is accurately filled in.

Figure 4. Graph showing how the default values of the self-support angle vary as a function of contour width for the two layer thickness options available for ULTEM. Lower the angle, less the support needed.

4. Remove Supports Immediately

Supports are best removed when the model-support interface is hot. The best time to do this is right after you remove the parts from the print chamber, which is held at 195 C for ULTEM-9085. Ensure you have safety glasses on, work with thermal gloves and have a plier handy to pull out the support. In theory the parts can be re-heated again (175 C is a reasonable value for the oven), but Stratasys suggests that each re-heat cycle actually strengthens the interface, making it harder to remove. As a result, the best time to remove the supports is immediately out of the printer. Figure 5 shows the results of support removal for the intake manifold parts, including the build sheet.

Figure 5. Support removal can be a messy affair as you beat the clock against the cooling parts. Ensure you have gloves, a plier and safety glasses on.

Figure 5. Support removal can be a messy affair as you beat the clock against the cooling parts. Ensure you have gloves, a plier and safety glasses on.

5. Other Observations: the Interface of Separation

It helps to visualize what we are trying to do when we remove supports. There are two interfaces in question here, as shown in Figure 6. One is the model-support interface, the other is the support-box structure interface. We need separation at the model-support interface since removing the thin piece of interface material can prove challenging if the box supports have broken off (as happened for the piece below). What this means is as you remove support, you need to not just pull the supports but also add some peeling force that creates the separation. Once you create separation at the correct interface, you can pull the supports and should have proper cleavage.

Figure 6. (top) Support-model interface surface, and (bottom) support structure interface - it is important to get separation at the former interface

Figure 6. (top) Support-model interface surface, and (bottom) support structure interface – it is important to get separation at the former interface

One final point to keep in mind is that in some cases, eliminating internal supports may be impossible, as shown for a different part in Figure 7 below. The point is to eliminate the support in places you cannot reach with your pliers and get enough peeling force applied to. In the case below, I chose to have supports at the wide opening since I had adequate access to them. With practice, you will get a better sense of what supports can and cannot be removed and use that intuition to better shape your design and process layout decisions before you print.

Figure 6. Support in internal features are alright as long as you have access to them

Figure 7. Support in internal features are alright as long as you have access to them

Figure 7. The final part!

Figure 8. The final part

The ULTEM intake manifold runner and plenum being put through its paces at the ASU Formula SAE test rig

Figure 9. The ULTEM intake manifold runner along with a plenum that we also printed, both being put through their paces at the ASU Formula SAE test rig (Photo Ack: Michael Conard)

Show your support for ASU’s Formula SAE team at their Facebook page and see a video about the endeavor here.

Posted in Additive Manufacturing | Tagged , , , , , | Comments Off on Support Design and Removal for 3D Printed ULTEM-9085 (Case Study: Intake Manifold)

Phoenix Business Journal: ​For tech companies, ‘green’ is all about efficiency, stupid

pbj-phoenix-business-journal-logoEngineers see the serious problems of climate change, lost habitat, pollution, and sustainability differently. This article, “For tech companies, ‘green’ is all about efficiency, stupid” is about how tech companies need to ignore the rhetoric and noise and focus on using science to produce solutions.

Posted in Publications | Tagged , , , , , , , , | Comments Off on Phoenix Business Journal: ​For tech companies, ‘green’ is all about efficiency, stupid

Kids, Pizza, Engineering – A Fantastic SciTech Festival Open House at PADT

ScitechFestivalLogoWe thought we would open PADT’s doors to families and maybe a few people would stop by. Over 250 people did just that.  What a great evening of smiling kids and adults enjoying the excitement of engineering.  Exciting engineering? Yes, we know enough to not talk about quality system protocols, matrix inversions, and non-linear turbulence model convergence. We stuck to 3D Printing, elephants on skateboards, and 3D scanners. And we fed everyone pizza.

FullSizeRenderIt was a great evening where everyone learned something.  The focus was on exposing what engineers do, what PADT does, to people who may not be technical. Mostly kids but we also saw it as a way for engineers to show their family members and friends what engineering is about.  The results far exceeded our expectation, mostly because of how great everyone who showed up was.

Some of the quotes from people who have emailed to thank us are:

“Thank you for opening up your office to me.  What a cool place!  Even though I have been familiar with and worked with 3D printing for 20+ years, it is always nice to see the new technology, products, and the output of the products. “

“… to see my son and all of the other kids so excited and amazed was truly awesome. Mason told me it was the best night of his life! And this morning his first words to me where thanking me for taking him to the event and when can we go back.”

“This is such a great opportunity for me to show my grandkids what I spent my life doing, and seeing them get so excited about it is wonderful”  

The best part of the event for most of us here at PADT were the fantastic questions.  As one of our engineers said “for 2 hours I was just lost in the joy of positive human interaction.”  We do love what we do here, but it was nice to share it with other people.

Below are some pictures from the evening.  Make sure you sign up for PADT’s email list to get invites to future events.

IMG_9051

We were pleased to be named a AZ SciTech Festival Signature Event

 

At several points in the evening, the line was headed out the door.

At several points in the evening, the line was headed out the door.

 

The Demo room was full of 3D Printers and the kids loved handling the parts.

The Demo room was full of 3D Printers and the kids loved handling the parts.

IMG_6080

Our office robot was a huge hit.

IMG_9042

The seminar room was turned into a hands-on lab for everyone to touch and feel the engineering tools we use.

IMG_5977

Some of the youngest attendees were able to give ANSYS AIM a literal spin and model the effect of a kid, a dad, and an elephant standing on a skateboard.

IMG_9045

Some people just took to a given tool, even advanced simulation.

Students with exposure to engineering were able to ask our experts in-depth questions about technologies.

IMG_6064

The haptic device was a huge hit. It give real feedback as you edit and probe an object on the computer. Needless to say, kids adapted to it far faster than the adults.

IMG_6109

Engineering students were able to dive deep into the mechanics behind 3D Printing as well as its real world applications in industry.

IMG_9039

This is Ovid. He is PADT’s new mascot. We hope to use him more in the future to help explain what we do here.

IMG_9037

This station shows how 3D Printing works, by stacking layers of material. Ovid doesn’t look as good in low resolution.

IMG_6150

Scanning was a great way for everyone to see how we inspect and reverse engineer objects.

Posted in Education, Events, Fun, News | Tagged , , , , , , , , | Comments Off on Kids, Pizza, Engineering – A Fantastic SciTech Festival Open House at PADT

Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 3)

ansys-fortran-to-c-cpp-1-00In the last post of this series I illustrated how I handled the nested call structure of the procedural interface to ANSYS’ BinLib routines.  If you recall, any time you need to extract some information from an ANSYS result file, you have to bracket the function call that extracts the information with a *Begin and *End set of function calls.  These two functions setup and tear down internal structures needed by the FORTRAN library.  I showed how I used RAII principles in C++ along with a stack data structure to manage this pairing implicitly.  However, I have yet to actually read anything truly useful off of the result file!  This post centers on the design of a set of C++ iterators that are responsible for actually reading data off of the file.  By taking the time to write iterators, we expose the ANSYS RST library to many of the algorithms available within the standard template library (STL), and we also make our own job of writing custom algorithms that consume result file data much easier.  So, I think the investment is worthwhile.

If you’ve programmed in C++ within the last 10 years, you’ve undoubtedly been exposed to the standard template library.  The design of the library is really rather profound.  This image represents the high level design of the library in a pictorial fashion:

ansys-fortran-to-c-cpp-3-01

On one hand, the library provides a set of generic container objects that provide a robust implementation of many of the classic data structures available within the field of computer science.  The collection of containers includes things like arbitrarily sized contiguous arrays (vectors), linked lists, associative arrays, which are implemented as either binary trees or as a hash container, as well as many more.  The set of containers alone make the STL quite valuable for most programmers.

On the other hand, the library provides a set of generic algorithms that encompass a whole suite of functionality defined in classic computer science.  Sorting, searching, rearranging, merging, etc… are just a handful of the algorithms provided by the library.  Furthermore, extreme care has been taken within the implementation of these algorithms such that an average programmer would hard pressed to produce something safer and more efficient on their own.

However, the real gem of the standard library are iterators.  Iterators bridge the gap between generic containers on one side and the generic algorithms on the other side.  Need to sort a vector of integers, or a double ended queue of strings?  If so, you just call the same sort function and pass it a set of iterators.  These iterators “know” how to traverse their parent container.  (Remember containers are the data structures.)

So, what if we could write a series of iterators to access data from within an ANSYS result file?  What would that buy us?  Well, depending upon which concepts our iterators model, having them available would open up access to at least some of the STL suite of algorithms.  That’s good.  Furthermore, having iterators defined would open up the possibility of providing range objects.  If we can provide range objects, then all of the sudden range based for loops are possible.  These types of loops are more than just syntactic sugar.  By encapsulating the bounds of iteration within a range, and by using iterators in general to perform the iteration, the burden of a correct implementation is placed on the iterators themselves.  If you spend the time to get the iterator implementation correct, then any loop you write after that using either the iterators or better yet the range object will implicitly be correct from a loop construct standpoint.  Range based for loops also make your code cleaner and easier to reason about locally.

Now for the downside…  Iterators are kind of hard to write.  The price for the flexibility they offer is paid for in the amount of code it takes to write them.  Again, though, the idea is that you (or, better yet somebody else) writes these iterators once and then you have them available to use from that point forward.

Because of their flexibility, standard conformant iterators come in a number of different flavors.  In fact, they are very much like an ice cream Sunday where you can pick and choose what features to mix in or add on top.  This is great, but again it makes implementing them a bit of a chore.  Here are some of the design decisions you have to answer when implementing an iterator:

Decision Options Choice for RST Reader Iterators
Dereference Data Type Anything you want Special structs for each type of iterator.
Iteration Category 1.       Forward iterator
2.       Single pass iterator
3.       Bidirectional iterator
4.       Random access iterator
Forward, Single Pass

Iterators syntactically function much like pointers in C or C++.  That is, like a pointer you can increment an iterator with the ++ operator, you can dereference an iterator with the * operator and you can compare two iterators for equality.  We will talk more about incrementing and comparisons in a minute, but first let’s focus on dereferencing.  One thing we have to decide is what type of data the client of our iterator will receive when they dereference it.  My choice is to return a simple C++ structure with data members for each piece of data.  For example, when we are iterating over the nodal geometry, the RST file contains the node number, the nodal coordinates and the nodal rotations.  To represent this data, I create a structure like this:ansys-fortran-to-c-cpp-3-02

I think this is pretty self-explanatory.  Likewise, if we are iterating over the element geometry section of an RST file, there is quite a bit of useful information for each element.  The structure I use in that case looks like this:

ansys-fortran-to-c-cpp-3-03

 

Again, pretty self-explanatory.  So, when I’m building a node geometry iterator, I’m going to choose the NodalCoordinateData structure as my dereference type.

The next decision I have to make is what “kind” of iterator I’m going to create.  That is, what types of “iteration” will it support?  The C++ standard supports a variety of iterator categories.  You may be wondering why anyone would ever care about an “iteration category”?  Well, the reason is fundamental to the design of the STL.   Remember that the primary reason iterators exist is to provide a bridge between generic containers and generic algorithms.  However, any one particular algorithm may impose certain requirements on the underlying iterator for the algorithm to function appropriately.

Take the algorithm “sort” for example.  There are, in fact, lots of different “sort” algorithms.  The most efficient versions of the “sort” algorithm require that an iterator be able to jump around randomly in constant time within the container.  If the iterator supports jumping around (a.k.a. random access) then you can use it within the most efficient sort algorithm.   However, there are certain kinds of iterators that don’t support jumping around.  Take a linked list container as an example.  You cannot randomly jump around in a linked list in constant time.  To get to item B from item A you have to follow the links, which means you have to jump from link to link to link, where each jump takes some amount of processing time.  This means, for example, there is no easy way to cut a linked list exactly in half even if you know how many items in total are in the list.  To cut it in half you have to start at the beginning and follow the links until you’ve followed size/2 number of links.  At that point you are at the “center” of the list.  However, with an array, you simply choose an index equal to size/2 and you automatically get to the center of the array in one step.  Many sort algorithms, as an example, obtain their efficiency by effectively chopping the container into two equal pieces and recursively sorting the two pieces.  You lose all that efficiency if you have to walk out to the center.

If you look at the “types” of iterators in the table above you will see that they build upon one another.  That is, at the lowest level, I have to answer the question, can I just move forward one step?  If I can’t even do that, then I’m not an iterator at all.  After that, assuming I can move forward one step, can I only go through the range once, or can I go over the range multiple times?  If I can only go over the range once, I’m a single pass iterator.  Truthfully, the forward iterator concept and the single pass iterator concept form level 1A and 1B of the iterator hierarchy.  The next higher level of functionality is a bidirectional iterator.  This type of iterator can go forward and backwards one step in constant time.  Think of a doubly linked list.  With forward and backward links, I can go either direction one step in constant time.  Finally, the most flexible iterator is the random access iterator.  These are iterators that really are like raw pointers.  With a pointer you can perform pointer arithmetic such that you can add an arbitrary offset to a base pointer and end up at some random location in a range.  It’s up to you to make sure that you stay within bounds.  Certain classes of iterators provide this level of functionality, namely those associated with vectors and deques.

So, the question is what type of iterator should we support?  Perusing through the FORTRAN code shipped with ANSYS, there doesn’t appear to be an inherent limitation within the functions themselves that would preclude random access.  But, my assumption is that the routines were designed to access the data sequentially.  (At least, if I were the author of the functions that is what I would expect clients to do.)  So, I don’t know how well they would be tested regarding jumping around.  Furthermore, disk controllers and disk subsystems are most likely going to buffer the data as it is read, and they very likely perform best if the data access is sequential.  So, even if it is possible to randomly jump around on the result file, I’m not sold on it being a good idea from a performance standpoint.  Lastly, I explicitly want to keep all of the data on the disk, and not buffer large chunks of it into RAM within my library.  So, I settled on expressing my iterators as single pass, forward iterators.  These are fairly restrictive in nature, but I think they will serve the purpose of reading data off of the file quite nicely.

Regarding my choice to not buffer the data, let me pause for a minute and explain why I want to keep the data on the disk. First, in order to buffer the data from disk into RAM you have to read the data off of the disk one time to fill the buffer.  So, that process automatically incurs one disk read.  Therefore, if you only ever need to iterate over the data once, perhaps to load it into a more specialized data structure, buffering it first into an intermediate RAM storage will actually slow you down, and consume more RAM.  The reason for this is that you would first iterate over the data stored on the disk and read it into an intermediate buffer.  Then, you would let your client know the data is ready and they would iterate over your internal buffer to access the data.  They might as well just read the data off the disk themselves! If the end user really wants to buffer the data, that’s totally fine.  They can choose to do that themselves, but they shouldn’t have to pay for it if they don’t need it.

Finally, we are ready to implement the iterators themselves.  To do this I rely on a very high quality open source library called Boost.  Boost has within it a library called iterator_facade that takes care of supplying most all of the boilerplate code needed to create a conformant iterator.  Using it has proven to be a real time saver.  To define the actual iterator, you derive your iterator class from iterator_facade and pass it a few template parameters.  One is the category defining the type of iterator you are creating.  Here is the definition for the nodal geometry iterator:

ansys-fortran-to-c-cpp-3-04

You can see that there are a few private functions here that actually do all of the work.  The function “increment” is responsible for moving the iterator forward one spot.  The function “equal” is responsible for determining if two different iterators are in fact equal.  And the function “dereference” is used to return the data associated with the current iteration spot.  You will also notice that I locally buffer the single piece of data associated with the current location in the iteration space inside the iterator.  This is stored in the pData member function.  I also locally store the current index.   Here are the implementations of the functions just mentioned:

ansys-fortran-to-c-cpp-3-05

First you can see that testing iterator equality is easy.  All we do is just look to see if the two iterators are pointing to the same index.  If they are, we define them as equal. (Note, an important nuance of this is that we don’t test to see if their buffered data is equal, just their index.  This is important later on.)  Likewise, increment is easy to understand as well.  We just increase the index by one, and then buffer the new data off of disk into our local storage.  Finally, dereference is easy too.  All we do here is just return a reference to the local data store that holds this one node’s data.  The only real work occurs in the readData() function.  Inside that function you will see the actual call to the CResRdNode() function.  We pass that function our current index and it populates an array of 6 doubles with data and returns the actual node number.  After we have that, we simply parse out of that array of 6 doubles the coordinates and rotations, storing them in our local storage.  That’s all there is to it.  A little more work, but not bad.

With these handful of operations, the boost iterator_facade class can actually build up a fully conformant iterator will all the proper operator overloads, etc… It just works.  Now that we have iterators, we need to provide a “begin” and “end” function just like the standard containers do.  These functions should return iterators that point to the beginning of our data set and to one past the end of our data set.  You may be thinking to yourself, wait a minute, how to we provide an “end” iterator without reading the whole set of nodes?  The reality is, we just need to provide an iterator that “equality tests” to be equal to the end of our iteration space?  What does that mean?  Well, what it means is that we just need to provide an iterator that, when compared to another iterator which has walked all the way to the end, it passes the “equal” test.  Look at the “equal” function above.  What do two iterators need to have in common to be considered equal?  They need to have the same index.  So, the “end” iterator simply has an index equal to one past the end of the iteration space.  We know how big our iteration space is because that is one of the pieces of metadata supplied by those ResRd*Begin functions.  So, here are our begin/end functions to give us a pair of conformant iterators.

ansys-fortran-to-c-cpp-3-06

Notice, that the nodes_end() function creates a NodeIterator and passes it an index that is one past the maximum number of nodes that have coordinate data stored on file.  You will also notice, that it does not have a second Boolean argument associated with it.  I use that second argument to determine if I should immediately read data off of the disk when the iterator is constructed.  For the begin iterator, I need to do that.  For the end iterator, I don’t actually need to cache any data.  In fact, no data for that node is defined on disk.  I just need a sentinel iterator that is one past the iteration space.

So, there you have it.  Iterators are defined that implicitly walk over the rst file pulling data off as needed and locally buffering one piece of it.  These iterators are standard conformant and thus can be used with any STL algorithm that accepts a single pass, read only, forward iterator.  They are efficient in time and storage.  There is, though, one last thing that would be nice.  That is to provide a range object so that we can have our cake and eat it too.  That is, so we can write these C++11 range based for loops.  Like this:ansys-fortran-to-c-cpp-3-07

To do that we need a bit of template magic.  Consider this template and type definition:

ansys-fortran-to-c-cpp-3-08

There is a bit of machinery that is going on here, but the concept is simple.  I just want the compiler to stamp out a new type that has a “begin()” and “end()” member function that actually call my “nodes_begin()” and “nodes_end()” functions.  That is what this template will do.  I can also create a type that will call my “elements_begin()” and “elements_end()” function.  Once I have those types, creating range objects suitable for C++11 range based for loops is a snap.  You just make a function like this:

ansys-fortran-to-c-cpp-3-09

 

This function creates one of these special range types and passes in a pointer to our RST reader.  When the compiler then sees this code:

ansys-fortran-to-c-cpp-3-10

It sees a range object as the return type of the “nodes()” function.  That range object is compatible with the semantics of range based for loops, and therefore the compiler happily generates code for this construction.

Now, after all of this work, the client of the RST reader library can open a result file, select something of interest, and start looping over the items in that category; all in three lines of code.  There is no need to understand the nuances of the binlib functions.  But best of all, there is no appreciable performance hit for this abstraction.  At the end of the day, we’re not computationally doing anything more than what a raw use of the binlib functions would perform.  But, we’re adding a great deal of type safety, and, in my opinion, readability to the code.  But, then again, I’m only slightly partial to C++.  Your mileage may vary…

Posted in The Focus | Tagged , , , , , , , , | Comments Off on Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 3)

Phoenix Business Journal: When did starting a new company become about funding?

pbj-phoenix-business-journal-logoRaising money is critical, but at some point it became what startups were about. In “When did starting a new company become about funding?” I take a look at this phenomenon and offer some reasons why we should focus more on the product or service.

Posted in Publications | Tagged , , , , , , | Comments Off on Phoenix Business Journal: When did starting a new company become about funding?

Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 2)

ansys-fortran-to-c-cpp-1-00In the last post in this series I illustrated how you can interface C code with FORTRAN code so that it is possible to use the ANSYS, Inc. BinLib routines to read data off of an ANSYS result file within a C or C++ program.  If you recall, the routines in BinLib are written in FORTRAN, and my solution was to use the interoperability features of the Intel FORTRAN compiler to create a shim library that sits between my C++ code and the BinLib code. In essence, I replicated all of the functions in the original BinLib library, but gave them a C interface. I call this library CBinLib.

You may remember from the last post that I wanted to add a more C++ friendly interface on top of the CBinLib functions.  In particular, I showed this piece of code, and alluded to an explanation of how I made this happen.  This post covers the first half of what it takes to make the code below possible.

ansys-fortran-to-c-cpp-2-01

What you see in the code above is the use of C++11 range based “for loops” to iterate over the nodes and elements stored on the result file.  To accomplish this we need to create conformant STL style iterators and ranges that iterate over some space.  I’ll describe the creation of those in a subsequent post.  In this post, however, we have to tackle a different problem.  The solution to the problem is hidden behind the “select” function call shown in the code above.  In order to provide some context for the problem, let me first show you the calling sequence for the procedural interface to BinLib.  This is how you would use BinLib if you were programming in FORTRAN or if you were directly using the CBinLib library described in the previous post.  Here is the recommended calling sequence:

ansys-fortran-to-c-cpp-2-02

You can see the design pattern clearly in this skeleton code.  You start by calling ResRdBegin, which gives you a bunch of useful data about the contents of the file in general.  Then, if you want to read geometric data, you need to call ResRdGeomBegin, which gives you a little more useful metadata.  After that, if you want to read the nodal coordinate data you call ResRdNodeBegin followed by a loop over nodes calling ResRdNode, which gives you the actual data about individual nodes, and then finally call ResRdNodeEnd.  If at that point you are done with reading geometric data, you then call ResRdGeomEnd.  And, if you are done with the file you call ResRdEnd.

Now, one thing jumps off the page immediately.  It looks like it is important to pair up the *Begin and*End calls.  In fact, if you peruse the ResRd.F FORTRAN file included with the ANSYS distribution you will see that in many of the *End functions, they release resources that were allocated and setup in the corresponding *Begin function.

So, if you forget to call the appropriate *End, you might leak resources.  And, if you forget to call the appropriate *Begin, things might not be setup properly for you to iterate.  Therefore, in either case, if you fail to call the right function, things are going to go badly for you.

This type of design pattern where you “construct” some scaffolding, do some work, and then “destruct” the scaffolding is ripe for abstracting away in a C++ type.  In fact, one of the design principles of C++ known as RAII (Resource Acquisition Is Initialization) maps directly to this problem.  Imagine that we create a class in which in the constructor of the class we call the corresponding *Begin function.  Likewise, in the destructor of the class we call the corresponding *End function.  Now, as long as we create an instance of the class before we begin iterating, and then hang onto that instance until we are done iterating, we will properly match up the *Begin, *End calls.  All we have to do is create classes for each of these function pairs and then create an instance of that class before we start iterating.  As long as that instance is still alive until we are finished iterating, we are good.

Ok, so abstracting the *Begin and *End function pairs away into classes is nice, but how does that actually help us?  You would still have to create an instance of the class, hold onto it while you are iterating, and then destroy it when you are done.  That sounds like more work than just calling the *Begin, *End directly.  Well, at first glance it is, but let’s see if we can use the paradigm more intelligently.  For the rest of this article, I’ll refer to these types of classes as BeginEnd classes, though I call them something different in the code.

First, what we really want is to fire and forget with these classes.  That is, we want to eliminate the need to manually manage the lifetime of these BeginEnd classes.  If I don’t accomplish this, then I’ve failed to reduce the complexity of the *Begin and *End requirements.  So, what I would like to do is to create the appropriate BeginEnd class when I’m ready to extract a certain type of data off of the file, and then later on have it magically delete itself (and thus call the appropriate *End function) at the right time.  Now, one more complication.  You will notice that these *Begin and*End function pairs are nested.  That is, I need to call ResRdGeomBegin before I call ResRdNodeBegin.  So, not only do I want a solution that allows me to fire and forget, but I want a solution that manages this nesting.

Whenever you see nesting, you should think of a stack data structure.  To increase the nesting level, you push an item onto the stack.  To decrease the nesting level, you pop and item off of the stack.  So, we’re going to maintain a stack of these BeginEnd classes.  As an added benefit, when we introduce a container into the design space, we’ve introduced something that will control object lifetime for us.  So, this stack is going to serve two functions for us.  It’s going to ensure we call the *Begin’s and *End’s in the right nested order, and second, it’s going to maintain the BeginEnd object lifetimes for us implicitly.

To show some code, here is the prototype for my pure virtual class that serves as a base class for all of the BeginEnd classes.  (In my code, I call these classes FileSection classes)

ansys-fortran-to-c-cpp-2-03

You can see that it is an interface class by noting the pure virtual function getLevel.  You will also notice that this function returns a ResultFileSectionLevel.  This is just an enum over file section types.  I like to use an enum as opposed to relying on RTTI.  Now, for each BeginEnd pair, I create an appropriate derived class from this base ResultFileSection class.  Within the destructor of each of the derived classes I call the appropriate *End function.  Finally, here is my stack data structure definition:

ansys-fortran-to-c-cpp-2-03p5

 

You can see that it is just a std::stack holding objects of the type SectionPtrT.  A SectionPtrT is a std::unique_ptr for objects convertible to my base section class.  This will enable the stack to hold polymorphic data, and the std::unique_ptr will manage the lifetime of the objects appropriately.   That is, when we pop and object off of the stack, the std::unique_ptr will make sure to call delete, which will call the destructor.  The destructor calls the appropriate *End function as we’ve mentioned before.

At this point, we’ve reduced our problem to managing items on a stack.  We’re getting closer to making our lives easier, trust me!  Let’s look at a couple of different functions to show how we pull these pieces together.  The first function is called reduceToLevelOrBegin(level).  See the code below:ansys-fortran-to-c-cpp-2-04

The operation of this function is fairly straightforward, yet it serves an integral role in our BeginEnd management infrastructure.   What this function does is it iteratively pops items off of our section stack until it either reaches the specified level, or it reaches the topmost ResRdBegin level.  Again, through the magic of C++ polymorphism, when an item gets popped off of the stack, eventually its destructor is called and that in turn calls the appropriate *End function.  So, what this function accomplishes is it puts us at a known level in the nested section hierarchy and, while doing so, ensures that any necessary *End functions are called appropriately to free resources on the FORTRAN side of things.  Notice that all of that happens automatically because of the type system in C++.  By popping items off of the stack, I implicitly clean up after myself.

The second function to consider is one of a family of similar functions.  We will look at the function that prepares the result file reader to read element geometry data off of the file.  Here it is:

ansys-fortran-to-c-cpp-2-05

You will notice that we start by reducing the nested level to either the “Geometry” level or the “Begin” level.  Effectively what this does is unwind any nesting we have done previously.  This is the machinery that makes “fire and forget” possible.  That is, whenever in ages past that we requested something to be read off of the result file, we would have pushed onto the stack a series of objects to represent the level needed to read the data in question.  Now that we wish to read something else, we unwind any previously existing nested Begin calls before doing so.   That is, we clean up after ourselves only when we ask to read a different set of data.  By waiting until we ask to read some new set of data to unwind the stack, we implicitly allow the lifetime of our BeginEnd classes to live beyond iteration.

At this point we have the stack in a known state; either it is at the Begin level or the Geometry level.  So, we simply call the appropriate *Begin functions depending on what level we are at, and push the appropriate type of BeginEnd objects onto the stack to record our traversal for later cleanup.  At this point, we are ready to begin iterating.  I’ll describe the process of creating iterators in the next post.  Clearly, there are lots of different select*** functions within my class.  I have chosen to make all of them private and have a single select function that takes an enum descriptor of what to select and some additional information for specifying result data.

One last thing to note with this design.  Closing the result file is easy. All that is required is that we simply fully unwind the stack.  That will ensure all of the appropriate FORTRAN cleanup code is called in the right order.  Here is the close function:

ansys-fortran-to-c-cpp-2-06

As you can see, cleanup is handled automatically.  So, to summarize, we use a stack of polymorphic data to manage the BeginEnd function calls that are necessary in the FORTRAN interface.  By doing this we ensure a level of safety in our class design.  Also, this moves us one step closer to this code:

ansys-fortran-to-c-cpp-2-07

In the next post I will show how I created iterators and range objects to enable clean for loops like the ones shown above.

Posted in The Focus | Tagged , , , , , , , , | Comments Off on Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 2)

How To Install And Configure xRDP and Same Session xRDP on CentOS 6.7 / RHEL 6.7

Introduction

What s xRDP? Taking directly from the xRDP website.

“Xrdp is the main server accepting connections from RDP clients. Xrdp contains the RDP, security, MCS, ISO, and TCP layers, a simple window manager and a few controls. Its a multi threaded single process server. It is in this process were the central management of the sessions are maintained. Central management includes shadowing a session and administrating pop ups to users. Xrdp is control by the configuration file xrdp.ini.

RDP has 3 security levels between the RDP server and RDP client. Low, medium and high. Low is 40 bit, data from the client to server is encrypted, medium is 40 bit encryption both ways and high is 128 bit encryption both ways. Xrdp currently supports all 3 encryption levels via the xrdp.ini file. RSA key exchange is used with both client and server randoms to establish the RC4 keys before the client connect.

Modules are loaded at runtime to provide the real functionality. Many different modules can be created to present one of many different desktops to the user. The modules are loadable to conserve memory and support both GPL and non GPL modules.

Multi threaded to provide optimal user performance. One client can’t slow them all down. One multi threaded process is also required for session shadowing with any module. The module doesn’t have to consider shadowing, the xrdp server does it. For example, you could shadow a VNC, RDP or a custom module session all from the same shadowing tool.

Build in window manager for sending pop ups to any user running any module. Also can be user to provide connection errors or prompts.

libvnc

Libvnc, a VNC module for xrdp. Libvnc provides a connection to VNC servers. Its a simple client only supporting a few VNC encodings(raw, cursor, copyrect). Emphasis on being small and fast. Normally, the xrdp server and the Xvnc server are the same machine so bitmap compression encodings would only slow down the session.

librdp

Librdp, an RDP module for xrdp. Librdp provides a connection to RDP servers. It only supports RDP4 connections currently.

sesman

Sesman, the session manager. Sesman is xrdp’s session manager. Xrdp connect to sesman to verify the user name / password, and also starts the user session if credentials are ok. This is a multi process / Linux only session manager. Sessions can be started or viewed from the command line via sesrun.”

STEP 1 – Setup xRDP Same on your CUBE Linux Compute Server:

  1. Add the following repository for the needed extra packages for enterprise linux
    • rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
      I am using the platform CentOS release 6.7 – 64 Bit for this installation of xRDP
  2. Install xRDP
    • yum install xrdp tigervnc-server -y
  3. Start xRDP
    • service xrdp start
  4. Enter the following commands to ensure that the xRDP services restart on a reboot
    • chkconfig xrdp on
    • chkconfig vncserver on
  5. Add the ANSYS linux users into the following groups:
    • users & video
  6. Now try it out!

mstsc

STEP 2.0.0 (optional) – How To Setup xRDP Same Session Remote Desktop on your CUBE Linux Compute Server:

2.0.1) Login as root via SSH

2.0.2) cd /etc/xrdp/

2.0.3) Edit the xrdp.ini file as the root user. Open and edit the xrdp.ini file. For same session sharing, locate and modify the last line of the xrdp.ini configuration file.

  • Change from port=-1 to port=ask-1

vi /etc/X11/Xrdp.ini
[globals]
bitmap_cache=yes
bitmap_compression=yes
port=3389
crypt_level=high
channel_code=1
max_bpp=24
#black=000000
#grey=d6d3ce
#dark_grey=808080
#blue=08246b
#dark_blue=08246b
#white=ffffff
#red=ff0000
#green=00ff00
#background=626c72
[xrdp1]
name=sesman-Xvnc
lib=libvnc.so
username=ask
password=ask
ip=127.0.0.1
port=ask-1

xrdp-1

2.0.4) Save the xrdp.ini and restart the xrdp service (command is below)

  • service xrdp restart

2.0.5) Next, For you MPI local or distributed Users, edit the following files

  • cd /etc/pam.d/
  • edit the file xrdp-sesman
  • add –> session required pam_limits.so

2.0.6) For users of xRDP same session management.

  • cd /etc/pam.d/
  • edit the common-session file
  • add –> session required pam_limits.so

STEP 2.1.0 – Open the Microsoft Remote Desktop client on your Windows Machine.

  • Try logging in from two machines or two sessions of Microsoft Remote Desktop
  • Enter the hostname or IP address of your CUBE Linux Compute Server
  • Login

(see screen capture below)

xrdp-login-presentation-graphic

STEP 2.2.0 – Pay Attention to a few things while logging in.

  • For you the originator of the RDP desktop session:
  • AS You are logging into the linux machine note the port number used for your login as the login window script executes.
  • PORT 5910

(see screen capture below)

xrdp-port-num

  •  Login! The new xRDP console session has been created on the Linux machine.
    • This session is the remote desktop session that you created so that you can share the same desktop with another user.

STEP 2.3.0 – Login process for you the secondary RDP user:

  • As you begin the remote desktop login process. Enter the port provided or that was created for the primary user. Our primary user noted and informed you that the port number for his RDP session was 5910.
  • Enter this port number into your session window when entering your login information via RDP:

(see screen capture below)

xrdp-port-num-5910

  •  Click OK to login to the desktop
  • Success! You are now both logged into the same RDP session. Both users will see the same screen and cursor move being controlled by the one or other user.

(see screen capture below)

xrdp-same-session-login

Final Thoughts pertaining to xRDP/remote desktop connections and screen sharing on 64-bit Linux.

Other/Secondary users who do not need to login to an already running/existing remote desktop session. Do not enter the port number the server, leave the port setting as -1. Logging in this way ensure you will have a unique NONSHARED remote desktop experience.

The Primary or the originator of the xRDP session. Do not use SYSTEM –> LOGOUT to close the RDP session.Simply minimize the session or click the X to close your window out.

(see screen capture below)

click-the-x

Are you aware that ANSYS recently released ANSYS 17.0? Well for you ANSYS CFD users check out the beautiful ANSYS FLUENT 17.0 GUI for Linux. If you look close enough at the screen capture you will notice that I was running one of the ANSYS fluent benchmarks.

The External Flow Over a Truck Body with a Polyhedral Mesh (truck_poly_14m) an ANSYS FLUENT benchmark.

(see screen capture below)

fluent-17.0-picture4

References/Notes/Performance Tuning for xRDP:

xRDP website – xRDP

Nvidia’s website reference: NVIDIA Graphics Cards: NVIDIA How To

Performance Tuning:

Verify that you have the latest Nvidia graphics card driver and/or you are having openGL issues:

  1. Not sure what Nvidia graphics card you have?
    1. Try running this command –> lspci -k | grep -A 2 -E “(VGA|3D)”
  2. If you already have the Nvidia graphics card driver installed but you are unsure what driver version is currently installed.
    1. Try running this command –> nvidia-smi
  3. Direct rendering –> Yes or No
    1. glxinfo|head -n 25
    2. glxinfo | grep OpenGL

Uh Oh! If the output of these commands look something like what you see below:

$ glxinfo|head -n 25
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Error: couldn’t find RGB GLX visual or fbconfig
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
Xlib: extension “GLX” missing on display “:11.0”.
name of display: :11.0

Then please add this information to the end of the xorg.conf file and reboot the server.

  • The xorg.conf file is located in: /etc/X11
  • Section “Module”
    Load “extmod”
    Load “dbe”
    Load “type1”
    Load “freetype”
    Load “glx”
    EndSection

Other Features of the NVIDIA Installer

Without options, the .run file executes the installer after unpacking it. The installer can be run as a separate step in the process, or can be run at a later time to get updates, etc. Some of the more important commandline options of nvidia-installer are:

nvidia-installer options

–uninstall
During installation, the installer will make backups of any conflicting files and record the installation of new files. The uninstall option undoes an install, restoring the system to its pre-install state.

–latest
Connect to NVIDIA’s FTP site, and report the latest driver version and the url to the latest driver file.

–update
Connect to NVIDIA’s FTP site, download the most recent driver file, and install it.

–ui=none
The installer uses an ncurses-based user interface if it is able to locate the correct ncurses library. Otherwise, it will fall back to a simple commandline user interface. This option disables the use of the ncurses library.

This how to install for xRDP was installed onto a CentOS release 6.7 (Final) Linux using PADT, Inc. – CUBE engineering simulation compute servers.

Posted in The Focus | Comments Off on How To Install And Configure xRDP and Same Session xRDP on CentOS 6.7 / RHEL 6.7

Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 1)

ansys-fortran-to-c-cpp-1-00Recently, I’ve encountered the need to read the contents of ANSYS Mechanical result files (e.g. file.rst, file.rth) into a C++ application that I am writing for a client. Obviously, these files are stored in a proprietary binary format owned by ANSYS, Inc.  Even if the format were published, it would be daunting to write a parser to handle it.  Fortunately, however, ANSYS supplies a series of routines that are stored in a library called BinLib which allow a programmer to access the contents of a result file in a procedural way.  That’s great!  But, the catch is the routines are written in FORTRAN… I’ve been programming for a long time now, and I’ll be honest, I can’t quite stomach FORTRAN.  Yes, the punch card days were before my time, but seriously, doesn’t a compiler have something better to do than gripe about what column I’m typing on… (Editor’s note: Matt does not understand the pure elegance of FORTRAN’s majestic simplicity. Any and all FORTRAN bashing is the personal opinion of Mr. Sutton and in no way reflects the opinion of PADT as a company or its owners. – EM) 

So, the problem shifts from how to read an ANSYS result file to how to interface between C/C++ and FORTRAN.  It turns out this is more complicated than it really should be, and that is almost exclusively because of the abomination known as CHARACTER(*) arrays.  Ah, FORTRAN… You see, if weren’t for the shoddy character of CHARACTER(*) arrays the mapping between the basic data types in FORTRAN and C would be virtually one for one. And thus, the mechanics of function calls could fairly easily be made to be identical between the two languages.   If the function call semantics were made identical, then sharing code between the two languages would be quite straightforward.  Alas, because a CHARACTER array has a kind of implicit length associated with it, the compiler has to do some kind of magic within any function signature that passes one or more of these arrays.  Some compilers hide parameters for the length and then tack them on to the end of the function call.  Some stuff the hidden parameters right after the CHARACTER array in the call sequence.  Some create a kind of structure that combines the length with the actual data into a special type. And then some compilers do who knows what…  The point is, there is no convention among FORTRAN compilers for handling the function call semantics, so there is no clean interoperability between C and FORTRAN.

Fortunately, the Intel FORTRAN compiler has created this markup language for FORTRAN that functions as an interoperability framework that enables FORTRAN to speak C and vice versa.  There are some limitations, however, which I won’t go into detail on here.  If you are interested you can read about it in the Intel FORTRAN compiler manual.  What I want to do is highlight an example of what this looks like and then describe how I used it to solve my problem.  First, an example:

ansys-fortran-to-c-cpp-1-01

What you see in this image is code for the first function you would call if you want to read an ANSYS result file.  There are a lot of arguments to this function, but in essence what you do is pass in the file name of the result file you wish to open (Fname), and if everything goes well, this function sends back a whole bunch of data about the contents of the file.  Now, this function represents code that I have written, but it is a mirror image of the ANSYS routine stored in the binlib library.

I’ve highlighted some aspects of the code that constitute part of the interoperability markup.  First of all, you’ll notice the markup BIND highlighted in red.  This markup for the FORTRAN function tells the compiler that I want it to generate code that can be called from C and I want the name of the C function to be “CResRdBegin”.  This is the first step towards making this function callable from C.  Next, you will see highlighted in blue something that looks like a comment.  This however, instructs the compiler to generate a stub in the exports library for this routine if you choose to compile it into a DLL.  You won’t get a .lib file when compiling this as a .dll without this attribute.  Finally, you see the ISO_C_BINDING and definition of the type of character data we can make interoperable.  That is, instead of a CHARACTER(261) data type, we use an array of single CHARACTER(1) data.  This more closely matches the layout of C, and allows the FORTRAN compiler to generate compatible code.  There is a catch here, though, and that is in the Title parameter.  ANSYS, Inc. defines this as an array of CHARACTER(80) data types.  Unfortunately, the interoperability stuff from Intel doesn’t support arrays of CHARACTER(*) data types.  So, we flatten it here into a single string.  More on that in a minute.

You will notice too, that there are markups like (c_int), etc… that the compiler uses to explicitly map the FORTRAN data type to a C data type.  This is just so that everything is explicitly called out, and there is no guesswork when it comes to calling the routine.  Now, consider this bit of code:

ansys-fortran-to-c-cpp-1-02

First, I direct your attention to the big red circle. Here you see that all I am doing is collecting up a bunch of arguments and passing them on to the ANSYS, Inc. routine stored in BinLib.lib.  You also should notice the naming convention.  My FORTRAN function is named CResRdBegin, whereas the ANSYS, Inc. function is named ResRdBegin.  I continue this pattern for all of the functions defined in the BinLib library.  So, this function is nothing more than a wrapper around the corresponding binlib routine, but it is annotated and constrained to be interoperable with the C programming language.  Once I compile this function with the FORTRAN compiler, the resulting code will be callable directly from C.

Now, there are a few more items that have to be straightened up.  I direct your attention to the black arrow.  Here, what I am doing is converting the passed in array of CHARACTER(1) data into a CHARACTER(*) data type.  This is because the ANSYS, Inc. version of this function expects that data type.  Also, the ANSYS, Inc. version needs to know the length of the file path string.  This is stored in the variable ncFname.  You can see that I compute this value using some intrinsics available within the compiler by searching for the C NULL character.  (Remember that all C strings are null terminated and the intent is to call this function from C and pass in a C string.)

Finally, after the call to the base function is made, the strings representing the JobName and Title must be converted back to a form compatible with C.  For the jobname, that is a fairly straightforward process.  The only thing to note is how I append the C_NULL_CHAR to the end of the string so that it is a properly terminated C string.

For the Title variable, I have to do something different.  Here I need to take the array of title strings and somehow represent that array as one string.  My choice is to delimit each title string with a newline character in the final output string.  So, there is a nested loop structure to build up the output string appropriately.

After all of this, we have a C function that we can call directly.  Here is a function prototype for this particular function.

ansys-fortran-to-c-cpp-1-03

So, with this technique in place, it’s just a matter of wrapping the remaining 50 functions in binlib appropriately!  Now, I was pleased with my return to the land of C, but I really wanted more.  The architecture of the binlib routines is quite easy to follow and very well laid out; however, it is very, very procedural for my tastes.  I’m writing my program in C++, so I would really like to hide as much of this procedural stuff as I can.   Let’s say I want to read the nodes and elements off of a result file.  Wouldn’t it be nice if my loops could look like this:

ansys-fortran-to-c-cpp-1-04

That is, I just do the following:

  1. Ask to open a file (First arrow)
  2. Tell the library I want to read nodal geometric data (Second arrow)
  3. Loop over all of the nodes on the RST file using C++11 range based for loops
  4. Repeat for elements

Isn’t that a lot cleaner?  What if we could do it without buffering data and have it compile down to something very close to the original FORTRAN code in size and speed?  Wouldn’t that be nice?  I’ll show you how I approached it in Part 2.

Posted in The Focus | Tagged , , , , , , , , | Comments Off on Reading ANSYS Mechanical Result Files (.RST) from C/C++ (Part 1)

Can I parameterize ANSYS Mechanical material assignments?

So we have known for a long time that we can parameterize material properties in the Engineering Data screen. That works great if we want to adjust the modulus of a material to account for material irregularities. But what if you want to change the entire material of a part from steel to aluminum? Or if you have 5 different types of aluminum to choose, on several different parts, and you want to run a Design Study to see what combination of materials is the best? Well, then you do this. The process includes some extra bodies, some Named Selections, and a single command snippet.
The first thing to do is to add a small body to your model for each different material that you want to swap in and out, and assign your needed material to them. You’ll have to add the materials to your Engineering Data prior to this. For my example I added three cubes and just put Frictionless supports on three sides of each cube. This assures that they are constrained but not going to cause any stresses from thermal loads if you forget and import a thermal profile for “All Bodies”.

ansys-material-parameters-01

Next, you make a Named Selection for each cube, named Holder1, Holder2, etc. This allows us to later grab the correct material based on the number of the Holder.

ansys-material-parameters-02

You also make a Named selection for each group of bodies for which you want to swap the materials. Name these selections as MatSwap1, MatSwap2, etc.

ansys-material-parameters-03

The command snippet goes in the Environment Branch. (ex. Static Structural, Steady-State Thermal, etc.)

ansys-material-parameters-04

!###############################################################################################################################
! MATSWAP.MAC
! Created by Joe Woodward at PADT,Inc.
! Created on 2/12/2016
!
! Usage: Create Named Selections, Holder1, Holder2, etc.,for BODIES using the materials that you want to use.
! Create Named Selections called MatSwap1, MatSwap2, etc. for the groups of BODIES for which you want to swap materials.
! Set ARG1 equal to the Holder number that has the material to give to MatSwap1.
! Set ARG2 equal to the Holder number that has the material to give to MatSwap2.
! And so on....
! A value of 0 will not swap materials for that given group.
!
! Use as is. No Modification to this command snippet is necessary.
!###############################################################################################################################
/prep7
*CREATE,MATSWAP,MAC
*if,arg1,NE,0,then
 *get,isthere,COMP,holder%arg1%,TYPE
 *get,swapgood,COMP,matswap%ARG2%,TYPE
 *if,isthere,eq,2,then
 esel,s,,,holder%arg1%
 *get,newmat,elem,ELNEXT(0),ATTR,MAT
 !swap material for Body 1
 *if,swapgood,eq,2,then
 esel,s,,,matswap%ARG2%
 emodif,all,mat,newmat
 *else
 /COM,The Named Selection - MatSwap%ARG2% is not set to one or more bodies
 *endif
 *else
 /COM,The Named Selection Holder%ARG1% is not set to one or more bodies
*endif
*endif
*END
MATSWAP,ARG1,1 !Use material from Holder1 for Swap1
MATSWAP,ARG2,2 !Use material from Holder1 for Swap2
MATSWAP,ARG3,3 !Use material from Holder1 for Swap3
MATSWAP,ARG4,4 !Use material from Holder1 for Swap4
MATSWAP,ARG5,5 !Use material from Holder1 for Swap5
MATSWAP,ARG6,6 !Use material from Holder1 for Swap6
MATSWAP,ARG7,7 !Use material from Holder1 for Swap7
MATSWAP,ARG8,8 !Use material from Holder1 for Swap8
MATSWAP,ARG9,9 !Use material from Holder1 for Swap9

alls
/solu

Now, each of the Arguments in the Command Snippet Details corresponds to the ‘MatSwap’ Name Selection of the same number. ARG1 controls the material assignment for all the bodies in the MatSwap1 name selection. The value of the argument is the number of the ‘Holder’ body with the material that you want to use. A value of zero leaves the material assignment alone and does not change the original material assignment for the bodies of that particular ‘MatSwap’ Named Selection. There is no limit on the number of ‘Holder’ bodies and materials that you can use, but there is a limit of nine ‘MatSwap’ groups that you can modify, because there are only nine ARG variables that you can parameterize in the Command Snippet details.

ansys-material-parameters-05

You can see how the deflection changes for the different material combinations. These three steps, holder bodies, Named Selections, and the command snippet above, will give you design study options that were not available before. Hopefully I’ll have an even simpler way in the future. Stay tuned.

Posted in News, The Focus | Tagged , , , | Comments Off on Can I parameterize ANSYS Mechanical material assignments?

Phoenix Business Journal: When was the last time you thanked an engineer?

pbj-phoenix-business-journal-logoHave you ever thanked an engineer?  In this week’s TechFlash post I explore how we live in a world that has been transformed for the better (mostly) by engineers.  We are simple creatures who avoid the spotlight… but a thanks you would be nice. When was the last time you thanked an engineer?

Posted in News, Publications | Comments Off on Phoenix Business Journal: When was the last time you thanked an engineer?

The 3D Printing Value Proposition

At a recent Lunch-n-Learn organized by the Arizona Technology Council, I had the opportunity to speak for 10 minutes on 3D printing. I decided to focus my talk on trying to answer one question: how can I determine if 3D printing can benefit my business? In this blog post, I attempt to expand on the ideas I presented there.

While a full analysis of the Return-On-Investment would require a more rigorous and quantitative approach, I believe there are 5 key drivers that determine the value proposition for a company to invest in 3D printing, be it in the form of outsourced services or capital expenditure. If these drivers resonate with opportunities and challenges you see in your business, it is likely that 3D printing can benefit you.

1. Accelerating Product Development

3D printing has its origins in technologies that enabled Rapid Prototyping (RP), a field that continues to have a significant impact in product development and is one most people are familiar with. As shown in Figure 1, PADT’s own product development process involves using prototypes for alpha and beta development and for testing. RP is a cost- and time effective way of iterating upon design ideas to find ones that work, without investing in expensive tooling and long lead times. If you work in product development you are very likely already using RP in your design cycle. Some of the considerations then become:

  • Are you leveraging the complete range of materials including high temperature polymers (such as ULTEM), Nylons and metals for your prototyping work? Many of these materials can be used in functional tests and not just form and fit assessments.
  • Should you outsource your RP work to a service bureau or purchase the equipment to do it in-house? This will be determined by your RP needs and one possibility is to purchase lower-cost equipment for your most basic RP jobs (using ABS, for example) and outsource only those jobs requiring specialized materials like the ones mentioned above.
PADT's Product Development process showing the role of prototypes (3D printed most of the time)

Figure 1. PADT’s Product Development process showing the role of prototypes (most often 3D printed)

The video below contains several examples of prototypes made by PADT using a range of technologies over the past two decades.

2. Exploiting Design Freedom

Due to its additive nature, 3D printing allows for the manufacturing of intricate part geometries that are prohibitively expensive (or in some cases impossible) to manufacture with traditional means. If you work with parts and designs that have complex geometries, or are finding your designs constrained by the requirements of manufacturing, 3D printing can help. This design freedom can be leveraged for several different benefits, four of which I list below:

2.1 Internal Features

As a result of its layer-by-layer approach to manufacturing a part, 3D printing enables complex internal geometries that are cost prohibitive or even impossible to manufacture with traditional means. The exhaust gas probe in Fig. 2 was developed by RSC engineering in partnership with Concept Laser has 6 internal pipes surrounded by cooling channels and was printed as one part.

3D Printed Exhaust Gas Probe (RSC Engineering and Concept Laser Inc.)

Fig 2. 3D Printed Exhaust Gas Probe with intricate internal features (RSC Engineering and Concept Laser Inc.)

2.2 Strength-to-Weight Optimization

One of the reasons the aerospace industry has been a leader in the application of 3D printing is the fact that you are now able to manufacture complex geometries that emerge from a topology optimization solution and reduce component weight, as shown in the bracket manufactured by Airbus in Figure 3.

Titanium Airbus bracket made by Concept Laser on board the A350

Fig 3. Titanium Airbus bracket made by Concept Laser on board the A350

2.3 Assembly Consolidation

The ability to work in a significantly less constrained design space also allows the designer to integrate parts in an assembly thereby reducing assembly costs and sourcing headaches. The part below (also from Airbus) is a fuel assembly that integrated 10 parts into 1 printed part.

Airbus Fuel Assembly 3D printed out of metal (Airbus / Concept Laser)

Fig 4. Airbus Fuel Assembly 3D printed out of metal (Airbus / Concept Laser)

2.4 Bio-inspiration

Nature provides several design cues, optimized through the process of evolution over millenia. Some of these include lattices and hierarchical structures. 3D printing makes it possible to translate more of these design concepts into engineering structures and parts for benefits of material usage minimization and property optimization. The titanium implant shown in Figure 5 exploits lattice designs to optimize the effective modulus in different locations to more closely represent the properties of an individuals bone in that region.

Titanium implant leveraging lattice designs (Concept Laser)

Fig 5. Titanium implant leveraging lattice designs (Concept Laser)

3. Simplifying the Supply Chain, Reducing Lead Times

One of the most significant impacts 3D printing has is on lead time reduction, and this is the reason why it is the preferred technology for “rapid” prototyping. Most users of 3D printing for end-part manufacturing identify a 70-90% reduction in lead time, primarily as a result of not requiring the manufacturing of tooling, reducing the need to identify one or more suppliers. Additionally, businesses can reduce their supplier management burden by in-sourcing the manufacturing of these parts. Finally, because of the reduced lead times, inventory levels can be significantly reduced. The US Air Force sees 3D printing as a key technology in improving their sustainability efforts to reduce the downtime associated with aircraft awaiting parts. Airbus recently also used 3D printing to print seat belt holders for their A310 – the original supplier was out of business and the cost and lead time to identify and re-tool a new supplier were far greater than 3D printed parts.

4. Reducing Costs for High Mix Low Volume Manufacturing

According to the 2015 Wohlers report, about 43% of the revenue generated in 3D printing comes from the manufacturing of functional, or end-use parts. When 3D printing is the process of choice for the actual manufacturing of end-use parts, it adds a direct cost to each unit manufactured (as opposed to an indirect R&D cost associated with developing the product). This cost, when compared to traditional means of manufacturing, is significantly lower for high mix low volume manufacturing (High Mix – LVM), and this is shown in Figure 6 for two extreme cases. At one extreme is mass customization, where each individual part has a unique geometry of construction (e.g. hearing aids, dental aligners) – in these cases, 3D printing is very likely to be the lowest cost manufacturing process. At the other end of the spectrum is High Volume Manufacturing (HVM) (e.g. semiconductor manufacturing, children’s toys), where the use of traditional methods lowers costs. The break-point lies somewhere in between and will vary by the the part being produced and the volumes anticipated. A unit cost assessment that includes the cost of labor, materials, equipment depreciation, facilities, floor space, tooling and other costs can aid with this determination.

Chart showing how volumes drive unit prices and where 3D Printing can be the cheaper option

Fig 6. Chart showing how volumes drive unit prices and where 3D Printing can be the cheaper option for low volumes and high mix manufacturing

5. Developing New Applications

Perhaps the most exciting aspect of 3D printing is how people all around the world are using it for new applications that go beyond improving upon conventional manufacturing techniques. Dr. Anthony Atala’s 2011 TED talk involved the demonstration of an early stage technique of depositing human kidney cells that could someday aid with kidney transplants (see Figure 7). Rarely does a week go by with some new 3D printing application making the news: space construction, 3D surgical guides, customized medicine to name a few. The elegant and intuitive method of building something layer-by-layer lends itself wonderfully to the imagination. And the ability to test and iterate rapidly with a 3D printer by your side allows for accelerating innovation at a rate unlike any manufacturing process that has come before it.

Dr. Anthony Atala showing a 3D printed kidney [Image Attr. Steve Jurvetson]

Fig 7. Dr. Anthony Atala showing a 3D printed kidney [Image Attr. Steve Jurvetson, Wikimedia Commons]

Conclusion

As I mentioned in the introduction, if you or your company have challenges and needs in one or more of the 5 areas above, it is unlikely to be a question of whether 3D printing can be of benefit to you (it will), but one of how you should best invest in it for maximum return. Further, it is likely that you will accrue a combination of benefits (such as assembly consolidation and supply simplification) across a range of parts, making this technology an attractive long term investment. At PADT, we offer 3D printing both as a service and also sell most of the printers we use on a daily basis and are thus well positioned to help you make this assessment, so contact us!

Posted in Additive Manufacturing, Product Development | Tagged , , , , , , | Comments Off on The 3D Printing Value Proposition

The very latest install guide for PuTTY and Xming is here!

cubelogo-2014

This how to describes how to install PuTTY and Xming and then hook the two together to provide you the end-user with an X Window System display server, a set of traditional sample X applications and tools, and a set of fonts. These two products will help to eliminate many of your frustrations! Xming features support of several languages that many of our ANSYS Analyst’s use here at PADT, Inc. We truly enjoy and use these two products. One reason for why would should be interested is that by combining Xming and PuTTY for use in numerical simulation Mesa 3D, OpenGL, and GLX 3D graphics extensions capabilities work amazingly well! Kudos to the programmers, we love you!

Program references:

Xming

PuTTY

Server: CUBE Linux 64-bit Server
Client: Windows 7 Professional 64-bit

Step 1 – Install PuTTY first (accept defaults)

Step 2 – Install Xming (accept defaults)
o Download and install the program and fonts for XMING files:
 Program:
 Fonts:

Double-check that the Normal PuTTy link with SSH client is checked

xming1

Step 3 – After the program has completed installation.

Step 4 – Install the Xming fonts that you had downloaded earlier.

Verify that Xming has been started. You will notice a new running task inside of your task bar. If you hover over the X icon in your taskbar. It should Say something like “Xming Server:0.0”

Now let us hook them together. It is X and PUTTY time!

Step 5 – Open your PUTTY application.

xming2

  • Enter the hostname or IP address.
  • Enter in a Session name:
  • On the left side bar within PUTTY. Locate –> Connection  and then expand out –> SSH –> X11
    o Check –> Enable X11 forwarding

xming3

Save the new session –> Locating on the left panel of your PUTTY program (you may need to scroll up a little bit).

Click on the text –> Session and then Save the new session.

xming2

 

Yay! now open your newly saved session and login to a CUBE linux server to test and verify.

I always forget to remember tell people this TIP but for multi display types:  Start Xming in -multiwindow mode.

How? from Command Prompt (the Windows cmd console) or create a desktop shortcut.

“C:\Program Files\Xming\Xming.exe” -multiwindow -clipboard

Have a Happy Valentines Day Weekend and do not forget to show the penguin some love too. This penguin looks lonely and maybe needs a date?

penguin_sh

Posted in The Focus | Comments Off on The very latest install guide for PuTTY and Xming is here!