GiD - The personal pre and post processor

Macros

Definition

What we call here as 'macro' is a button packed in the 'macros toolbar' (shown usually on the left side). When the user click the button a function is invoked.

This function in this case is a Tcl scripting procedure (in GiD it is possible to define and invoke Tcl code in much other ways)

By default GiD provide some predefined macros, but the user could modify this toolbar, adding its own macros.

The definition of these macros will be stored in a user folder in a file named 'Macros.tcl'.

Creation of a macro

  1. Create an empty macro, by clicking on the Record macro icon and the Stop record macro icon , both on the macros toolbar.Ā Then a new button named 'Macro1' will appear on the toolbar and it will invoke the process commands used while recording the macro
  2. Edit the macro with the icon on the same macros toolbar, and enter the Tcl code that do you want to be invoked in the code box:

Edit macros window, click on the button pointed by the red arrow to expand the window and enter the code

In this case we set as code

W "Hello world"


Remember to press "Apply" after change some macro parameter.
Then to test the macro click the new toolbar button and it will open a new window showing the message "Hello world"

Note: W is a short alias to WarnWinText, that is a procedure defined in GiD to open a window and show a message


Off course we can replace the code to do a more interesting thing.
The macro could be customized a little more:

  • Setting an special icon (selecting a predefined icon or getting it from an image file)
  • Specifying if the macro must be visible only in pre, only in post of both (default)
  • Providing a description that will be shown as contextual help on the button.
  • Defining some key accelerator to run it easily.

Macro to create a graph of a gauss point result

The aim of this tutorial is to show how to create a user macro to plot a graph of a gauss-point result.

A full copy of the code of this macro is provided in the file 'GraphResult.tcl'

We will use for this tutorial a GiD model named 'cross' that represents a cross street has been calculated by the Iber solver (http://www.iberaula.es) and has some results 'on gauss points'.

Open this model and switch to post-process to see its results, e.g. a contour fill of the result named 'Depth (m)' on the last time step

In GiD postprocess it is possible to create a graph along the time of a result on a node or on an element, but the result is mapped to nodes and averaged to create a continuous field and then interpolated with shape functions to inner points.
This averaging and interpolation process modifies the 'calculated result' and the user could prefer the original unmodified value (discontinuous between neighbor elements)

This feature is not implemented, but can be achieved with a custom macro.

The things to do are conceptually simple:
1- Allow the user to select an element and specify its gauss point and the result that want to plot.
2- For each time step ask GiD for the value of this result on this location
3- Create a new graph with the list of these values.

1- Select the element, gauss point and result

To simplify the code we could assume that initially the element id and the result name is known at programming time.

In a final step we could enhance it to allow select the element picking in screen.

2- Get the list of values for all time steps

Some difficulties could appear for the developer: how to know the result of an element?

To answer this question must find in the GiD documentation:Ā Help->Customization help->Tcl and Tk extension

GiD_Info command provide a lot of information of GiD data.

It is possible to use "GiD_Info list_entities elements ...." to get the information of results you want

GiD_ResultĀ is a more specialized command than can create and get information from results, we will use it.

For example, to know the value in the element number 676 of the result named 'Velocity (m/s)' of the analysis named 'Hidraulic' in the last time step=35.0 we can write this in the command line

(-np- is a GiD trick that mean that the next is a Tcl command instead of 'GiD process keywords')

-np- W [GiD_Result get -selection {676} [list "Velocity (m/s)" "Hydraulic" 35.0]]

and we will obtain something like this:

{Result {Velocity (m/s)} Hydraulic 35.0 Vector OnGaussPoints GPQ} {Unit {}} {ComponentNames Vx Vy . {|Velocity (m/s)|}} {676 {0.08044888079166412 -0.28458309173583984 0.0 0.295735627412796}}


We must parse the part of the text we are interested on, in this case we want for example to get only the result vx=0.08044888079166412

The string is formatted as Tcl nested lists, it is easy to get the appropriated item with the lindex Tcl command

set data [GiD_Result get -selection {676} [list "Velocity (m/s)" "Hydraulic" 35.0]]
set vx [lindex [lindex [lindex $data 3] 1] 0]

Note: Tcl commands syntax could be seen in Internet, for example at www.tcl.tk/man/tcl/TclCmd/contents.htm

lindex ā€” Retrieve an element from a list

set ā€” Read and write variables

proc ā€” Create a Tcl procedure

#result_id : list with 3 items: { result_name analysis_name time_step }
proc GraphElementResult_GetElementResult { result_id element_id component_i gauss_i } {    
    set data [GiD_Result get -selection [list $element_id] $result_id]
    set num_components [expr [llength [lindex $data 2]]-1]
    set pos_gauss [expr $gauss_i*$num_components+$component_i]
    set value [lindex [lindex [lindex $data 3] 1] $pos_gauss]    
    return $value
}

GiD_ResultĀ is a GiD-added Tcl command, the rest (expr, llength) are Tcl standard commands.

$x returns the value of the variable named x (similar to 'set x')


We must use this procedure to get the values for all time steps, with this other procedure, that return an item with two sublists, one for the time steps and another for the result values on these steps.

proc GraphElementResult_GetResultAllTimeSteps { analysis_name result_name element_id component_i gauss_i } {
    set time_steps [list]
    set values [list]
    if { [lsearch [GiD_Info postprocess get all_analysis] $analysis_name] == -1 } {
        error "Analysis '$analysis_name' doesn't found"
    } else {
        set all_time_steps [GiD_Info postprocess get all_steps $analysis_name]
        foreach time_step $all_time_steps {
            set result_id [list $result_name $analysis_name $time_step]
            set value [GraphElementResult_GetElementResult $result_id $element_id $component_i $gauss_i]
            if { [string is double -strict $value] } {
                lappend time_steps $time_step
                lappend values $value
            }
        }
    } 
    return [list $time_steps $values]
}

GiD_InfoĀ is a GiD-added Tcl command, the rest (list, lsearch, error, foreach, string, lappend, return) are Tcl standard commands.

3- Create a graph with the values

There is an special Tcl command to handle postprocess graphs, like create a new graph
GiD_Graph create <graph_name> <label_x> <label_y> <x_values> <y_values> <x_unit> <y_unit> ?<graphset_name>?

We want to create a new graph with the extracted information, checking that its name doesn't exists with this procedure

#get an unused graph_name, adding a suffix -2, ...-3 if base_name already exists
proc GraphElementResult_GetUnusedGraphName { base_name } {
    set graph_name $base_name
    if { [GiD_Graph exists $graph_name] } {
        for {set i 2} {$i < 10000} {incr i} {
            set graph_name $base_name-$i
            if { ![GiD_Graph exists $graph_name] } {
                break
            }
        } 
    }
    return $graph_name
}

and this procedure create the new graph

proc GraphElementResult_NewGraph { analysis_name result_name result_component element_id gauss_i } {
    if { $result_component == "" } {
        set component_i 0
        set label_y $result_name
    } else {
        set data [GiD_Result get -selection [list $element_id] [list $result_name $analysis_name 0]]
        set component_i [lsearch [GiD_Info postprocess get cur_components_list $result_name] $result_component]
        if { $component_i == -1 } {
            error "result_component '$result_component' doesn't found"
        } else {
            set label_y $result_component
        }
    }
    set graph_values [GraphElementResult_GetResultAllTimeSteps $analysis_name $result_name $element_id $component_i $gauss_i]    
    if { [llength [lindex $graph_values 0]] } {
        set graph_name [GraphElementResult_GetUnusedGraphName "Evolution element $element_id"]
        GiD_Graph create $graph_name Time $label_y {*}$graph_values "Sec" "" ""
    }
}

When creating the new graph it is interesting to show it, opening the graphs window, this can ben done using this procedure

GidUtils::OpenWindow GRAPHS

The procedure is defined in the file scripts\dev_kit.tcl, that is a file of special interest for Tcl developers because include common tools.
Now it is possible to create a graph for the analysis name Hydraulic, result name "Depth (m)" for the element number 676 (using the first component in case of more than one, like vectorial, and the first gauss point in case of more than one) with something like this

-np- GraphElementResult_NewGraph Hydraulic "Depth (m)" 0 676 0
-np- GidUtils::OpenWindow GRAPHS

but this is not comfortable for a final user.
To invoke our code we will add a new button to the 'macros toolbar', and when pressing the button a menu will be shown with the current results to be selected, and the user must select in screen the elements to be plotted.

4- Enhance the GUI


The next procedure creates a new Tk menu widget and add to it items for the current results with the procedure AddGraphsResultsToMenu (that is defined somewhere in the GiD scripts to do this task), and then shows the menu on the right of the widget provided as parameter (e.g. our toolbar button)

proc GraphElementResult_ShowMenuResults { w } {
    set r_menu .gid.mGraphGaussResult    
    if { ![ winfo exists $r_menu]} {
        menu $r_menu
    }   
    #trick, must prefix with [namespace current] because macros are defined in the "toolbarmacros::macrospace" namespaceto not pollute the global names
    AddGraphsResultsToMenu $r_menu [namespace current]::GraphElementResult_SelectedResult Point_Evolution
    set x [expr {[winfo rootx $w]+[winfo width $w]}]
    set y [winfo rooty $w]
    tk_popup $r_menu $x $y
}

When selecting a menu option it will invoke the procedure GraphElementResult_SelectedResult that will do the task we want: allow the user selection of elements and create its graphs.

proc GraphElementResult_SelectedResult { args } {
    lassign $args result_name result_component           
    set current_analysis [GiD_Info postprocess get cur_analysis]
    set current_step [GiD_Info postprocess get cur_step]
    set header [GiD_Result get -info [list $result_name $current_analysis $current_step]]
    if { [lindex [lindex $header 0] 5] != "OnGaussPoints" } {
        W "This tool is only valid for elemental gauss-points results"
    } else {
        set gauss_i 0 ;#set hardcoded the first gauss point of the element (can allow user selection in case of more than one)
        set element_ids [GidUtils::PickEntities Elements multiple]
        if { $element_ids != "" } {            
            foreach element_id $element_ids {                          
                GraphElementResult_NewGraph $current_analysis $result_name $result_component $element_id $gauss_i
            }
            GidUtils::OpenWindow GRAPHS
            GiD_Redraw
        }
    }
}

The procede AddGraphsResultsToMenuĀ verify that our result is one defined on gauss points, else a message is raised

GidUtils::PickEntities is a GiD Tcl procedure defined in 'dev_kit.tcl' that allow a interactive selection of entities.
Finally we create the graphs with GraphElementResult_NewGraph , show its window and GiD_Redraw force a redraw the screen to show the selected elements in the normal way.

Finally we must change the tcl code of our macro button to invoke GraphElementResult_ShowMenuResults, but this procedure require the Tk button name to place the menu over them.

This is a problem because we don't know its name (the macros toolbar doesn't provide the button name to its command). We define an auxiliary procedure that returns this name in a tricky way (getting the name from the stack of Tcl procedures with the info level Tcl command).

#trick to be able to show the menu on the right of a macro button (because macros doesn't provide the button name to its command)
proc GraphElementResult_FindParentButton { } {
    set command [info level -1]
    set b ""
    set w .gid.bitmapsMacrosToolbar
    set inum 0
    while { [winfo exists $w.w$inum] } {
        if { [winfo class $w.w$inum] == "TButton" && [$w.w$inum cget -command] == $command } {
            set b $w.w$inum
            break
        }
        incr inum
    }
    return $b
}

and this is the code that must be finally invoked by our macro:
GraphElementResult_ShowMenuResults [GraphElementResult_FindParentButton]

Note: the macro code must include this line and all required procedures that are not defined in another place.

This is the final aspect of this macro button and its result (selecting the Deph result for the elementsĀ  676, 695 and 753.


Menu of results to plot

Ā 
Graph of the result of three selected elements

COPYRIGHT Ā© 2022 Ā· GID Ā· CIMNE