NaxToPy.Core package#

Subpackages#

Submodules#

NaxToPy.Core.N2PModelContent module#

class NaxToPy.Core.N2PModelContent.N2PModelContent(path, parallelprocessing, solver=None)#

Bases: object

Main Class of the NaxToPy package. Keeps almost all the information contained in the output result.

Attributes:

FilePath: str Solver: str AbaqusVersion: str LoadCases: list[N2PLoadCases] NumberLoadCases: int Parts: list[str]

property AbaqusVersion: str#

Returns the Abaqus version used in the output result file if the solver is Abaqus

property ConnectorsDict: OrderedDict[tuple[int, int], N2PConnector]#

Returns a dictionary with the N2PConnector of the model as values. The key is the tuple (id, partid)

property ElementsDict: OrderedDict[tuple[int, int], N2PElement]#

Returns a dictionary with the N2PElement of the model as values. The key is the tuple (id, partid)

property FilePath: str#
property LoadCases: list[N2PLoadCase, ...]#

Returns a list with all the of N2PLoadCase

property MaterialDict: dict[int, N2PMaterial]#

Property of the N2PModelContent class that returns the dictionary of materials. This is an attribute of the class, but it is not initialize at first, only when it is needed.

Returns:

dict[tuple[ID]] = N2PMaterial

property ModelInputData: N2PModelInputData#

Returns a N2PModelInputData with the information of the input data file

property NodesDict: OrderedDict[tuple[int, int], N2PNode]#

Returns a dictionary with the N2PNode of the model as values. The key is the tuple (id, partid)

property NumberLoadCases: int#
property Parts: list[str]#

Returns the list of parts/superelements of the model

property PropertyDict: dict[tuple, N2PProperty]#

Property of the N2PModelContent class that returns the dictionary of properties. This is an attribute of the class, but it is not initialize at first, only when it is needed

Returns:

dict[tuple[ID, PartID]] = N2PProperty

property SetList: list[N2PSet, ...]#

Returns a list of N2PSet kept in the model

property Solver: str#
clear_results_memory() None#

Method that delete the results data store at low level. It is useful when a lot of results are asked and kept in Python memory

create_free_body(name: str, loadcase: N2PLoadCase, increment: N2PIncrement = None, nodes: list[N2PNode] = None, elements: list[N2PElement] = None, outpoint: tuple[float, ...] = None, coordsysout: N2PCoord = None) N2PFreeBody#

Method that creates a N2PFreeBody object, keeps in N2PModelContent.FreeBodiesDict and returns it.

A N2PFreeBody contains the information of the cross-section defined by the user and the forces and moments calculated by NaxToPy durin the instance of the object.

Args:

name: str -> Must be unique. If a new FreeBody is name as an old one, the old FreeBody will be deleted. loadcase: N2PLoadCase increment: N2PIncrement nodes: list[N2PNode] elements: list[N2PElement] outpoint: tuple[float] coordsysout: N2PCoord

Returns:

freebody: N2PFreeBody

Example:
>>> model = load_model("model.op2")
>>> lc = model.get_load_case(5)
>>> incr = lc.ActiveN2PIncrement
>>> node_list = model.get_nodes([1000, 1001, 1002, 1003, 1004, 1005])
>>> elem_list = model.get_elements([1000, 1001, 1002, 1003, 1004])
elementnodal() dict[int, tuple]#

Method that generate the dictionary for the element-nodal mesh.

Use the internal id for unsew nodes as key and a tuple (ID_Part_Solver, ID_Node_Solver, ID_Element_Solver) as a value. If the dictionary has already created it is pointed instead.

Returns:

dict[internal_node_unsew] = (Part_Solver, ID_Node_Solver, ID_Element_Solver)

get_connectors(ids=0) N2PConnector#

General method for obtain connectors.

If it has no argument or is 0: returns all the elements. If it has one id as argument: returns one N2PConnector. If it has a list as argument it returns a list of N2PConnector. The ids should be a tuple (id, part_id). If not, part_id = 0 by default.

Args:

ids: int | list[int] | tuple[int, str] | list[tuple[int, str]]

Returns:

object: N2PConnector | list[N2PConnector]

get_coords(ids=0) N2PCoord#

General method for obtain coordinate systems.

If it has no argument or is 0: returns all the coordinate systems If it has one id as argument: returns one N2PCoord If it has a list as argument it returns a list of N2PCoord The ids should be a tuple (id, part_id). If not, part_id = 0 by default

Args:

ids: int | list[int] | tuple[int, str] | list[tuple[int, str]]

Returns:

object: N2PCoord | list[N2PCoord]

get_elements(ids: tuple[int, str] | list | int = 0) N2PElement | list[N2PElement]#

General method for obtain elements.

If it has no argument or is 0: returns all the elements If it has one id as argument: returns one N2PElement If it has a list as argument it returns a list of N2PElement The ids should be a tuple (id, part_id). If not, part_id = 0 by default

Args:

ids: int | list[int] | tuple[int, str] | list[tuple[int, str]]

Returns:

object: N2PElement | list[N2PElement]

get_elements_adjacent(cells: list[N2PElement, N2PConnector, ...], domain: list[N2PElement, N2PConnector, ...] = None) list[N2PElement, N2PConnector, ...]#

Method of N2PModelContent that returns a list of N2PElement and N2PConnector that are adjacent to selected ones. If a domain is selected, the adjacent elements only will be searched in that domain.

Args:

cells: list[N2PElement, N2PConnector, …] domain: list[N2PElement, N2PConnector, …] -> Optional. Set the domain where to look for the adjacent elements

Returns:

list[N2PElement, N2PConnector, …]

Example:
>>> model = load_model("model.odb")
>>> domain_S4 = [e for e in model.get_elements() if e.TypeElement == "S4"]
>>> elems_adj = model.get_elements_adjacent(model.get_elements(17500), domain=domain_S4)
get_elements_attached(cells: list[N2PElement, N2PConnector, ...], domain: list[N2PElement, N2PConnector, ...] = None) list[N2PElement, N2PConnector, ...]#

Method of N2PModelContent that returns a list of N2PElement and N2PConnector that are attached to selected ones. If a domain is selected, the attached elements only will be searched in that domain.

Args:

cells: list[N2PElement, N2PConnector, …] domain: list[N2PElement, N2PConnector, …] -> Optional. Set the domain where to look for the adjacent elements

Returns:

list[N2PElement, N2PConnector, …]

Example:
>>> model = load_model("model.h3d")
>>> domain_elems = model.get_elements()
>>> elems_att = model.get_elements_attached(model.get_elements(17500), domain=domain_elems)
get_elements_by_face(cells: list[N2PElement, N2PConnector, ...], tolerance_angle: float = 30, one_element_adjacent: bool = True, domain: list[N2PElement, N2PConnector, ...] = None) list[N2PElement, N2PConnector, ...]#

Method of N2PModelContent that returns a list of N2PElement and N2PConnector that are in the same face as the selected ones. If a domain is selected, the face elements only will be searched in that domain. To be considered in the same face, the adjacent element must share an arist and the angle between the elements must be lower than the tolerance angle.

Args:

cells: list[N2PElement, N2PConnector, …]

tolerance_angle: float -> Optional (30º by default). Max angle[º] between two elements to be considered in the same face

one_element_adjacent: bool -> Optional (True by default). If true, two elements are connected to arist of a selected element they will no be consisidered.

domain: list[N2PElement, N2PConnector, …] -> Optional. Set the domain where to look for the adjacent elements

Returns:

list[N2PElement, N2PConnector, …]

Example:
>>> model = load_model("model.op2")
>>> elems1 = model.get_elements_by_face(model.get_elements(17500))
>>> domain_cquad = [e for e in model.get_elements() if e.TypeElement == "CQUAD4"]
>>> elems2 = model.get_elements_by_face(model.get_elements([17500, 17501]), 25, domain=domain_cquad)
get_free_edges(domain: list[N2PElement, N2PConnector, ...] = None) list[tuple[N2PElement, N2PNode, N2PNode], ...]#

Method of N2PModelContent that returns a list of tuples of a N2PElement and two N2PNode of that element. The two nodes define the edge of the element that is contained in the free edge of the mesh If a domain is selected, the tuple will only be searched in that domain. Notice that connectors, although they may be given in the domain, they are never included in the free edges.

Args:

domain: list[N2PElement, N2PConnector, …] -> Optional. Set the domain where to look for the free edges

Returns:

list[tuple[N2PElement, N2PNode, N2PNode], …]

get_load_case(id: int) list[N2PLoadCase] | N2PLoadCase | None#
get_load_case(name: str) list[N2PLoadCase] | N2PLoadCase | None

Returns a list of N2PLoadCase objects with all the load cases contained in the output result file.

Args:

id (int, optional): ID of the load case. Defaults to None. name (str, optional): Name of the load case. Defaults to None.

Returns:

N2PLoadCase: load_case

get_nodes(ids=0) N2PNode | list[N2PNode]#

General method for obtain nodes.

If it has no argument or is 0: returns all the nodes. If it has one id as argument: returns one N2PNode. If it has a list as argument it returns a list of N2PNode. The ids should be a tuple (id, part_id). If not, part_id = 0 by default.

Args:

ids: int | list[int] | tuple[int, str] | list[tuple[int, str]]

Returns:

object: N2PNode | list[N2PNode]

get_result_by_LCs_Incr(list_lc_incr: list[tuple[N2PLoadCase, N2PIncrement], ...] | list[tuple[int, int], ...], result: str, component: str, sections=None, aveSections=-1, cornerData=False, aveNodes=-1, variation=100, realPolar=0, coordsys: int = -1000, v1: tuple = (1, 0, 0), v2: tuple = (0, 1, 0)) dict[slice(<class 'tuple'>, 'ndarray', None)]#

Method to ask for results of a component in several loadcases and increments. It uses parallel subprocesses to speed up the calculus. Returns a dictionary where the keys are tuples with the IDs of LoadCase and Increment and the values are numpy arrays.

Examples:
>>> vonmises = N2PModelContent.get_result_by_LCs_Incr([(1,2),(2,2)], "STRESSES", "VON_MISES")
>>> XX = N2PModelContent.get_result_by_LCs_Incr([(loadcase1, increment2), (loadcase2, increment2), "STRAINS", "XX"])

Args:

list_lc_incr: list[tuple] -> list with the tuples of the loadcase|increment asked for the component

result: str -> String with the result

component: str -> String with the component

sections: list[str] | list[N2PSection] -> Sections which operations are done.

None (Default) = All Sections

aveSections: int -> Operation Among Sections.

-1 : Maximum (Default), -2 : Minimum, -3 : Average, -4 : Extreme, -6 : Difference.

cornerData: bool -> flag to get results in element nodal.

True : Results in Element-Nodal, False : Results in centroid (Default).

aveNodes: int -> Operation among nodes when cornerData is selected.

0 : None, -1 : Maximum (Default), -2 : Minimum, -3 : Average, -5 : Average with variation parameter, -6 : Difference.

variation: int -> Integer between 0 & 100 to select.

0 : No average between nodes, 100 : Total average between nodes (Default).

realPolar: int -> data type when complex result.

1 : Real / Imaginary, 2 : Magnitude / Phase.

coordsys: int -> Coordinate System where the result_array will be represented.

0 : Global, -1 : Material Coordinate System, -10 : User defined, -20 : Element/Node User Defined, >0 : Solver ID of the Predefined Coordinate System.

v1: tuple

v2: tuple -> Directions vectors that generate the coordinate system axis:

x=v1, z=v1^v2, y=z^x.

Returns:

dict[tuple: ndarray] -> results for the component ordered in a dictionary

import_results_from_files(results_files: list[str, ...]) None#

Method of N2PModelContent that reads an output result file from Nastran, Abaqus, Optistruct or Ansys and add the results to the N2PModelContent Object.

Supports .op2, .xdb, .odb, .h5, .h3d and .rst file extensions read from a local filesystem or URL.

Args:

results_files: list[str, …]

Example:
>>> model1 = load_model("model1_lc1.odb")
>>> model1.import_results_from_files(["model1_lc2.odb", "mode1l_lc3.odb"])
>>> model2 = load_model("model2.dat", "InputFileNastran")
>>> model2.import_results_from_files(["model2_lc1.op2", "model2_lc2.op2"])
load_user_coord_sys_from_csv(path: str, where: Literal['NODES', 'ELEMENTS']) None#

Method that loads a coordinate system for each node/element as a user coordinate system from a CSV file.

The user can define a different system for each element or node and ask for results in that system using the optional argument “coordsys=-20”

The structure of the csv must have the node/element identification, and the coordinates of the vectors v1 and v2 that generates the system: x = v1; z = v1^v2; y = z^v1. The structure for elements and nodes must be:

node_id_1,part_id_1,x11,y11,z11,x12,y12,z12

user_system_elements_example.csv:

1001,0,1,0,0,0,1,0

1002,0,0.3,0.2,0,0,1,0

1003,0,0,1,0,1,1,0

1004,0,2,0,1,0.4,1,3

Warnings:

If a CSV is loaded and the another is loaded, the previous information will be deleted.

Args:

path: path for a CSV. where: “NODES”|”ELEMENTS”. The user coordinate systems are for the nodes or the elements.

Examples:
>>> N2PModelContent.load_user_coord_sys_from_csv(path="user_system_elements_example.csv", where="ELEMENTS")
>>> N2PModelContent.load_user_coord_sys_from_csv("node_sys.csv", "NODES")
new_derived_loadcase(name: str, formula: str) N2PLoadCase#

Method of N2PModelContent that generate a new N2PLoadCase by lineal combination of n loadcases|frames.

In order to define the combination a string with the load case and frame and the arithmetical commands as strings must be passed as arguments. The name of the new derived loadcase must be set, but the id not. The id will be a negative integer. The loadcases|frames must have this structure: <LCXX:FRYY>. Examples of formulas:

  • formula = “<LC1:FR1>+2*<LC2:FR1>+0.5*<LC5:FR3>”

  • formula = “0.5*<LC1:FR2>”

  • formula = “5*<LC2:FR3>-2*<LC3:FR3>”

Note:

The derived load cases will have only one frame/increment with id 0. So it is used in a formula the string will be “<LC-1:FR0>”.

Args:

name: str -> String with the name of the load case. formula: str -> String that must have the loadcase|frame is intended to use and the arithmetical opreations.

Returns:

N2PLoadCase -> Derived load case

Examples:
>>> dev_lc1 = new_derived_loadcase("dev_lc1", "<LC1:FR1>+2*<LC2:FR1>+0.5*<LC5:FR3>")
>>> dev_lc2 = new_derived_loadcase("dev_lc2", "0.5*<LC1:FR2>")
>>> dev_lc3 = new_derived_loadcase("dev_lc3", "5*<LC-1:FR0>-2*<LC3:FR3>")
new_envelope_loadcase(name: str, formula: str, criteria: Literal['ExtremeMax', 'ExtremeMin', 'Max', 'Min', 'Range'] = 'ExtremeMax', envelgroup: Literal['ByContour', 'ByLoadCaseID', 'ByIncrement'] = 'ByContour') N2PLoadCase#

Method of N2PModelContent that generate a new N2PLoadCase that is the envelope of the load cases and increments selected.

The id is automatically generated. It will be negative, starting at -1. If the new load case use a derivated or envelope load case use LCD1 in the formula instead of LC-1:

Args:

name (str) -> Name of the envelope load case. It mustn’t be repeated.

formula (str) -> formula that define the loadcases and increments must have this structure: <LCXX:FRYY>

exmaple: “<LC1:FR1>,<LCD2:FR1>,<LC2:FR10>”

criteria (str): Criteria for selecting the results to build the new derived load case. Possible values:

  • ‘ExtremeMax’

  • ‘ExtremeMin’

  • ‘Max’

  • ‘Min’

  • ‘Range’

envelgroup (str): Criteria to select the data asociated to the elements/nodes:

  • ‘ByContour’: The data will be the actual value (XX stress for example)

  • ‘ByLoadCaseID’: The data will be the id of the original load case that is critical (LC 6363 for example)

  • ‘ByIncrement’: The data will be the id of the increment that is critical

Returns:

N2PLoadCase

Examples:
>>> env_lc1 = new_envelope_loadcase("env_lc1", formula="<LC1:FR1>,<LC2:FR1>")
>>> env_lc2 = new_envelope_loadcase("env_lc2", formula="<LC1:FR1>,<LC2:FR8>,<LC-3:FR0>", criteria="Min", envelgroup="ByLoadCaseID")
new_report(lc_incr: str, allincr: bool, result: str, componentssections: str, ifenvelope: bool, selection: list[N2PNode, N2PElement], sortby: str, aveSections=-1, cornerData=False, aveNodes=-1, variation=100, realPolar=0, coordsys: int = -1000, v1: tuple | ndarray = (1, 0, 0), v2: tuple | ndarray = (0, 1, 0)) N2PReport#

Method of N2PModelContent that generates a N2PReport. A N2PReport object contains the information of the load cases, increments, components and sections for a result in the selection specified (nodes or elements).

The N2PReport has a method that calculate the array result for the desired parameter and returns two ndarray of numpy (dtype = str): the array of headers, and the array of results.

The N2PReport has also a method to write into a CSV all these data.

Note:

Only one result is available per report. Example: DISPLACEMENTS -> All components, for all load cases, but not STRESSES at the same time.

Args:
lc_incr: str -> Formula of the loadcases-increments desired. Each pair LC-FR must have the following

structure <LCX:FRY> where X is the id of the load case and Y the id of the increment/frame. Example: “<LC1:FR1>,<LC1:FR2>,<LC2:FR1>,<LC2:FR2>”.

allincr: bool -> Parameter for asking all increments for the load cases asked.

result: str -> Name of the result to ask.

componentssections: str -> Formula with the components and the section desired. Each component can have

several sections, and the structure must be: <ComopnentName:X#Y#Z#> where X, Y, Z are the names of the section. After each name of section there must be an #, even if there is only one. Example: “<VONMISES:Z1#Z2#>,<MAX_SHEAR:Z1#Z2#>”. If there is no section, use NONE#: “<FX:NONE#>,<FY:NONE#>”

ifenvelope: bool -> Parameter to ask only for the results of the envelope of the load cases

selection: list -> List of N2PElement or N2PNode where the results are desired. The user must take care that

with displacements the list must be nodes and for stresses must be elements.

sortby: str -> This parameter have two options: “LC” and “IDS”. Specify if the results should be sorted by

load cases or ids.

aveSections: int -> Optional. Operation Among Sections.

-1 : Maximum (Default), -2 : Minimum, -3 : Average, -4 : Extreme, -6 : Difference.

cornerData: bool -> Optional. Flag to get results in element nodal.

True : Results in Element-Nodal, False : Results in centroid (Default).

aveNodes: int -> Optional. Operation among nodes when cornerData is selected.

0 : None, -1 : Maximum (Default), -2 : Minimum, -3 : Average, -5 : Average with variation parameter, -6 : Difference.

variation: int -> Optional. Integer between 0 & 100 to select.

0 : No average between nodes, 100 : Total average between nodes (Default).

realPolar: int -> Optional. Data type when complex result.

1 : Real / Imaginary, 2 : Magnitude / Phase.

coordsys: int -> Optional. Coordinate System where the result_array will be represented.

0 : Global, -1 : Material Coordinate System, -10 : User defined, -20 : Element/Node User Defined, >0 : Solver ID of the Predefined Coordinate System.

v1: tuple -> Optional.

v2: tuple -> Optional. Directions vectors that generate the coordinate system axis:

x=v1, z=v1^v2, y=z^x.

Examples:
>>> report1 = model.new_report("<LC1:FR1>,<LC2:FR1>", False, "DISPLACEMNETS", "<X:NONE#>,<Y:NONE#>", False, list_n2pnodes, "LC")
>>> report2 = model.new_report("<LC1:FR1>,<LC1:FR2>,<LC4:FR6>", False, "STRESSES", "<VON_MISES:Z1#Z2#>,<MAX_SHEAR:Z1#Z2#>",                                            False, list_n2pelements, "IDS", aveSections=-4, coordsys=-1)
set_user_coord_sys(array2d: list | ndarray, where: Literal['NODES', 'ELEMENTS']) None#

Method that sets a coordinate system for each node/element as a user coordinate system using an array defined by the user.

The user can define a different system for each element or node and ask for results in that system using the optional argument “coordsys=-20”

The structure of the array must have the node/element identification, and the coordinates of the vectors v1 and v2 that generates the system: x = v1; z = v1^v2; y = z^v1. The structure for elements and nodes must be:

[ [node_id_1,part_id_1,x11,y11,z11,x12,y12,z12], [node_id_2,part_id_2,x21,y21,z21,x22,y22,z22], … ]

user_system_elements_example.csv:

[ [1001,0,1,0,0,0,1,0], [1002,0,0.3,0.2,0,0,1,0], [1003,0,0,1,0,1,1,0], [1004,0,2,0,1,0.4,1,3] ]

Warnings:

If an array is passed to this method and the another is passed, the previous information will be deleted.

Args:

array2d: list|np.ndarray. The array can be a list of list or a two dymensional array of numpy with the type float where: “NODES”|”ELEMENTS”. The user coordinate systems are for the nodes or the elements.

Examples:
>>> array_ele = [ [1001,0,1,0,0,0,1,0], [1002,0,0.3,0.2,0,0,1,0], [1003,0,0,1,0,1,1,0],
>>> ...           [1004,0,2,0,1,0.4,1,3] ]
>>> array_node = np.array([ [2001,0,1,0,0,0,1,0], [2002,0,0.3,0.2,0,0,1,0], [2003,0,0,1,0,1,1,0],
>>> ...           [2004,0,2,0,1,0.4,1,3] ], dtype=float)
>>>
>>> N2PModelContent.set_user_coord_sys(array2d=array_ele, where="ELEMENTS")
>>> N2PModelContent.set_user_coord_sys(array_node, "NODES")
NaxToPy.Core.N2PModelContent.initialize(path: str, parallelprocessing: bool = False) N2PModelContent#

Deprecated function. This funtion has been substituted by load_model()

NaxToPy.Core.N2PModelContent.load_model(path: str, parallelprocessing: bool = False, file_type: Literal['InputFileNastran', 'Binary'] = None) N2PModelContent#

Read an output result file in binary format from Nastran, Abaqus, Optistruct or Ansys and transform it into a N2PModelContent Object. It also can read models from input files in Nastran format.

Supports .op2, .xdb, .odb, .h5, .h3d and .rst file extensions read from a local filesystem or URL.

Supports Nastran Input Files. (Typically .bdf extension)

Args:

path: str parallelprocessing: bool -> Optional. If true, the low libraries open the result files in several processes. It is slightly faster. file_type: str -> Optional. It specifies if it is Nastran input file (“InputFileNastran”) or binary result file (“Binary”).

Returns:

model: N2PModelContent

Examples:
>>> model1 = load_model(r"C:\MODELS\FEM\model1.dat")
>>> # file_type is not needed. It only helps the program and saves a checking
>>> model2 = load_model(r"C:\MODELS\FEM\model2.dat", file_type="InputFileNastran")
>>> # parallelprocessing is only aviable for Binary files. It is helpful in some big files.
>>> model3 = load_model(r"C:\MODELS\RESULTS\model1.op2", parallelprocessing=True)
>>> model4 = load_model(r"C:\MODELS\RESULTS\model2.xdb", file_type="Binary")
>>> model5 = load_model(r"C:\MODELS\RESULTS\model5.h3d")
>>> model6 = load_model(r"C:\MODELS\RESULTS\model6.odb", True, "Binary")

Module contents#