TCL script not working when partition>1
-
konstantinosch
- Posts: 12
- Joined: Mon Jul 29, 2024 5:03 pm
TCL script not working when partition>1
Dear all,
I want to run a simulation of a moving load on saturated porous media. For this purpose, I created a TCL script that applies a vertical load to nodes along a line. The node coordinates are read from the nodes.tcl file.
The script was working as expected when I used the SP solver. However, after introducing the ASDAborbingBoundary3DAuto, the relevant Misc command for updating the stage value stopped working with the SP solver.
I then switched to the MP solver, and the ASDAborbingBoundary3DAuto was successfully incorporated into the model. However, when the mesh partition is greater than 1, the TCL script is unable to locate the nodes along the line and apply the vertical loads.
Is this a known issue with the MP Solver? Please find the relevant file attached. Thank you very much for your help.
Kind regards,
Konstantinos
I want to run a simulation of a moving load on saturated porous media. For this purpose, I created a TCL script that applies a vertical load to nodes along a line. The node coordinates are read from the nodes.tcl file.
The script was working as expected when I used the SP solver. However, after introducing the ASDAborbingBoundary3DAuto, the relevant Misc command for updating the stage value stopped working with the SP solver.
I then switched to the MP solver, and the ASDAborbingBoundary3DAuto was successfully incorporated into the model. However, when the mesh partition is greater than 1, the TCL script is unable to locate the nodes along the line and apply the vertical loads.
Is this a known issue with the MP Solver? Please find the relevant file attached. Thank you very much for your help.
Kind regards,
Konstantinos
Re: TCL script not working when partition>1
In OpenSeesMP you need to take care of the ProcessID the node belongs to.
Here I read the process ID of each node.
I make sure not to have duplicates, since a node may be in more than one process (nodes in the boundaries between partitions, the load should be on only one of them).
Finally I apply the load only if the node process ID is equal to the output of [getPID] (opensees' function to obtain the current process ID)
In this way you make sure to touch only nodes available in the current process (keep in mind that each instance of OpenSeesMP, 1 per process, is processing your Tcl file!)
Try this:
Here I read the process ID of each node.
I make sure not to have duplicates, since a node may be in more than one process (nodes in the boundaries between partitions, the load should be on only one of them).
Finally I apply the load only if the node process ID is equal to the output of [getPID] (opensees' function to obtain the current process ID)
In this way you make sure to touch only nodes available in the current process (keep in mind that each instance of OpenSeesMP, 1 per process, is processing your Tcl file!)
Try this:
Code: Select all
# Function to read nodes from a text file
proc read_nodes_from_file {filename} {
set nodes_with_coords [list]
set current_process_id 0
set file [open $filename r]
set processed_nodes {}
while {[gets $file line] != -1} {
if {[regexp {^.*STKO_VAR_process_id == (\d+).*$} $line -> the_pid]} {
set current_process_id $the_pid
}
if {[regexp {^.*node (\d+) ([\d\.eE+-]+) ([\d\.eE+-]+) ([\d\.eE+-]+).*$} $line -> node_number x y z]} {
if {[lsearch $processed_nodes $node_number] < 0} {
# APPEND ALSO THE PARTITION ID
lappend nodes_with_coords [list $node_number $x $y $z $current_process_id]
lappend processed_nodes $node_number
}
}
}
close $file
return $nodes_with_coords
}
# Function to find and sort nodes within the specified line
proc find_and_sort_nodes_within_line {nodes_with_coords} {
# Define the line coordinates
set x1 5.0
set y1 0.0
set z1 20.0
set x2 5.0
set y2 50.0
set z2 20.0
set tolerance 0.01
# List to store the nodes within the specified line bounds along with their y-coordinates
set nodes_with_y [list]
foreach node_with_coords $nodes_with_coords {
set node [lindex $node_with_coords 0]
set x [expr {double([lindex $node_with_coords 1])}]
set y [expr {double([lindex $node_with_coords 2])}]
set z [expr {double([lindex $node_with_coords 3])}]
set the_pid [expr {int([lindex $node_with_coords 4])}]
# Check if the node is within the line bounds
if {([expr {abs($x - $x1)}] <= $tolerance) && ([expr {abs($z - $z1)}] <= $tolerance) && ($y != $y1) && ($y != $y2)} {
lappend nodes_with_y [list $node $y $the_pid]
}
}
# Debugging output for nodes that match the condition
puts "Nodes that match the condition:"
foreach node_with_y $nodes_with_y {
puts "Node [lindex $node_with_y 0]: y = [lindex $node_with_y 1]"
}
# Sort the nodes by y-coordinate
set sorted_nodes_with_y [lsort -real -index 1 $nodes_with_y]
# Extract the sorted node tags
set sorted_nodes [list]
foreach node_with_y $sorted_nodes_with_y {
lappend sorted_nodes [list [lindex $node_with_y 0] [lindex $node_with_y 2]]
puts "Sorted Node: [lindex $node_with_y 0], y = [lindex $node_with_y 1]"
}
return $sorted_nodes
}
# Function to apply triangular pulse to nodes sequentially
proc apply_triangular_pulse_to_nodes {nodes max_load velocity distance} {
# Calculate duration and time interval based on velocity and distance
set duration [expr {2.0 * $distance / $velocity}]
set time_interval [expr {$duration / 2.0}]
set period [expr {2.0 * $duration}]
set initial_delay 0.01
set i 0
foreach node_and_pid $nodes {
set node [lindex $node_and_pid 0]
set the_pid [lindex $node_and_pid 1]
if {$the_pid != [getPID]} {
continue
}
# Define the time series for the triangular pulse
set time_series_tag [expr {1000 + $i}]
set start_time [expr {double($i) * $time_interval + $initial_delay}]
set end_time [expr {$start_time + $duration}]
# Debugging output
puts "Time Series Tag: $time_series_tag"
puts "Start Time: $start_time"
puts "End Time: $end_time"
puts "Period: $period"
# Ensure start_time and end_time are properly formatted as floating-point numbers
timeSeries Triangle $time_series_tag $start_time $end_time $period -factor 1
# Define the load pattern
set load_pattern_tag [expr {2000 + $i}]
pattern Plain $load_pattern_tag $time_series_tag {
# Apply the load to the node
load $node 0.0 0.0 $max_load 0.0 ;# Assuming the load is applied in the z-direction;
}
incr i
}
}
# Main script
set filename "nodes.tcl"
set nodes_with_coords [read_nodes_from_file $filename]
set sorted_nodes_in_line [find_and_sort_nodes_within_line $nodes_with_coords]
puts "Sorted nodes within the specified line: $sorted_nodes_in_line"
# Define parameters for the triangular pulse
set max_load -10000.0 ;# Maximum load value
set velocity 50.0 ;# Velocity in units per second
set distance 0.5 ;# Distance in units between nodes
# Apply the triangular pulse to the sorted nodes
apply_triangular_pulse_to_nodes $sorted_nodes_in_line $max_load $velocity $distance
# Function to print sorted node coordinates
proc print_sorted_node_coordinates {} {
set sorted_nodes_with_coords [find_and_sort_nodes_within_line $nodes_with_coords]
puts "Sorted nodes within the specified line:"
foreach node_with_coords $sorted_nodes_with_coords {
set node [lindex $node_with_coords 0]
set coords [lindex $node_with_coords 1]
puts "Node $node: Coordinates $coords"
}
}
-
konstantinosch
- Posts: 12
- Joined: Mon Jul 29, 2024 5:03 pm
Re: TCL script not working when partition>1
Thank you very much for your immediate reply. It was really helpful!
I modified the script a bit, as the load was applied simultaneously on multiple locations based on the partitioning of the mesh.
Below the updated script where the load is applied on every node at a time based on the y_coord and the velocity of the load.
I modified the script a bit, as the load was applied simultaneously on multiple locations based on the partitioning of the mesh.
Below the updated script where the load is applied on every node at a time based on the y_coord and the velocity of the load.
Code: Select all
# Function to read nodes from a text file
proc read_nodes_from_file {filename} {
set nodes_with_coords [list]
set current_process_id 0
set file [open $filename r]
set processed_nodes {}
while {[gets $file line] != -1} {
if {[regexp {^.*STKO_VAR_process_id == (\d+).*$} $line -> the_pid]} {
set current_process_id $the_pid
}
if {[regexp {^.*node (\d+) ([\d\.eE+-]+) ([\d\.eE+-]+) ([\d\.eE+-]+).*$} $line -> node_number x y z]} {
if {[lsearch $processed_nodes $node_number] < 0} {
# APPEND ALSO THE PARTITION ID
lappend nodes_with_coords [list $node_number $x $y $z $current_process_id]
lappend processed_nodes $node_number
}
}
}
close $file
return $nodes_with_coords
}
# Function to find and sort nodes within the specified line
proc find_and_sort_nodes_within_line {nodes_with_coords} {
# Define the line coordinates
set x1 5.0
set y1 0.0
set z1 20.0
set x2 5.0
set y2 50.0
set z2 20.0
set tolerance 0.01
# List to store the nodes within the specified line bounds along with their y-coordinates
set nodes_with_y [list]
foreach node_with_coords $nodes_with_coords {
set node [lindex $node_with_coords 0]
set x [expr {double([lindex $node_with_coords 1])}]
set y [expr {double([lindex $node_with_coords 2])}]
set z [expr {double([lindex $node_with_coords 3])}]
set the_pid [expr {int([lindex $node_with_coords 4])}]
# Check if the node is within the line bounds
if {([expr {abs($x - $x1)}] <= $tolerance) && ([expr {abs($z - $z1)}] <= $tolerance) && ($y != $y1) && ($y != $y2)} {
lappend nodes_with_y [list $node $y $the_pid]
}
}
# Debugging output for nodes that match the condition
puts "Nodes that match the condition:"
foreach node_with_y $nodes_with_y {
puts "Node [lindex $node_with_y 0]: y = [lindex $node_with_y 1]"
}
# Sort the nodes by y-coordinate
set sorted_nodes_with_y [lsort -real -index 1 $nodes_with_y]
# Extract the sorted node tags
set sorted_nodes [list]
foreach node_with_y $sorted_nodes_with_y {
lappend sorted_nodes [list [lindex $node_with_y 0] [lindex $node_with_y 1] [lindex $node_with_y 2]]
# puts "Sorted Node: [lindex $node_with_y 0], y = [lindex $node_with_y 1]"
}
return $sorted_nodes
}
# Function to apply triangular pulse to nodes sequentially
proc apply_triangular_pulse_to_nodes {nodes max_load velocity distance} {
# Calculate duration and time interval based on velocity and distance
set duration [expr {2.0 * $distance / $velocity}]
set time_interval [expr {$duration / 2.0}]
set period [expr {2.0 * $duration}]
set initial_delay 0.01
set i 0
foreach node_and_ycoord_and_pid $nodes {
set node [lindex $node_and_ycoord_and_pid 0]
set y_coord [lindex $node_and_ycoord_and_pid 1]
set the_pid [lindex $node_and_ycoord_and_pid 2]
if {$the_pid != [getPID]} {
continue
}
# Define the time series for the triangular pulse
set time_series_tag [expr {int(1000 + 2 * $y_coord)}]
set start_time [expr {$y_coord / $velocity + $initial_delay}]
set end_time [expr {$start_time + $duration}]
# Debugging output
puts "Time Series Tag: $time_series_tag"
puts "Start Time: $start_time"
puts "End Time: $end_time"
puts "Period: $period"
# Ensure start_time and end_time are properly formatted as floating-point numbers
timeSeries Triangle $time_series_tag $start_time $end_time $period -factor 1
# Define the load pattern
set load_pattern_tag [expr {int(2000 + 2 * $y_coord)}]
pattern Plain $load_pattern_tag $time_series_tag {
# Apply the load to the node
load $node 0.0 0.0 $max_load 0.0 ;# Assuming the load is applied in the z-direction;
}
incr i
}
}
# Main script
set filename "nodes.tcl"
set nodes_with_coords [read_nodes_from_file $filename]
set sorted_nodes_in_line [find_and_sort_nodes_within_line $nodes_with_coords]
puts "Sorted nodes within the specified line: $sorted_nodes_in_line"
# Define parameters for the triangular pulse
set max_load -10000.0 ;# Maximum load value
set velocity 50.0 ;# Velocity in units per second
set distance 0.5 ;# Distance in units between nodes
# Apply the triangular pulse to the sorted nodes
apply_triangular_pulse_to_nodes $sorted_nodes_in_line $max_load $velocity $distance
# Function to print sorted node coordinates
# proc print_sorted_node_coordinates {} {
# set sorted_nodes_with_coords [find_and_sort_nodes_within_line $nodes_with_coords]
# puts "Sorted nodes within the specified line:"
# foreach node_with_coords $sorted_nodes_with_coords {
# set node [lindex $node_with_coords 0]
# set coords [lindex $node_with_coords 1]
#puts "Node $node: Coordinates $coords"
#}
#}
Re: TCL script not working when partition>1
Yes, I didn't take care of the part regarding the timeSeries and load patterns.