Read stresses 'S' of Abaqus results with python - python

Good evening,
i have done a script for getting a model and to generate results. I've tried to write in the same script a way for getting to read the values of stresses but python says :
" File "C:/Users/TFG", line 250, in <module> RegionTen=odb.rootAssembly.noseSets['Set-1'] KeyError: Set-1 "
I understand like Set-1 doesnt exit but that's not true. I hope someones can help me.
I create Set-1 :
mdb.models['Model-1'].parts['Part-1'].Set(faces= mdb.models['Model-1'].parts['Part-1'].faces.getSequenceFromMask(('[#1 ]', ), ), name='Set-1')
And my code for getting to read the stresses is:
odb = openOdb( path='C:\Temp\Job-1.odb')
RegionTen = odb.rootAssembly.nodeSets['Set-1']
tamFrames = len(odb.steps['Step-1'].frames)
lastFrames = odb.steps['Step-1'].frames[tamFrames-1]
stress33 = lastFrame.fieldOutputs['S'].getSubset(position=ELEMENT_NODAL, region=RegionTen)
stress13 = lastFrame.fieldOutputs['CTSHR13'].getSubset(position=ELEMENT_NODAL, region=RegionTen)
stress23 = lastFrame.fieldOutputs['CTSHR23'].getSubset(position=ELEMENT_NODAL, region=RegionTen)
print(stress11, stress22, stress12)

You are now trying to get an assembly level node set. Yet, you are defining your node set inside a part. Inside the Odb, you need to access this node set through an instance.
Figure out the instance name from the part name. Most likely it's just 'PART-1-1'. After you do this, get the region like this:
regionTen = odb.rootAssembly.instances['instanceName'].nodeSets['Set-1']
You can see the difference between these set types in Abaqus. Instance level node sets have a prefix - 'InstanceName.'. Notice a dot after an instance name.

You can access the Node Sets defined in the Assembly using the following way:
odb.rootAssembly.nodeSets.keys()
And yes they seem to appear all in upper case.

Related

Dynamo Revit set formula for a parameter in a family

I am trying to add a formula to a parameter within a Revit Family.
Currently I have multiple families in a project. I run Dynamo from within that project then I extract the families that I want to modify using Dynamo standard nodes.
Then I use a python script node that goes through every selected family and find the parameter I am interested in, and assign a formula for it.
That seemed fine until I noticed that it is not assigning the formula, but it is entering it as a string — as in it is in quotes. And sure enough, the code i am using will only work with Text type parameters.
Can someone shed the light on how to assign a formula to a parameter using dynamo?
see line 32 in code below
Thanks
for family in families:
TransactionManager.Instance.ForceCloseTransaction()
famdoc = doc.EditFamily(family)
FamilyMan = famdoc.FamilyManager
found.append(family.Name)
TransactionManager.Instance.EnsureInTransaction(famdoc)
check = 0
# Loop thru the list of parameters to assign formula values to them... these are given as imput
for r in range(len(param_name_lst)):
# Loop thru the list of parameters in the current family per the families outter loop above.
for param in FamilyMan.Parameters:
#for param in FamilyMan.get_Parameter(param_name_lst[r]):
# for each of the parameters get their name and store in paramName.
paramName = param.Definition.Name
# Check if we have a match in parameter name.
if param_name_lst[r] in paramName:
if param.CanAssignFormula:
canassignformula.append(param_name_lst[r])
else:
cannotassignformula.append(param_name_lst[r])
try:
# Make sure that the parameter is not locked.
if FamilyMan.IsParameterLocked(param):
FamilyMan.SetParameterLocked(param,False)
locked.append(paraName)
# Enter formula value to parameter.
FamilyMan.SetFormula(param, param_value_lst[r])
check += 1
except:
failed.append(paramName)
else:
continue
Actually, you can access the family from the main project, and you can assign a formula automatically.... That's what i currently do, i load all the families i want in one project and run the script.
After a lot of work, i was able to figure out what i was doing wrong, and in it is not in my code... my code was fine.
The main problem is that i need to have all of my formula's dependencies lined up.... just like in manual mode.
so if my formula is:
size_lookup(MY_ID_tbl, "MY_VAR", "MY_DefaultValue", ND1,ND2)
then i need to have the following:
MY_ID_tbl should exist and be assigned a valid value, in this case it should have a csv filename. Moreover, that file should be also loaded. This is important for the next steps.
MY_VAR should be defined in that csv file, so Does ND1, ND2
The default value (My_Default_Value) should match what that csv file says about that variable...in this case, it is a text.
Needless to say, i did not have all of the above lined up as it should be, once i fixed that, my setFormula code did its job. And i had to change my process altogether, cause i have to first create the MY_ID_tbl and load the csv file which i also do using dynamo, then i go and enter the formulas using dynamo.
Revit parameters can only be assigned to a formula inside the family editor only, that is the first point, so you should run your dynamo script inside the family editor for each family which will be a waste of time and you just edit the parameter's formula manually inside each family.
and the second point, I don't even think that it is possible to set a certain parameter's formula automatically, it must be done manually ( I haven't seen anything for it in the Revit API docs).

Abaqus python scripting - Creating assembly level element set from elements of two parts

I would like to create an assembly level set from two part sets using python scripting. Note that each part has a native mesh associated with it. Here is my attempt:
elsetPart1 = part1.Set(name='allElements', elements=part1.elements)
elsetPart2 = part2.Set(name='allElements', elements=part2.elements)
elsetAssembly = model.rootAssembly.Set('assemblyElements',
elements=(elsetPart1.elements,elsetPart2.elements))
print(len(elsetPart1.elements), len(elsetPart2.elements),
len(elsetAssembly.elements))
Output: (3608, 2500, 0)
Why is this giving me zero elements in elsetAssembly, when there are clearly elements in each part?
There are two issues in the above piece of code,
elsetPart1 and elsetPart2 are of <type 'MeshElementArray'> which could be concatenated with `+' rather than combining them as a tuple.
From my understanding set Object from part and assembly are different. So, access the elsetPart1 from assembly.
elsetPart_a = mdb.rootAssembly.instances[<part1>].sets[<elSetName>].elements
elsetPart_b = mdb.rootAssembly.instances[<part2>].sets[<elSetName>].elements
elsetAssembly = model.rootAssembly.Set('assemblyElements',
elements=elsetPart_a+elsetPart_b)

Getting element density from abaqus output database using python scripting

I'm trying to get the element density from the abaqus output database. I know you can request a field output for the volume using 'EVOL', is something similar possible for the density?
I'm afraid it's not because of this: Getting element mass in Abaqus postprocessor
What would be the most efficient way to get the density? Look for every element in which section set it is?
Found a solution, I don't know if it's the fastest but it works:
odb_file_path=r'your_path\file.odb'
odb = session.openOdb(name=odb_file_path)
instance = odb.rootAssembly.instances['MY_PART']
material_name = instance.elements[0].sectionCategory.name[8:-2]
density=odb.materials[material_name].density.table[0][0])
note: the 'name' attribute will give you a string like, 'solid MATERIALNAME'. So I just cut out the part of the string that gave me the real material name. So it's the sectionCategory attribute of an OdbElementObject that is the answer.
EDIT: This doesn't seem to work after all, it turns out that it gives all elements the same material name, being the name of the first material.
The properties are associated something like this:
sectionAssignment connects section to set
set is the container for element
section connects sectionAssignment to material
instance is connected to part (could be from a part from another model)
part is connected to model
model is connected to section
Use the .inp or .cae file if you can. The following gets it from an opened cae file. To thoroughly get elements from materials, you would do something like the following, assuming you're starting your search in rootAssembly.instances:
Find the parts which the instances were created from.
Find the models which contain these parts.
Look for all sections with material_name in these parts, and store all the sectionNames associated with this section
Look for all sectionAssignments which references these sectionNames
Under each of these sectionAssignments, there is an associated region object which has the name (as a string) of an elementSet and the name of a part. Get all the elements from this elementSet in this part.
Cleanup:
Use the Python set object to remove any multiple references to the same element.
Multiply the number of elements in this set by the number of identical part instances that refer to this material in rootAssembly.
E.g., for some cae model variable called model:
model_part_repeats = {}
model_part_elemLabels = {}
for instance in model.rootAssembly.instances.values():
p = instance.part.name
m = instance.part.modelName
try:
model_part_repeats[(m, p)] += 1
continue
except KeyError:
model_part_repeats[(m, p)] = 1
# Get all sections in model
sectionNames = []
for s in mdb.models[m].sections.values():
if s.material == material_name: # material_name is already known
# This is a valid section - search for section assignments
# in part for this section, and then the associated set
sectionNames.append(s.name)
if sectionNames:
labels = []
for sa in mdb.models[m].parts[p].sectionAssignments:
if sa.sectionName in sectionNames:
eset = sa.region[0]
labels = labels + [e.label for e in mdb.models[m].parts[p].sets[eset].elements]
labels = list(set(labels))
model_part_elemLabels[(m,p)] = labels
else:
model_part_elemLabels[(m,p)] = []
num_elements_with_material = sum([model_part_repeats[k]*len(model_part_elemLabels[k]) for k in model_part_repeats])
Finally, grab the material density associated with material_name then multiply it by num_elements_with_material.
Of course, this method will be extremely slow for larger models, and it is more advisable to use string techniques on the .inp file for faster performance.

Python- how to query database by class

I have a Python project (I'm quite new to Python), and on one of the webpages, there is a drop-down box which should display a list of all of the projects whose 'status' fields are set to 'live'.
It seems that a couple of particular objects are not being displayed in this drop-down box, so I want to manually query the database to check what their 'status' fields are set to.
How do I manually query the database for these particular projects by their 'project name'/ 'project code', both of which I know are unique?
I've tried getting a list of all of the projects in the shell, so that I can query that list by project_name for the particular projects that I want using the commands:
from projects.models import Project
prjcts = []
prjcts = Project.objects.all()
This gets all of the Project objects and assigns them to the list prjcts. I now want to query that list for a particular project, and have tried doing so like this:
6Stoke = prjcts.get(project_code = 6SPR)
My intention was that the project with the project_code whose value was 6SPR would be assigned to the variable 6Stoke, so that I could then find look at all of the information for that particular project. However, when I tried running this line in the console, I got a
SyntaxError: invalid syntax
warning which highlighted the end of the 6Stoke part of the line.
What is wrong with my syntax here? How can I get the project that has the specified project_code and assign it to a variable?
Edit
Ah, ok- thanks. I changed the variable name, and ran the query again, assigning its results to the variable sixStokeList, i.e.
sixStokeList = Project.objects.filter(project_code = "6SPR")
this returned two items, and having printed the elements of the array to the console, i.e. sixStokeList[0] & sixStokeList[1], I know which one I want, so I've assigned that particular one to a variable with:
sixStoke = sixStokeList[1]
I have then typed sixStoke. and pressed 'tab' in the console to see what's available to this variable. I did the same with another project, i.e.
theFoss = Project.objects.filter(project_code= "1TF")
theFoss. (& pressed 'tab')
The list of available options given after typing variable + . + tab was different for each project instance, even though I had got them both in exactly the same way, which would indicate to me that they are not instances of the same class... how can this be, given that I got them both by querying the same class?
You can't name a variable beginning with a number

Assigning variable for dynamic filename in Python

I am new to python scripting and am required to build a script for WebLogic Server. The requirement is to use a file (type .rpd) from assigned location for deployment. The file type would remain same throughout, however, the file name would change.
Given this condition, I tried the below methods on assigning file to the variable. Both the below methods are not working.
rpdfile = "*.rpd"
rpdlocation = "/u02/RPD_Upload/"+rpdfile+
or
rpdlocation = "/u02/RPD_Upload/*.rpd
I get invalid syntax error while running the python. Experts please help me understand on assigning such variables.
For your first method, you are not appending correctly. You have an extra '+' at the end of the line. It should look like this:
rpdfile = "*.rpd"
rpdlocation = "/u02/RPD_Upload/" + rpdfile
For your second method, you are not closing the double-quote. See below:
rpdlocation = "/u02/RPD_Upload/*.rpd"

Categories