PyNite icon indicating copy to clipboard operation
PyNite copied to clipboard

Plotting: Array dims not matching, Reporting module: LoadCombo not being detected

Open OjjoJR opened this issue 10 months ago • 8 comments

Describe the bug Using the example: Examples/Simple Beam - Point Load.py

There are 2 bugs:

Bug 1

https://github.com/JWock82/Pynite/blob/04ab0745f36913fb4f77849544889d90475a9d0d/Examples/Simple%20Beam%20-%20Point%20Load.py#L57

produces the following error:

Traceback (most recent call last):
  File "[removed]", line 57, in <module>
    simple_beam.members['M1'].plot_shear('Fy', '1.2D+1.6L')
  File "[removed]\site-packages\Pynite\PhysMember.py", line 253, in plot_shear
    x_submember, V_submember = submember.shear_array(Direction, n_points, combo_name)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[removed]\site-packages\Pynite\Member3D.py", line 965, in shear_array
    return self._extract_vector_results(self.SegmentsZ, x_array, 'shear')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[removed]\site-packages\Pynite\Member3D.py", line 2278, in _extract_vector_results
    return vstack((x_array2, hstack(segment_results)))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[removed]\site-packages\numpy\_core\shape_base.py", line 292, in vstack
    return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 10 and the array at index 1 has size 20

Bug 2

I commented out the simple_beam.members['M1'].plot_ items, to try and use the reporting functionality.

https://github.com/JWock82/Pynite/blob/04ab0745f36913fb4f77849544889d90475a9d0d/Examples/Simple%20Beam%20-%20Point%20Load.py#L80

produces the following error:

Traceback (most recent call last):
  File "[removed]", line 80, in <module>
    Reporting.create_report(simple_beam, output_filepath=Path('./Pynite Report.pdf'), node_table=False, plate_table=False, plate_corner_forces=False, plate_center_forces=False, plate_corner_membrane=False, plate_center_membrane=False)
  File "[removed]\site-packages\Pynite\Reporting.py", line 68, in create_report
    HTML = template.render(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[removed]\site-packages\jinja2\environment.py", line 1295, in render
    self.environment.handle_exception()
  File "[removed]\site-packages\jinja2\environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "[removed]\site-packages\Pynite\Report_Template.html", line 210, in top-level template code
    <td>{{ "%.4g" | format(node.RxnFX[combo]) }}</td>
^^^^^^^^^
  File "[removed]\site-packages\jinja2\filters.py", line 1043, in do_format
    return soft_str(value) % (kwargs or args)
           ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
jinja2.exceptions.UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at [memory address]>

To Reproduce run Examples/Simple Beam - Point Load.py, with and without the simple_beam.members['M1'].plot_ items.

Expected behavior plotting and reporting

Additional context I'm guessing recent updates have changed the member arrays, affecting plotting. I'm not sure why the jinja report is not accessing load combinations properly, however.

Thanks for the help!

OjjoJR avatar Jun 06 '25 00:06 OjjoJR

Which version are you using? I recently made changes to address a bug relating to array results.

JWock82 avatar Jun 06 '25 00:06 JWock82

@JWock82 - Using version 1.1.0

OjjoJR avatar Jun 06 '25 00:06 OjjoJR

I think I’ve got this issue already fixed in the development version. I’ll issue v1.2.0 here soon which will have this fixed.

JWock82 avatar Jun 06 '25 00:06 JWock82

Thanks! Is the reporting module error in that update as well? I am not super sure about the source for that one

OjjoJR avatar Jun 06 '25 00:06 OjjoJR

@JWock82 I found the source of this error, mentioned in the original issue: jinja2.exceptions.UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at [memory address]>

model.load_combos.values() in this line should be changed to model.load_combos.keys(), as the node values dicts and member value access methods use the load combination keys instead of the actual load combo class objects.

https://github.com/JWock82/Pynite/blob/0a6b11d68d2cc7bf46d16e68ce1856d09c652849/Pynite/Reporting.py#L65

https://github.com/JWock82/Pynite/blob/0a6b11d68d2cc7bf46d16e68ce1856d09c652849/Pynite/Report_Template.html#L285

OjjoJR avatar Jul 24 '25 01:07 OjjoJR

I also am getting this error on trying to generate a report with the "Example of a basic 2D moment frame with gravity and lateral loads". It also goes away when I switch that line to kwargs['load_combos'] = model.load_combos.keys():

# Import the reporting module
from Pynite import Reporting
from pathlib import Path

# Create the report
Reporting.create_report(frame, output_filepath=Path('./SpaceFrameReport.pdf'))
---------------------------------------------------------------------------
UndefinedError                            Traceback (most recent call last)
Cell In[17], line 6
      3 from pathlib import Path
      5 # Create the report
----> 6 Reporting.create_report(frame, output_filepath=Path('./SpaceFrameReport.pdf'))

File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/Pynite/Reporting.py:68, in create_report(model, output_filepath, **kwargs)
     65 kwargs['load_combos'] = model.load_combos.values()
     67 # Create the report HTML using jinja2
---> 68 HTML = template.render(**kwargs)
     70 # Convert the HTML to pdf format using PDFKit
     71 # Note that wkhtmltopdf must be installed on the system, and included on the system's PATH environment variable for PDFKit to work
     72 pdfkit.from_string(HTML, output_filepath, css=path / './MainStyleSheet.css')

File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/environment.py:1295, in Template.render(self, *args, **kwargs)
   1293     return self.environment.concat(self.root_render_func(ctx))  # type: ignore
   1294 except Exception:
-> 1295     self.environment.handle_exception()

File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/environment.py:942, in Environment.handle_exception(self, source)
    937 """Exception handling helper.  This is used internally to either raise
    938 rewritten exceptions or return a rendered traceback for the template.
    939 """
    940 from .debug import rewrite_traceback_stack
--> 942 raise rewrite_traceback_stack(source=source)

File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/Pynite/Report_Template.html:210, in top-level template code()
    208 <td>{{ node.name }}</td>
    209 <td>{{ combo }}</td>
--> 210 <td>{{ "%.4g" | format(node.RxnFX[combo]) }}</td>
    211 <td>{{ "%.4g" | format(node.RxnFY[combo]) }}</td>
    212 <td>{{ "%.4g" | format(node.RxnFZ[combo]) }}</td>

File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/filters.py:1043, in do_format(value, *args, **kwargs)
   1038 if args and kwargs:
   1039     raise FilterArgumentError(
   1040         "can't handle positional and keyword arguments at the same time"
   1041     )
-> 1043 return soft_str(value) % (kwargs or args)

UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at 0x3120f1190>

amole-arup avatar Aug 19 '25 14:08 amole-arup

I recently updated the reporting code. It had not been kept up with the rest of the program. I think this issue has been resolved. Can you verify on your end?

JWock82 avatar Oct 09 '25 14:10 JWock82

Yes - v 1.5.0 has fixed the reporting problem for that example.

I have however come across similar-looking error for the following example. Should I report this as a new issue?

Examples/Shear Wall - Advanced.py

from Pynite import Reporting
Reporting.create_report(model, format='html', output_filepath='./ModelReport.html')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[28], [line 9](vscode-notebook-cell:?execution_count=28&line=9)
      5 print(f'{pynite_get_version("Pynite")}') 
      7 # Create the report
      8 # Reporting.create_report(my_model, output_filepath='./My Report.pdf')
----> [9](vscode-notebook-cell:?execution_count=28&line=9) Reporting.create_report(model, format='html', output_filepath='./ModelReport.html')

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Reporting.py:101, in create_report(model, output_filepath, format, log, **kwargs)
     98 kwargs['load_combos'] = model.load_combos.values()
    100 # Render HTML from Template
--> [101](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Reporting.py:101) HTML = template.render(**kwargs)
    103 # Check if a PDF file has been requested
    104 if format.upper() == 'PDF':
    105 
    106     # Import PDFKit

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:1295, in Template.render(self, *args, **kwargs)
   1293     return self.environment.concat(self.root_render_func(ctx))  # type: ignore
   1294 except Exception:
-> [1295](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:1295)     self.environment.handle_exception()

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:942, in Environment.handle_exception(self, source)
    937 """Exception handling helper.  This is used internally to either raise
    938 rewritten exceptions or return a rendered traceback for the template.
    939 """
    940 from .debug import rewrite_traceback_stack
--> [942](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:942) raise rewrite_traceback_stack(source=source)

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Report_Template.html:426, in top-level template code()
    424 <td>{{ quad.name }}</td>
    425 <td>{{ combo.name }}</td>
--> [426](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Report_Template.html:426) <td>{{ "%.3g" | format(quad.shear(-1, -1, combo.name)[0][0]) }}</td>
    427 <td>{{ "%.3g" | format(quad.shear(-1, -1, combo.name)[1][0]) }}</td>
    428 <td>{{ "%.3g" | format(quad.moment(-1, -1, combo.name)[0][0]) }}</td>

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:1034, in Quad3D.shear(self, xi, eta, local, combo_name)
   1015 """
   1016 Returns the interal shears at any point in the quad element.
   1017 
   (...)   1030 Internal shear force per unit length of the quad element: [[Qx], [Qy]]
   1031 """
   1033 # Get the plate's local displacement vector
-> [1034](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:1034) d = self.d(combo_name)
   1036 # Correct the sign convention for x-axis rotation - note that +x bending and +x rotation are opposite in the DKMQ derivation. Hence when correcting d we correct the x terms, but when correcting k we correct the y terms
   1037 d[[3, 9, 15, 21], :] *= -1

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:793, in Quad3D.d(self, combo_name)
    788 """
    789 Returns the quad element's local displacement vector
    790 """
    792 # Calculate and return the local displacement vector
--> [793](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:793) return self.T() @ self.D(combo_name)

File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:824, in Quad3D.D(self, combo_name)
    821 D = np.zeros((24, 1))
    823 # Read in the global displacements from the nodes
--> [824](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:824) D[0, 0] = self.i_node.DX[combo_name]
    825 D[1, 0] = self.i_node.DY[combo_name]
    826 D[2, 0] = self.i_node.DZ[combo_name]

KeyError: 'Combo 1'

boustrephon avatar Oct 10 '25 09:10 boustrephon