Skip to content

Commit

Permalink
bump to v0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
akaszynski committed Sep 9, 2024
2 parents 1861f53 + 4173b6f commit 767c20b
Show file tree
Hide file tree
Showing 8 changed files with 752 additions and 35 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This library can be used to read in LS-DYNA meshes stored within keyword
(`*.k`, `*.key`, `*.dyn`) files, also known as keyword format "input
decks".
decks". Full documentation for this repository can be found at [lsdyna-mesh-reader Documentation](https://akaszynski.github.io/lsdyna-mesh-reader/).

Many of these example files were obtained from the excellent documentation at
[LS-DYNA Examples](https://www.dynaexamples.com/).
Expand Down Expand Up @@ -169,7 +169,7 @@ PyVista. For example, you could plot the resulting mesh. Here's a full example u
>>> grid.plot(color="w", smooth_shading=True, show_edges=True)
```

![Yaris Static Suspension Mesh](https://github.com/akaszynski/lsdyna-mesh-reader/blob/main/docs/source/images/yaris-mesh.png)
![Yaris Static Suspension Mesh](https://github.com/akaszynski/lsdyna-mesh-reader/raw/main/docs/source/images/yaris-mesh.png)

### Caveats and Limitations

Expand All @@ -181,6 +181,7 @@ Additionally, this reader only supports the following keywords:
* `*NODE`
* `*ELEMENT_SHELL`
* `*ELEMENT_SOLID`
* `*ELEMENT_TSHELL` (note: sections encoded as solid sections)

The VTK UnstructuredGrid contains only the linear element conversion of the
underlying LS-DYNA elements, and only supports `VTK_QUAD`, `VTK_TRIANGLE`,
Expand Down
9 changes: 9 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ API Reference

The following section contains the API reference for ``lsdyna-mesh-reader``.

**Reader**

.. autosummary::
:toctree: _autosummary
:template: custom-class-template.rst
Expand All @@ -11,3 +13,10 @@ The following section contains the API reference for ``lsdyna-mesh-reader``.
lsdyna_mesh_reader._deck.NodeSection
lsdyna_mesh_reader._deck.ElementShellSection
lsdyna_mesh_reader._deck.ElementSolidSection

**Examples**

.. autosummary::
:toctree: _autosummary

lsdyna_mesh_reader.examples
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ description = "Read nodes and elements from LS-DYNA decks."
name = "lsdyna-mesh-reader"
readme = "README.md"
requires-python = ">=3.9"
version = "0.1.0"
version = "0.1.1"

[project.optional-dependencies]
docs = ["pydata-sphinx-theme", "numpydoc", "sphinx", "sphinx-copybutton", "myst-parser"]

[project.urls]
Documentation = "https://akaszynski.github.io/lsdyna-mesh-reader/"
Repository = "https://github.com/akaszynski/lsdyna-mesh-reader"

[tool.cibuildwheel]
archs = ["auto64"] # 64-bit only
skip = "cp38-* cp313-* pp* *musllinux*" # 3.9-3.12 and no PyPy and musl-based wheels
test-command = "pytest {project}/tests"
test-command = "pytest {project}/tests -v"
test-requires = "pytest pyvista"

[tool.cibuildwheel.macos]
Expand Down
61 changes: 34 additions & 27 deletions src/deck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,12 @@ class MemoryMappedFile {
}
}

// True when at end of file
bool eof() { return current >= start + size; }

// True when at end of line (DOS and UNIX EOF)
bool eol() { return *current == '\n' || *current == '\r'; }

bool read_line() {
line.clear();
if (current >= start + size) {
Expand Down Expand Up @@ -355,26 +359,21 @@ struct NodeSection {
NDArray<int, 1> tc;
NDArray<int, 1> rc;
int n_nodes = 0;
bool _has_constraints;

// Default constructor
NodeSection() {}

NodeSection(std::vector<int> nid_vec, std::vector<double> nodes_vec,
std::vector<int> tc_vec, std::vector<int> rc_vec,
bool has_constraints) {
_has_constraints = has_constraints;
std::vector<int> tc_vec, std::vector<int> rc_vec) {
n_nodes = nid_vec.size();
std::array<int, 1> nid_shape = {static_cast<int>(n_nodes)};
std::array<int, 2> coord_shape = {static_cast<int>(n_nodes), 3};

// Wrap vectors as NDArrays
nid = WrapVectorAsNDArray(std::move(nid_vec), nid_shape);
coord = WrapVectorAsNDArray(std::move(nodes_vec), coord_shape);
if (has_constraints) {
tc = WrapVectorAsNDArray(std::move(tc_vec), nid_shape);
rc = WrapVectorAsNDArray(std::move(rc_vec), nid_shape);
}
tc = WrapVectorAsNDArray(std::move(tc_vec), nid_shape);
rc = WrapVectorAsNDArray(std::move(rc_vec), nid_shape);
}

int Length() { return n_nodes; }
Expand Down Expand Up @@ -403,10 +402,9 @@ struct NodeSection {
<< std::setw(15) << std::scientific << std::setprecision(8)
<< coord(i, 2) << " "; // Z

if (_has_constraints) {
oss << std::setw(8) << tc(i) << " " // tc
<< std::setw(8) << rc(i); // rc
}
// constraints
oss << std::setw(8) << tc(i) << " " // tc
<< std::setw(8) << rc(i); // rc

oss << "\n";
}
Expand Down Expand Up @@ -669,8 +667,6 @@ class Deck {
std::cout << "Reading node section" << std::endl;
#endif

bool has_constraints = true; // assume true

// Since we don't know the total number of nodes, we'll use vectors here,
// even though a malloc would be more efficient. Seems they don't store the
// total number of nodes per section.
Expand Down Expand Up @@ -722,24 +718,32 @@ class Deck {
std::cout << "Done reading coordinates " << std::endl;
#endif

// constraints
if (memmap[0] == '\n') {
has_constraints = false;
}

if (has_constraints) {
// Populate constraints. These may be missing from the node section, and
// if they are, populate a zero.
if (memmap.eol()) {
#ifdef DEBUG
std::cout << "EOL on tc" << std::endl;
#endif
tc.push_back(0);
} else {
tc.push_back(fast_atoi(memmap.current, 8));
memmap += 8;
}

if (memmap.eol()) {
#ifdef DEBUG
std::cout << "EOL on rc" << std::endl;
#endif
rc.push_back(0);
} else {
rc.push_back(fast_atoi(memmap.current, 8));
memmap += 8;
}

// skip remainder of the line
memmap.seek_eol();
}

NodeSection *node_section =
new NodeSection(nid, coord, tc, rc, has_constraints);
NodeSection *node_section = new NodeSection(nid, coord, tc, rc);
node_sections.push_back(*node_section);

return;
Expand Down Expand Up @@ -831,10 +835,11 @@ class Deck {
}

first_char = memmap[0];
// #ifdef DEBUG
// std::cout << "Read character: " <<
// static_cast<char>(first_char) << std::endl;
// #endif
#ifdef DEBUG
std::cout << "Read character: " << static_cast<char>(first_char)
<< std::endl;
#endif

// Check if line contains a keyword
if (first_char != '*') {
memmap.seek_eol();
Expand All @@ -848,6 +853,8 @@ class Deck {
ReadElementSolidSection();
} else if (memmap.line.compare(0, 14, "*ELEMENT_SHELL") == 0) {
ReadElementShellSection();
} else if (memmap.line.compare(0, 15, "*ELEMENT_TSHELL") == 0) {
ReadElementSolidSection();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lsdyna_mesh_reader/deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@


class Deck:
"""LS-DYNA deck.
r"""LS-DYNA deck.
Parameters
----------
filename : str | pathlib.Path
Path to the keyword file (\*.k, \*.key, \*.dyn).
Path to the keyword file (`*.k`, `*.key`, `*.dyn`).
Examples
--------
Expand Down
100 changes: 98 additions & 2 deletions src/lsdyna_mesh_reader/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""LS-DYNA examples module.
"""LS-DYNA Mesh Reader examples module.
Content reused based on the following implicit open to use license from
https://www.dynaexamples.com/
`LS-DYNA Examples <https://www.dynaexamples.com/>`_.
**Usage Notice from LS-DYNA**
The input files and several class notes are available for download. The
download is free of charge, a login is not required. All examples are
Expand All @@ -11,6 +13,96 @@
The content is prepared for educational purposes. Hence, material
properties and other parameters might be non-physic for simplification.
Copyright (c) 2014 DYNAmore GmbH (www.dynamore.de)
Copying for non-commercial usage allowed, if this notice is included.
Example Files
^^^^^^^^^^^^^
.. py:data:: lsdyna_mesh_reader.examples.birdball
:annotation: = str
Path to the `Contact Eroding I <https://www.dynaexamples.com/introduction/intro-by-a.-tabiei/contact/contact-eroding-i>`_ example file. Usage:
.. code:: pycon
>>> from lsdyna_mesh_reader import examples
>>> import lsdyna_mesh_reader
>>> deck = lsdyna_mesh_reader.Deck(examples.birdball)
>>> deck
LSDYNA Deck with:
Node sections: 1
Element Solid sections: 1
Element Shell sections: 1
.. py:data:: lsdyna_mesh_reader.examples.joint_screw
:annotation: = str
Path to the `Joint Screw <https://www.dynaexamples.com/show-cases/joint-screw/>`_ example file. Usage:
.. code:: pycon
>>> from lsdyna_mesh_reader import examples
>>> import lsdyna_mesh_reader
>>> deck = lsdyna_mesh_reader.Deck(examples.joint_screw)
>>> deck
LSDYNA Deck with:
Node sections: 1
Element Solid sections: 1
Element Shell sections: 1
.. py:data:: lsdyna_mesh_reader.examples.wheel
:annotation: = str
Path to the `SSD with a wheel rim <https://www.dynaexamples.com/nvh/example-05-03>`_ example file. Usage:
.. code:: pycon
>>> from lsdyna_mesh_reader import examples
>>> import lsdyna_mesh_reader
>>> deck = lsdyna_mesh_reader.Deck(examples.wheel)
>>> deck
LSDYNA Deck with:
Node sections: 1
Element Solid sections: 0
Element Shell sections: 1
.. py:data:: lsdyna_mesh_reader.examples.bracket
:annotation: = str
Path to `An aluminium bracket <https://www.dynaexamples.com/nvh/example-05-03>`_ example file. Usage:
.. code:: pycon
>>> from lsdyna_mesh_reader import examples
>>> import lsdyna_mesh_reader
>>> deck = lsdyna_mesh_reader.Deck(examples.bracket)
>>> deck
LSDYNA Deck with:
Node sections: 1
Element Solid sections: 0
Element Shell sections: 1
.. py:data:: lsdyna_mesh_reader.examples.simple_plate
:annotation: = str
Path to the `Square Plate Out-of-Plane Vibration (thick shell mesh) <https://www.dynaexamples.com/nvh/example-05-03>`_ example file. Usage:
.. code:: pycon
>>> from lsdyna_mesh_reader import examples
>>> import lsdyna_mesh_reader
>>> deck = lsdyna_mesh_reader.Deck(examples.simple_plate)
>>> deck
LSDYNA Deck with:
Node sections: 1
Element Solid sections: 0
Element Shell sections: 1
"""

import os
Expand All @@ -29,9 +121,13 @@
# https://www.dynaexamples.com/nvh/example-07-01
bracket = os.path.join(dir_path, "bracket.k")

# https://www.dynaexamples.com/introduction/Introduction/example-13
simple_plate = os.path.join(dir_path, "ex_13_thick_shell_elform_2.k")

__all__ = [
"birdball",
"joint_screw",
"wheel",
"bracket",
"simple_plate",
]
Loading

0 comments on commit 767c20b

Please sign in to comment.