CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (http://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   functionObject to write out cgns files (http://www.cfd-online.com/Forums/openfoam-programming-development/80199-functionobject-write-out-cgns-files.html)

braennstroem September 18, 2010 08:45

functionObject to write out cgns files
 
Hi,

I am trying to write a functionObject to sample patch data during runtime in cgns format. The implementation is based on the cgns-stuff (libraries and options-file settings) from the Turbomachinery-SIG and the mtv writer from simpleFunctionObjects.

Unfortunately, the complilation gives me this error message:

/usr/bin/ld: /home/gcae504/HOME/Dissertation/simulation_calc/OpenFOAM/gcae504-1.5-dev/TurboMachinery/src/cgnslib_2.5/platforms/linux64GccDPOpt/lib/libcgns_2.5.a(cgns_error.o): relocation R_X86_64_32 against `cgns_error_mess' can not be used when making a shared object; recompile with -fPIC
/home/gcae504/HOME/Dissertation/simulation_calc/OpenFOAM/gcae504-1.5-dev/TurboMachinery/src/cgnslib_2.5/platforms/linux64GccDPOpt/lib/libcgns_2.5.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [/home/gcae504/HOME/Dissertation/simulation_calc/OpenFOAM/OpenFOAM-1.7.x/lib/linux64GccDPOpt/libsampling.so] Error 1

Do you have a hint, what this error message mean and how I could avoid this?
Fabian

wyldckat September 18, 2010 14:52

Greetings Fabian,

Looks to me that the library libcgns_2.5.a was built with incompatible options (i.e., missing the "-fPIC" that the error message told you about) or perhaps an incompatible gcc version... or even binutils version! Try rebuilding that library with the same tools (gcc + binutils) with which you built OpenFOAM 1.7.x.

I tried the other day to build a recent OpenFOAM-1.5-dev SVN version and it seems to work very well with gcc 4.4.x! So, my guess is that you won't have to worry about 1.5-dev not building with a recent gcc version... although my bet is that it won't work all that well with gcc's 4.5.x series :(.

edit: I stand corrected - 2/3 days ago changes were submitted to the SVN at the -extend project for compiling 1.5-dev with gcc 4.5.0!!

Best regards,
Bruno

braennstroem September 19, 2010 14:08

Hi Bruno,

thanks for the help. It works with the fPIC option (though it does not write out anything yet...), which I actually tried before, but not in a correct way.

Thanks!
Fabian

braennstroem September 19, 2010 14:13

Now, the trouble is that I am looking for a way to just use scalars...
The class looks like:

template<class Type>
void Foam::cgnsSurfaceWriter<Type>::write
(
const fileName& samplePath,
// const fileName& timeDir,
const fileName& surfaceName,
const pointField& points,
const faceList& faces,
const fileName& fieldName,
const Field<Type>& values,
const bool verbose
) const

where values can be anything from scalarFields, vectorFields and some tensor-fields.
The cgns function gets an ordinary float array called "floatArray" in this case:

cg_field_write(cgflowfile,cgflowbase,cgflowzone, cgflowindex,RealSingle,"Pressure", floatArray,&cgflowfield);

Does anyone know, how to tell openfoam, that it uses just scalarFields for this kind of surfaceWriter?

Fabian

wyldckat September 19, 2010 16:05

Hi Fabian,

Unfortunately, I have no clue about the specifics for that :( But I do know that if you examine ccm26ToFoam and it's dependency library libccmio, you might be able figure that and other issues as well! Because libccmio is based on ADF, which in turn is based on cgns... Although it's the reverse of what you want, i.e., "pseudo-cgns to foam".

Good luck!
Bruno

olesen September 20, 2010 09:26

Quote:

Originally Posted by braennstroem (Post 275745)
Now, the trouble is that I am looking for a way to just use scalars...

template<class Type>
void Foam::cgnsSurfaceWriter<Type>::write
...
The cgns function gets an ordinary float array called "floatArray" in this case:

cg_field_write(cgflowfile,cgflowbase,cgflowzone, cgflowindex,RealSingle,"Pressure", floatArray,&cgflowfield);

Does anyone know, how to tell openfoam, that it uses just scalarFields for this kind of surfaceWriter?

The solution is two parts.
1. you need to figure out how you want the OpenFOAM data structure mapped to cgns representations (eg, you may want to map a vector as three scalar fields).
2. you need template specializations for each of these cases.

braennstroem September 20, 2010 12:17

Thanks to you both!
As it seems, I am not able to directly declare:

template<class Type>
void Foam::cgnsSurfaceWriter<Type>::write
(
const fileName& samplePath,
// const fileName& timeDir,
const fileName& surfaceName,
const pointField& points,
const faceList& faces,
const fileName& fieldName,
const Field<Foam::Scalar>& values,
const bool verbose
) const

I will try out the approach from the vtk-writer, which has different 'writeData' depending on the type of simulation:

template<>
void Foam::vtkSurfaceWriter<Foam::scalar>::writeData
(
Ostream& os,
const Field<Foam::scalar>& values
)
{
...
//do conversion of values to floaArray
double *floatArray = new double[surface.nPoints()];
forAll(surface.points(), i)
{
floatArray[i] = values[i];
}

cg_field_write(cgflowfile,cgflowbase,cgflowzone, cgflowindex,RealSingle,"Pressure", floatArray,&cgflowfield);
}

and

static void writeData(Ostream&, const Field<Type>& values)

in the declaration of the class. The other type of fields I would just keep blank!?

Fabian

braennstroem September 20, 2010 15:32

me again... ok,this seems to work, but now I got trouble getting the current time step into the cgns file. This is what I got so far:

namespace Foam
{
template<>
void Foam::cgnsSurfaceWriter<Foam::scalar>::writeData
(
const Field<Foam::scalar>& values,
int numberPoints,
int cgflowfile,
int cgflowbase,
int cgflowzone,
int cgflowindex,
int cgflowfield
)
{
Info << "ScalarField Transformation" << endl;
float *pressure = new float[numberPoints];
for (int i=0; i<numberPoints; i++)
{
pressure[i] = values[i];
}

cg_field_write(cgflowfile,cgflowbase,cgflowzone, cgflowindex,RealSingle,"Pressure", pressure,&cgflowfield);
}
}

template<class Type>
void Foam::cgnsSurfaceWriter<Type>::writeData
(
const Field<Type>& values,
int numberPoints,
int cgflowfile, int cgflowbase, int cgflowzone, int cgflowindex, int cgflowfield
)
{
Info << "Generic type" << endl;
// Info << values << endl;
}

// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //

template<class Type>
void Foam::cgnsSurfaceWriter<Type>::write
(
const fileName& samplePath,
const fileName& surfaceName,
const pointField& points,
const faceList& faces,
const fileName& fieldName,
const Field<Type>& values,
const bool verbose
) const
{
if (values.size()==faces.size())
{
FatalErrorIn("cgnsSurfaceWriter::write()")
<< "Only interpolated planes are currently supported."
<< abort(FatalError);
}


fileName timeDir("1111");
//fileName surfaceDir(samplePath/timeDir);
//fileName outputDir = mesh_.time().timeName();
fileName surfaceDir(samplePath);

if (!exists(surfaceDir))
{
mkDir(surfaceDir);
}


// Convert faces to triangles.
DynamicList<labelledTri> tris(faces.size());

forAll(faces, i)
{
const face& f = faces[i];

faceList triFaces(f.nTriangles(points));
label nTris = 0;
f.triangles(points, nTris, triFaces);

forAll(triFaces, triI)
{
const face& tri = triFaces[triI];
tris.append(labelledTri(tri[0], tri[1], tri[2], 0));
}
}

triSurface tS
(
tris.shrink(),
geometricSurfacePatchList
(
1,
geometricSurfacePatch
(
"patch", // geometricType
string::validate<word>(fieldName), // fieldName
0 // index
)
),
points
);

//================================== //================================== //================================== /
//================================== //================================== //================================== /
// write mesh file
//================================== //================================== //================================== /

int CellDim = 2, PhyDim = 2;
int size[3];

size[0] = tS.nPoints();
size[1] = tS.size();
size[2] = 0;

fileName cgnsMeshFileName;
cgnsMeshFileName=surfaceDir/fieldName + "_mesh" + ".cgns";
const fileName writeFile=cgnsMeshFileName;

int cgfile, cgbase, cgzone, cgcoord, cgsect;
cg_open(writeFile.c_str(),MODE_WRITE,&cgfile);
cg_base_write(cgfile,"Cavity", CellDim, PhyDim, &cgbase);

cg_simulation_type_write(cgfile,cgbase,TimeAccurat e);

label nPoints = tS.nPoints();
Info << "local Surface Points: " << nPoints << endl;
float *xcoord = new float[nPoints];
float *ycoord = new float[nPoints];
float *zcoord = new float[nPoints];

forAll(tS.points(), lpi)
{
xcoord[lpi] = tS.points()[lpi].x();
ycoord[lpi] = tS.points()[lpi].y();
zcoord[lpi] = tS.points()[lpi].z();
}

cg_zone_write(cgfile, cgbase,"Zone1", size, Unstructured, &cgzone);
cg_goto(cgfile, cgbase, "Zone_t", cgzone, "end");

cg_coord_write(cgfile, cgbase, cgzone, RealSingle,"CoordinateX", xcoord , &cgcoord);
cg_coord_write(cgfile, cgbase, cgzone, RealSingle,"CoordinateY", ycoord , &cgcoord);
cg_coord_write(cgfile, cgbase, cgzone, RealSingle,"CoordinateZ", zcoord , &cgcoord);

int *faces1 = new int[3*tS.size()];

label nf = 0;
forAll(tS, facei)
{
faces1[nf++] = tS[facei][0]+1;
faces1[nf++] = tS[facei][1]+1;
faces1[nf++] = tS[facei][2]+1;
}

cg_section_write(cgfile, cgbase, cgzone, "Face to Vertex Map", TRI_3, 1, tS.size(), 0, faces1, &cgsect);

cg_close(cgfile);

delete [] faces1;
delete [] xcoord;
delete [] ycoord;
delete [] zcoord;

//================================== //================================== //==================================
//================================== //================================== //==================================
// write flow field information
//================================== //================================== //==================================

int nsteps = 1;
float timeDump = runTime.value();

//float timeDump = 1.0110;
int timeStep= 10;

int cgflowfile,cgflowbase,cgflowzone,cgflowindex,cgflo wfield;


fileName surfFName;
surfFName=surfaceDir/samplePath+fieldName + '_' + surfaceName + ".cgns";

cg_open(surfFName.c_str(),MODE_WRITE,&cgflowfile);

cg_base_write(cgflowfile,"Cavity", CellDim, PhyDim, &cgflowbase);

cg_simulation_type_write(cgflowfile,cgflowbase,Tim eAccurate);

cg_biter_write(cgflowfile,cgflowbase,"TimeIterValu es",nsteps);

cg_goto(cgflowfile,cgflowbase,"BaseIterativeData_t ",1,"end");

cg_array_write("TimeValues",RealSingle,1,&nsteps,& timeDump);

cg_array_write("IterationValues",Integer,1,&nsteps ,&timeStep);

cg_zone_write(cgflowfile, cgflowbase,"Zone1", size, Unstructured, &cgflowzone);

cg_goto(cgflowfile, cgflowbase, "Zone_t", cgflowzone, "end");

cg_link_write("GridCoordinates",cgnsMeshFileName.c _str(), "Cavity/Zone1/GridCoordinates");

cg_link_write("Face to Vertex Map",cgnsMeshFileName.c_str(), "Cavity/Zone1/Face to Vertex Map");

cg_descriptor_write("Export Option", "Acoustic Dipole");

cg_sol_write(cgflowfile,cgflowbase,cgflowzone, "Flow Solution",Vertex,&cgflowindex);

int numberPoints=tS.nPoints();
writeData(values,numberPoints,cgflowfile,cgflowbas e,cgflowzone, cgflowindex,cgflowfield);

cg_goto(cgflowfile,cgflowbase,"BaseIterativeData_t ",1,"end");

cg_ziter_write(cgflowfile,cgflowbase,cgflowzone,"Z oneIterativeData");

cg_goto(cgflowfile, cgflowbase, "Zone_t", cgflowzone,"ZoneIterativeData_t",1, "end");

int idata[2];
idata[0] = 32;
idata[1] = 1;

cg_array_write("FlowSolutionPointers",Character,2, idata,"Flow Solution");

cg_close(cgflowfile);

}

The tough part (for me) is to get now the current time and the iteration number correct, right now, they are fixed:

float timeDump = 1.0110;
int timeStep= 10;

cg_array_write("TimeValues",RealSingle,1,&nsteps,& timeDump);
cg_array_write("IterationValues",Integer,1,&nsteps ,&timeStep);

Do you have an idea, how I get the current simulation time into it? And what could be the best procedure to get the 'timeStep'? To start with I would set it to zero in the beginning...!?

Would be nice, if you have some hints!
Thanks!
Fabian

olesen September 24, 2010 02:26

Quote:

Originally Posted by braennstroem (Post 275873)
me again... ok,this seems to work, but now I got trouble getting the current time step into the cgns file. This is what I got so far:

namespace Foam
{
template<>
void Foam::cgnsSurfaceWriter<Foam::scalar>::writeData
(
const Field<Foam::scalar>& values,
int numberPoints,
int cgflowfile,
int cgflowbase,
int cgflowzone,
int cgflowindex,
int cgflowfield
)
{
Info << "ScalarField Transformation" << endl;
float *pressure = new float[numberPoints];
for (int i=0; i<numberPoints; i++)
{
pressure[i] = values[i];
}

cg_field_write(cgflowfile,cgflowbase,cgflowzone, cgflowindex,RealSingle,"Pressure", pressure,&cgflowfield);
}
}

You've got a memory leak in the above code (a new without a delete).
If you don't mind writing out doubles, you can just use the scalarField contents directly and avoid allocation/deallocation:

Code:

namespace Foam
{
    template<>
    void Foam::cgnsSurfaceWriter<Foam::scalar>::writeData
    (
        const Field<Foam::scalar>& values,
        int cgflowfile,
        int cgflowbase,
        int cgflowzone,
        int cgflowindex,
        int cgflowfield
    )
    {
        Info<< "ScalarField Transformation" << endl;
        cg_field_write
        (
            cgflowfile,
            cgflowbase,
            cgflowzone,
            cgflowindex,
            RealDouble,
            "Pressure",
            values->cdata(),
            &cgflowfield
        );
    }
}


Quote:

Originally Posted by braennstroem (Post 275873)

Do you have an idea, how I get the current simulation time into it? And what could be the best procedure to get the 'timeStep'?

Since you originally started with a volScalarField, you have access to its time information (via its mesh). So you could either pass this through as an additional parameter to your writer, or change your writer to use volume fields directly.


All times are GMT -4. The time now is 08:25.