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 |
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 |
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 |
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 |
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 |
Quote:
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. |
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 |
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 |
Quote:
If you don't mind writing out doubles, you can just use the scalarField contents directly and avoid allocation/deallocation: Code:
namespace Foam Quote:
|
This thread is too old, I wonder if currently there is a function object developed for writing or sampling data in CGNS format?!
|
Quick answer: No function object AFAIK, but I did port (part of) the CGNS utilities from the SIG TurboMachinery: https://github.com/wyldckat/cgnsToFromFoam/
|
Quote:
Regards, Syavash |
All times are GMT -4. The time now is 21:10. |