CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   custom solver interDyMFoam : how to read the centreOfRotation ? (https://www.cfd-online.com/Forums/openfoam-programming-development/145645-custom-solver-interdymfoam-how-read-centreofrotation.html)

jmf December 9, 2014 17:02

custom solver interDyMFoam : how to read the centreOfRotation ?
 
Hi


I would like to implement a sort of position control for floating objects. For this I attempt to customize interDyMFoam.
But I am new in C++, and doing this is a steep mountain for me !

This is my modified interDyMFoam.C. I try to read the current position of the floating object like this :
Code:

#include "fvCFD.H"
#include "dynamicFvMesh.H"
#include "CMULES.H"
#include "subCycle.H"
#include "immiscibleIncompressibleTwoPhaseMixture.H"
#include "turbulenceModel.H"
#include "pimpleControl.H"
#include "fvIOoptionList.H"
#include "fixedFluxPressureFvPatchScalarField.H"


// my additions :
#include "sixDoFRigidBodyMotion.H"
#include "sixDoFRigidBodyMotionI.H"
#include "sixDoFRigidBodyMotionState.H"
#include "sixDoFRigidBodyMotionStateI.H"
#include "point.H"


    while (runTime.run())
    {
        #include "readControls.H"
        #include "alphaCourantNo.H"
        #include "CourantNo.H"
        #include "setDeltaT.H"

        runTime++;
        Info<< "Time = " << runTime.timeName() << nl << endl;


        // this is my attempt to access to the motion state
        Foam::point centre;
        Foam::sixDoFRigidBodyMotionState motionState;
        centre = motionState.centreOfRotation();

The compilation error is :
Code:

Make/linux64GccDPOpt/interRelativeDyMFoam.o: In function `main':
interRelativeDyMFoam.C:(.text.startup+0x23ec): undefined reference to `Foam::sixDoFRigidBodyMotionState::sixDoFRigidBodyMotionState()'
interRelativeDyMFoam.C:(.text.startup+0x5a7a): undefined reference to `Foam::sixDoFRigidBodyMotionState::~sixDoFRigidBodyMotionState()'
interRelativeDyMFoam.C:(.text.startup+0x63e0): undefined reference to `Foam::sixDoFRigidBodyMotionState::~sixDoFRigidBodyMotionState()'
collect2: error: ld returned 1 exit status

Can I access to the motion variables from here ? Otherwise how to do this ? Any hint would be useful

Kind regards

Jean-Michel

jmf December 9, 2014 17:35

custom solver interDyMFoam : how to read the centreOfRotation ?
 
1 Attachment(s)
Oh, of course it was an extract of the code

Please find attached the c++ source. It is for OF2.3.0


Best wishes

Jean-Michel

alexeym December 10, 2014 02:21

Hi,

1. It seems you're missing -lsixDoFRigidBodyMotion in your Make/options

2. Maybe I miss something but sixDoFRigidBodyMotionState doesn't have centreOfRotation method (only centreOfMass). Also the way you're constructing the object value will be vector::zero.

jmf December 10, 2014 15:39

custom solver interDyMFoam : how to read the centreOfRotation ?
 
Dear Alexey


Thanks for your kind attention


Your first suggestion solved the compilation error, thanks.

The compilator doesn't complain about centreOfRotation, which is a method declared in 'sixDoFRigidBodyMotionState.H'.

Now you are fully right, the point 'centre' is always zero. I don't know how to solve this. I only know Python, and in C++ the way to call an existing class instance is obscur to me.

How to find the first usage of the class, and the name of the objects ?
What is the role of the third constructor in 'sixDoFRigidBodyMotionState.C' ? is it the one I should use ? If yes, what should be the arguments ?

Sorry for my elementary questions.

Best wishes

Jean-Michel

alexeym December 10, 2014 16:20

Hi,

Quote:

How to find the first usage of the class, and the name of the objects ?
What is the role of the third constructor in 'sixDoFRigidBodyMotionState.C' ? is it the one I should use ? If yes, what should be the arguments ?
The first constructor is null-constructor (or default constructor) with no arguments, which you've used. It sets all properties of the class to 0. The second is a constructor from dictionary, i.e. you create dictionary object using one of its constructors, and the pass this object to sixDoFRigidBodyMotionState constructor and so constructor fills object with values from dictionary:

Code:

    centreOfRotation_
    (
        dict.lookupOrDefault
        (
            "centreOfRotation",
            dict.lookupOrDefault("centreOfMass", vector::zero)
        )
    ),
    Q_(dict.lookupOrDefault("orientation", tensor::I)),
    v_(dict.lookupOrDefault("velocity", vector::zero)),
    a_(dict.lookupOrDefault("acceleration", vector::zero)),
    pi_(dict.lookupOrDefault("angularMomentum", vector::zero)),
    tau_(dict.lookupOrDefault("torque", vector::zero))

The third constructor just creates a copy of another sixDoFRigidBodyMotionState object.

jmf December 10, 2014 16:45

custom solver interDyMFoam : how to read the centreOfRotation ?
 
Dear Alexey


What I miss are the classes and objects involved in the 6DOFmotion analysis.

I understood that the dynamic mesh is created in 'createDynamicFvMesh.H' and the object is called 'mesh'.

But after I don't see anything in the main() that invoques the class 'sixDoFRigidBodyMotion' and creates an object like 'motion'. Despite this, the link between 'mesh' and 'motion' is likely existing, since 'sixDoFRigidBodyMotionRestraint' work as expected.

I I don't know how to access this mysterious object 'motion' through 'motionState()'.

Wow, diving into OpenFoam is not the easiest way to begin in C++!


Jean-Michel

alexeym December 11, 2014 03:28

Well, if you take a look at createDynamicFvMesh.H:

Code:

    autoPtr<dynamicFvMesh> meshPtr
    (
        dynamicFvMesh::New
        (
            IOobject
            (
                dynamicFvMesh::defaultRegion,
                runTime.timeName(),
                runTime,
                IOobject::MUST_READ
            )
        )
    );

There's only one call to New method of dynamicFvMesh, if you look at dynamicFvMeshNew.C:

Code:

Foam::autoPtr<Foam::dynamicFvMesh> Foam::dynamicFvMesh::New(const IOobject& io)
{
...
    IOdictionary dict
    (
        IOobject
        (
            "dynamicMeshDict",
            io.time().constant(),
            (io.name() == polyMesh::defaultRegion ? "" : io.name()),
            io.db(),
            IOobject::MUST_READ_IF_MODIFIED,
            IOobject::NO_WRITE,
            false
        )
    );

    const word dynamicFvMeshTypeName(dict.lookup("dynamicFvMesh"));
...
    IOobjectConstructorTable::iterator cstrIter =
        IOobjectConstructorTablePtr_->find(dynamicFvMeshTypeName);
...
}

I.e. code reads dynamicMeshDict, looks up dynamicFvMesh key in the dictionary and creates class according to the description (ex. in tutorials/multiphase/interDyMFoam/ras/floatingObject/constant/dynamicMeshDict it is dynamicMotionSolverFvMesh).

Then in you take a look at the constructor of dynamicMotionSolverFvMesh, it's just

Code:

Foam::dynamicMotionSolverFvMesh::dynamicMotionSolverFvMesh(const IOobject& io)
:
    dynamicFvMesh(io),
    motionPtr_(motionSolver::New(*this))
{}

Motion solver is again created according to dynamicMeshDict dictionary. And so on.

If you just need to know centre of rotation, you can read it from dictionary with something like:

Code:

dictionary dict_
(
    IOobject
    (
        "dynamicMeshDict",
        mesh.time().constant(),
        mesh,
        IOobject::MUST_READ,
        IOobject::NO_WRITE
    )
);

vector c(dict_.subDict("sixDoFRigidBodyMotionCoeffs").lookupOrDefault<vector>("centreOfMass", vector::zero));


jmf December 12, 2014 06:03

custom solver interDyMFoam : how to read the centreOfRotation ?
 
Should I rebuild an instance of the motion from the dynamicMeshDictionary, its values will remain constant, won't they ?

I need rather the current values of the motion, at each real time step. A solution would be to call a global variable with the current state of the motion.

I digged around what is done in 'linearSpring.C' in 'sixDoFRigidBodyMotion/sixDoFRigidBodyMotion/restraints' : there is a member function that calculates a restraint force depending on the current motion position. It is exactely what I need, but I was not able to reproduce it in interDyMFoam.C, and access to that current position

Jean-Michel
*

alexeym December 12, 2014 10:56

Yes, value read from dictionary will be constant.

You don't have direct access to from solver but you can create your own myDynamicMotionSolverFvMesh based upon dynamicMotionSolverFvMesh and expose motionSolver property to your solver (i.e. move definition of autoPtr<motionSolver> motionPtr_ from private to public). This is quick and dirty way to get access to motionState object in solver.

jmf December 15, 2014 14:19

custom solver interDyMFoam : how to read the centreOfRotation ?
 
i will try this.
Since I first have to learn C++, it won't be quick. But dirty for sure...

Thanks

haze_1986 March 24, 2015 11:49

Just curious, since I am working on something similar, would it be possible to create access functions in the sixDoFRigidBodyMotion?

Would we need to modify the motionSolver class as well?

jmf April 8, 2015 20:56

Custom solver interDyMFoam : how to read the centreOfRotation ?
 
Hi

I obtained something working, based on a global variable (c++ specialists will object for sure)

In myInterDyMFoam.C:
Code:

// global variables
Foam::point g_Centre; //  updated in myRestraint.C
...
while (runTime.run())
    {
        #include "readControls.H"
        #include "alphaCourantNo.H"
        #include "CourantNo.H"
        #include "setDeltaT.H"

        runTime++;
        ...
        Info << nl << nl << "> Running myInterDyMFoam"  << endl;
        Info<< "Main: centre = " << g_Centre << endl;
        ....

In sixDofRigidBodyMotion/restraints I added a custom restraint /myRestraint/myRestraint.C, derived from an existing restraint.C, with :
Code:

g_Centre = motion.centreOfRotation();
An the declaration is a myRestraint.H:
Code:

extern Foam::point g_Centre;
That's it

Hope it helps

Jean-Michel

haze_1986 April 11, 2015 04:56

Quote:

Originally Posted by jmf (Post 540667)
Hi

I obtained something working, based on a global variable (c++ specialists will object for sure)

In myInterDyMFoam.C:
Code:

// global variables
Foam::point g_Centre; //  updated in myRestraint.C
...
while (runTime.run())
    {
        #include "readControls.H"
        #include "alphaCourantNo.H"
        #include "CourantNo.H"
        #include "setDeltaT.H"

        runTime++;
        ...
        Info << nl << nl << "> Running myInterDyMFoam"  << endl;
        Info<< "Main: centre = " << g_Centre << endl;
        ....

In sixDofRigidBodyMotion/restraints I added a custom restraint /myRestraint/myRestraint.C, derived from an existing restraint.C, with :
Code:

g_Centre = motion.centreOfRotation();
An the declaration is a myRestraint.H:
Code:

extern Foam::point g_Centre;
That's it

Hope it helps

Jean-Michel

Hi thanks for sharing. Would like to check with you how do you declare the extern in the header file? Every time I do that I get:
Code:

error: storage class specified for g_Centre

jmf April 14, 2015 18:28

Custom solver interDyMFoam : how to read the centreOfRotation ?
 
Hi

Did you solve your 'error: storage class specified' ?

The declaration is just as written :
Code:

extern Foam::point g_Centre;
It might be simply a missing ) or : or ; somewhere

Best wishes

Jean-Michel

haze_1986 April 14, 2015 23:35

I read that extern cannot be declared within the class, do tell me if otherwise. Declaring at the top outside the class compiles fine but didnt work when running with an error saying that solver table is empty.


All times are GMT -4. The time now is 17:59.