Tuesday, October 25, 2022

Combining Ruby with ICM SWMM Network


ICM InfoWorks by Autodesk Innovyze is a complicated program with many parts and a state-of-the-art 1D and 2D engine. One way to deal with the complexity is to automate complicated or repetitive tasks with SQL and Ruby. In this blog, we will use SQL and Ruby to automate the process of assigning Watershed outlet nodes for ICM SWMM Networks.

What are we hoping to achieve by Combining Ruby with ICM SWMM Networks?

  1. We want to find the outlet ID for the closest node to a Subcatchment in an ICM SWMM Network.
  2. Ruby will use the Geometry tools of ICM to find the closest node.
  3. What is an ICM SWMM Network? It is a Network in ICM that uses SWMM 5.1.015 data and most/many of the tools of the ICM GUI. ICM of course also has InfoWorks Networks.
  4. What am I showing in the Post header image? Autodesk has Subscription versions of ICM (Standard and Ultimate), but I am showing the Thales versions of ICM which are both 32bit and 64bit, and comingled ICM InfoWorks and ICM SWMM Networks. I also use InfoWater Pro (Arc GIS Pro) and InfoSWMM which uses Arc Map and has a direct import into an ICM SWMM Network.

ICM SWMM Network Data in the Autodesk Innvovyze ICM GUI
ICM SWMM Network Subcatchment Data

Why use Ruby for InfoWorks ICM SWMM Networks?

Why Ruby - it is part of ICM and easy to understand with a lot of Modeling features. It is part of Network Menu Commands. You can use a new Script or a past used script so it is easy to find.
No alt text provided for this image

What is an InfoWorks ICM SWMM Network?

ICM SWMM uses the SWMM 5.1.015 engine and has most of the UX features of ICM InfoWorks Networks including 2D. A different 1D network and solution of course.

What is an example of Ruby Scripts?

net=WSApplication.current_network
puts 'Running ruby for SWMM Networks'
nodes=Array.new
net.row_object_collection('sw_node').each do |n|
        if n.selected?
                temp=Array.new
                temp << n.id
                temp << n.x
                temp << n.y
                nodes << temp
        end
end
net.transaction_begin
net.row_object_collection('sw_subcatchment').each do |s|
        if s.selected?
                sx = s.x
                sy = s.y
                nearest_distance = 999999999.9
                (0...nodes.size).each do |i|
                        nx = nodes[i][1]
                        ny = nodes[i][2]
                        n_id = nodes[i][0]
                        distance=((sx-nx)*(sx-nx))+((sy-ny)*(sy-ny))
                        if distance < nearest_distance
                                nearest_distance=distance
                                s.outlet_id = n_id
                        end
                end
        else
        puts 'You forgot to select anything'
        end
        s.write
end
puts 'Ending ruby'
net.transaction_commit

Where can I find the Ruby Scripts?

Innovyze has a Github that you can use to copy or download dozens of Ruby and SQL scripts. If registered on our Portal, you can find Salesforce Knowledge Base articles and many other sources of help. at https://github.com/innovyze/Open-Source-Support. SQL and Ruby functionality exist to be used by users with knowledge of programming languages. We provide resources to assist customers in building their scripts through the existing self-help frameworks, including documentation on Ruby, help files, and more recently a wealth of GitHub examples - link above.

How do I use Ruby Scripts?

Easy - Go to the Network Menu and choose Run Ruby Scripts or Recent Ruby Scripts
No alt text provided for this image

Do I need to use SQL?

It helps if you have a simple global grid command and you do not want to edit the grid. Here is a simple SQL that sets the SWMM Network OUTLET_ID to blank. You can save the SQL on the project explorer window and click to activate the dialog.

No alt text provided for this image

What does each line of the Ruby Script represent and what does it perform for the ICM SWMM Network?

The annotated snippet below shows the steps used in the script. ICM SWMM Networks are sw_ whereas ICM InfoWorks Networks are hw_ (for reference)

net=WSApplication.current_network

# Opens the current network on the ICM Geoplan

puts 'Running ruby for SWMM Networks'

# Tell the user some actions are being done by the script

nodes=Array.new

# Makes a new array - uses swmm nodes or sw_node

net.row_object_collection('sw_node').each do |n|
        if n.selected?
                temp=Array.new
                temp << n.id
                temp << n.x
                temp << n.y
                nodes << temp
        end
end
# Save the id, x coordinate, y coordinate to the nodes array of SELECTED Elements

net.transaction_begin

# start finding the nodes to set to the outlet of the subcatchment

net.row_object_collection('sw_subcatchment').each do |s|

# use swmm subcatchments or sw_subcatchment

        if s.selected?

# use the SELECTED Elements

                sx = s.x
                sy = s.y

# use the centroid of the subcatchment

                nearest_distance = 999999999.9
                (0...nodes.size).each do |i|
                        nx = nodes[i][1]
                        ny = nodes[i][2]
                        n_id = nodes[i][0]

# for each node find the x and y coordinates

                        distance=((sx-nx)*(sx-nx))+((sy-ny)*(sy-ny))

# compute the node to subcatchment distance
 
                       if distance < nearest_distance
                                nearest_distance=distance
                                s.outlet_id = n_id

# We have found the closed node and set the outlet ID to the node ID
                        end
                end
        else
        puts 'You forgot to select anything'

# message to remind ourself we forget to select any nodes or subcatchments

        end
        s.write
end
puts 'Ending ruby'
# Tell the user some actions were by the script

net.transaction_commit

# commit our new found ID to the current network (ICM SWMM Network)

I'm attaching a YouTube video that explains the previous stages. It is for ICM SWMM Networks, which utilizes SQL to remove or set the SWMM Subcatchment's OUTLET ID to Null and Ruby to determine the closest node to the Subcatchment's centroid and assign it as the OUTLET ID. I made a mistake and ran Ruby without using ICM to pick any items, which resulted in nothing being done, but at least I received a notice about not choosing any components.





No comments:

New Culvert Code for Culverts in ICM 2023.2+ Versions

Culvert inlets and outlets To improve the process of defining culvert inlet and culvert outlet losses for an InfoWorks network, a new fiel...