Commit 50d10e74 authored by Kirill Terekhov's avatar Kirill Terekhov

Added functionality and fixed issues.

Fixes for GCC.

Moved functionality to operate with dense matrices as INMOST service.

Added possibility to exchange data of type DATA_VARIABLE in parallel.

Added possibility to include external content in xml format.

Moved overloaded operators for variables from namespace INMOST into
global scope to prevent possible ambiguities in compilers.

Added perturbation algorithm for BCGS solver.
parent d03993fe
......@@ -240,6 +240,7 @@ set(INMOST_INSTALL_HEADERS Source/Headers/inmost.h
Source/Headers/inmost_autodiff.h
Source/Headers/inmost_common.h
Source/Headers/inmost_data.h
Source/Headers/inmost_dense.h
Source/Headers/inmost_expression.h
Source/Headers/inmost_mesh.h
Source/Headers/inmost_nonlinear.h
......@@ -268,6 +269,7 @@ set_property(TARGET inmost PROPERTY PUBLIC_HEADER
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_autodiff.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_common.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_data.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_dense.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_expression.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_mesh.h"
"${PROJECT_SOURCE_DIR}/Source/Headers/inmost_nonlinear.h"
......
project(ADMFD)
set(SOURCE main.cpp matrix.hpp)
set(SOURCE main.cpp)
add_executable(ADMFD ${SOURCE})
......
......@@ -4,7 +4,6 @@
#include <string.h>
#include "inmost.h"
#include "matrix.hpp"
using namespace INMOST;
#ifndef M_PI
......@@ -184,8 +183,8 @@ int main(int argc,char ** argv)
rMatrix nKL(3,1); //normal to face
rMatrix lKs(3,1); //reminder of the co-normal vector Kn in cell K when projection to normal is substracted, i.e. (Kn - n n.Kn)
rMatrix lLs(3,1); //reminder of the co-normal vector Kn in cell L when projection to normal is substracted, i.e. (Kn - n n.Kn)
rMatrix KK = FromTensor(cK->RealArray(tag_K)).Transpose(); //diffusion tensor in cell K
rMatrix KL = FromTensor(cL->RealArray(tag_K)).Transpose(); //diffusion tensor in cell L
rMatrix KK = rMatrix::FromTensor(cK->RealArray(tag_K).data(),cK->RealArray(tag_K).size()).Transpose(); //diffusion tensor in cell K
rMatrix KL = rMatrix::FromTensor(cL->RealArray(tag_K).data(),cL->RealArray(tag_K).size()).Transpose(); //diffusion tensor in cell L
cK->Centroid(xK.data()); //retrive center of cell K
cL->Centroid(xL.data()); //retrive center of cell L
......@@ -237,7 +236,7 @@ int main(int argc,char ** argv)
real aF, vP = cell->Volume(); //area of the face
cell->Centroid(xP); //obtain cell center
ElementArray<Face> faces = cell->getFaces(); //obtain faces of the cell
enumerator NF = faces.size(), k; //number of faces;
enumerator NF = (enumerator)faces.size(), k; //number of faces;
rMatrix IP(NF,NF), N(NF,3), R(NF,3); //matrices for inner product
......@@ -261,8 +260,8 @@ int main(int argc,char ** argv)
} //end of loop over faces
//inner product definition from Corollary 4.2, "Mimetic scalar products of differential forms" by Brezzi et al
IP = R*(R.Transpose()*N).Invert()*R.Transpose(); // Consistency part
IP += (rMatrix::Unit(NF) - N*(N.Transpose()*N).Invert()*N.Transpose())*(2.0/static_cast<real>(NF)*IP.Trace()); //Stability part
IP = R*(R.Transpose()*N).Invert().first*R.Transpose(); // Consistency part
IP += (rMatrix::Unit(NF) - N*(N.Transpose()*N).Invert().first*N.Transpose())*(2.0/static_cast<real>(NF)*IP.Trace()); //Stability part
//assert(IP.isSymmetric()); //test positive definitiness as well!
/*
......@@ -288,9 +287,9 @@ int main(int argc,char ** argv)
real nF[3]; //normal to the face
cell->Centroid(xP);
ElementArray<Face> faces = cell->getFaces(); //obtain faces of the cell
enumerator NF = faces.size(), k; //number of faces;
enumerator NF = (enumerator)faces.size(), k; //number of faces;
dynarray<real,64> NG(NF,0), G(NF,0); // count how many times gradient was calculated for face
rMatrix K = FromTensor(cell->RealArrayDF(tag_K)); //get permeability for the cell
rMatrix K = rMatrix::FromTensor(cell->RealArrayDF(tag_K).data(),cell->RealArrayDF(tag_K).size()); //get permeability for the cell
rMatrix GRAD(NF,NF), NK(NF,3), R(NF,3); //big gradient matrix, co-normals, directions
rMatrix GRADF(NF,NF), NKF(NF,3), RF(NF,3); //corresponding matrices with masked negative values when multiplied by individual co-normals
rMatrix GRADFstab(NF,NF);
......@@ -305,18 +304,18 @@ int main(int argc,char ** argv)
R(k,1) = (yF[1]-xP[1]);
R(k,2) = (yF[2]-xP[2]);
// assemble matrix of co-normals
rMatrix nK = FromVector(nF).Transpose()*K;
rMatrix nK = rMatrix::FromVector(nF,3).Transpose()*K;
NK(k,0) = nK(0,0);
NK(k,1) = nK(0,1);
NK(k,2) = nK(0,2);
k++;
} //end of loop over faces
GRAD = NK*(NK.Transpose()*R).Invert()*NK.Transpose(); //stability part
GRAD = NK*(NK.Transpose()*R).Invert().first*NK.Transpose(); //stability part
//std::cout << "consistency" << std::endl;
//GRADF.Print();
GRAD += (rMatrix::Unit(NF) - R*(R.Transpose()*R).Invert()*R.Transpose())*(2.0/NF*GRADF.Trace());
GRAD += (rMatrix::Unit(NF) - R*(R.Transpose()*R).Invert().first*R.Transpose())*(2.0/NF*GRADF.Trace());
/*
std::cout << "stability" << std::endl;
......@@ -400,7 +399,7 @@ int main(int argc,char ** argv)
for(Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell)
{
ElementArray<Face> faces = cell->getFaces(); //obtain faces of the cell
enumerator NF = faces.size(), k = 0;
enumerator NF = (enumerator)faces.size(), k = 0;
Cell cK = cell->self();
real gK = cK->Real(tag_F0), gL; //force on current cell and on adjacent cell
rMatrix M(cK->RealArrayDF(tag_M).data(),NF,NF); //inner product matrix
......@@ -475,7 +474,7 @@ int main(int argc,char ** argv)
for(Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell) //loop over cells
{
ElementArray<Face> faces = cell->getFaces(); //obtain faces of the cell
enumerator NF = faces.size(), k = 0;
enumerator NF = (enumerator)faces.size(), k = 0;
Cell cK = cell->self();
variable pK = P(cK), pL; //pressure for back and front cells
rMatrix GRAD(cK->RealArrayDV(tag_W).data(),NF,NF); //Matrix for gradient
......@@ -509,7 +508,7 @@ int main(int argc,char ** argv)
for(Mesh::iteratorCell cell = m->BeginCell(); cell != m->EndCell(); ++cell) //loop over cells
{
ElementArray<Face> facesK = cell->getFaces(), facesL; //obtain faces of the cell
enumerator NF = facesK.size(), k, l;
enumerator NF = (enumerator)facesK.size(), k, l;
Cell cK = cell->self();
variable pK = P(cK), pL; //pressure for back and front cells
rMatrix GRAD(cK->RealArrayDV(tag_W).data(),NF,NF); //Matrix for gradient
......
This diff is collapsed.
......@@ -201,15 +201,16 @@ namespace INMOST
INMOST_DATA_REAL_TYPE Automatizator::Derivative(expr & var, const Storage & e, Sparse::Row & out, Storage::real multiply, void * user_data)
{
Sparse::RowMerger & m = GetMerger();
INMOST_DATA_REAL_TYPE ret;
var.current_stencil.resize(1);
var.current_stencil[0] = stencil_pair(e->GetHandle(),1.0);
var.resize_for_stencil();
ret = EvaluateSub(var,0,ENUMUNDEF,user_data);
merger.PushRow(1.0,out);
DerivativeFill(var, 0, ENUMUNDEF, merger, multiply, user_data);
merger.RetriveRow(out);
merger.Clear();
m.PushRow(1.0,out);
DerivativeFill(var, 0, ENUMUNDEF, m, multiply, user_data);
m.RetriveRow(out);
m.Clear();
return ret*multiply;
}
#else
......
......@@ -11,7 +11,9 @@ namespace INMOST
case DATA_INTEGER: return "INTEGER";
case DATA_BULK: return "BULK";
case DATA_REFERENCE: return "REFERENCE";
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: return "VARIABLE";
#endif
}
return "UNKNOWN";
}
......@@ -25,7 +27,9 @@ namespace INMOST
case DATA_INTEGER: return sizeof(INMOST_DATA_INTEGER_TYPE);
case DATA_REAL: return sizeof(INMOST_DATA_REAL_TYPE);
case DATA_REFERENCE: return sizeof(HandleType);
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: return sizeof(variable);
#endif
}
return 0;
}
......@@ -39,7 +43,9 @@ namespace INMOST
case DATA_INTEGER: return sizeof(inner_integer_array);
case DATA_BULK: return sizeof(inner_bulk_array);
case DATA_REFERENCE: return sizeof(inner_reference_array);
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: return sizeof(inner_variable_array);
#endif
}
return 0;
}
......@@ -73,13 +79,17 @@ namespace INMOST
else if( type == DATA_INTEGER ) new (adata) inner_integer_array (*static_cast<const inner_integer_array * >(bdata));
else if( type == DATA_BULK ) new (adata) inner_bulk_array (*static_cast<const inner_bulk_array * >(bdata));
else if( type == DATA_REFERENCE ) new (adata) inner_reference_array(*static_cast<const inner_reference_array * >(bdata));
#if defined(USE_AUTODIFF)
else if( type == DATA_VARIABLE ) new (adata) inner_variable_array (*static_cast<const inner_variable_array * >(bdata));
#endif
}
#if defined(USE_AUTODIFF)
else if( type == DATA_VARIABLE ) //have to call constructor
{
for(INMOST_DATA_ENUM_TYPE k = 0; k < data_size; ++k)
new (static_cast<variable *>(adata)+k) variable(*(static_cast<const variable *>(bdata)+k));
}
#endif
else // fixed size array
memcpy(adata,bdata,data_size*bytes);
}
......@@ -109,11 +119,13 @@ namespace INMOST
(*static_cast<inner_reference_array *> (adata)).~inner_reference_array();
new (adata) inner_reference_array();
}
#if defined(USE_AUTODIFF)
else if( type == DATA_VARIABLE )
{
(*static_cast<inner_variable_array *> (adata)).~inner_variable_array();
new (adata) inner_variable_array();
}
#endif
}
}
......@@ -177,7 +189,12 @@ namespace INMOST
case DATA_REAL: mem->bulk_data_type = INMOST_MPI_DATA_REAL_TYPE; break;
case DATA_INTEGER: mem->bulk_data_type = INMOST_MPI_DATA_INTEGER_TYPE; break;
case DATA_REFERENCE: mem->bulk_data_type = INMOST_MPI_DATA_ENUM_TYPE; break;
case DATA_VARIABLE: mem->bulk_data_type = INMOST_MPI_DATA_REAL_TYPE; break; //mixture of types, should not get here
#if defined(USE_AUTODIFF)
case DATA_VARIABLE:
if( !Sparse::HaveRowEntryType() ) Sparse::CreateRowEntryType();
mem->bulk_data_type = Sparse::GetRowEntryType();
break;
#endif
}
mem->bytes_size = DataTypeBytesSize(mem->dtype);
if(mem->size == ENUMUNDEF )
......@@ -481,7 +498,9 @@ namespace INMOST
case DATA_INTEGER: for(INMOST_DATA_ENUM_TYPE it = new_size; it < old_size; ++it) {void * p = static_cast<void *>(&arr[it]); if( p != NULL ) (*static_cast<inner_integer_array *>( p )).~inner_integer_array(); } break;
case DATA_BULK: for(INMOST_DATA_ENUM_TYPE it = new_size; it < old_size; ++it) {void * p = static_cast<void *>(&arr[it]); if( p != NULL ) (*static_cast<inner_bulk_array *>( p )).~inner_bulk_array(); } break;
case DATA_REFERENCE: for(INMOST_DATA_ENUM_TYPE it = new_size; it < old_size; ++it) {void * p = static_cast<void *>(&arr[it]); if( p != NULL ) (*static_cast<inner_reference_array *>( p )).~inner_reference_array();} break;
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: for(INMOST_DATA_ENUM_TYPE it = new_size; it < old_size; ++it) {void * p = static_cast<void *>(&arr[it]); if( p != NULL ) (*static_cast<inner_variable_array *>( p )).~inner_variable_array(); } break;
#endif
}
}
}
......@@ -499,7 +518,9 @@ namespace INMOST
case DATA_INTEGER: for(INMOST_DATA_ENUM_TYPE it = old_size; it < new_size; ++it) new ( &arr[it] ) inner_integer_array(); break;
case DATA_BULK: for(INMOST_DATA_ENUM_TYPE it = old_size; it < new_size; ++it) new ( &arr[it] ) inner_bulk_array(); break;
case DATA_REFERENCE: for(INMOST_DATA_ENUM_TYPE it = old_size; it < new_size; ++it) new ( &arr[it] ) inner_reference_array(); break;
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: for(INMOST_DATA_ENUM_TYPE it = old_size; it < new_size; ++it) new ( &arr[it] ) inner_variable_array(); break;
#endif
}
}
}
......
......@@ -9,6 +9,7 @@ set(HEADER
${CMAKE_CURRENT_SOURCE_DIR}/inmost_options_cmake.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_common.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_data.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_dense.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_mesh.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_solver.h
${CMAKE_CURRENT_SOURCE_DIR}/inmost_partitioner.h
......
......@@ -4,6 +4,7 @@
#include "inmost_common.h"
#include "inmost_mesh.h"
#include "inmost_dense.h"
#include "inmost_solver.h"
#include "inmost_partitioner.h"
#include "inmost_variable.h"
......
This diff is collapsed.
......@@ -99,7 +99,9 @@
#if defined(USE_OMP)
#include <omp.h>
#endif
#if defined(USE_MPI)
#include <mpi.h>
#endif
#if !defined(USE_MPI)
#define INMOST_MPI_Request int
......@@ -111,6 +113,7 @@
#define INMOST_MPI_DOUBLE 0
#define INMOST_MPI_UNSIGNED 0
#define INMOST_MPI_Win int
#define INMOST_MPI_DATATYPE_NULL 0
#else
#define INMOST_MPI_Request MPI_Request
#define INMOST_MPI_Type MPI_Datatype
......@@ -121,8 +124,10 @@
#define INMOST_MPI_DOUBLE MPI_DOUBLE
#define INMOST_MPI_UNSIGNED MPI_UNSIGNED
#define INMOST_MPI_Win MPI_Win
#define INMOST_MPI_DATATYPE_NULL MPI_DATATYPE_NULL
#endif
#define INMOST_MPI_SIZE int //in case MPI standard changes and compiler gives tons of warning
#define INMOST_DATA_INTEGER_TYPE int
......
......@@ -435,12 +435,21 @@ namespace INMOST
/// Return the data length associated with Tag.
/// For abstract data return the number of bytes, otherwise return the length of associated array.
/// @param tag tag that represents the data
/// @see Storage::SetDataSize
/// @see Mesh::GetDataSize
__INLINE INMOST_DATA_ENUM_TYPE GetDataSize (const Tag & tag) const;
/// Return the size of the structure required to represent the data on current element.
/// This is equal to GetDataSize times Tag::GetBytesSize for all the data types,
/// except for DATA_VARIABLE, that requires a larger structure to accomodate derivatives.
/// @param tag tag that represents the data
/// @see Mesh::GetDataCapacity
__INLINE INMOST_DATA_ENUM_TYPE GetDataCapacity (const Tag & tag) const;
/// Set the length of data associated with Tag.
/// @param tag Identifying Tag.
/// @param new_size The number of bytes for abstract data, otherwise the length of the array.
/// @see Storage::GetDataSize
/// @see Mesh::SetDataSize
__INLINE void SetDataSize (const Tag & tag,
INMOST_DATA_ENUM_TYPE new_size) const;
/// Extract part of the data associated with Tag.
......
This diff is collapsed.
This diff is collapsed.
......@@ -1851,8 +1851,14 @@ namespace INMOST
/// For constant size array returns the same value that may be obtained through GetSize.
/// @param h handle of element
/// @param tag tag that represents the data
/// @see Mesh::GetSize
/// @see Tag::GetSize
INMOST_DATA_ENUM_TYPE GetDataSize (HandleType h,const Tag & tag) const; //For DATA_BULK return number of bytes, otherwise return the length of array
/// Return the size of the structure required to represent the data on current element.
/// This is equal to GetDataSize times Tag::GetBytesSize for all the data types,
/// except for DATA_VARIABLE, that requires a larger structure to accomodate derivatives.
/// @param h handle of element
/// @param tag tag that represents the data
INMOST_DATA_ENUM_TYPE GetDataCapacity (HandleType h,const Tag & tag) const;
/// Sets the size of the array for data of variable size.
/// If you try to change size of data of constant size then if size is
/// different from current then in debug mode (NDEBUG not set) assertion will fail,
......@@ -2845,6 +2851,7 @@ namespace INMOST
bool remember[5][3];
private:
void RestoreGeometricTags();
void RepairGeometricTags();
bool HideGeometricData (GeometricData type, ElementType mask) {return remember[type][ElementNum(mask)-1] = false;}
bool ShowGeometricData (GeometricData type, ElementType mask) {return remember[type][ElementNum(mask)-1] = true;}
public:
......@@ -3217,6 +3224,10 @@ namespace INMOST
{
return GetMeshLink()->GetDataSize(GetHandle(),tag);
}
__INLINE INMOST_DATA_ENUM_TYPE Storage::GetDataCapacity(const Tag & tag) const
{
return GetMeshLink()->GetDataCapacity(GetHandle(),tag);
}
__INLINE void Storage::SetDataSize(const Tag & tag,INMOST_DATA_ENUM_TYPE new_size) const
{
GetMeshLink()->SetDataSize(GetHandle(),tag,new_size);
......
......@@ -58,7 +58,7 @@ namespace INMOST
};
static std::string TypeName(Type t);
static INMOST_MPI_Type & GetRowEntryType() {return RowEntryType;}
//solver.cpp::::::::::::::::::::::::::::::::::::::::::::::::::::
public:
......@@ -347,7 +347,6 @@ namespace INMOST
static void Finalize();
static bool isInitialized() {return is_initialized;}
static bool isFinalized() {return is_finalized;}
/// Clear all internal data of the current solver including matrix, preconditioner etc.
void Clear();
};
......
......@@ -14,6 +14,11 @@ namespace INMOST
{
namespace Sparse
{
INMOST_MPI_Type GetRowEntryType();
void CreateRowEntryType();
void DestroyRowEntryType();
bool HaveRowEntryType();
/// Distributed vector class.
/// This class can be used to store both local and distributed dense data of real type.
/// For example, to form the right-hand side or initial guess to the solution.
......
This diff is collapsed.
......@@ -261,7 +261,7 @@ class XMLReader
};
Interpreter intrp;
std::string src;
std::istream & inp;
std::vector<std::istream *> inp;
int linebreak, linechar;
int hadlinebreak, hadlinechar;
int verbose;
......@@ -295,13 +295,14 @@ class XMLReader
EndOfFile, // end of file reached
Failure //unexpected error
} _state;
std::istream & get_stream() {return *inp.back();}
//should not share the reference to the stream with another reader
XMLReader(const XMLReader & other) :src(other.src), inp(other.inp) {}
XMLReader(const XMLReader & other) {}
XMLReader & operator =(XMLReader & other) {return *this;}
char GetChar()
{
char c = '\0';
inp.get(c);
get_stream().get(c);
hadlinebreak = linebreak;
hadlinechar = linechar;
if( c == '\n' )
......@@ -318,8 +319,8 @@ class XMLReader
{
linebreak = hadlinebreak;
linechar = hadlinechar;
inp.unget();
if( inp.fail() )
get_stream().unget();
if( get_stream().fail() )
{
Report("Stream failed while ungetting the char");
_state = Failure;
......@@ -417,7 +418,14 @@ public:
}
std::cout << std::endl;
}
XMLReader(std::string sourcename, std::istream & input) :intrp(),src(sourcename),inp(input),linebreak(0),linechar(0),_state(Intro){verbose = 0;}
XMLReader(std::string sourcename, std::istream & input) :intrp(),src(sourcename),linebreak(0),linechar(0),_state(Intro){inp.push_back(&input); verbose = 0;}
void PushStream(std::istream & stream) {inp.push_back(&stream);}
void PopStream()
{
inp.pop_back();
if( _state == EndOfFile && !inp.empty() )
_state = Intro;
}
//read in <TagName returns TagName
std::string ReadOpenTag()
{
......@@ -499,7 +507,7 @@ public:
return ret;
}
//read > or /> skipping for attributes
bool ReadCloseTag()
int ReadCloseTag()
{
char tmp[2];
tmp[0] = GetChar();
......@@ -507,7 +515,7 @@ public:
{
_state = Intro;
if( verbose ) Report("info: closed tag");
return true;
return 1; //tag was finished with >
}
else if( tmp[0] == '/' ) //close single stage tag
{
......@@ -516,13 +524,13 @@ public:
{
_state = Intro;
if( verbose ) Report("info: closed tag");
return true;
return 2; //tag was halted with />
}
Report("Encountered '%c%c' while expecting '/>' for tag closing",tmp[0],tmp[1]);
}
Report("Encountered '%c' while expecting '>' for tag closing",tmp[0]);
_state = Failure;
return false;
return 0;
}
bool isTagFinish() {return _state == ReadCloseTagSlash;}
//read </TagName> or fail
......@@ -839,8 +847,7 @@ public:
{
if( ret[ret.size()-2] == ']' && ret[ret.size()-1] == ']' )
{
ret.pop_back();
ret.pop_back();
ret.resize(ret.size()-2);
RetChar(); //return '>'
_state = EndContents;
break;
......@@ -896,13 +903,13 @@ public:
case ReadContentsMultiplier:
if( isspace(c) )
{
if( ret.back() != '*' ) //maybe user have put a space after the multiplier
if( ret[ret.size()-1] != '*' ) //maybe user have put a space after the multiplier
{
done = true;
_state = WaitContents;
}
}
else if( c == '(' && ret.back() == '*' ) //expression for the skope
else if( c == '(' && ret[ret.size()-1] == '*' ) //expression for the skope
{
ret.push_back(c);
_state = ReadContentsMultiplierSkopes;
......@@ -921,9 +928,9 @@ public:
case ReadContentsQuotes:
if( c == '"' )
{
if( ret.back() == '\\' ) //this was a guarded quote
if( ret[ret.size()-1] == '\\' ) //this was a guarded quote
{
ret.pop_back(); //remove guard
ret.resize(ret.size()-1); //remove guard
ret.push_back(c); //put skope
}
else //may have a multiplier after the closing quote
......@@ -1249,8 +1256,8 @@ namespace INMOST
std::vector<Tag> tags;
std::vector<HandleType> new_nodes, new_edges, new_faces, new_cells, new_sets;
std::vector<ElementSet::ComparatorType> set_comparators;
std::string tag, attr, val, save;
int nmeshes = 1;
std::string tag, attr, val, save, incl;
int nmeshes = 1, fintag;
tag = reader.ReadOpenTag(); //ParallelMesh
if( tag != "ParallelMesh" )
{
......@@ -1374,6 +1381,7 @@ namespace INMOST
}
{ //Nodes
incl = "";
int nnodes = 0, ndims = 3;
tag = reader.ReadOpenTag();
if( tag != "Nodes" )
......@@ -1391,45 +1399,59 @@ namespace INMOST
ndims = atoi(val.c_str());
if( ndims != 3 || GetDimensions() != ndims ) SetDimensions(ndims);
}
else if( attr == "IncludeContents" )
incl = attr;
else reader.Report("Unused attribute for Tags %s='%s'",attr.c_str(),val.c_str());
attr = reader.AttributeName();
}
reader.ReadCloseTag();
fintag = reader.ReadCloseTag();
new_nodes.reserve(nnodes);
if( reader.ReadOpenContents() )
{
std::vector<double> Vector;
int Repeat;
dynarray<Storage::real,3> xyz;
val = reader.GetContentsWord();
while(!reader.isContentsEnded() )
std::fstream incl_stream;
if( !incl.empty() )
{
bool vector = false;
reader.ParseReal(val,Vector,Repeat,nnodes);
for(int l = 0; l < Repeat; ++l)
incl_stream.open(incl.c_str(),std::ios::in);
reader.PushStream(incl_stream);
}
if( reader.ReadOpenContents() )
{
std::vector<double> Vector;
int Repeat;
dynarray<Storage::real,3> xyz;
val = reader.GetContentsWord();
while(!reader.isContentsEnded() )
{
for(int q = 0; q < (int)Vector.size(); ++q)
bool vector = false;
reader.ParseReal(val,Vector,Repeat,nnodes);
for(int l = 0; l < Repeat; ++l)
{
xyz.push_back(Vector[q]);
if( xyz.size() == ndims )
for(int q = 0; q < (int)Vector.size(); ++q)
{
new_nodes.push_back(CreateNode(xyz.data())->GetHandle());
xyz.clear();
xyz.push_back(Vector[q]);
if( xyz.size() == ndims )
{
new_nodes.push_back(CreateNode(xyz.data())->GetHandle());
xyz.clear();
}
}
}
val = reader.GetContentsWord();
}
val = reader.GetContentsWord();
reader.ReadCloseContents();
}
reader.ReadCloseContents();
}
else
{
reader.Report("Cannot find contents of XML tag");
throw BadFile;
else
{
reader.Report("Cannot find contents of XML tag");
throw BadFile;
}
if( !incl.empty() ) reader.PopStream();
if( fintag != 2 ) reader.ReadFinishTag("Nodes");
}
reader.ReadFinishTag("Nodes");
if( new_nodes.size() != nnodes )
{
......@@ -2048,6 +2070,8 @@ namespace INMOST
reader.ReadFinishTag("Mesh");
RepairGeometricTags();
if( repair_orientation )
{
int numfixed = 0;
......@@ -2088,8 +2112,8 @@ namespace INMOST
if( tags[k].isDefined(etype) ) definition += names[ElementNum(etype)] + ",";
if( tags[k].isSparse(etype) ) sparse += names[ElementNum(etype)] + ",";
}
if( !definition.empty() ) definition.pop_back(); //remove trailing comma
if( !sparse.empty() ) sparse.pop_back(); //remove trailing comma
if( !definition.empty() ) definition.resize(definition.size()-1); //remove trailing comma
if( !sparse.empty() ) sparse.resize(sparse.size()-1); //remove trailing comma
if( sparse == "" ) sparse = "None";
fout << "\t\t\t<Tag Name =\"" << tags[k].GetTagName() << "\"\n";
if( tags[k].GetSize() !=ENUMUNDEF )
......
......@@ -425,7 +425,7 @@ namespace INMOST
for(GeometricData gtype = MEASURE; gtype <= NORMAL; gtype++)
{
bool restore = false;
for(ElementType etype = EDGE; etype <= CELL && !restore; etype = etype << 1)
for(ElementType etype = EDGE; etype <= CELL && !restore; etype = NextElementType(etype))
if( HaveGeometricData(gtype,etype) )
restore = true;
if( restore )
......@@ -440,6 +440,38 @@ namespace INMOST
}
}
}
void Mesh::RepairGeometricTags()
{
if( HaveTag("GEOM_UTIL_MEASURE") )
{
measure_tag = GetTag("GEOM_UTIL_MEASURE");
for(ElementType etype = EDGE; etype <= CELL; etype = NextElementType(etype))
if( measure_tag.isDefined(etype) && !HaveGeometricData(MEASURE,etype) )
ShowGeometricData(MEASURE,etype);
}
if( HaveTag("GEOM_UTIL_CENTROID") )
{
centroid_tag = GetTag("GEOM_UTIL_CENTROID");
for(ElementType etype = EDGE; etype <= CELL; etype = NextElementType(etype))
if( centroid_tag.isDefined(etype) && !HaveGeometricData(CENTROID,etype) )
ShowGeometricData(CENTROID,etype);
}
if( HaveTag("GEOM_UTIL_BARYCENTER") )
{
barycenter_tag = GetTag("GEOM_UTIL_BARYCENTER");
for(ElementType etype = EDGE; etype <= CELL; etype = NextElementType(etype))
if( barycenter_tag.isDefined(etype) && !HaveGeometricData(BARYCENTER,etype) )
ShowGeometricData(BARYCENTER,etype);
}
if( HaveTag("GEOM_UTIL_NORMAL") )
{
normal_tag = GetTag("GEOM_UTIL_NORMAL");
for(ElementType etype = EDGE; etype <= CELL; etype = NextElementType(etype))
if( normal_tag.isDefined(etype) && !HaveGeometricData(NORMAL,etype) )
ShowGeometricData(NORMAL,etype);
}
}
void Mesh::PrepareGeometricData(GeomParam table)
{
......
......@@ -1972,11 +1972,51 @@ namespace INMOST
case DATA_INTEGER: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_integer_array *>(adata)->size());
case DATA_BULK: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_bulk_array *>(adata)->size());
case DATA_REFERENCE:return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_reference_array*>(adata)->size());
#if defined(USE_AUTODIFF)
case DATA_VARIABLE: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_variable_array *>(adata)->size());
#endif
}
throw BadTag;
}
return tag.GetSize();
}
INMOST_DATA_ENUM_TYPE Mesh::GetDataCapacity(HandleType h,const Tag & tag) const
{
assert( tag.GetMeshLink() == this );
if( tag.GetSize() == ENUMUNDEF )
{
const void * adata = MGetLink(h,tag);
assert( adata != NULL );
switch(tag.GetDataType())
{
case DATA_REAL: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_real_array *>(adata)->size())*tag.GetBytesSize();
case DATA_INTEGER: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_integer_array *>(adata)->size())*tag.GetBytesSize();
case DATA_BULK: return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_bulk_array *>(adata)->size())*tag.GetBytesSize();
case DATA_REFERENCE:return static_cast<INMOST_DATA_ENUM_TYPE>(static_cast<const inner_reference_array*>(adata)->size())*tag.GetBytesSize();
#if defined(USE_AUTODIFF)
case DATA_VARIABLE:
{
INMOST_DATA_ENUM_TYPE ret = 0;
const inner_variable_array * arr = static_cast<const inner_variable_array *>(adata);
ret += arr->size();
for(inner_variable_array::size_type k = 0; k < arr->size(); ++k)
ret += (*arr)[k].GetRow().Size();
return ret*sizeof(Sparse::Row::entry_s);