How to get circumferential grids by selecting a node using TCL

Altair Forum User
Altair Forum User
Altair Employee
edited October 2020 in Community Q&A

Hi,

I have a meshed cylinder (2d) on which i want to give an option to select a node to user. Once the node is selected, and clicked on proceed button it should display all the circumferential grids having a user defined number to the grids. Let's say i select a grid having ID as 122. Now, i want to display all the circumferential grid starting from 123 on the same station location where user has picked the node. I want to do it using TCL/ TK.

Thanks

«1

Answers

  • tinh
    tinh Altair Community Member
    edited September 2017

    Is that node located on free edge?

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    Is that node located on free edge?

    It's located on the circumference anywhere the user selects.

  • tinh
    tinh Altair Community Member
    edited September 2017

    It's not easy I think

  • tinh
    tinh Altair Community Member
    edited September 2017

    Do the nodes form a circle or an ellip possibly?

  • tinh
    tinh Altair Community Member
    edited September 2017

    You said a cylinder so the nodes will be planar

    You can select them by createmark 'on plane'

    You have to detect cylinder axis vector, with base node is selected one, will define a plane, as args of createmark

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    You said a cylinder so the nodes will be planar

    You can select them by createmark 'on plane'

    You have to detect cylinder axis vector, with base node is selected one, will define a plane, as args of createmark

    I think there is a bit of confusion here. Refer the image, as can be seen i have a node selected using '*createentitypanel node'. Now, as the black circles shows circumferential node locations on the same axial station. I want to get their IDs as stated in the problem. Or just if i can get any info for all the nodes on that circumference. 

    <?xml version="1.0" encoding="UTF-8"?>selected node.PNG

  • tinh
    tinh Altair Community Member
    edited September 2017

    Yeh. I do talk that

    You can get ids by createmark 'on plane'

    Can you fetch axis vector of the cylinder?

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    Yeh. I do talk that

    You can get ids by createmark 'on plane'

    Can you fetch axis vector of the cylinder?

    I'm not sure about it. I'll need to try that. But how would you suggest the approaches if i can fetch the axis vector or if i can not fetch the axis vector?

  • tinh
    tinh Altair Community Member
    edited September 2017

    Another way: get normal vector at the white node, get 2 intersected points of this with cylynder, get mid point, then get closest nodes to midpoint

  • tinh
    tinh Altair Community Member
    edited September 2017

    You can fetch axis vector by surf lines, one of them is parallel to axis

    If noone is, create parametric lines which will be parallel to axis

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    Another way: get normal vector at the white node, get 2 intersected points of this with cylynder, get mid point, then get closest nodes to midpoint

    Which APIs i can use to get normal vector and do the following?

  • tinh
    tinh Altair Community Member
    edited September 2017

    use hm_getsurfacenormal nodes $your_selected_nodeid

    the node must be associated to surface.

    if the node is not associated, use hm_getsurfacenormalatcoordinate

    to find intersection points between normal vector and surf, use *nodecreateatplaneintersection

    and to find mid node of 2 intersected nodes, use *createnodesbetweennodes

    to find nodes closest to the mid node, use hm_getclosestnode

     

    I think it is better to get it by *createmark 'on plane'

    like this:

     *createmarkpanel nodes 1 'Pick a node on cylinder:' set Node1 [hm_getmark nodes 1] if {[hm_entityinfo exist nodes $Node1]} {   set SurfId [hm_getentityvalue nodes $Node1 surfaceid 0]   if {[hm_entityinfo exist surfs $SurfId]} {     *createmark lines 1 'by surface' $SurfId     foreach LineId [hm_getmark lines 1] {         if {[hm_getlinetype]==2} {           lassign [hm_getlinetgstartpoint $LineId] Vx Vy Vz           eval *createmark nodes 1 {'on plane'} [expr [hm_nodevalue $Node1]] $Vx $Vy $Vz $Tolerance 1 1           *createmark nodes 2 displayed           *markintersection nodes 1 nodes 2           if {[hm_marklength nodes 1]} {             *numbersmark nodes 1 1           }           *clearmarkall 1; *clearmarkall 2; break         }     }   } }

     

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    use hm_getsurfacenormal nodes $your_selected_nodeid

    the node must be associated to surface.

    if the node is not associated, use hm_getsurfacenormalatcoordinate

    to find intersection points between normal vector and surf, use *nodecreateatplaneintersection

    and to find mid node of 2 intersected nodes, use *createnodesbetweennodes

    to find nodes closest to the mid node, use hm_getclosestnode

     

    I think it is better to get it by *createmark 'on plane'

    like this:

      *createmarkpanel nodes 1 'Pick a node on cylinder:' set Node1 [hm_getmark nodes 1] if {[hm_entityinfo exist nodes $Node1]} {   set SurfId [hm_getentityvalue nodes $Node1 surfaceid 0]   if {[hm_entityinfo exist surfs $SurfId]} {     *createmark lines 1 'by surface' $SurfId     foreach LineId [hm_getmark lines 1] {         if {[hm_getlinetype]==2} {           lassign [hm_getlinetgstartpoint $LineId] Vx Vy Vz           eval *createmark nodes 1 {'on plane'} [expr [hm_nodevalue $Node1]] $Vx $Vy $Vz $Tolerance 1 1           *createmark nodes 2 displayed           *markintersection nodes 1 nodes 2           if {[hm_marklength nodes 1]} {             *numbersmark nodes 1 1           }           *clearmarkall 1; *clearmarkall 2; break         }     }   } }

     

    What if there are no surfaces and lines in the model. There are only elements and nodes. any suggestion?

  • tinh
    tinh Altair Community Member
    edited September 2017

    It is even easier,:rolleyes:/emoticons/default_rolleyes.gif' title=':rolleyes:' /> from free edges, find elems 'by adjacent' until selected elems contain $your_selected_node

    Within each searching loop, save old nodes and subtract them at next search to get expected nodes 

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    It is even easier,:rolleyes:/emoticons/default_rolleyes.gif' title=':rolleyes:' /> from free edges, find elems 'by adjacent' until selected elems contain $your_selected_node

    Within each searching loop, save old nodes and subtract them at next search to get expected nodes 

    Can you please elaborate using code? i am unable to write the logic... 

  • tinh
    tinh Altair Community Member
    edited September 2017

    Like this

    -select a node on comp

    -find edges of comp

    -turn off comp

    -get edge elem list

    -createmark 1 edge elem

    -appendmark 1 by attached

    -turn on comp

    -loop:

        -createmark nodes by elem mark 1

        - check mark if contain selected node

               -markdifference nodes 1 nodes 2

               -return nodes in mark 1

         -else

               -createmark nodes 2 by elems in mark 1

                -append mark elems 1 by adjacent

    -endloop

     

    Is that enough logic?

     

     

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    Like this

    -select a node on comp

    -find edges of comp

    -turn off comp

    -get edge elem list

    -createmark 1 edge elem

    -appendmark 1 by attached

    -turn on comp

    -loop:

        -createmark nodes by elem mark 1

        - check mark if contain selected node

               -markdifference nodes 1 nodes 2

               -return nodes in mark 1

         -else

               -createmark nodes 2 by elems in mark 1

                -append mark elems 1 by adjacent

    -endloop

     

    Is that enough logic?

     

     

    What if the selected node is not on free edge? what if it's somewhere in the middle?

  • tinh
    tinh Altair Community Member
    edited September 2017

    If it is in middle, the loop will find it

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    If it is in middle, the loop will find it

    Hi Tinh,

    Thanks for your help. I'll need a little different thing now as per change in requirement.

    1. Before iterating i need to find, whether the node is created using Cartesian coordinates or cylindrical! 

    a. If it's a cylindrical system, then i should follow the above approach and then define coincident grids.

    b. else if it's Cartesian i need to define RBE elements.

     

  • tinh
    tinh Altair Community Member
    edited September 2017

    I don't understand.

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited September 2017

    I don't understand.

    See if i query for a selected node, i get the coordinates x,y,z. But i want to check if these nodes were created using cylindrical coordinate system (r,theta,Z)[local CSYS] or Cartesian (x,y,z) [global WCS]. and then if it is the second one, then do the above steps, means to select all circumferential grids.

  • tinh
    tinh Altair Community Member
    edited September 2017

    So you ought to ask 'how to check input system type of a node'

    You had node id, then:

    set UseCartesian [expr ![hm_getentityvalue nodes $NodeId inputsystem.type 0]]

     

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited October 2017

    So you ought to ask 'how to check input system type of a node'

    You had node id, then:

    set UseCartesian [expr ![hm_getentityvalue nodes $NodeId inputsystem.type 0]]

     

    Yes exactly. Thanks for your help.

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited October 2017

    Hi Tinh,

     

    For the above discussion, if i want to get all the nodes in circumference where user will select a single node (having local r,t,z) values, how can i write the logic?

    I tried this way,

    1. Select a node, get r,t,z values.

    2. Write a loop varying t value from 0 to 360, keeping r and z same and use *getclosestnode and pass these 3 values to get the node lying on these passed coordinates.

    Problems: 1.  hm_getclosestnode doesn't give me the exact node for which the coordinates were passed. (Not sure which closest node it finds)

    2. I don't have idea which API should i use to get all those circumferential grids.

     

    Can you please help me resolving my issue, i am new to customization. It'll also be helpful if we need to write any other logic.

  • tinh
    tinh Altair Community Member
    edited October 2017

    You have to define problem logically and do not change initial conditions

    I guess you cannot do it because each time I guide you then you change assumption, i would not waste my time if you make clear at beginning

    Now i want you to confirm what you want? what is input data that you have?

  • tinh
    tinh Altair Community Member
    edited October 2017

    Hi,

    assumption:

    - you have a cylindrical mesh (not have surf)

    - mesh is quad only, equally

    then, the proc below will select a circumference nodes base on a preselected node not lay on ends of cylinder

    you can modify it to select nodes at 2 ends of cylinder (it's easy)

     proc ::p_SelectCircumferentialNodes {{PreselectedNodeId {}}} { 	if {![hm_entityinfo exist nodes $PreselectedNodeId]} { 		*createmarkpanel nodes 1 'Pick a node on cylinder:' 		if {[hm_marklength nodes 1]!=1} return 		set PreselectedNodeId [hm_getmark nodes 1] 	} 	#we will find 4 quads attached to the node: 	*createmark elems 1 'by node' $PreselectedNodeId 	if {[hm_marklength elems 1]!=4} {*clearmarkall 1; return -code error 'not valid cylinder'} 	if {![string equal 104 [lsort -unique [hm_getmarkvalue elems 1 config 0]]]} {*clearmarkall 1; return -code error 'not valid cylinder'} 	lassign [hm_getmark elems 1] Elem1 Elem2 Elem3 Elem4 	set nx1 [hm_getentityvalue elems $Elem1 normalx 0] 	set ny1 [hm_getentityvalue elems $Elem1 normaly 0] 	set nz1 [hm_getentityvalue elems $Elem1 normalz 0] 	set NodeList [hm_nodelist $Elem1] 	set nx 0; set ny 0; set nz 0 	set TripleCosMin 1 	foreach ElemId [list $Elem2 $Elem3 $Elem4] { 		if {[llength [lsort -unique [eval linsert [list $NodeList] end [hm_nodelist $ElemId]]]]==6} { 			set nx2 [hm_getentityvalue elems $ElemId normalx 0] 			set ny2 [hm_getentityvalue elems $ElemId normaly 0] 			set nz2 [hm_getentityvalue elems $ElemId normalz 0] 			set TripleCos [expr abs([hm_triplecos $nx1 $ny1 $nz1 $nx2 $ny2 $nz2])] 			if {$TripleCos<$TripleCosMin} { 				set TripleCosMin $TripleCos 				set nx $nx2 				set ny $ny2 				set nz $nz2 			} 		} 	} 	if {!$nx&&!$ny&&!$nz} {*clearmarkall 1; return -code error 'not valid cylinder'} 	set vx [expr $ny1*$nz-$nz1*$ny] 	set vy [expr $nx1*$nz-$nz1*$nx] 	set vz [expr $nx1*$ny-$ny1*$nx] 	list $vx $vy $vz 	*appendmark elems 1 'by attached' 	*findmark elems 1 1 1 nodes 0 2 	lassign [join [hm_nodevalue $PreselectedNodeId]] x y z 	*createmark nodes 1 'on plane' $x $y $z $vx $vy $vz 0.1 1 1 	*markintersection nodes 1 nodes 2 	hm_highlightmark nodes 1 h 	*clearmark nodes 2; *clearmark elems 1 }

     

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited October 2017

    Hi,

    assumption:

    - you have a cylindrical mesh (not have surf)

    - mesh is quad only, equally

    then, the proc below will select a circumference nodes base on a preselected node not lay on ends of cylinder

    you can modify it to select nodes at 2 ends of cylinder (it's easy)

      proc ::p_SelectCircumferentialNodes {{PreselectedNodeId {}}} { 	if {![hm_entityinfo exist nodes $PreselectedNodeId]} { 		*createmarkpanel nodes 1 'Pick a node on cylinder:' 		if {[hm_marklength nodes 1]!=1} return 		set PreselectedNodeId [hm_getmark nodes 1] 	} 	#we will find 4 quads attached to the node: 	*createmark elems 1 'by node' $PreselectedNodeId 	if {[hm_marklength elems 1]!=4} {*clearmarkall 1; return -code error 'not valid cylinder'} 	if {![string equal 104 [lsort -unique [hm_getmarkvalue elems 1 config 0]]]} {*clearmarkall 1; return -code error 'not valid cylinder'} 	lassign [hm_getmark elems 1] Elem1 Elem2 Elem3 Elem4 	set nx1 [hm_getentityvalue elems $Elem1 normalx 0] 	set ny1 [hm_getentityvalue elems $Elem1 normaly 0] 	set nz1 [hm_getentityvalue elems $Elem1 normalz 0] 	set NodeList [hm_nodelist $Elem1] 	set nx 0; set ny 0; set nz 0 	set TripleCosMin 1 	foreach ElemId [list $Elem2 $Elem3 $Elem4] { 		if {[llength [lsort -unique [eval linsert [list $NodeList] end [hm_nodelist $ElemId]]]]==6} { 			set nx2 [hm_getentityvalue elems $ElemId normalx 0] 			set ny2 [hm_getentityvalue elems $ElemId normaly 0] 			set nz2 [hm_getentityvalue elems $ElemId normalz 0] 			set TripleCos [expr abs([hm_triplecos $nx1 $ny1 $nz1 $nx2 $ny2 $nz2])] 			if {$TripleCos<$TripleCosMin} { 				set TripleCosMin $TripleCos 				set nx $nx2 				set ny $ny2 				set nz $nz2 			} 		} 	} 	if {!$nx&&!$ny&&!$nz} {*clearmarkall 1; return -code error 'not valid cylinder'} 	set vx [expr $ny1*$nz-$nz1*$ny] 	set vy [expr $nx1*$nz-$nz1*$nx] 	set vz [expr $nx1*$ny-$ny1*$nx] 	list $vx $vy $vz 	*appendmark elems 1 'by attached' 	*findmark elems 1 1 1 nodes 0 2 	lassign [join [hm_nodevalue $PreselectedNodeId]] x y z 	*createmark nodes 1 'on plane' $x $y $z $vx $vy $vz 0.1 1 1 	*markintersection nodes 1 nodes 2 	hm_highlightmark nodes 1 h 	*clearmark nodes 2; *clearmark elems 1 }

     

    Hey Tinh,

     

    I'm sorry about change in conditions. i'll make sure that doesn't happen again. The above code works perfectly, and selects all the nodes in the circumference.

    Just two questions here, 

    1. How do i print a list of all these selected nodes so further i can work on them as per my requirement.

    2. How can i bring in the concept of axial and radial tolerances, suppose some of the nodes are slightly away from axial location and radial location from the selected node's axial and radial location within these two tolerances provided by user.

  • tinh
    tinh Altair Community Member
    edited October 2017

    Hi,

    To print out selected nodes:

    ::p_SelectCircumferentialNodes

    set selected_nodes [hm_getmark nodes 1]

    puts $selected_nodes

     

    To select nodes with a tolerance, You can modify proc to 

    proc ::p_SelectCircumferentialNodes {tolerance} {

    #........

    *createmark nodes 1 'on plane' $x $y $z $vx $vy $vz $tolerance 1 1

    #........

    }

     

     

    About radial tolerance, could you try moving a node radially and confirm it is sensitive or not?  It will affect to element normals but i am not sure how to estimate it affection

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited October 2017

    Hi,

    To print out selected nodes:

    ::p_SelectCircumferentialNodes

    set selected_nodes [hm_getmark nodes 1]

    puts $selected_nodes

     

    To select nodes with a tolerance, You can modify proc to 

    proc ::p_SelectCircumferentialNodes {tolerance} {

    #........

    *createmark nodes 1 'on plane' $x $y $z $vx $vy $vz $tolerance 1 1

    #........

    }

     

     

    About radial tolerance, could you try moving a node radially and confirm it is sensitive or not?  It will affect to element normals but i am not sure how to estimate it affection

     

    Hey Tinh,

     

    Will try that. Thanks a lot.

  • Altair Forum User
    Altair Forum User
    Altair Employee
    edited October 2017

    Hi Tinh,

     

    I've got a problem here. This code works fine only for few axial stations. Sometimes, it's just getting 2 or even single node on the circumference.

     

    What could be the reason?

    <?xml version="1.0" encoding="UTF-8"?>2.PNG

    <?xml version="1.0" encoding="UTF-8"?>3.PNG

    <?xml version="1.0" encoding="UTF-8"?>1.PNG