SteveDoyle2 / pyNastran

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

Writing RBE3 cards in double precision format using D notation results in a fatal error #762

Closed fmamitrotta closed 5 months ago

fmamitrotta commented 6 months ago

Summary

I'm using write_bdf with is_double=True and when I try to run an analysis with an RBE3 element I get a fatal error.

After some debugging I've found out that Nastran does not like the letter D for the exponential notation of the weighting factors WTi. If I change D to E the analysis works. However, this is only true if only one weighting factor is used for the card, if the weighting factors are >=2 then the analysis fails regardless of letter D and E.

Not sure what is going on here, my guess is that there must be something going on with single and double precision when Nastran deals with the constraint matrix of the RBE3 elements.

Should RBE3 elements be excluded from double precision writing to the bdf file?

Reproduction

Have a look at the files in the attached zip folder. They show four cases:

rbe3_tests.zip

Versions

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

SteveDoyle2 commented 6 months ago

That's so random. It probably also a version specific bug. I'm fine with RBE3s not being double precision. I just modified the write_card method to be;

    def write_card(self, size: int=8, is_double: bool=False) -> str:
        card = self.repr_fields()
        return write_card(self.comment, card, size, is_double=False)

I guess why are you using the weighting factors? I've never set them to anything besides 1.0.

fmamitrotta commented 6 months ago

Yeah, I thought too that it was quite random! 😅

On the weighting factors: I believe there's a limitation in the way the RBE3 card is implemented in pyNastran. In theory, you should be able to use each weighting factor and the associated components with a list of nodes. In practice, the RBE3 card in pyNastran expects the list of weighting factors, of the components and of the nodes to be of the same length. As a consequence I cannot just use one weighting factor (equal to 1) with a list of nodes, but I have to use a list to weighting factors (all equal to 1), where each is associated to a different node. Does this make sense?

I would be nice if the RBE3 card could accept a list of lists for the nodes (the Gijs). Should I open a different issue for this?

SteveDoyle2 commented 6 months ago

I thought the only requirement was that the number of weights and components was the same. The nodes can be different.

If you have an example that runs that doesn’t work in pynastran and runs (so bdf/op2 ideally), I’m happy to fix it.

Hopefully it’s just a mod to the existing structure. I’d be fine with a different way to make an rbe3 though.

On Wed, Mar 6, 2024 at 01:43 Francesco M. A. Mitrotta < @.***> wrote:

Yeah, I thought too that it was quite random! 😅

On the weighting factors: I believe there's a limitation in the way the RBE3 card is implemented in pyNastran. In theory, you should be able to use each weighting factor and the associated components with a list of nodes. In practice, the RBE3 card in pyNastran expects the list of weighting factors, of the components and of the nodes to be of the same length. As a consequence I cannot just use one weighting factor (equal to 1) with a list of nodes, but I have to use a list to weighting factors (all equal to 1), where each is associated to a different node. Does this make sense?

I would be nice if the RBE3 card could accept a list of lists for the nodes (the Gijs). Should I open a different issue for this?

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

fmamitrotta commented 6 months ago

Steve, I was actually wrong, you can specify a list of list of nodes indeed. I've been always mislead by the definition and the description of the add_rbe3 function:

    def add_rbe3(self, eid: int, refgrid: int, refc: str,
                 weights: list[float], comps: list[str], Gijs: list[int],
                 Gmi=None, Cmi=None,
                 alpha: float=0.0, tref: float=0.0,
                 comment: str='') -> RBE3:
        """
        Creates an RBE3 element

        Parameters
        ----------
        eid : int
            element id
        refgrid : int
            dependent node
        refc - str
            dependent components for refgrid???
        GiJs : list[int, ..., int]
            independent nodes
        comps : list[str, ..., str]
            independent components
        weights : list[float, ..., float]
            independent weights for the importance of the DOF
        Gmi : list[int, ..., int]; default=None -> []
            dependent nodes / UM Set
        Cmi : list[str, ..., str]; default=None -> []
            dependent components / UM Set
        alpha : float; default=0.0
            thermal expansion coefficient
        tref : float; default=0.0
            reference temperature
        comment : str; default=''
            a comment for the card

        """

I've always thought that Gijs had to be a list of integers, but I've tested it and it's not the case. Maybe it's worth changing the type into Union[list[int], list[list[int]]?

SteveDoyle2 commented 6 months ago

Yeah :)

Unfortunately types in python are all just lies. I’m sure I’ve added a whole bunch of checks for the RBE3 just because I messed it up in the past, so if it gets through it’s probably good.

I’ll update the docs.

On Wed, Mar 6, 2024 at 10:19 Francesco M. A. Mitrotta < @.***> wrote:

Steve, I was actually wrong, you can specify a list of list of nodes indeed. I've been always mislead by the definition and the description of the add_rbe3 function:

def add_rbe3(self, eid: int, refgrid: int, refc: str,
             weights: list[float], comps: list[str], Gijs: list[int],
             Gmi=None, Cmi=None,
             alpha: float=0.0, tref: float=0.0,
             comment: str='') -> RBE3:
    """        Creates an RBE3 element        Parameters        ----------        eid : int            element id        refgrid : int            dependent node        refc - str            dependent components for refgrid???        GiJs : list[int, ..., int]            independent nodes        comps : list[str, ..., str]            independent components        weights : list[float, ..., float]            independent weights for the importance of the DOF        Gmi : list[int, ..., int]; default=None -> []            dependent nodes / UM Set        Cmi : list[str, ..., str]; default=None -> []            dependent components / UM Set        alpha : float; default=0.0            thermal expansion coefficient        tref : float; default=0.0            reference temperature        comment : str; default=''            a comment for the card        """

I've always thought that Gijs had to be a list of integers, but I've tested it and it's not the case. Maybe it's worth changing the type into Union[list[int], list[list[int]]?

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

fmamitrotta commented 6 months ago

"Types in python are all just lies" is a quote that I'm going to use 😁

Cool, thanks Steve.

On another note: why in general do you use the letter D when writing the bdf with large field entries (is_double=True)? I've been told from MSC Nastran support that D was used in old versions of Nastran to store real numbers over two i4 words to give them double precision, while newer versions of Nastran store real numbers in one i8 word.

Would it make sense to write the entries with the E exponent, or even without any exponent (1.2+01 is equivalent to 1.2E+01)?

Let me know if you prefer me to open another issue for this matter.

SteveDoyle2 commented 6 months ago

I hadn’t heard that. I learned Nastran on MSC 2005 andI haven’t checked in a while. Not everyone is up to date on their Nastran, so I don’t think it would be good. I guess now I’m even more confused why the D on the RBE3 weight doesn’t work if it’s all just double precision anyways.

Regarding 1.2E+3 vs 1.2E3 vs 1.2+3, the only requirement is that the maximum precision is used. If it’s the same and it’s faster, sure.

On Thu, Mar 7, 2024 at 02:36 Francesco M. A. Mitrotta < @.***> wrote:

"Types in python are all just lies" is a quote that I'm going to use 😁

Cool, thanks Steve.

On another note: why in general do you use the letter D when writing the bdf with large field entries (is_double=True)? I've been told from MSC Nastran support that D was used in old versions of Nastran to store real numbers over two i4 words to give them double precision, while newer versions of Nastran store real numbers in one i8 word.

Would it make sense to write the entries with the E exponent, or even without any exponent (1.2+01 is equivalent to 1.2E+01)?

Let me know if you prefer me to open another issue for this matter.

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

fmamitrotta commented 6 months ago

I thought about why the D on the RBE3 weight doesn't work, and my guess is that probably D forces Nastran to store the value in a way that the internal code does not like. With the E (or without exponent) it adapts to whatever the code wants. Who knows! 🤷‍♂️

As far as I know in all those cases (1.2E+3 vs 1.2E3 vs 1.2+3) the number is stored in full precision (supposing we're using large field entries). I can test to check the speed on my Nastran (MSC 2021.4). I guess to use the maximum precision it would make sense not to use any exponent and have the smallest number of digit possible (e.g. +3 instead of +03), so that we gain the maximum possible number of digits available in the 16 character field. Does this make sense?

I've not understood whether you would be willing to move away from writing with the D exponent though.

SteveDoyle2 commented 6 months ago

I guess to use the maximum precision it would make sense not to use any exponent and have the smallest number of digit possible (e.g. +3 instead of +03), so that we gain the maximum possible number of digits available in the 16 character field. Does this make sense?

For 8-character fields, it definitely matters and is done. For 16-character width, you could replace E+ with E and add precision. However, in my experience, the only time you'd use that is if you're setting matrices. The 16-character field definitely loses some precision over what the internal data type has. This can be fixed by writing out your matrix, loading it back in, diff'ing in, and writing out the residual. You can also just use a binary op4. If you're using the D flag, you have to have the D, so because of that, I don't bother with the E+ vs. E flag.

I've not understood whether you would be willing to move away from writing with the D exponent though.

No. It's not the default and not hurting anything, so I don't think there is any benefit.

On Thu, Mar 7, 2024 at 9:38 AM Francesco M. A. Mitrotta < @.***> wrote:

I thought about why the D on the RBE3 weight doesn't work, and my guess is that probably D forces Nastran to store the value in a way that the internal code does not like. With the E (or without exponent) it adapts to whatever the code wants. Who knows! 🤷‍♂️

As far as I know in all those cases (1.2E+3 vs 1.2E3 vs 1.2+3) the number is stored in full precision (supposing we're using large field entries). I can test to check the speed on my Nastran (MSC 2021.4). I guess to use the maximum precision it would make sense not to use any exponent and have the smallest number of digit possible (e.g. +3 instead of +03), so that we gain the maximum possible number of digits available in the 16 character field. Does this make sense?

I've not understood whether you would be willing to move away from writing with the D exponent though.

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