N2PNastranInputData#

class NaxToPy.Core.Classes.N2PNastranInputData.N2PNastranInputData(dictcardscston2p: dict, inputfiledata)[source]#

Bases: object

Class with the complete data of a MEF input file (text file).

Note

The property N2PModelContent.ModelInputData can be a N2PNastranInputData if the input file is from Nastran (.bdf) or Opstitruct (.fem), or a N2PAbaqusInputData (.inp) if is from Abaqus.

Example

>>> model = n2p.load_model("my_nastran_input_file.bdf")
>>> inputdata = model.ModelInputData  # This is a N2PNastranInputData
create_bdf_file(file_name: str, parent_bdf_file: str = None) str | None[source]#

Adds a new auxiliary BDF file to a loaded model and links it through an INCLUDE statement inside parent_bdf_file (defaulting to the launcher file when omitted). The new file is registered in memory only — it is materialized to disk on the next update_file() or rebuild_file() call. Returns the new BdfFile ready to be populated through create_card().

Parameters:
  • file_name – Name of the new BDF file (e.g. "custom_materials.bdf"). Sub-directories are supported with forward slashes ("extras/load_cases.bdf"); .. is rejected. The extension is not added automatically — supply it explicitly.

  • parent_bdf_file – Absolute path of an existing BDF in the model where the INCLUDE statement will be inserted. Defaults to the launcher file when None.

Returns:

The new BdfFile instance on success, or None when the C# layer rejects the operation (empty model, invalid file name, path collision, include cycle, etc.). Diagnostic detail is available from the model’s operation registry.

Example

>>> extras = model.ModelInputData.create_bdf_file("extras/custom_materials.bdf")
>>> mat = model.ModelInputData.create_card("MAT1", extras.BdfFilePath)
>>> mat.MID = 999
>>> model.ModelInputData.update_file()
create_card(card_type: str, bdf_file: str, rawContent: str = None, superElemntId: int = 0) N2PCard[source]#

Method that creates a new card of the type specified. By default, the card is created empty, with small field format.

Example

>>> new_cbar = model.ModelInputData.create_card("CBAR", "C:\bdf\mesh\model.bdf")
>>> # new_cbar is now a N2PCard object of type CBAR empty. You can set its properties:
>>> new_cbar.EID = 1001
>>> new_cbar.PID = 2001
>>> new_cbar.GA = 10
>>> new_cbar.GB = 20
>>> new_cbar.X1 = 1.0
>>> new_cbar.X2 = 0.0
>>> new_cbar.X3 = 0.0
>>> # It is also possible to create a card with raw content and specifying the superelement id:
>>> raw_content = "CBAR        1002    2001      30      40     0.0     1.0     0.0"
>>> new_cbar2 = model.ModelInputData.create_card("CBAR", "C:\bdf\mesh\model.bdf", rawContent=raw_content, superElemntId=0)
find_cards(category: Literal['GRID', 'ELEMENT', 'CONNECTOR', 'PROPERTY', 'MATERIAL', 'COORDINATESYSTEM', 'LOAD', 'CONSTRAINT', 'SETDEFINITION'], cardTypes: list[str] = None, filters: dict[str, object] = None, superElements: int = None) list[N2PCard][source]#

Searches for cards based on specified criteria.

Parameters:
  • category – Card category to search. Case insensitive. Valid values: GRID, ELEMENT, PROPERTY, MATERIAL, COORDINATESYSTEM, CONNECTOR, LOAD, CONSTRAINT, SETDEFINITION. COORDINATESYSTEM also accepts the spellings “coordinate system” and “coordinate_system”.

  • cardTypes – Specific card types to filter by (e.g., CQUAD4, PBEAM, COORD2R). Case insensitive. If None or empty, every card type in the category is returned.

  • filters – Dictionary of field-value pairs to narrow the result. Which fields are available depends on the category. Each list starts with the identifier the category is looked up by and continues with the other fields worth searching on: - GRID: “ID”, “CP”, “CD”, “PS”, “SEID”, “X1”, “X2”, “X3” - ELEMENT: “EID”, “PID”, “NODE” - PROPERTY: “PID” - MATERIAL: “MID” - COORDINATESYSTEM: “CID”, “RID” - CONNECTOR: “EID” - LOAD: “SID” - CONSTRAINT: “SID” - SETDEFINITION: “SID” Filter names are case insensitive. A name the category does not know is discarded and the remaining filters still apply; if NO filter can be applied the result is an empty list, since asking to narrow and failing is not the same as not asking. Beware that a SID identifies a whole set rather than a single card: one load case or one constraint set is built by many cards sharing it, so filtering by SID returns all of them. Only SETDEFINITION SIDs are unique.

  • superElements – Superelement (part) ID to search within. Use 0 for the global model. Accepts a list of IDs. If None or empty, searches across all superelements. Unlike the filter values, this parameter takes only built-in ints: a numpy integer raises ValueError here, so convert it with int() first.

Asking for a blank field:

Passing None as a filter value matches the cards that leave that field blank, which no other value can express. Accepted by CP, CD, PS, SEID, X1, X2 and X3 -the GRID fields that may be absent-. On any other filter it matches no card.

How several criteria combine:

Every criterion narrows the previous one. A card is returned only when its type is among cardTypes AND every filter in the dictionary holds AND it belongs to one of the requested superelements. There is no way to express “either of these two conditions” across different filters.

Within a single filter the rule is the opposite: a collection of values matches a card whose property is ANY of them. So {“PID”: [3, 4], “NODE”: 7} reads as “property 3 or 4, and touching node 7”.

The distinction matters most on NODE, whose card side is itself a list of grids. {“NODE”: [5, 9]} returns the elements that use grid 5 OR grid 9, not the ones that use both. There is no filter for “uses all of these grids”; build it by intersecting the results.

Filtering by several values at once:

A filter value may be a collection -list, tuple, set, range, numpy array- instead of a single value. The card then matches when its property is among the requested values, which resolves in one call what would otherwise take one call per identifier.

Only integer elements are used. Anything else in the collection is SKIPPED SILENTLY: the search is not interrupted and no exception is raised, so a collection carrying a string or a float filters by its integer elements alone. Check the collection before passing it if that matters.

An empty collection matches no card, which is the opposite of an empty filters dictionary: the latter means “do not narrow” and returns everything.

Every filter accepts collections except the X1, X2 and X3 coordinates of GRID. Passing one to those applies the filter without matching any card.

When the result comes back empty:

A search that finds nothing and a search that asks for something that does not exist both return an empty list. Nothing is raised, so a typo looks exactly like a model that has no such cards. If a result is unexpectedly empty, suspect the query before the model and check, in this order:

  • the category name. An unknown one -“GRIDS”, “NODES”, “ELEMENTS”- yields an empty list rather than an error.

  • the category itself. Card types are distributed by role, and the split is not always the intuitive one: RBE2 and RBE3 are CONNECTOR, not CONSTRAINT, which holds SPC and MPC.

  • the card type. One absent from the category, or misspelled, matches nothing.

  • the type of the value. A filter compared as an integer rejects the same number written as text, so {“PS”: “123456”} matches nothing where {“PS”: 123456} works.

Returns:

List of N2PCard objects matching the specified criteria.

What can be read back from a card is decided by its TYPE, not by its category, and a category holds several types. A PSHELL names its materials MID1 to MID4, a PSOLID names its only one MID, and a PCOMP names none of them as fields at all; a CQUAD4 carries its grids as G1 to G4 while a CFAST carries GA, GB and GS. Reading a type-specific attribute across a whole category therefore raises AttributeError on the first card that does not have it, which is why the chaining examples below pin the card type.

The reliable subset is the filter list itself: every filter name of a category is also an attribute of every card in it -EID and PID on any element, SID on any load- with one exception. NODE is a filter name and not an attribute: an element exposes its grids one field at a time under names that vary by type, never as a list called NODE.

Independently of type, every card exposes CardType, RawContent and BdfFilePath, which is useful when the result mixes types or spans includes.

Examples

>>> inp = model.ModelInputData

Whole categories >>> grids = inp.find_cards(“GRID”) # every grid in the model >>> grids_main = inp.find_cards(“GRID”, superElements=0) # only the global model >>> materials = inp.find_cards(“MATERIAL”) >>> sets = inp.find_cards(“SETDEFINITION”)

Narrowing by card type >>> quads = inp.find_cards(“ELEMENT”, [“CQUAD4”]) >>> shells = inp.find_cards(“ELEMENT”, [“CQUAD4”, “CQUAD8”, “CTRIA3”]) >>> quads = inp.find_cards(“ELEMENT”, [“cquad4”]) # case insensitive >>> cords = inp.find_cards(“COORDINATESYSTEM”, [“CORD2R”])

One card by its identifier >>> grid_5 = inp.find_cards(“GRID”, filters={“ID”: 5}) >>> pshell_3 = inp.find_cards(“PROPERTY”, [“PSHELL”], {“PID”: 3}) >>> mat_1 = inp.find_cards(“MATERIAL”, filters={“MID”: 1}) >>> rbe = inp.find_cards(“CONNECTOR”, filters={“EID”: 90001})

Several identifiers in ONE call, instead of one call each >>> some_grids = inp.find_cards(“GRID”, filters={“ID”: [5, 9, 12]}) >>> a_range = inp.find_cards(“GRID”, filters={“ID”: range(100, 200)}) >>> from_array = inp.find_cards(“GRID”, filters={“ID”: ids_array}) # numpy works >>> two_props = inp.find_cards(“PROPERTY”, filters={“PID”: {10, 20}})

Each call walks its category once, so asking for the identifiers one at a time repeats that walk as many times as identifiers there are: >>> found = [c for i in wanted for c in inp.find_cards(“GRID”, filters={“ID”: i})] >>> found = inp.find_cards(“GRID”, filters={“ID”: wanted}) # same cards, one walk

Filtering by a field that is not the identifier >>> in_frame_10 = inp.find_cards(“GRID”, filters={“CP”: 10}) # positioned in system 10 >>> output_10 = inp.find_cards(“GRID”, filters={“CD”: 10}) # results in system 10 >>> clamped = inp.find_cards(“GRID”, filters={“PS”: 123456}) # the integer, not “123456” >>> on_basic = inp.find_cards(“COORDINATESYSTEM”, filters={“RID”: 0})

Whole load cases and constraint sets >>> case_10 = inp.find_cards(“LOAD”, filters={“SID”: 10}) # every card of the case >>> two_cases = inp.find_cards(“LOAD”, filters={“SID”: [10, 20]}) >>> spc_set = inp.find_cards(“CONSTRAINT”, [“SPC1”], {“SID”: 5}) # SPC1 only, not MPC

Cards that leave a field blank >>> no_cp = inp.find_cards(“GRID”, filters={“CP”: None}) >>> no_seid = inp.find_cards(“GRID”, filters={“SEID”: None})

Combining criteria >>> quads_of_prop = inp.find_cards(“ELEMENT”, [“CQUAD4”], {“PID”: 3}) >>> in_part_2 = inp.find_cards(“GRID”, filters={“ID”: [5, 9]}, superElements=2) >>> several_parts = inp.find_cards(“GRID”, superElements=[0, 1, 2]) >>> narrow = inp.find_cards(“ELEMENT”, [“CQUAD4”], {“PID”: [3, 4]}, superElements=0)

Searching by geometry and by connectivity >>> at_origin = inp.find_cards(“GRID”, filters={“X1”: 0.0, “X2”: 0.0, “X3”: 0.0}) >>> touching = inp.find_cards(“ELEMENT”, filters={“NODE”: 5}) # elements using grid 5 >>> using_any = inp.find_cards(“ELEMENT”, filters={“NODE”: [5, 9]}) # grid 5 OR grid 9

“Uses every one of these grids” is not a filter. Intersect two results: >>> with_9 = {e.EID for e in inp.find_cards(“ELEMENT”, filters={“NODE”: 9})} >>> using_both = [e for e in touching if e.EID in with_9]

Chaining one query into the next. Note that each step names a card type: the attribute being read exists on that type, not on the whole category. >>> quads = inp.find_cards(“ELEMENT”, [“CQUAD4”], {“PID”: 3}) >>> shells = inp.find_cards(“PROPERTY”, [“PSHELL”], {“PID”: {q.PID for q in quads}}) >>> mats = inp.find_cards(“MATERIAL”, filters={“MID”: {s.MID1 for s in shells}})

>>> corners = {g for q in quads for g in (q.G1, q.G2, q.G3, q.G4)}
>>> grids = inp.find_cards("GRID", filters={"ID": corners})  # grids of those elements

Reading the result >>> for card in inp.find_cards(“GRID”, filters={“ID”: [5, 9]}): … print(card.ID, card.X1, card.X2, card.X3)

>>> for el in inp.find_cards("ELEMENT", ["CQUAD4"], {"PID": 3}):
...     print(el.EID, el.G1, el.G2, el.G3, el.G4)   # grids come one field at a time
>>> by_id = {g.ID: g for g in inp.find_cards("GRID")}   # index once, look up often
>>> for card in inp.find_cards("PROPERTY"):
...     print(card.CardType, card.PID, card.BdfFilePath)  # its type and its file
get_cards_by_field(fields: list[str], row: int = 0, col: int = 0) list[N2PCard][source]#

ATTENTION: Deprecated method in version 3.2.0. Use find_cards() instead.

get_failed_cards() list[N2PCard][source]#

Method that returns a list with the N2PCard objects of the input FEM file that have not been mapped correctly.

print_include_hierarchy() None[source]#

Function that prints in the console the hierarchy of includes of a Nastran input file.

print_model_directory_structure() None[source]#

Function that prints in the console the directory structure of a Nastran input file.

rebuild_file(folder: str) None[source]#

Method that writes the solver input file with the same file structure that was read in the folder is specified

Parameters:

folder – str -> Path of the folder where the file or files will be written.

update_model() None[source]#

Selectively saves the model in place: rewrites only the BDF files that contain user-modified cards, leaving unmodified files untouched (content and timestamp preserved). No destination folder needed — each BdfFile is written back to its original absolute path.

property CaseControlInstructions: list[N2PInputDataNas]#

Executive Control Statements and Control Case Commands

Type:

List with the instructions of the model. They are the commands above the BEGIN BULK

property ExecutiveControlInstructions: list[N2PInputDataNas]#

Executive Control Statements and Control Case Commands

Type:

List with the instructions of the model. They are the commands above the BEGIN BULK

property GetAbsolutePathsOfBdfFiles: list[str]#

List with theabsolute file paths of all BDF files that compose this model

property ListBulkDataCards: list[N2PCard]#

List with the N2PCard objects of the input FEM file. It has all bulk data cards of the model

property ListInstructions: list[N2PInputDataNas]#

Executive Control Statements and Control Case Commands

Type:

List with the instructions of the model. They are the commands above the BEGIN BULK

N2PInputDataNas#

class NaxToPy.Core.Classes.N2PNastranInputData.N2PInputDataNas(inputdata)[source]#

Bases: object

General class for the information in an input file of Nastran

last_status_message() None[source]#

Method that forwards to the register the last operation annotated by the reader, if any.

It is registered with the severity the reader gave it: an error as an error, a warning as a warning and a successful operation as information.

property BdfFile: str#
property BdfFilePath: str#
property RawContent: str#
property SectionInfo: object#