Extracting node/element presence in model from *.mpco databases

Post Reply
Edward_Hayes
Posts: 3
Joined: Fri Jul 16, 2021 10:17 am

Extracting node/element presence in model from *.mpco databases

Post by Edward_Hayes » Thu Aug 05, 2021 4:15 pm

Hi all,

I am performing a progressive collapse analysis with a linear timeSeries in OpenSees using an external Tcl Script, and then loading mpco databases into the Post Processor. I want to compare two simulation models (one with damage and one without) that are otherwise identical.

In the analysis, elements and nodes are removed as they fail limit state checks. When elements/nodes are removed I 'pause time' by using the setTime command and subtracting $timeIncr of the timeSeries:

Code: Select all

	# ___TCL___
		# Pause time if failures occur:
		if {[llength $failure_list] > 0} {
			setTime [expr [getTime] - $timeIncrement];
		};
As a result, the Analysis Steps and model time are not consistent in each model as the number of time pauses depends on the number of failures and time at which they occur.

As part of my post-processing analysis, I want to identify which elements/nodes are present at each Analysis Step and relate this to a time using the getStepTimes PyMpc function (db.getStepTimes(stage_i)). Then I want to compare the elements/nodes present at a given time in the damaged and undamaged model towards generating a consequence or change in performance due to the damage applied.

To do this in the STKO Post-Processor Python API, I have been looping through each $nodeTag from an list generated inside OpenSees and then requesting a recorder result from the MPCO database using PyMpc commands, with a try: except: RuntimeError included to distinguish between components in the model and not in the model for a each analysis step.

Is there a better way to achieve this (see code snippet below) as all PyMpc errors are specified by RuntimeError and this would not be a robust solution. In the code node 111000 is a node which does exist and node 123456 does not.

Code: Select all

# ___Python API___
resultsField_u_Disp = db_u.getNodalResult("Displacement", match = MpcOdb.Contains)
# Check if node still exists in model:
for Analysis_Step_u in [1,2,3,4,5,6,7,8,9,10]:
	opt_u.step = Analysis_Step_u
	field = resultsField_u_Disp.evaluate(opt_u)
	row_u_does_exist = MpcOdbResultField.node(111000)
	row_u_does_not_exist = MpcOdbResultField.node(123456)
	x_disp = field[row_u_does_exist, 0]
	y_disp = field[row_u_does_exist, 1]
	print("When Node Does Exist in model:")
	print("x("+str(row_u_does_exist.n)+"): "+str(x_disp))
	print("y("+str(row_u_does_exist.n)+"): "+str(y_disp))
	print("When Node Does NOT Exist in model:")
	try:
		y_not_exist_disp = field[row_u_does_not_exist, 1]
		x_not_exist_disp = field[row_u_does_not_exist, 0]
	except RuntimeError as ex:
		template = "An exception of type {0} occurred. Arguments:\n{1!r}"
		message = template.format(type(ex).__name__, ex.args)
		print(message)
		print(traceback.format_exc())
		print("Node Selection "+str(row_u_does_not_exist.n)+" Not in Model")
		y_not_exist_disp = None
		x_not_exist_disp = None
		pass
	print("x("+str(row_u_does_not_exist.n)+"): "+str(x_not_exist_disp))
	print("y("+str(row_u_does_not_exist.n)+"): "+str(y_not_exist_disp))


I have also been unable to import modules like h5py to try and extract the data visible in the mpco files using HDFView (e.g. retrieve nodes or elements Tags from a set in an MPCO file which (as I understand it) corresponds to the region command in Tcl OpenSees) - although I am relatively new to Python and until now have been just using pip install <name> in the Windows cmd to this point alongside PyCharm + Python 3.9.6.

In summary:
1) Is there a better way to identify that a node or element exists at a given Analysis step using PyMpc functions and the mpco database than the try: except RuntimeError with a recorder output request? For example, a boolean or -1 value when using MpcOdbResultField.node(<nodeTag>) to identify the row index of <nodeTag> in the mpco database? PyMpc documentation: https://asdeasoft.net/stko-wiki/class_p ... ml#details

2) Is there a way to extract a list/vector of eleTags/nodeTags from the sets in mpco objects (Tcl Regions) and then update their 'presence' at each analysis step?

3) If these are not trivial to achieve with PyMpc functions, how would you go about installing a compatible version of h5py for use with STKO's Python API? (Plan would be to recursively identify keys in MPCO database and use regular expressions or a string search to access the relevant sets etc...)

STKO Team
Posts: 3066
Joined: Tue Oct 29, 2019 8:45 am

Re: Extracting node/element presence in model from *.mpco databases

Post by STKO Team » Thu Aug 05, 2021 5:24 pm

1) Is there a better way to identify that a node or element exists at a given Analysis step using PyMpc functions and the mpco database than the try: except RuntimeError with a recorder output request? For example, a boolean or -1 value when using MpcOdbResultField.node(<nodeTag>) to identify the row index of <nodeTag> in the mpco database?
Yes and it is very easy. You need a couple of concepts:
  • the evaluate(opt) method of MpcOdbVirtualResult produces a MpcOdbResultField.
  • the mesh attribute of MpcOdbResultField gives you the mesh at the stage specified in opt (MpcOdbVirtualResultEvaluationOptions)
  • every time you remove a node/element, OpenSees issues the domainChange method, that leads to a new ModelStage in MPCO. This means that you don't need to check every step of every stage, but just the first step of each stage.

Code: Select all

from PyMpc import *
from PyMpc import MpcOdbVirtualResult as vr

App.clearTerminal()
doc = App.postDocument()
db = doc.getDatabase(1)

# the node we want to check.
# we can check the presence of a node from the mesh in
# the result field
check_node = 134

# we need a result to generate a field, and to
# get the mesh from the field
result = db.getNodalResult('Displacement', match=MpcOdb.Contains)

# create the eval options
opt = MpcOdbVirtualResultEvaluationOptions()

# keep in mind that when you remove a node or an element,
# we have a new model stage (due to the domainChange method).
# so we don't need to evaluate the result
all_stages = db.getStageIDs()
for i in range(len(all_stages)):
	# the current stage_id
	stage_id = all_stages[i]
	# get all step id and time for this stage
	steps = list(db.getStepIDs(stage_id))
	times = list(db.getStepTimes(stage_id))
	# make sure we have at least 1 step
	if len(steps) > 0:
		# take the first one
		step_id = steps[0]
		time = times[0]
		# make field
		opt.stage = stage_id
		opt.step = step_id
		field = result.evaluate(opt)
		mesh = field.mesh
		exists = check_node in mesh.nodes
		print('Stage: {}, Start Time: {}, Start Step: {}, Exists ? {}'.format(
			stage_id, time, step_id, exists))
2) Is there a way to extract a list/vector of eleTags/nodeTags from the sets in mpco objects (Tcl Regions) and then update their 'presence' at each analysis step?
There is no way to extract info from the OpenSees' regions. And they are not saved in the MPCO recorder.
However, if you generate your model from the STKO pre-processor, STKO generates a *.mpco.cdata file that contains all information coming from the pre-processor.
Among them you can find SELECTION_SETS. It will be very easy to parse this file:
sset.png
sset.png (72.12 KiB) Viewed 3851 times

Edward_Hayes
Posts: 3
Joined: Fri Jul 16, 2021 10:17 am

Re: Extracting node/element presence in model from *.mpco databases

Post by Edward_Hayes » Tue Nov 09, 2021 10:49 am

The above answer was very helpful, however, since updating to STKO 2.0.4 from 2.0.3 the Python Post-processing script I made using the above advice has stopped working.

After updating to STKO 2.0.4 I attempted to run a script using the above method (which worked previously in version 2.0.3) to load MPCO databases compare nodes/elements and investigate nodal displacements (amongst other things).

The basis of the code is:

Code: Select all

from PyMpc import *
import os
import sys
import inspect
import traceback
import pdb
import pickle
import math
from os import chdir
from inspect import getmembers, isfunction
App.clearTerminal()
doc=App.postDocument()
MPCO_filename_u = "filename_u.mpco"
MPCO_filename_d = "filename_d.mpco"
export_dir = "export_dir_full_pathname"
if not os.path.exists(export_dir):
	os.makedirs(export_dir)
App.runCommand("OpenDatabase", MPCO_filename_u)
App.setBusy(False)
App.runCommand("OpenDataBase", MPCO_filename_d)
# Set loaded databases to variable names
db_u = doc.getDatabase(1)
db_d = doc.getDatabase(2)
# Get Model Stages
stages_u = db_u.getStageIDs() # type() = int_array
stages_d = db_d.getStageIDs() # type() = int_array
# Get Analysis Step IDs
current_stage_u = stages_u[0]
current_stage_d = stages_d[0]
analysisSteps_u_curr_stage = db_u.getStepIDs(current_stage_u)
analysisSteps_d_curr_stage = db_d.getStepIDs(current_stage_d)
# Set Options
opt_u = MpcOdbVirtualResultEvaluationOptions()
opt_d = MpcOdbVirtualResultEvaluationOptions()
opt_u.stage = current_stage_u
opt_d.stage = current_stage_d
# Get timeSteps for current model stages
timeSteps_u_curr_stage = db_u.getStepTimes(current_stage_u)
timeSteps_d_curr_stage = db_d.getStepTimes(current_stage_d) 
All of the above code runs and prints the correct Model-Stages, time-steps, analysis-steps which matches the data visible in the MPCO file using HDFView.

However, upon attempting to retrieve the nodal displacement result field (for which the data exists inside HDFView) the terminal throws a very long error which it did not previously in Version 2.0.3 which was used when the original question was solved/asked and used to make these scripts.

Code: Select all

result_field_u = db_u.getNodalResult('Displacement', match=MpcOdb.Contains)
result_field_d = db_d.getNodalResult('Displacement', match=MpcOdb.Contains)
The error received reads as in the image below:
Image



The Nodal Displacements are recorded inside the MPCO file in question as seen inside HDFView (see image below)


Image

Is there something obvious missing or that has changed between versions here?

Thanks,

Ed

STKO Team
Posts: 3066
Joined: Tue Oct 29, 2019 8:45 am

Re: Extracting node/element presence in model from *.mpco databases

Post by STKO Team » Tue Nov 09, 2021 2:51 pm

Yes, this issue has been already discussed here:
viewtopic.php?f=27&t=2080

You can follow the advice given there to fix it.
It will be permanently fixed in version 2.0.5 that will be released in the next few days

Edward_Hayes
Posts: 3
Joined: Fri Jul 16, 2021 10:17 am

Re: Extracting node/element presence in model from *.mpco databases

Post by Edward_Hayes » Wed Nov 10, 2021 12:15 pm

Hi,

After following the forum links' advice, I replaced the

Code: Select all

result_field_u = db_u.getNodalResult('Displacement', match=MpcOdb.Contains)
with:

Code: Select all

result_field_u = db_u.getNodalResult('Displacement', match=3)
Upon doing so, the error message pictured in the previous post persisted.

This also occurred when I edited from the example script posted in the linked forum (4th post on page 1 from marafini.f on 28 Sep 2021 viewtopic.php?f=27&t=2080 )

The displacements of the MPCO model are available in the STKO Plot Groups.

The code being used:

Code: Select all

from PyMpc import *
from PyMpc import MpcOdbVirtualResult as vr
import os
import sys
import inspect
import traceback
import pdb
import pickle
import math
from os import chdir
from read_txt_to_arr import read_txt_to_arr
from inspect import getmembers, isfunction
from interr_PyMpc_obj import interr_PyMpc_obj
App.clearTerminal() # Clear the STKO Terminal

# get document
doc = App.postDocument()
# open database
input_sim_no = 1000
undamaged_filename = "MPCO_1006_UND.mpco"
App.runCommand("OpenDatabase", undamaged_filename)

# get first database
if len(doc.databases) == 0:
	raise Exception("You need a database with ID = 1 for this test")
db = doc.getDatabase(1)

# create evaluation options
# here we want to extract data for all steps of the last stage
all_stages = db.getStageIDs()  # get all model stages
last_stage = all_stages[-1]  # get the last stage (pushover)
first_stage = all_stages[0] # get the first stage
all_stage1_steps = db.getStepIDs(first_stage)
all_stage1_times = db.getStepTimes(first_stage)
all_steps = db.getStepIDs(last_stage)  # get all steps of the last stage
all_times = db.getStepTimes(last_stage)  # get all step times of the last stage

step = all_stage1_steps[-1]
print(step)
InitialReactionForce = db.getNodalResult("Displacement", match=3)

App.processEvents()

# initialize the evaluation options with the last stage
#result_field_u = db.getNodalResult("Displacement", match = MpcOdb.Contains)
result_field_u = db.getNodalResult("Displacement", match = 3)

STKO Team
Posts: 3066
Joined: Tue Oct 29, 2019 8:45 am

Re: Extracting node/element presence in model from *.mpco databases

Post by STKO Team » Wed Nov 10, 2021 5:07 pm

Yes, I confirm that this trick is not working.
Probably when I suggested it to the other user, I tested it on the newer version.

Anyway, tomorrow we will release STKO version 2.0.5 where this error will be fixed, and you can keep on using MpcOdb.Containts etc...

Sorry for the incovenience.

Post Reply