turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Navigation
- Simcenter
- Forums
- Blogs
- Knowledge Bases

- Siemens PLM Community
- Simcenter
- 3D Simulation - Femap Forum
- Get element centroid by array

Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

05-31-2016 07:25 AM

Hello,

I'm trying to speed up my API/Excel code. At the moment I'm looping through the elements:

While feSet.Next 'Get element info rc = feElem.Get(feSet.CurrentID) rc = feElem.GetCentroid(arrCG) 'Set arrays for addarray load sequence nFace = 2 'Face of element to be analyzed arrnFace(setCount * 3) = nFace arrnFace(setCount * 3 + 1) = nFace arrnFace(setCount * 3 + 2) = nFace arreID(setCount) = feSet.CurrentID arrFunctionID(setCount * 5) = 0 setCount = setCount + 1 Wend

Looping through 15.000 elements makes this a bit slow. Is there a way to get the ID information and centroid information of the elements as an array from the femap database?

Thanks in advance,

Casper

Solved! Go to Solution.

18 REPLIES

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-03-2016 07:34 AM

Hello Casper,

You can get all elements IDs and coordinates using one call Element.GetAllArray. The function is a bit complex and requires to filter coordinates.

In the Nodes - you can find coordinates.

If works very quickly. Let me know if you need an example. I think I have it somewhere.

Yarko

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-03-2016 09:16 AM

Hello Yarko,

Aha, I've been looking at that method, but thought it was possible to extract elements centroid coordinates.

I'll give it a try, but an extra example is always appreciated!

Thanks in advance.

Casper

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-03-2016 06:42 PM

Hello Casper,

I've prepared a script which calculates centroid for elements. As I mentioned in previous post - Element.GetAllArray function was used. Also Node.GetCoordArray is used, because Ifirst function gives nodeIds but not coordinates as I thought.

I've added some comments to explain what I did.

Sub Main Dim App As femap.model Set App = feFemap() 'Get all elements Dim Element As femap.Elem Set Element = App.feElem Dim numElem As Long Dim entID As Variant Dim propID As Variant Dim elemType As Variant Dim topology As Variant Dim Lyr As Variant Dim color As Variant Dim formulation As Variant Dim orient As Variant Dim offset As Variant Dim release As Variant Dim orientSET As Variant Dim orientID As Variant Dim Nodes As Variant Dim connectTYPE As Variant Dim connectSEG As Variant Element.GetAllArray(0, numElem, entID, propID, _ elemType, topology, Lyr, color, formulation,orient,offset, _ release, orientSET, orientID, Nodes, connectTYPE, connectSEG ) 'Get coordinates of all nodes Dim n As femap.Node Set n = App.feNode Dim NumNode As Long Dim nodeID As Variant Dim Xyz As Variant n.GetCoordArray(0, NumNode, nodeID, Xyz) Dim ElementNodes(19) As Integer 'Loop through all elements and calculate centroid for each For i = 0 To numElem - 1 'copy elements nodes to separate array For j = 0 To 19 ElementNodes(j) = Nodes(j + i* 20) Next 'calculate centroid based on nodes coordinates. Quick Method. Dim centroid() As Double centroid = CalculateCentroid(ElementNodes,NumNode, nodeID, Xyz) 'printing a message will slow down the tool. Use only for testing 'App.feAppMessage(FCM_NORMAL, "Method1. Element ID = " & entID(i) & " x = " & centroid(0) & ", y = " & centroid(1) & ", z = " & centroid(2)) 'calculate centroid using Element.GetCentroid. For testing purpose 'Dim centroid2() As Double 'centroid2 = CalculateCentroidUsingFemapFunction(Element, entID(i)) 'App.feAppMessage(FCM_NORMAL, "MEthod2. Element ID = " & entID(i) & " x = " & centroid2(0) & ", y = " & centroid2(1) & ", z = " & centroid2(2)) Next End Sub Function CalculateCentroid(ByVal ElementNodes As Variant, ByVal NumNode As Integer, ByVal NodesIDs As Variant, ByVal Xyz As Variant) As Double() Dim centroid(2) As Double Dim count As Integer For i = 0 To 19 If ElementNodes(i) <> 0 Then For j = 0 To NumNode-1 If (NodesIDs(j) = ElementNodes(i)) Then centroid(0) += Xyz(j*3) centroid(1) += Xyz(j*3+1) centroid(2) += Xyz(j*3 + 2) count += 1 End If Next End If Next centroid(0) /= count centroid(1) /= count centroid(2) /= count CalculateCentroid = centroid End Function Function CalculateCentroidUsingFemapFunction(ByVal Element As femap.Elem, ByVal ElementId As Integer) As Double() Dim centroid(2) As Double Dim cgXyz As Variant Element.Get(ElementId) Element.GetCentroid(cgXyz) centroid(0) = cgXyz(0) centroid(1) = cgXyz(1) centroid(2) = cgXyz(2) CalculateCentroidUsingFemapFunction = cgXyz End Function

I've create 2 methods: 1)**CalculateCentroid** - fast method. 2) CalculateCentroidUsingFemapFunction - slow method, call foreach element GetCentroid, it is for testing purpose.

The results for the tool:

Method1. Element ID = 1 x = -0.08333335, y = 0.4, z = 0

MEthod2. Element ID = 1 x = -0.08333335, y = 0.4, z = 0

Method1. Element ID = 2 x = -0.08333335, y = 0.2, z = 0

MEthod2. Element ID = 2 x = -0.08333335, y = 0.2, z = 0

Method1. Element ID = 3 x = -0.08333335, y = 0, z = 0

MEthod2. Element ID = 3 x = -0.08333335, y = 0, z = 0

Method1. Element ID = 4 x = -0.08333335, y = -0.2, z = 0

MEthod2. Element ID = 4 x = -0.08333335, y = -0.2, z = 0

Let me know if you are happy with performance. Because there is one possible improvement but a bit tricky.

If you have question about the code don't hesitate to ask.

Yarko

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 03:36 AM

Hi Yarko,

Thanks that you'vw wirten out the code already. I was underway writing down the concept myself.

however upon testing the code (I'm running it from excel VBA) I'm getting an overflow error message. Me and my colleague have investigated it, but without any solution.

The error appears in this part of the code:

1 For i = 0 To numElem - 1 2 'copy elements nodes to separate array 3 For j = 0 To 19 4 ElementNodes(j) = Nodes(j + i * 20) 5 Next 6 7 'calculate centroid based on nodes coordinates. Quick Method. 8 Dim mycentroid2() As Double 9 mycentroid2 = CalculateCentroid(ElementNodes, NumNode, nodeID, Xyz)

Either at the 4th line, or at the 9th line..

I'm without any clues on possibilities. Do you have any clue?

Thanks in advance. Casper

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 03:55 AM

Hi Casper,

I've tested this script only in Femap on small model.

I will try to run it on big model from Femap and also will check from Excel VBA.

When I will find something I will let you know.

Yarko

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 05:01 AM

Hello Casper,

I've found where was the problem. In the following line:

Dim ElementNodes(19) As Integer

If replace on this, it works.

Dim ElementNodes(19) As Long

But I've did a test on model 9000 elements and 6000 nodes. And it turns out that my method is slow. I suspect it can happen, because I'm looking for coordinates for each element in big array - 6000 nodes.

When I run second method it turns to be very quick. It takes me about 1-2 seconds to get all centroids. It strange because I do 18000 calls to Femap.

I've update my script and attached. Can you try to use it and check if you have same performance using second method?

My first required optimization to be quick. Let me know if second method is slow and I will try to optimize first method (that use coordinates). If you performance is ok for you we will leave it as it is.

Yarko

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 05:06 AM - edited 06-07-2016 05:20 AM

Reply to message 06-07-2016 09:55 AM

Hi Yarko,

I've located it myself already!

Dim ElementNodes(19) As Long

1) Should be declared as Long instead of integer

Function CalculateCentroid(ByVal ElementNodes As Variant, ByVal NumNode As Long, ByVal NodesIDs As Variant, ByVal Xyz As Variant) As Double()

2) NumNode should be Long instead of integer

3) i and j weren't declared yet

The code runs slower due to the lookup list in the second function, with respect to my original one. However, I'm thinking of tuning it to list the nodes and elements in 2 arrays, by which the function can be calculated linear and hopefully faster.

Preliminary code now:

Option Explicit Public Sub Main() 'Start Stopwatch timer; not actual used, only for optimizing code processing time Dim sw As Stopwatch Set sw = New Stopwatch sw.StartTimer Dim App As Object: Set App = GetObject(, "femap.model") 'Get all elements Dim Element As femap.Elem Set Element = App.feElem Dim feSet As femap.Set: Set feSet = App.feSet Dim n As femap.Node Set n = App.feNode Dim i As Long Dim j As Long Dim NumNode As Long Dim nodeID As Variant Dim Xyz As Variant Dim ElementNodes(19) As Long Dim centroid() As Double Dim numElem As Long Dim entID As Variant Dim propID As Variant Dim elemType As Variant Dim topology As Variant Dim Lyr As Variant Dim color As Variant Dim formulation As Variant Dim orient As Variant Dim offset As Variant Dim release As Variant Dim orientSET As Variant Dim orientID As Variant Dim Nodes As Variant Dim connectTYPE As Variant Dim connectSEG As Variant Dim msg As VbMsgBoxResult Dim rc As zReturnCode rc = feSet.Select(FT_ELEM, True, "Select elements for sea pressure application") 'Select by user input in query box 'rc = feSet.AddGroup(FT_ELEM, 41) 'Select with pre defined group number If rc = FE_CANCEL Or rc = FE_NOT_EXIST Then Exit Sub rc = Element.GetAllArray(feSet.ID, numElem, entID, propID, _ elemType, topology, Lyr, color, formulation, orient, offset, _ release, orientSET, orientID, Nodes, connectTYPE, connectSEG) 'Get coordinates of all nodes rc = n.GetCoordArray(0, NumNode, nodeID, Xyz) 'Loop through all elements and calculate centroid for each For i = 0 To numElem - 1 'copy elements nodes to separate array For j = 0 To 19 ElementNodes(j) = Nodes(j + i * 20) Next 'calculate centroid based on nodes coordinates. Quick Method. centroid = CalculateCentroid(ElementNodes, NumNode, nodeID, Xyz) 'printing a message will slow down the tool. Use only for testing 'App.feAppMessage(FCM_NORMAL, "Method1. Element ID = " & entID(i) & " x = " & centroid(0) & ", y = " & centroid(1) & ", z = " & centroid(2)) 'calculate centroid using Element.GetCentroid. For testing purpose 'Dim centroid() As Double 'centroid = CalculateCentroidUsingFemapFunction(Element, entID(i)) 'App.feAppMessage(FCM_NORMAL, "MEthod2. Element ID = " & entID(i) & " x = " & centroid2(0) & ", y = " & centroid2(1) & ", z = " & centroid2(2)) Next msg = MsgBox("Load application completed!" & vbNewLine & _ "That took: " & Format(sw.EndTimer / 1000, "#,#0.0") & "seconds") Application.StatusBar = "" End Sub Function CalculateCentroid(ByVal ElementNodes As Variant, ByVal NumNode As Long, ByVal NodesIDs As Variant, ByVal Xyz As Variant) As Double() Dim mycentroid(2) As Double Dim count As Integer Dim i As Long Dim j As Long count = 0 For i = 0 To 19 If ElementNodes(i) <> 0 Then For j = 0 To NumNode - 1 If (NodesIDs(j) = ElementNodes(i)) Then mycentroid(0) = mycentroid(0) + Xyz(j * 3) mycentroid(1) = mycentroid(1) + Xyz(j * 3 + 1) mycentroid(2) = mycentroid(2) + Xyz(j * 3 + 2) count = count + 1 End If Next End If Next mycentroid(0) = mycentroid(0) / count mycentroid(1) = mycentroid(1) / count mycentroid(2) = mycentroid(2) / count CalculateCentroid = mycentroid End Function

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 05:33 AM

Hi Yarko,

Yes, I've tested it on a selection with 15.000 elements / 16.000 nodes

Whole model contains: 96.000 elements / 68.500 nodes

Speed on testing the selection of elements & nodes:

Method 2: 17,0 seconds

Method 1: not tested

Original method: 16,7 seconds (similar functions as your method 2, but code written different)

I would be delighted to have a optimized method 1, since I'll have to perform the operation multiple times..

Thanks in advance!

Casper

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-07-2016 05:38 AM

Dear Casper,

Today in the evening I will do some optimization then for method 1.

Short question: you say you will run this method few times. Maybe it is possible to call it once and put into some matrix and use later from this matrix?

Yarko

Follow Siemens PLM Software

© 2017 Siemens Product Lifecycle Management Software Inc