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/)
-   -   Extract data in volVectorField to a primitive C or C++ data type (https://www.cfd-online.com/Forums/openfoam-programming-development/166578-extract-data-volvectorfield-primitive-c-c-data-type.html)

cfbaptista February 12, 2016 07:45

Extract data in volVectorField to a primitive C or C++ data type
 
Consider a volVectorField like U. How can I extract the data inside the object to a primitive C or C++ data type?

I want the data in memory but not in a OpenFOAM-specific object. Basically what I want is just a std::vector (or even better: a C array) containing the values in e.g. 0/U.

My goal is to write a function which computes vorticity and returns just a C pointer to the first value in memory.

dkxls February 12, 2016 09:17

I would recommend you to take a look at OpenFOAM's container classes as they build the underlying data structure for the fields (e.g. volVectorField or volScalarField). Specifically have a look at the List [1] and UList [2] classes.

Now, assuming f is of type volScalarField, you would get access to the internal field (i.e. without the boundaries) like this:
Code:

    const scalarField& fCellValues = f.internalField();
To get access to the C data structure something like this should do the trick:
Code:

    const double* data = fCellValues.cdata();
Now, for vector fields that might be a bit different, since I cannot recall how they are stored exactly (e.g. if the data arrays are contiguous). But maybe somebody else can comment on that.

Hope that helped!

-Armin

[1] https://github.com/OpenFOAM/OpenFOAM...ts/List/List.H
[2] https://github.com/OpenFOAM/OpenFOAM.../UList/UList.H

mkiewat February 12, 2016 09:49

I'm dealing with a similar problem. I managed to extract the entire field to std namespace vectors using the object registry to get the components of the vectorfield (u_,v_,w_), then I copy them cell by cell (which is probably not a good idea at all) into the std vector structure (u,v,w).
Code:

const volScalarField u_(obr().objectRegistry::lookupObject<volVectorField>("U").component(vector::X));
const volScalarField v_(obr().objectRegistry::lookupObject<volVectorField>("U").component(vector::Y));
const volScalarField w_(obr().objectRegistry::lookupObject<volVectorField>("U").component(vector::Z));
   
const int nCells(v_.size());
   
std::vector<double> u(nCells,0);
std::vector<double> v(nCells,0);
std::vector<double> w(nCells,0);
   
forAll(u_, cellI)
{
        u[cellI]=u_[cellI];
        v[cellI]=v_[cellI];
        w[cellI]=w_[cellI];
}

My current problem is, that I want to extract only a certain sub-volume of cells to such a data structure. For this I copied the cellSource functionObject and started to look for the right location to implement that data extraction and transfer. I figured, the function Foam::fieldValues::cellSource::writeValues(const word& fieldName) from cellSourceTemplates.C might be a good place, since the sub-volume field data is already available by the variable "values". The problem: how do I extract the respective velocity components (or pressure values) from this structure? The values variable can contain: <scalar> <vector> <sphericalTensor> <symmTensor> <tensor>. Depending on the function call "writeValues" the type of values is different. I would like to extract the numbers stored in "values". At the end I want to transfer a p-vector and vectors for each velocity component. Any help is appreciated.

Here is the function that I want to edit and use:
Code:

template<class Type>
bool Foam::fieldValues::cellToMat::writeValues(const word& fieldName)
{
    const bool ok = validField<Type>(fieldName);

    if (ok)
    {
        Field<Type> values(setFieldValues<Type>(fieldName));
        scalarField V(filterField(mesh().V()));
        scalarField weightField(values.size(), 1.0);

        if (weightFieldName_ != "none")
        {
            weightField = setFieldValues<scalar>(weightFieldName_, true);
        }

        // Combine onto master
        combineFields(values);
        combineFields(V);
        combineFields(weightField);

        // apply weight field
        values *= weightField;

        if (Pstream::master())
        {
            Type result = processValues(values, V, weightField);

            // add to result dictionary, over-writing any previous entry
            resultDict_.add(fieldName, result, true);

            if (valueOutput_)
            {
                IOField<Type>
                (
                    IOobject
                    (
                        fieldName + "_" + sourceTypeNames_[source_] + "-"
                            + sourceName_,
                        obr_.time().timeName(),
                        obr_,
                        IOobject::NO_READ,
                        IOobject::NO_WRITE
                    ),
                    values
                ).write();
            }

            file()<< tab << result;

            Info(log_)<< "    " << operationTypeNames_[operation_]
                << "(" << sourceName_ << ") for " << fieldName
                <<  " = " << result << endl;
           
            //----- moving field to MATLAB starts here --------//
            // available variables:
            // - sourceName_ = "sampleBox" -> cellZone name
            // - fieldName  = "U" -> name of the currently processed field
            // - operationTypeNames_[operation_] = "none" -> operation to be applied to the field
            //                                    (can be:"none","sum","average","weightedAverage"
            //                                            "volAverage","volIntegrate","min","max","CoV")
            // - result      = (0 0 0) -> result from operation
            // - obr_.time().timeName() = "100.01"
            Info << nl << "Transferring " << fieldName
                      << " to MATLAB at t= " << obr_.time().timeName() << endl;

            if(fieldName == "U")
            {
                //const scalarField& test(values.component(vector::X));
                const volScalarField u_(values.component(vector::X));
                //Info << nl << "!!!!now U!!! " << values[0].component(vector::X) << endl;
                //int* temp = values[0];
               
                //ptr->DoSomething(); // Use the object in some way.
            }
            else if(fieldName == "p")
            {
                Info << nl << "!!!!now p!!!" << values[0] << endl;
            }
//const DimensionedField<Type,volMesh>& iField = this->dimensionedInternalField();
//const Field<Type>& iField = this->internalField();
// if (!iField.name().compare("U"))
// {
//  Info << nl << "SUCCESS "  << endl;
// }

           
        }
    }

    return ok;
}


mkiewat February 12, 2016 09:54

..........

cfbaptista February 15, 2016 06:02

Thanks dkxls!

From what I gathered is that in a volVectorField all the components are stored in a separate Foam::Vector. You can then do something like:

Code:

const Foam::Vector<double>& u = U.internalField()[0];
const Foam::Vector<double>& v = U.internalField()[1];
const Foam::Vector<double>& w = U.internalField()[2];

But I need all the components in a single contiguous array. Although not efficient, I am now copying the values into a C-style array:

NOTE: i is the cell index and j is the component index

Code:

vorticity = fvc::curl(U);

int index = 0;

// Copy vorticity components stored in volVectorField object to C-style array
forAll( vorticity.internalField(), i )
{
    for ( int j = 0; j < mesh.nGeometricD(); j++ )
    {
        eulerianVorticity[index] = vorticity.internalField()[i][j];
        index++;
    }
}

// Check if size of input array exactly matches number of copied values
if ( index+1 != nbValues )
{
    if ( index+1 > nbValues )
    {
        Info<< "ERROR: Size of input array for vorticity is too small\n" << endl;
    }
    else if ( index+1 < nbValues )
    {
        Info<< "ERROR: Size of input array for vorticity is too large\n" << endl;
    }
    Info<< "ERROR: Expected size: " << nbValues << ", received size: " << index+1 << "\n" << endl;
}

If there is a more efficient or succinct way of doing this please let me know!


All times are GMT -4. The time now is 19:02.