Commit 9088109a authored by Kirill Terekhov's avatar Kirill Terekhov
Browse files

Updates for XML file specification and handling

parent 811ced06
......@@ -64,57 +64,6 @@ The example of the layout of the file is presented below.
<ParallelMesh Number="2" [Layers="2" Element="Face"]>
<!-- Definition of the first mesh-->
<Mesh [Name="Box"] [RepairOrientation="False"]>
<!-- Describe data that is defined on the mesh -->
<!-- Number can be used to match
the number of entries and
optimize memory allocation -->
<Tags [Number="8"]>
<!-- See further text for description of each attribute -->
<Tag Name="GLOBAL_ID"
Size="1"
Type="Integer"
Sparse="Sets"
Definition="Cells,Faces,Nodes,Sets" />
<!-- Size is optional, default: Variable,
Type is optional, default: Real,
Sparsity is optional, default: None,
Name and Definition are mandatory -->
<Tag Name="PERMEABILITY_TENSOR"
[Size="6"]
[Type="Real" ]
[Sparse="None"]
Definition="Cells" />
<Tag Name="BOUNDARY_PRESSURE"
Size="1"
Type="Real"
Sparse="Faces"
Definition="Faces" />
<Tag Name="WELL_INDEX_WELL0"
Size="1"
Type="Real"
Sparse="Cells"
Definition="Cells" />
<Tag Name="BOUNDARY_DISPLACEMENT"
Size="3"
Type="Real"
Sparse="True"
Definition="Nodes" />
<Tag Name="CONNECTIONS"
Size="Variable"
Type="Reference"
Sparse="None"
Definition="Faces" />
<Tag Name="FLUX"
Size="1"
Type="Variable"
Sparse="None"
Definition="Faces" />
<Tag Name="WHATEVER"
Size="Variable"
Type="Bulk"
Sparse="Sets"
Definition="Sets" />
</Tags>
<!-- Define all the nodes of the mesh -->
<Nodes Number="100" [Dimension="3"]>
<![CDATA[
......@@ -202,6 +151,57 @@ The example of the layout of the file is presented below.
</Set>
<Set> ... </Set>
</Sets>
<!-- Describe data that is defined on the mesh -->
<!-- Number can be used to match
the number of entries and
optimize memory allocation -->
<Tags [Number="8"]>
<!-- See further text for description of each attribute -->
<Tag Name="GLOBAL_ID"
Size="1"
Type="Integer"
Sparse="Sets"
Definition="Cells,Faces,Nodes,Sets" />
<!-- Size is optional, default: Variable,
Type is optional, default: Real,
Sparsity is optional, default: None,
Name and Definition are mandatory -->
<Tag Name="PERMEABILITY_TENSOR"
[Size="6"]
[Type="Real" ]
[Sparse="None"]
Definition="Cells" />
<Tag Name="BOUNDARY_PRESSURE"
Size="1"
Type="Real"
Sparse="Faces"
Definition="Faces" />
<Tag Name="WELL_INDEX_WELL0"
Size="1"
Type="Real"
Sparse="Cells"
Definition="Cells" />
<Tag Name="BOUNDARY_DISPLACEMENT"
Size="3"
Type="Real"
Sparse="True"
Definition="Nodes" />
<Tag Name="CONNECTIONS"
Size="Variable"
Type="Reference"
Sparse="None"
Definition="Faces" />
<Tag Name="FLUX"
Size="1"
Type="Variable"
Sparse="None"
Definition="Faces" />
<Tag Name="WHATEVER"
Size="Variable"
Type="Bulk"
Sparse="Sets"
Definition="Sets" />
</Tags>
<!-- Define the data, the number of data sets should be equal to the number of tags -->
<Data Number="11">
<!-- TagName maps data set to the tag -->
......@@ -310,25 +310,20 @@ The example of the layout of the file is presented below.
The purpose of this XML tag is to optionally describe the number of meshes contained in the file in attribute "Number". As an additional information it can provide number of ghost layers between meshes in attribute "Layers" and the type of elements used to compute adjacency for ghost layers in attribute "Element". This information is reserved for the future use.
\section{Mesh}
This xml tag wraps all the data of the mesh. The optional attribute "Name" can be used to address elements of this mesh from another mesh. The optional attribute "RepairOrientation" if set to "True" will correct the orientation of the faces.
\section{Tags}
This xml tag declares the tags of the data that are present on the mesh. Optional attribute "Number" corresponds to the total number of tags defined.
\subsection{Tag}
Each xml tag contains attributes that describe the way the data is stored on the mesh. The following attributes can be defined:
\begin{itemize}
\item[Name] The name assigned to the data. Cannot be the same for two different tags. Mandatory to provide.
\item[Size] Number of records of the data on each element. Can be any positive number or "Variable". "Variable" means that the data may have different number of entries on each element. Optional, default: "Variable".
\item[Type] Type of the data that tag represents, can be either "Real" or "Integer" or "Bulk", or "Variable" or "Reference" or "RemoteReference". "Real" corresponds to floating numbers; "Integer" - to integral numbers; "Bulk" can represent any binary data; "Variable" can store a floating point value and corresponding variations represented by pairs of integral number and floating point coefficient; "Reference" and "RemoteReference" represent links to mesh elements or sets or mesh itself. Optional, default: "Real".
\item[Sparse] Defines that data is present only on some elements of the indicated element type. Can be either Sets or Cells or Faces or Edges or Nodes or None. Optional, default: None.
\item[Definition] Defines types of elements that posses the data. Can be Mesh, Sets, Cells, Faces, Edges or Nodes. Mandatory to provide.
\end{itemize}
The "GLOBAL\_ID" tag in the example defines a single integer entry on all the nodes, faces and cells, and on some sets. The "WHATEVER" tag defines a binary data of arbitrary size only to some sets. When one would like to have just a handful of entries unrelated to the mesh elements one can prescribe them to the mesh, i.e. write Definition="Mesh".
\section{Nodes}
This is a mandatory XML tag for the file that describes all the nodes of the mesh. The "Number" attribute describes the total number of nodes. Optional attribute "Dimension" tells the number of space dimensions, that is the number of coordinates in each entry, defaults to 3. The contents of the XML tag inside of "$<![CDATA[]]>$" can be entered in any format suitable to represent vectors as described in \S~\ref{data_format}. Nodes are mesh elements of dimension 0.
\section{Faces, Edges, Cells}
XML Tags Faces and Edges are optional and could be used to define only some of the elements of the mesh. For example one may introduce only boundary faces in XML tag Faces. The XML Tag Cells is mandatory and it represents cells of the mesh. One can optionally provide an optional attribute "Number" that will be used to check that the number of elements red is correct. Edges, faces and cells are mesh elements of dimension 1, 2 and 3 respectively.
\subsubsection{Connections}
XML tag "Connections" is used to provide the connection of each listed element to elements of lower dimension. Attributes are "Type" that describe types of listed elements; "Number" - total number of listed elements; "Offset" - optional attribute that describes first position of listed elements, default 0. It's required that the type of elements in "Type" has lower dimension than constructed element. It is possible to describe some cells constructed of nodes and some cells constructed of faces by using consecutive XML tags "Connections", see example for details.
XML tag "Connections" is used to provide the connection of each listed element to elements of lower dimension. Attributes are:
\begin{itemize}
\item[Type] Describe types of listed elements. It's required that the type of elements in "Type" has lower dimension than constructed element.
\item[Number] Total number of listed elements, mandatory.
\item[Offset] Optional attribute that describes first position of listed elements, default 0.
\item[Dimensions] This attribute is used to distinguish definition of 3D cells from 2D cells defined by nodes. Set to 2 to define 2D polygons and to 3 to define 3D volumetric cells, default 3.
\end{itemize}
It is possible to describe some cells constructed of nodes and some cells constructed of faces by using consecutive XML tags "Connections", see example for details.
The content of the XML tag inside of "$<![CDATA[]]>$" should start from the number of elements connected followed by a list of positions of elements. For example if we have a record $3 1 2 3$ for a face with connection to nodes then this record specifies that the face consists of 3 nodes namely node 1, node 2 and node 3. Enumeration of nodes here corresponds to the order of nodes in which their coordinates are listed in XML tag "Nodes".
\section{Sets}
......@@ -345,6 +340,19 @@ Describes each set. Sets could be arranged into an arbitrary tree, such as an oc
\item [Offset] Sets a shift in the enumeration of elements. Optional, default: 0.
\end{itemize}
In the contents of the XML tag "Set" inside of "$<![CDATA[]]>$" all the mesh elements are listed in whatever order is needed. They will be reordered internally if ordering was prescribed. The ordering happens after the mesh data is attached to the elements. Each element is listed as "type:position" where type can be either Mesh or Set or Cell or Face or Edge or Node. The position corresponds to the position in the order of elements in which their records are encountered in corresponding XML tags.
\section{Tags}
This xml tag declares the tags of the data that are present on the mesh. Optional attribute "Number" corresponds to the total number of tags defined.
\subsection{Tag}
Each xml tag contains attributes that describe the way the data is stored on the mesh. The following attributes can be defined:
\begin{itemize}
\item[Name] The name assigned to the data. Cannot be the same for two different tags. Mandatory to provide.
\item[Size] Number of records of the data on each element. Can be any positive number or "Variable". "Variable" means that the data may have different number of entries on each element. Optional, default: "Variable".
\item[Type] Type of the data that tag represents, can be either "Real" or "Integer" or "Bulk", or "Variable" or "Reference" or "RemoteReference". "Real" corresponds to floating numbers; "Integer" - to integral numbers; "Bulk" can represent any binary data; "Variable" can store a floating point value and corresponding variations represented by pairs of integral number and floating point coefficient; "Reference" and "RemoteReference" represent links to mesh elements or sets or mesh itself. Optional, default: "Real".
\item[Sparse] Defines that data is present only on some elements of the indicated element type. Can be either Sets or Cells or Faces or Edges or Nodes or None. Optional, default: None.
\item[Definition] Defines types of elements that posses the data. Can be Mesh, Sets, Cells, Faces, Edges or Nodes. Mandatory to provide.
\end{itemize}
The "GLOBAL\_ID" tag in the example defines a single integer entry on all the nodes, faces and cells, and on some sets. The "WHATEVER" tag defines a binary data of arbitrary size only to some sets. When one would like to have just a handful of entries unrelated to the mesh elements one can prescribe them to the mesh, i.e. write Definition="Mesh".
\section{Data}
Encloses all the data of the mesh. Optional attribute "Number" can be added to control the number of "DataSet" XML tags encountered.
\subsection{DataSet} \label{tag_dataset}
......
......@@ -40,91 +40,6 @@ namespace INMOST
else reader.Report("Unused attribute for Tags %s='%s'",attr.name.c_str(),attr.value.c_str());
}
{ //Tags
XMLReader::XMLTag TagTags = reader.OpenTag();
if( TagTags.name != "Tags" )
{
reader.Report("Incorrect XML tag %s expected Tags",TagTags.name.c_str());
throw BadFile;
}
int ntags = 0;
bool matchntags = false;
for(int q = 0; q < TagTags.NumAttrib(); ++q)
{
XMLReader::XMLAttrib & attr = TagTags.GetAttib(q);
if( attr.name == "Number" )
{
ntags = atoi(attr.value.c_str());
matchntags = true;
}
else reader.Report("Unused attribute for Tags %s='%s'",attr.name.c_str(),attr.value.c_str());
}
tags.reserve(ntags);
XMLReader::XMLTag TagTag;
for(TagTag = reader.OpenTag(); !TagTag.Finalize() && TagTag.name == "Tag"; reader.CloseTag(TagTag), TagTag = reader.OpenTag())
{
std::vector<std::string> parsed;
std::string tagname = "";
enumerator size = ENUMUNDEF;
DataType type = DATA_REAL;
ElementType sparse = NONE;
ElementType defined = NONE;
for(int q = 0; q < TagTag.NumAttrib(); ++q)
{
XMLReader::XMLAttrib & attr = TagTag.GetAttib(q);
if( attr.name == "Name" ) tagname = attr.value;
else if( attr.name == "Size" )
{
if( attr.value == "Variable" )
size = ENUMUNDEF;
else size = atoi(attr.value.c_str());
}
else if( attr.name == "Type" )
{
if( attr.value == "Real" ) type = DATA_REAL;
else if( attr.value == "Integer" ) type = DATA_INTEGER;
else if( attr.value == "Reference" ) type = DATA_REFERENCE;
else if( attr.value == "RemoteReference" ) type = DATA_REMOTE_REFERENCE;
else if( attr.value == "Bulk" ) type = DATA_BULK;
#if defined(USE_AUTODIFF)
else if( attr.value == "Variable" ) type = DATA_VARIABLE;
#endif
}
else if( attr.name == "Sparse" )
{
reader.ParseCommaSeparated(attr.value,parsed);
for(int q = 0; q < (int)parsed.size(); ++q) sparse |= reader.atoes(parsed[q].c_str());
}
else if( attr.name == "Definition" )
{
reader.ParseCommaSeparated(attr.value,parsed);
for(int q = 0; q < (int)parsed.size(); ++q) defined |= reader.atoes(parsed[q].c_str());
}
else reader.Report("Unused attribute for Tags %s='%s'",attr.name.c_str(),attr.value.c_str());
}
if( tagname == "" )
reader.Report("Tag name was not specified");
else if( defined == NONE )
reader.Report("Domain of definition for the tag was not specified");
tags.push_back(CreateTag(tagname,type,defined,sparse,size));
}
reader.CloseTag(TagTags);
if( !TagTag.Finalize() )
{
PassTag = TagTag;
pass_tag = true;
}
if( matchntags && ntags != tags.size() ) reader.Report("Number %d of XML tags Tag red do not match to the specified number %d",tags.size(),ntags);
}
{ //Nodes
int nnodes = 0, ndims = 3;
XMLReader::XMLTag TagNodes;
......@@ -267,11 +182,13 @@ namespace INMOST
{
int nconns = 0;
int offset = 0;
int dims = 3; //to distinguish 3d cells from 2d cells when they are created with nodes
ElementType subtype = NODE;
for(int q = 0; q < TagConns.NumAttrib(); ++q)
{
XMLReader::XMLAttrib & attr = TagConns.GetAttib(q);
if( attr.name == "Number" ) nconns = atoi(attr.value.c_str());
else if( attr.name == "Dimensions" ) dims = atoi(attr.value.c_str());
else if( attr.name == "Type" ) subtype = reader.atoes(attr.value.c_str());
else if( attr.name == "Offset" ) offset = atoi(attr.value.c_str());
else reader.Report("Unused attribute for %ss %s='%s'",TagConns.name.c_str(),attr.name.c_str(),attr.value.c_str());
......@@ -304,48 +221,77 @@ namespace INMOST
break;
case FACE:
if( subtype == NODE )
elems->push_back(CreateFace(subarr.Convert<Node>()).first.GetHandle());
{
Face f = CreateFace(subarr.Convert<Node>()).first;
if( repair_orientation ) f.FixEdgeOrder();
elems->push_back(f.GetHandle());
}
else if( subtype == EDGE )
elems->push_back(CreateFace(subarr.Convert<Edge>()).first.GetHandle());
{
Face f = CreateFace(subarr.Convert<Node>()).first;
if( repair_orientation ) f.FixEdgeOrder();
elems->push_back(f.GetHandle());
}
break;
case CELL:
if( subtype == NODE )
{
switch(subarr.size())
{
case 4: //Tetrahedron
{
const integer nodesnum[12] = {0,2,1,0,1,3,1,2,3,0,3,2};
const integer sizes[4] = {3,3,3,3};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,4).first.GetHandle());
}
break;
case 5: //Pyramid
{
const integer nodesnum[16] = {0,4,3,0,1,4,1,2,4,3,4,2,0,3,2,1};
const integer sizes[5] = {3,3,3,3,4};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,5).first.GetHandle());
}
break;
case 6: //Wedge or Prism
{
const integer nodesnum[18] = {0,2,5,3,1,4,5,2,0,3,4,1,3,5,4,0,1,2};
const integer sizes[5] = {4,4,4,3,3};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,5).first.GetHandle());
}
break;
case 8: //Hexahedron
{
const integer nodesnum[24] = {0,4,7,3,1,2,6,5,0,1,5,4,3,7,6,2,0,3,2,1,4,5,6,7};
const integer sizes[6] = {4,4,4,4,4,4};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,6).first.GetHandle());
}
break;
default:
reader.Report("Sorry, no rule to convert %d nodes into a cell",subarr.size());
throw BadFile;
break;
}
if( dims == 3 )
{
switch(subarr.size())
{
case 4: //Tetrahedron
{
const integer nodesnum[12] = {0,2,1,0,1,3,1,2,3,0,3,2};
const integer sizes[4] = {3,3,3,3};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,4).first.GetHandle());
}
break;
case 5: //Pyramid
{
const integer nodesnum[16] = {0,4,3,0,1,4,1,2,4,3,4,2,0,3,2,1};
const integer sizes[5] = {3,3,3,3,4};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,5).first.GetHandle());
}
break;
case 6: //Wedge or Prism
{
const integer nodesnum[18] = {0,2,5,3,1,4,5,2,0,3,4,1,3,5,4,0,1,2};
const integer sizes[5] = {4,4,4,3,3};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,5).first.GetHandle());
}
break;
case 8: //Hexahedron
{
const integer nodesnum[24] = {0,4,7,3,1,2,6,5,0,1,5,4,3,7,6,2,0,3,2,1,4,5,6,7};
const integer sizes[6] = {4,4,4,4,4,4};
elems->push_back(CreateCell(subarr.Convert<Node>(),nodesnum,sizes,6).first.GetHandle());
}
break;
default:
reader.Report("Sorry, no rule to convert %d nodes into a cell",subarr.size());
throw BadFile;
break;
}
}
else if( dims == 2 )
{
ElementArray<Node> e_nodes(this,1);
ElementArray<Edge> f_edges(this,2);
ElementArray<Face> c_faces;
for(unsigned int k = 0; k < subarr.size(); k++)
{
e_nodes.at(0) = subarr.at(k);
f_edges.at(0) = CreateEdge(e_nodes).first->GetHandle();
e_nodes.at(0) = subarr.at((k+1)%subarr.size());
f_edges.at(1) = CreateEdge(e_nodes).first->GetHandle();
c_faces.push_back(CreateFace(f_edges).first);
}
Cell c = CreateCell(c_faces).first;
if( repair_orientation ) c.FixEdgeOrder();
elems->push_back(c.GetHandle());
}
else reader.Report("Sorry, cannot understand number of dimensions %d for a cell",dims);
}
else if( subtype == EDGE )
{
......@@ -385,7 +331,84 @@ namespace INMOST
}
else TagSetsData = reader.OpenTag();
if( TagSetsData.name == "Sets" )
if( TagSetsData.name == "Tags" )
{
repeat = true;
int ntags = 0;
bool matchntags = false;
for(int q = 0; q < TagSetsData.NumAttrib(); ++q)
{
XMLReader::XMLAttrib & attr = TagSetsData.GetAttib(q);
if( attr.name == "Number" )
{
ntags = atoi(attr.value.c_str());
matchntags = true;
}
else reader.Report("Unused attribute for Tags %s='%s'",attr.name.c_str(),attr.value.c_str());
}
tags.reserve(ntags);
XMLReader::XMLTag TagTag;
for(TagTag = reader.OpenTag(); !TagTag.Finalize() && TagTag.name == "Tag"; reader.CloseTag(TagTag), TagTag = reader.OpenTag())
{
std::vector<std::string> parsed;
std::string tagname = "";
enumerator size = ENUMUNDEF;
DataType type = DATA_REAL;
ElementType sparse = NONE;
ElementType defined = NONE;
for(int q = 0; q < TagTag.NumAttrib(); ++q)
{
XMLReader::XMLAttrib & attr = TagTag.GetAttib(q);
if( attr.name == "Name" ) tagname = attr.value;
else if( attr.name == "Size" )
{
if( attr.value == "Variable" )
size = ENUMUNDEF;
else size = atoi(attr.value.c_str());
}
else if( attr.name == "Type" )
{
if( attr.value == "Real" ) type = DATA_REAL;
else if( attr.value == "Integer" ) type = DATA_INTEGER;
else if( attr.value == "Reference" ) type = DATA_REFERENCE;
else if( attr.value == "RemoteReference" ) type = DATA_REMOTE_REFERENCE;
else if( attr.value == "Bulk" ) type = DATA_BULK;
#if defined(USE_AUTODIFF)
else if( attr.value == "Variable" ) type = DATA_VARIABLE;
#endif
}
else if( attr.name == "Sparse" )
{
reader.ParseCommaSeparated(attr.value,parsed);
for(int q = 0; q < (int)parsed.size(); ++q) sparse |= reader.atoes(parsed[q].c_str());
}
else if( attr.name == "Definition" )
{
reader.ParseCommaSeparated(attr.value,parsed);
for(int q = 0; q < (int)parsed.size(); ++q) defined |= reader.atoes(parsed[q].c_str());
}
else reader.Report("Unused attribute for Tags %s='%s'",attr.name.c_str(),attr.value.c_str());
}
if( tagname == "" )
reader.Report("Tag name was not specified");
else if( defined == NONE )
reader.Report("Domain of definition for the tag was not specified");
tags.push_back(CreateTag(tagname,type,defined,sparse,size));
}
reader.CloseTag(TagSetsData);
if( !TagTag.Finalize() )
{
PassTag = TagTag;
pass_tag = true;
}
if( matchntags && ntags != tags.size() ) reader.Report("Number %d of XML tags Tag red do not match to the specified number %d",tags.size(),ntags);
}
else if( TagSetsData.name == "Sets" )
{
repeat = true;
HandleType * links[4] =
......@@ -836,9 +859,11 @@ namespace INMOST
pass_tag = true;
}
}
else if( TagSetsData.name == "" )
repeat = false;
else
{
reader.Report("Unexpected tag %s, expected Sets or Data",TagSetsData.name.c_str());
reader.Report("Unexpected tag %s, expected Tags or Sets or Data",TagSetsData.name.c_str());
throw BadFile;
}
} while(repeat);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment