SteveDoyle2 / pyNastran

A Python-based interface tool for Nastran's file formats
Other
385 stars 148 forks source link

WARNING: subcase.py:683 nwords_to_lsem=1000 nwords_to_lsem//4=250 #722

Open fmamitrotta opened 1 year ago

fmamitrotta commented 1 year ago

Summary

Preamble: this is not really an issue preventing me from doing anything in particular, it's rather a small inconvenience.

Whenever I use the read_op2 function, I always get the following warning twice for each subcase. WARNING: subcase.py:683 nwords_to_lsem=1000 nwords_to_lsem//4=250

Of course a warning or two in the console is not a big deal. However this becomes inconvenient when I use a jupyter notebook and I run an analysis with many subcases. The notebook becomes cluttered by warning messages and I would like to avoid that.

I looked into pyNastran\op2\tables\geom\subcase.py and I've seen that the warning message is prompted within the set_casecc function. I guess this function reads and assigns the case control commands to the Subcase object, correct?

Now it seems that all the ids are stored in the ints array and at a certain point nwords_to_lsem is taken from there. What does this variable represent? What is the reason to check whether the floor division of it is either 150 or 300?

Reproduction

Read the attached op2 file using:

read_op2(op2_filename='nonlinear_buckling_verification.op2', debug=None)

nonlinear_buckling_verification.zip

Versions

platform.python_version() --> 3.9.16 pyNastran.__version__ --> 1.4.0+dev.no.checksum.error (this commit)

SteveDoyle2 commented 1 year ago

That’s the MSC case control reader. Every year or so they add new parameters, so the length of the block changes. That’s why there are different numbers. The floor division is basically getting the number of subcases, which is an integer.

Writing a robust function for that is hard. I’m really busy, but would welcome a pull request to make it not hit the error.

On Tue, Mar 14, 2023 at 2:16 AM Francesco M. A. Mitrotta < @.***> wrote:

Summary

Preamble: this is not really an issue preventing me from doing anything in particular, it's rather a small inconvenience.

Whenever I use the read_op2 function, I always get the following warning twice for each subcase. WARNING: subcase.py:683 nwords_to_lsem=1000 nwords_to_lsem//4=250

Of course a warning or two in the console is not a big deal. However this becomes inconvenient when I use a jupyter notebook and I run an analysis with many subcases. The notebook becomes cluttered by warning messages and I would like to avoid that.

I looked into pyNastran\op2\tables\geom\subcase.py and I've seen that the warning message is prompted within the set_casecc function. I guess this function reads and assigns the case control commands to the Subcase object, correct?

Now it seems that all the ids are stored in the ints array and at a certain point nwords_to_lsem is taken from there. What does this variable represent? What is the reason to check whether the floor division of it is either 150 or 300? Reproduction

Read the attached op2 file using:

read_op2(op2_filename='nonlinear_buckling_verification.op2', debug=None)

nonlinear_buckling_verification.zip https://github.com/SteveDoyle2/pyNastran/files/10966536/nonlinear_buckling_verification.zip Versions

platform.python_version() --> 3.9.16 pyNastran.version --> 1.4.0+dev.no.checksum.error (this commit https://github.com/SteveDoyle2/pyNastran/commit/dc06aa01c0cddc125c6e3b582445825fcf75eeb3 )

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWLNQVHY6Y5LUIYOXMDW4AZQHANCNFSM6AAAAAAV2FFFDM . You are receiving this because you are subscribed to this thread.Message ID: @.***>

fmamitrotta commented 1 year ago

Sure, I am more than happy to work on a pull request for that! I just don't understand the aim of the warning message. nwords_to_lsem is taken from the 165th element of the ints array. Then we check whether the floor division by 4 is either 150 or 300. If it isn't, the warning message is prompted.

However nwords_to_lsem is no longer used in the remainder of the set_casecc function, so it seems that the warning is standing on its own without doing anything useful. What am I missing?

SteveDoyle2 commented 1 year ago

It’s a check on number of subcases. There are multiple possible sizes for the data. If they’re not the right length, it can’t parse and a warning is thrown.

On Tue, Mar 14, 2023 at 10:52 AM Francesco M. A. Mitrotta < @.***> wrote:

Sure, I am more than happy to work on a pull request for that! I just don't understand the aim of the warning message. nwords_to_lsem is taken from the 165th element of the ints array. Then we check whether the floor division by 4 is either 150 or 300. If it isn't, the warning message is prompted.

However nwords_to_lsem is no longer used in the remainder of the set_casecc function, so it seems that the warning is standing on its own without doing anything useful. What am I missing?

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1468563849, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWOJG5UU6DGZRDWG4ADW4CV5VANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>

fmamitrotta commented 1 year ago

Ok I understand. However as far as I can see from the code the parsing does not seem to be affected by check on the number of subcases. Maybe I'm missing something, let me debug line by line the set_casecc function and see what I find.

SteveDoyle2 commented 1 year ago

Correct. It’s a way to shortcut the code. More difficult logic is used inside the function

On Tue, Mar 14, 2023 at 11:56 AM Francesco M. A. Mitrotta < @.***> wrote:

Ok I understand. However as far as I can see from the code the parsing does not seem to be affected by check on the number of subcases. Maybe I'm missing something, let me debug line by line the set_casecc function and see what I find.

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1468656818, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWM3W52GPKYGPB77FSTW4C5MRANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>

fmamitrotta commented 1 year ago

I've had a closer look at the code, but I could not get my head around how the warning affects the logic of the function. I did some tests, and it seems that I can get the same results with and without the warning.

See for example the code below, where I plot the load-displacement diagram of the model attached in the first post. If I comment out the lines in subcase.py with the warning message (lines 682-683) I get the same results as with the original subcase.py without any issue. Is there a reason why those lines of code can't be removed?

from pyNastran.op2.op2 import read_op2
import numpy as np
import matplotlib.pyplot as plt

# Read op2 file
sol_106_op2 = read_op2(op2_filename='nonlinear_buckling_verification.op2', load_geometry=True, debug=None)

# Get load and displacement history
component_index = 2
loads = {}
displacements = {}
valid_subcase_ids = [subcase_id for subcase_id in sol_106_op2.load_vectors if
                         hasattr(sol_106_op2.load_vectors[subcase_id], 'lftsfqs')]
for subcase_id in valid_subcase_ids:
    loads[subcase_id] = np.apply_along_axis(np.sum, 1, sol_106_op2.load_vectors[subcase_id].data[:, :, component_index])
    displacements[subcase_id] = sol_106_op2.displacements[subcase_id].data[:, -1, component_index]

# Plot load-displacement diagram
load_history = np.concatenate([loads[subcase_id] for subcase_id in loads])
displacement_history = np.concatenate([displacements[subcase_id] for subcase_id in displacements])
_, ax = plt.subplots()
ax.plot(displacement_history, load_history, 'o-')
plt.xlabel('Tip displacement [mm]')
plt.ylabel('$P$ [N]')
plt.grid()
plt.show()
SteveDoyle2 commented 1 year ago

The function is just trying to parse the case control deck. If can get the case control deck that you had in your bdf from using only the op2. That’s useful from a speed standpoint (I don’t have to read the bdf so it’s faster) and a traceability standpoint (if I can recover information about the input file that is lost/wasn’t tracked), that’s useful as well.

It doesn’t find the expected format of the data so it gives up and writes a warning. You just don’t get that bit of data. It doesn’t affect the displacements. You can ignore it or pass in a logger that is set to error vs warning vs debug.

On Sat, Mar 25, 2023 at 9:16 AM Francesco M. A. Mitrotta < @.***> wrote:

I've had a closer look at the code, but I could not get my head around how the warning affects the logic of the function. I did some tests, and it seems that I can get the same results with and without the warning.

See for example the code below, where I plot the load-displacement diagram of the model attached in the first post. If I comment out the lines in subcase.py with the warning message (lines 682-683) I get the same results as with the original subcase.py without any issue. Is there a reason why those lines of code can't be removed?

from pyNastran.op2.op2 import read_op2 import numpy as np import matplotlib.pyplot as plt

Read op2 file

sol_106_op2 = read_op2(op2_filename='nonlinear_buckling_verification.op2', load_geometry=True, debug=None)

Get load and displacement history

component_index = 2 loads = {} displacements = {} valid_subcase_ids = [subcase_id for subcase_id in sol_106_op2.load_vectors if hasattr(sol_106_op2.load_vectors[subcase_id], 'lftsfqs')] for subcase_id in valid_subcase_ids: loads[subcase_id] = np.apply_along_axis(np.sum, 1, sol_106_op2.load_vectors[subcase_id].data[:, :, component_index]) displacements[subcase_id] = sol_106_op2.displacements[subcase_id].data[:, -1, component_index]

Plot load-displacement diagram

load_history = np.concatenate([loads[subcase_id] for subcase_id in loads]) displacement_history = np.concatenate([displacements[subcase_id] for subcaseid in displacements]) , ax = plt.subplots() ax.plot(displacement_history, load_history, 'o-') plt.xlabel('Tip displacement [mm]') plt.ylabel('$P$ [N]') plt.grid() plt.show()

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1483860958, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWMEOV4LPYMQ7DSRSDTW54K63ANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>

SteveDoyle2 commented 1 year ago

Maybe to be really clear. That check wouldn’t be necessary if the function worked.

On Sat, Mar 25, 2023 at 11:51 AM Steven Doyle @.***> wrote:

The function is just trying to parse the case control deck. If can get the case control deck that you had in your bdf from using only the op2. That’s useful from a speed standpoint (I don’t have to read the bdf so it’s faster) and a traceability standpoint (if I can recover information about the input file that is lost/wasn’t tracked), that’s useful as well.

It doesn’t find the expected format of the data so it gives up and writes a warning. You just don’t get that bit of data. It doesn’t affect the displacements. You can ignore it or pass in a logger that is set to error vs warning vs debug.

On Sat, Mar 25, 2023 at 9:16 AM Francesco M. A. Mitrotta < @.***> wrote:

I've had a closer look at the code, but I could not get my head around how the warning affects the logic of the function. I did some tests, and it seems that I can get the same results with and without the warning.

See for example the code below, where I plot the load-displacement diagram of the model attached in the first post. If I comment out the lines in subcase.py with the warning message (lines 682-683) I get the same results as with the original subcase.py without any issue. Is there a reason why those lines of code can't be removed?

from pyNastran.op2.op2 import read_op2 import numpy as np import matplotlib.pyplot as plt

Read op2 file

sol_106_op2 = read_op2(op2_filename='nonlinear_buckling_verification.op2', load_geometry=True, debug=None)

Get load and displacement history

component_index = 2 loads = {} displacements = {} valid_subcase_ids = [subcase_id for subcase_id in sol_106_op2.load_vectors if hasattr(sol_106_op2.load_vectors[subcase_id], 'lftsfqs')] for subcase_id in valid_subcase_ids: loads[subcase_id] = np.apply_along_axis(np.sum, 1, sol_106_op2.load_vectors[subcase_id].data[:, :, component_index]) displacements[subcase_id] = sol_106_op2.displacements[subcase_id].data[:, -1, component_index]

Plot load-displacement diagram

load_history = np.concatenate([loads[subcase_id] for subcase_id in loads]) displacement_history = np.concatenate([displacements[subcase_id] for subcaseid in displacements]) , ax = plt.subplots() ax.plot(displacement_history, load_history, 'o-') plt.xlabel('Tip displacement [mm]') plt.ylabel('$P$ [N]') plt.grid() plt.show()

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1483860958, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWMEOV4LPYMQ7DSRSDTW54K63ANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>

fmamitrotta commented 1 year ago

Thanks for the explanation Steve, I understand your point. However, what is the bit of data that we don't get when the expected format is not found? It is not clear within set_casecc, because the code around the if on nwords_to_lsem looks like the following:

    (sdisp_set, sdisp_media, sdisp_format,
     svelocity_set, svelocity_media, svelocity_format,
     saccel_set, saccel_media, saccel_format,
     nonlinear, partn, cyclic, random, nlparm, fmethod,
     nwords_to_lsem) = ints[150:166]
    if nwords_to_lsem // 4 not in {150, 300}:
        self.log.warning(f'nwords_to_lsem={nwords_to_lsem} nwords_to_lsem//4={nwords_to_lsem//4}')

    #assert nwords_to_lsem == 4 * 150, f'nwords_to_lsem={nwords_to_lsem} size={size} nwords_to_lsem//size={nwords_to_lsem//size}'
    # LCC=1200 @ word 166
    # LSM @ 658?

    #print(ints[144:166].tolist())
    (gpforce_set, gpforce_media, gpforce_format,
     ese_set, ese_media, ese_format,
     aerof_set, aerof_media, aerof_format,
     super_seid, super_load, gust, sefinal) = ints[166:179]

There is no action taken after the warning and the rest of the data seems to be read anyway.

I would be happy to work on improving the robustness of the function, as you were suggesting, but I cannot get my head around where the improvement is needed.

SteveDoyle2 commented 1 year ago

I was getting crashes. Rather than try-excepting it, I shortcutted it.

On Tue, Mar 28, 2023 at 1:43 AM Francesco M. A. Mitrotta < @.***> wrote:

Thanks for the explanation Steve, I understand your point. However, what is the bit of data that we don't get when the expected format is not found? It is not clear within set_casecc, because the code around the if on nwords_to_lsem looks like the following:

(sdisp_set, sdisp_media, sdisp_format,
 svelocity_set, svelocity_media, svelocity_format,
 saccel_set, saccel_media, saccel_format,
 nonlinear, partn, cyclic, random, nlparm, fmethod,
 nwords_to_lsem) = ints[150:166]
if nwords_to_lsem // 4 not in {150, 300}:
    self.log.warning(f'nwords_to_lsem={nwords_to_lsem} nwords_to_lsem//4={nwords_to_lsem//4}')

#assert nwords_to_lsem == 4 * 150, f'nwords_to_lsem={nwords_to_lsem} size={size} nwords_to_lsem//size={nwords_to_lsem//size}'
# LCC=1200 @ word 166
# LSM @ 658?

#print(ints[144:166].tolist())
(gpforce_set, gpforce_media, gpforce_format,
 ese_set, ese_media, ese_format,
 aerof_set, aerof_media, aerof_format,
 super_seid, super_load, gust, sefinal) = ints[166:179]

There is no action taken after the warning and the rest of the data seems to be read anyway.

I would be happy to work on improving the robustness of the function, as you were suggesting, but I cannot get my head around where the improvement is needed.

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1486453983, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWK7MKJZFI5P4QXSR3LW6KQE3ANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>

fmamitrotta commented 1 year ago

Do you mean that instead of try-excepting the assert statement, you shortcutted it with the if-warning?

SteveDoyle2 commented 1 year ago

I mean that without that I’d check, the code would crash on newer versions of MSC Nastran without a try except.

On Wed, Mar 29, 2023 at 12:36 AM Francesco M. A. Mitrotta < @.***> wrote:

Do you mean that instead of try-excepting the assert statement, you shortcutted it with the if-warning?

— Reply to this email directly, view it on GitHub https://github.com/SteveDoyle2/pyNastran/issues/722#issuecomment-1488090059, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAICUWJ4EPH5QSOCHX7374TW6PRBRANCNFSM6AAAAAAV2FFFDM . You are receiving this because you commented.Message ID: @.***>