FloatingArrayDesign / MoorDyn

a lumped-mass mooring line model intended for coupling with floating structure codes
https://moordyn.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
73 stars 42 forks source link

Fixes #207 #231

Closed sanguinariojoe closed 4 months ago

sanguinariojoe commented 4 months ago

See #207

RyanDavies19 commented 4 months ago

@AlexWKinley @sanguinariojoe Thank you all for putting this together and working out the math. This all looks good on my end, and I agree that MD was failing to account for the non-inertial reference frame. I will talk with @RBergua about this on the MDF side and address it in a PR there. I'm curious @AlexWKinley does this resolve your surface piercing buoys issues? USFLOWT is using MoorDyn for the same purpose.

AlexWKinley commented 4 months ago

I think this will do a solid job addressing my issues. I haven't had a chance to particularly rigorously test this. I'll try to find some time in the next day or two.

The overall surface piercing behavior is probably more complicated than just this particular issue, but that can be a later investigation.

RyanDavies19 commented 4 months ago

Once I get this in on the OpenFAST side I'll let you all know how it does resolving issues with USFLOWT. Agreed though the surface piercing is probably more than just this. If I come across any fixes on the MD-F side I'l open an issue here

AlexWKinley commented 4 months ago

Alright, I've had some time to test out this PR. Overall, everything works as expected.

The only additional thought I have related to this PR, is that we might want to also handle when the body CG is defined as not being at the origin of the body. I think this should be pretty straight forward. The code below seems to work at least in the context where there isn't added mass.

    // First, the body's own mass matrix must be adjusted based on its
    // orientation so that we have a mass matrix in the global orientation frame
    M = rotateMass6(OrMat, M0);

    // gravity forces and moments about body ref point given CG location
    const vec body_rCGrotated = OrMat * body_rCG;
    // weight+buoyancy vector
    const vec Fgrav =
        vec(0.0, 0.0, bodyV * env->rho_w * env->g - bodyM * env->g);
    F6net(Eigen::seqN(0, 3)) = Fgrav;
    F6net(Eigen::seqN(3, 3)) = body_rCGrotated.cross(Fgrav);

    // Centrifugal force due to COM not being at body origin
    const vec w = v6.tail<3>();
    F6net.head<3>() -=
        M.topLeftCorner(3, 3) * (w.cross(w.cross(body_rCGrotated)));

As potential future investigation, I now think @sanguinariojoe is correct that our 6dof kinematics are missing some sort of $\omega \times I_{cm} \omega$ term. This comes up if you give a body (with an attached rod), rotation around two separate axes. In those sitatuions the kinematics differ depending on where the body is, but both of the kinematics are incorrect so I don't think that should prevent merging this PR.

sanguinariojoe commented 4 months ago

Hey! Nice catch!

The bug you are tracing now I think is related with an inconsistency on the euler angles treatment I found this morning. It is a bit soon yet, but I am submitting a PR (and eventually an issue) asap

On Wed, 3 Jul 2024, 16:53 AlexWKinley, @.***> wrote:

Alright, I've had some time to test out this PR. Overall, everything works as expected.

The only additional thought I have related to this PR, is that we might want to also handle when the body CG is defined as not being at the origin of the body. I think this should be pretty straight forward. The code below seems to work at least in the context where there isn't added mass.

// First, the body's own mass matrix must be adjusted based on its // orientation so that we have a mass matrix in the global orientation frame M = rotateMass6(OrMat, M0);

// gravity forces and moments about body ref point given CG location const vec body_rCGrotated = OrMat body_rCG; // weight+buoyancy vector const vec Fgrav = vec(0.0, 0.0, bodyV env->rho_w env->g - bodyM env->g); F6net(Eigen::seqN(0, 3)) = Fgrav; F6net(Eigen::seqN(3, 3)) = body_rCGrotated.cross(Fgrav);

// Centrifugal force due to COM not being at body origin const vec w = v6.tail<3>(); F6net.head<3>() -= M.topLeftCorner(3, 3) * (w.cross(w.cross(body_rCGrotated)));

As potential future investigation, I now think @sanguinariojoe https://github.com/sanguinariojoe is correct that our 6dof kinematics are missing some sort of $\omega \times I_{cm} \omega$ term. This come up if you give a body (with an attached rod), rotation around two separate axes. It does happen that in that case, the kinematics differ depending on where the body is, but both of the kinematics are incorrect so I don't think that should prevent merging this PR.

— Reply to this email directly, view it on GitHub https://github.com/FloatingArrayDesign/MoorDyn/pull/231#issuecomment-2206402338, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMXKKBN5CLUS4XUT5LSKDDZKQF5DAVCNFSM6AAAAABKG6H7H2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBWGQYDEMZTHA . You are receiving this because you were mentioned.Message ID: @.***>