CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   Main CFD Forum (https://www.cfd-online.com/Forums/main/)
-   -   Reading a mesh from a CGNS file (https://www.cfd-online.com/Forums/main/175667-reading-mesh-cgns-file.html)

chaithu August 3, 2016 02:27

Reading a mesh from a CGNS file
 
Hi,
I have just started learning CFD. I just learnt the algorithm for structured non-orthogonal grids. I would like to implement them in C++, but I have no idea as to how to read the mesh file created in ICEM CFD into my C++ code.

Can someone please help me out.

Thanks in advance.:)

Pflaume1891 August 4, 2016 16:01

Use MSH File
 
Hi.

I'd advice you to use msh file for two reasons:
1. MSH Files are documented in the ANSYS Help. Look for it under
Appendix B. ANSYS Fluent File Formats
2. You can choose to output msh files in ascii format - that is more
easy to implement first. After it's functioning, you can also write a
algorithm for binary files - is also documented in the ansys help.

Regards,
Jan

t.teschner August 7, 2016 18:39

Having used CGNS extensively, I would tend to agree that something like the fluent *.msh file is probably something easy to start with, or maybe the star ccm format as well, but that is up to you. if you want to get started with cgns, i highly recommend to go through the user guide (it is not that long but in my opinion worthwhile to learn, cgns can greatly simplyfy thing for you in the future, but it also can be tricky at times)

http://cgns.github.io/CGNS_docs_curr...uide.3.1.3.pdf

now, if you want to continue down the cgns path, here are a few simple subroutines which will read the coordinates for you (its all c++, arrays and variables have been declared before elsewhere) and set up the boundary conditions.

Code:

#include <iostream>
#include "stdio.h"

#include "cgnslib.h"

#include "readmesh.h"

using namespace std;

void get_mesh_sizes(char *name, int **isize)
{
        int        index_file;
        char        zonename[100];

        cg_open(name,CG_MODE_READ,&index_file);
        cg_zone_read(index_file,1,1,zonename,isize[0]);

        cout << "number of vertices: " << isize[0][0] << endl;
        cout << "number of cells:    " << isize[0][1] << endl;

        cg_close(index_file);
}

void read_coordinates(char *name, float *x, float *y, int **con, int **isize)
{
        int                        index_file,irmin,irmax,istart,iend,nbndry,iparent_flag,iparentdata;
        int                        *ielem, counter;
        ElementType_t        itype;
        char                        sectionname[100];

        irmin = 1;
        irmax = isize[0][0];

        ielem = new int[isize[0][1]*3];

        cg_open(name,CG_MODE_READ,&index_file);
        cg_coord_read(index_file,1,1,"CoordinateX",RealSingle,&irmin,&irmax,x);
        cg_coord_read(index_file,1,1,"CoordinateY",RealSingle,&irmin,&irmax,y);

        cg_section_read(index_file,1,1,1,sectionname,&itype,&istart,&iend,&nbndry,&iparent_flag);
        cg_elements_read(index_file,1,1,1,&ielem[0],&iparentdata);

        counter = 0;
        for (int i = 0; i < isize[0][1]; i++)
        {
                for (int j = 0; j < 3; ++j)
                {
                        con[i][j] = ielem[counter];
                        counter += 1;
                }
        }

        cg_close(index_file);
}

int get_bc_num(char *name)
{
        int index_file,nbocos;

        cg_open(name,CG_MODE_READ,&index_file);
        cg_nbocos(index_file,1,1,&nbocos);
        cg_close(index_file);

        return nbocos-1;
}

int get_bc_ind_num(char *name, int ib)
{
        int                        index_file,nbocos;
        int                        normalindex[3],ndataset;
        char                        boconame[100];
        BCType_t                ibocotype;
        PointSetType_t        iptset;
        cgsize_t                npts,normallistflag;
        DataType_t                normaldatatype;

        cg_open(name,CG_MODE_READ,&index_file);
        cg_boco_info(index_file,1,1,ib,boconame,&ibocotype,
                  &iptset,&npts,normalindex,&normallistflag,&normaldatatype,&ndataset);
        cg_close(index_file);

        return npts;
}

void read_bc_conditions(char *name, int **bc)
{
        int                        index_file,nbocos,normallist;
        int                        normalindex[3],ndataset;
        char                        boconame[100];
        BCType_t                ibocotype;
        PointSetType_t        iptset;
        cgsize_t                npts,normallistflag;
        DataType_t                normaldatatype;
        cgsize_t                *ipnts;


        cg_open(name,CG_MODE_READ,&index_file);
        cg_nbocos(index_file,1,1,&nbocos);

        for (int ib = 2; ib <= nbocos; ib++)
        {
                cg_boco_info(index_file,1,1,ib,boconame,&ibocotype,
                  &iptset,&npts,normalindex,&normallistflag,&normaldatatype,&ndataset);

                ipnts    = new cgsize_t[npts];

                cg_boco_read(index_file,1,1,ib,ipnts,&normallist);
                for (int i=0; i < npts; i++)
                {
                        bc[ib-2][i] = ipnts[i];
                }

                delete ipnts;
        }

        cg_close(index_file);
}

note that normally you have a tree like structure in cgns, i.e. each cgns file can have bases under which are zones which then contain mesh coordinates and boundary conditions. think of it this way, if you have a moving mesh (which is remeshed at each timestep) then you would put each mesh for each timestep under one separate base. now each base in turn has zones, which for unstructured meshes are usually one, but if you have a structured mesh, you can have several blocks which would all sit under one zone. therefore, only under each zone you will find the coordinates and boudnary conditions. the above assumes you are using a single block (number of zones = 1) and no moving mesh (bases = 1) so that is why you will see most api calls starting with cg_function_name(index_file,1,1, ...) which basically means cg_function_name(index_file,index_base,index_zone, ...). also have a look at the api call references to check what you need to pass to functions and what parameter they require.

http://cgns.github.io/CGNS_docs_curr...vel/index.html

how as for the mesh above, get_mesh_sizes() will read the number of vertices and cells from a cgns file, read_coordinates() will read the arrays x and y holding the coordinates whereas ielem holds the lookup table to reconstruct the cells from the coordinates. i then rearrange it into the con array, which has dimensions of con[number_of_cells][number_of_vertices_per_element], here i use tri elements (3 vertices per element, therefore the 3). if you have more elements (tri, hexa ...), then you would need to inquire about them first (and you would probably also have two zones so you would need to get the number of zones as well, that all depends on the implementation from the mesh generator, see also below). get_bc_num() reads the number of boundary conditions and get_bc_ind_num() gives the number of elements making up that boundary (this function is called for each boundary condition). read_bc_conditions() reads the nodes which are on the boudnaries, note that i don't use ibocotype here but that would be the one to check which boundary condition to apply (in my case it was all walls so i didn't bother in this simple example).

the above worked for me when creating meshes with icem but i have to sat/stress at this point that a lot of people are contributing to cgns and everyone seems to have a different understanding of cgns. so for example, while the above was working for me using icem, i would be surprised if it would work out of the box for any other mesh generator. in fact, pointwise is interpreting the boudnaries to sit under the section and family nodes (which is permitted but confusing) and so if you wanted to have a general mesh reader, cgns will have a lot if case checking involved (i.e. which mesh generator was used and then tailoring the mesh reading part for them). similar things i noticed with reading solution files (based on cgns), while tecplot seems to have a proper understanding of cgns and implemented them will for what i can tell, paraview did a lousy job and you will only really be able to show the solution of a single file, good luck trying to get an animation with paraview, that has caused me several days/nights only to realise that it is not working/implemented in paraview ... but thats just a word of caution, overall i still use that format because, after all, if you know how it works, it is really powerful and can simplify things like mesh reading a lot

vidyadhar July 19, 2019 10:17

Hello Tom-Robin Teschner,


I have fluent case and data files read into Paraview. Now I have done some basic operations in paraview and left with certain part of the original domain.
I want this remaining part from paraview to be loaded into Fluent.
I am using save data option in paraview which saves in .cgns format.
But when I try to import this file, Fluent is giving errors and not reading the file.
I request your comments whether this is a correct procedure?


Thanks in advance!
vidyadhar

t.teschner July 19, 2019 20:13

Well if you would specify what "basic operations", "certain part" and "giving errors" means in your case maybe I can help but you have to be more specific. With the information given I can only assume that your file is not compliant with what fluent expects. Maybe paraview is not writing out the boundary conditions, or writing them as a family node and not a BC node... Several possibilities, the best chance you have is to compare the raw cgns file from fluent and paraview with cgnscheck or cgnsview (for that you have to download cgns and compile the library, this utilities will then be placed in the tools folder) and see the differences in the cgns tree

vidyadhar July 20, 2019 04:39

Hello Tom-Robin Teschner,
Thanks for the response.
1) I have exported Fluent solution data in Encase Gold Format and opened in Paraview. It displays "invalid VARIABLE line:SCRIPTS". But, I can perform all basic operations like clipping, iso-contours etc.
2) Even without performing any of the above "basic operations", I have done this in paraview: File --> Save Data --> .cgns file
But, when I try to import this cgns file into Fluent, it displays an error message saying "Error reading cgns file"
3) My intention was to CLIP vapor cells by a scalar of volumefraction=0.5 and save the data in cgns format, so that in Fluent I can read this and perform further simulations.
My queries: Whether saving data in CGNS format from paraview results in saving mesh&data at all the cells of the domain or only at the boundaries?


Thanks & Regards,
Vidyadhar


[Moderator note: Related thread: https://www.cfd-online.com/Forums/pa...tml#post736859 ]

t.teschner July 20, 2019 19:47

First off all, from your last answer I can see that your problem is not related to the original question. In the future, please open a new thread here on CFD online.
Secondly, how do you expect your work flow to work, if the simple import /export without any operations is not even working? Thirdly, I think what you are trying to achieve cannot be done in paraview (my best guess, anyways), paraview is only for visualisation. Sure, you can modify data and even export that, but how should fluent be able to interpret the new data you give it? Without having seen how paraview would export a clipping plane /iso contours etc. I would assume it will only export the locations with the value attached to it, not the whole mesh. I think what you need are user defined functions in fluent so that the solver knows what you want to do. If I were you I would consult the fluent forum here and see what that community would recommend.


All times are GMT -4. The time now is 04:09.