Commit 09c09f3b authored by Kirill Terekhov's avatar Kirill Terekhov

add some files

parent f823b8e7
......@@ -2,12 +2,8 @@ projects/
AsmJit/
compile32_vs2013/
compile64_vs2013/
development/
inmost_autodiff.h
autodiff.cpp
TODO.txt
examples/
examples/Data/
examples/Matrices/
examples/Grids/
tests/
\ No newline at end of file
tests/
//FOR 2D
// Node -> Vertex
// Edge -> Vertex
// Face -> Line, Curve
// Cell -> Tri, Quad, Polygon, MultiLine
//FOR 3D
// Node -> Vertex
// Edge -> Line, Curve
// Face -> Tri, Quad, Polygon, MultiLine
// Cell -> Tet, Hex, Prism, Pyramid, Polyhedron, MultiPolygon
//TODO:
1D???
//serial
//1.0 read/write formats
// 1.1 read gmv
// 1.2 read different kinds of vtk besides unstructured
// 1.3 read/write xml vtk formats
// 1.4 pmf: print error when markers cannot be represented in current type and data was lost
// 1.5 pmf: save hide_marker, new_marker values
// 1.6 pmf: save topology checking information
//2. enchance iterators
// iterators should return pointers or references?
//3. geometry.cpp
// 3.0 decide how FixNormalOrientation should update geometric data
// 3.1 replace calculation of normale by hyperplane equation for any dimension??
// 3.2 correct Inside function to check weather point inside Segment, Polygon
// 3.3 dynamically balanced obtree or octree or kd-tree to query elements by position
//4. (done, need check) add some low-level mesh modification procedures to elements
// 5.1 add some high-level mesh modification procedures: split by plane,
// 5.2 csg: difference, union, intersection
// 5.3 calculate volume for concave elements, choose elements by minimum volume, not minimum number of elements in incident_matrix class (modify.cpp)
//5. reduce size used by sparse data
//6. new ElementSet class, derived from Element class
// 6.1 support ierarhy
//7. algorithm that checks topology on element creation
// 7.1 complete unimplemented tests for star-shaped objects, concavity
//parallel:
//1. algorithm in EndModification or ResolveModification to keep the mesh in parallel consistent state after element creation/deletion
// 1.1 restore contiguous global id
//2. test algorithm that checks for halo in ExchangeMarked, if performance increases
//3. decide how to exchange ElementSets between processors
//4. exchange data of type DATA_REFERENCE, by GlobalID and ElementType
//5. mesh_file.cpp
// 5.1 on parallel load, when there are more processors then parts in mesh - duplicate mesh on other processors??
// 5.2 when mesh is duplicated over many processors use local clusterization algorithm in ResolveShared
// shared parallel
//1. avoid markers in nbAdjElements, getAdjElements, getNodes, getEdges, getFaces, getCells, BridgeAdjacency
// partitioner:
//1. implement K-means clustering
//solver:
//0. workaround for overlapping vertices and matrices
//1. read TODO on top of solver_*.hpp
//autodiff:
//1. read TODO on top of INMOST_autodiff.h
//TODO:
// Recheck computation of derivatives!!!!
// Detect similar parts of the tree in Automatizator
// Restructure tree expressions
// Intorduce multivariate tables
// Generate opencl code
// Make so that stencil may be represented by tags, by set or by callback_function
//RegisterTable and table implementation should account for boundary conditions beyond data
//SOLVER todo:
//TODO:
// how to calculate diagonal perturbation?
// how to calculate schur complement faster
//
// done! implement crout-ILU from
// Documents/Read/solver/crout/crout.pdf to ILUC_preconditioner
// done! implement condition estimation for |L^{-1}| and |U^{-1}| and adaptive tau for ILUC_preconditioner from
// Documents\Read\solver\Read_now\bollhofer_siam.pdf
// done! try to make ILUC2_preconditioner - second order ILU from ILUC_preconditioner
// done! implement diagonal pivoting for ILUC - maybe need to update diagonal at every step
// goto references [7],[10]-(data structure!) from
// Documents\Read\solver\crout\crout.pdf
// return dropped values to diagonal if control vector is provided from
// Documents\Read\solver\stabilization\milut.pdf
// try to apply dropping while forming linked list,should correctly calculate condition estimates
// Calculate schur complement faster:
// Documents\Read\solver\sparse_matmul\sparse.pdf
// in ILUC_preconditioner, replace matrix structures by CSR, estimate number of nonzeros in rows/cols
// before filling, if necessery (how?)
#include "inmost.h"
#if defined(USE_AUTODIFF)
#if defined(USE_AUTODIFF_ASMJIT)
#include "asmjit.h"
#endif
#if defined(USE_AUTODIFF_OPENCL)
#include <CL/cl.h>
#endif
namespace INMOST
{
INMOST_DATA_REAL_TYPE Automatizator::DerivativePrecompute(const expr & var, Storage * e, precomp_values_t & values, void * user_data)
{
/*
assert(var.op != AD_NONE);
INMOST_DATA_REAL_TYPE lval, rval, ret = 0.0;
switch (var.op)
{
case AD_COND:
lval = Evaluate(*var.left, e, user_data);
rval = DerivativePrecompute(*(lval > 0.0 ? var.right->left : var.right->right), e, values, user_data);
values.push_back(lval);
return rval*var.coef;
case AD_PLUS:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = DerivativePrecompute(*var.right, e, values, user_data);
return (lval + rval)*var.coef;
case AD_MINUS:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = DerivativePrecompute(*var.right, e, values, user_data);
return (lval - rval)*var.coef;
case AD_MULT:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = DerivativePrecompute(*var.right, e, values, user_data);
values.push_back(lval);
values.push_back(rval);
return (lval * rval)*var.coef;
case AD_DIV:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = DerivativePrecompute(*var.right, e, values, user_data);
values.push_back(lval);
values.push_back(rval);
return (lval / rval)*var.coef;
case AD_POW:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = DerivativePrecompute(*var.right, e, values, user_data);
values.push_back(lval);
values.push_back(rval);
ret = ::pow(lval, rval);
values.push_back(ret);
return ret*var.coef;
case AD_INV:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
return var.coef / lval;
case AD_ABS:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
return ::fabs(lval)*var.coef;
case AD_EXP:
lval = DerivativePrecompute(*var.left, e, values, user_data);
ret = ::exp(lval);
values.push_back(ret);
return ret*var.coef;
case AD_LOG:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
return ::log(lval)*var.coef;
case AD_SIN:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
return ::sin(lval)*var.coef;
case AD_COS:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
return ::cos(lval)*var.coef;
case AD_CONST:
return var.coef;
case AD_MES:
assert(!(e->GetElementType() & (ESET | MESH)));
m->GetGeometricData(static_cast<Element *>(e), MEASURE, &ret);
return ret*var.coef;
}
if (var.op >= AD_FUNC)
{
ret = reg_funcs[var.op].func(e, user_data);
return ret*var.coef;
}
else if (var.op >= AD_TABLE)
{
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
ret = reg_tables[var.op]->get_value(lval);
return ret*var.coef;
}
else if (var.op >= AD_STNCL)
{
stencil_kind_domain st = reg_stencils[var.op];
assert(st.domainmask == 0 || e->GetMarker(st.domainmask));
if (st.kind == 0)
{
Storage::reference_array elems = e->ReferenceArray(static_cast<stencil_tag *>(st.link)->elements);
Storage::real_array coefs = e->RealArray(static_cast<stencil_tag *>(st.link)->coefs);
assert(elems.size() == coefs.size());
for (INMOST_DATA_ENUM_TYPE k = 0; k < elems.size(); ++k)
{
lval = DerivativePrecompute(*var.left, elems[k], values, user_data);
ret += lval * coefs[k];
}
}
else if (st.kind == 1)
{
stencil_pairs get_st;
reinterpret_cast<stencil_callback>(st.link)(e, get_st, user_data);
for (INMOST_DATA_ENUM_TYPE k = 0; k < get_st.size(); ++k)
{
lval = DerivativePrecompute(*var.left, get_st[k].first, values, user_data);
ret += lval * get_st[k].second;
}
}
return ret*var.coef;
}
else if (var.op >= AD_CTAG)
{
INMOST_DATA_ENUM_TYPE comp = *(INMOST_DATA_ENUM_TYPE *)(&var.left);
ret = GetStaticValue(e, var.op, comp);
return ret * var.coef;
}
else if (var.op >= AD_TAG)
{
INMOST_DATA_ENUM_TYPE comp = *(INMOST_DATA_ENUM_TYPE *)(&var.left);
ret = GetDynamicValue(e, var.op, comp);
return ret*var.coef;
}
assert(false);
*/
return 0.0;
}
//! returns offset from the end of precomputed values
void Automatizator::DerivativeFill(const expr & var, Storage * e, Solver::Row & entries, precomp_values_t & values, INMOST_DATA_REAL_TYPE multval, void * user_data)
{
/*
assert(var.op != AD_NONE);
INMOST_DATA_REAL_TYPE lval, rval, ret;
switch (var.op)
{
case AD_COND:
lval = values.back(); values.pop_back();
DerivativeFill(*(lval > 0.0 ? var.right->left : var.right->right), e, entries, values, multval*var.coef, user_data);
return;
case AD_PLUS:
DerivativeFill(*var.right, e, entries, values, multval*var.coef, user_data);
DerivativeFill(*var.left, e, entries, values, multval*var.coef, user_data);
return;
case AD_MINUS:
DerivativeFill(*var.right, e, entries, values, -multval*var.coef, user_data);
DerivativeFill(*var.left, e, entries, values, multval*var.coef, user_data);
return;
case AD_MULT:
rval = values.back(); values.pop_back();
lval = values.back(); values.pop_back();
DerivativeFill(*var.right, e, entries, values, lval*multval*var.coef, user_data);
DerivativeFill(*var.left, e, entries, values, rval*multval*var.coef, user_data);
return;
case AD_DIV:
rval = values.back(); values.pop_back();
lval = values.back(); values.pop_back();
DerivativeFill(*var.right, e, entries, values, -multval * lval / (rval*rval) * var.coef, user_data);
DerivativeFill(*var.left, e, entries, values, multval / rval*var.coef, user_data);
return;
case AD_POW:
ret = values.back(); values.pop_back();
rval = values.back(); values.pop_back();
lval = values.back(); values.pop_back();
DerivativeFill(*var.right, e, entries, values, multval * ret * ::log(lval) * var.coef, user_data);
DerivativeFill(*var.left, e, entries, values, multval * ret * rval / lval * var.coef, user_data);
return;
case AD_INV:
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, -multval / (lval * lval) * var.coef, user_data);
return;
case AD_ABS:
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * var.coef * (lval > 0 ? 1.0 : -1.0), user_data);
return;
case AD_EXP:
ret = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * ret * var.coef, user_data);
return;
case AD_LOG:
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * var.coef / lval, user_data);
return;
case AD_SIN:
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * var.coef * ::cos(lval), user_data);
return;
case AD_COS:
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, -multval * var.coef * ::sin(lval), user_data);
return;
case AD_CONST: return;
case AD_MES: return;
}
if (var.op >= AD_FUNC)
{
return;
}
else if (var.op >= AD_TABLE)
{
lval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * var.coef * reg_tables[var.op]->get_derivative(lval), user_data);
return;
}
else if (var.op >= AD_STNCL)
{
stencil_kind_domain st = reg_stencils[var.op];
assert(st.domainmask == 0 || e->GetMarker(st.domainmask));
if (st.kind == 0)
{
Storage::reference_array elems = e->ReferenceArray(static_cast<stencil_tag *>(st.link)->elements);
Storage::real_array coefs = e->RealArray(static_cast<stencil_tag *>(st.link)->coefs);
assert(elems.size() == coefs.size());
for (INMOST_DATA_ENUM_TYPE k = elems.size(); k > 0; --k)
DerivativeFill(*var.left, elems[k - 1], entries, values, var.coef * coefs[k - 1] * multval, user_data);
}
else if (st.kind == 1)
{
stencil_pairs get_st;
reinterpret_cast<stencil_callback>(st.link)(e, get_st, user_data);
for (INMOST_DATA_ENUM_TYPE k = get_st.size(); k > 0; --k)
DerivativeFill(*var.left, get_st[k - 1].first, entries, values, var.coef * get_st[k - 1].second*multval, user_data);
}
return;
}
else if (var.op >= AD_CTAG) return;
else if (var.op >= AD_TAG)
{
if (isDynamicValid(e, var.op))
{
INMOST_DATA_ENUM_TYPE ind = GetDynamicIndex(e, var.op, *(INMOST_DATA_ENUM_TYPE *)(&var.left));
std::cout << ind << ", " << multval*var.coef << std::endl;
entries[ind] += multval * var.coef;
}
return;
}
assert(false);
*/
return;
}
INMOST_DATA_REAL_TYPE Automatizator::Evaluate(const expr & var, Storage * e, void * user_data)
{
return EvaluateSub(var, e, user_data, NULL);
}
INMOST_DATA_REAL_TYPE Automatizator::EvaluateSub(const expr & var, Storage * e, void * user_data, values_container * parent_values)
{
values_container values(var.data.size());
INMOST_DATA_ENUM_TYPE k = 0;
for (expr::data_type::const_iterator it = var.data.begin(); it != var.data.end(); ++it)
{
switch (it->op)
{
case AD_EXT: values[k] = (*parent_values)[it->right.i]; break;
case AD_COND:
if (values[it->left.i] > 0.0)
values[k] = EvaluateSub(*it->right.q->left.e, e, user_data,&values);
else
values[k] = EvaluateSub(*it->right.q->right.e, e, user_data,&values);
break;
case AD_PLUS: values[k] = values[it->left.i] + values[it->right.i]; break;
case AD_MINUS: values[k] = values[it->left.i] - values[it->right.i]; break;
case AD_MULT: values[k] = values[it->left.i] * values[it->right.i]; break;
case AD_DIV: values[k] = values[it->left.i] / values[it->right.i]; break;
case AD_POW: values[k] = ::pow(values[it->left.i], values[it->right.i]); break;
case AD_ABS: values[k] = ::fabs(values[it->left.i]); break;
case AD_EXP: values[k] = ::exp(values[it->left.i]); break;
case AD_LOG: values[k] = ::log(values[it->left.i]); break;
case AD_SIN: values[k] = ::sin(values[it->left.i]); break;
case AD_COS: values[k] = ::cos(values[it->left.i]); break;
case AD_CONST: values[k] = it->left.r; break;
case AD_MES: assert(!(e->GetElementType() & (ESET | MESH))); m->GetGeometricData(static_cast<Element *>(e), MEASURE, &values[k]); break;
default:
if (it->op >= AD_FUNC) values[k] = reg_funcs[it->op].func(e, user_data);
else if (it->op >= AD_TABLE) values[k] = reg_tables[it->op]->get_value(values[it->left.i]);
else if (it->op >= AD_STNCL)
{
stencil_pairs get_st;
GetStencil(it->op, e, user_data, get_st);
values[k] = 0.0;
for (INMOST_DATA_ENUM_TYPE k = 0; k < get_st.size(); ++k)
values[k] += EvaluateSub(*it->left.e, get_st[k].first, user_data,NULL) * get_st[k].second;
}
else if (it->op >= AD_CTAG) values[k] = GetStaticValue(e, it->op, it->left.i);
else if (it->op >= AD_TAG) values[k] = GetDynamicValue(e, it->op, it->left.i);
else assert(false);
}
k++;
}
return values[var.data.size()-1];
}
INMOST_DATA_REAL_TYPE Automatizator::Derivative(const expr & var, Storage * e, Solver::Row & out, void * user_data)
{
INMOST_DATA_REAL_TYPE ret;
precomp_values_t values;
ret = DerivativePrecompute(var, e, values, user_data);
DerivativeFill(var, e, out, values, 1.0, user_data);
return ret;
}
Automatizator::Automatizator(Mesh * m) :first_num(0), last_num(0), m(m) {}
Automatizator::~Automatizator()
{
for (unsigned k = 0; k < index_tags.size(); k++)
index_tags[k].indices = m->DeleteTag(index_tags[k].indices);
for (table_type::iterator it = reg_tables.begin(); it != reg_tables.end(); ++it)
{
delete[] it->second->args;
delete[] it->second->vals;
delete it->second;
}
for (stencil_type::iterator it = reg_stencils.begin(); it != reg_stencils.end(); ++it)
if (it->second.kind == 0)
delete static_cast<stencil_tag *>(it->second.link);
}
INMOST_DATA_ENUM_TYPE Automatizator::RegisterFunc(std::string name, func_callback func)
{
INMOST_DATA_ENUM_TYPE ret = reg_funcs.size() + AD_FUNC;
func_name_callback v;
v.name = name;
v.func = func;
reg_funcs[ret] = v;
return ret;
}
//register stencil that can be got from tags
INMOST_DATA_ENUM_TYPE Automatizator::RegisterStencil(std::string name, Tag elements_tag, Tag coefs_tag, MIDType domain_mask)
{
INMOST_DATA_ENUM_TYPE ret = reg_stencils.size() + AD_STNCL;
stencil_kind_domain st;
stencil_tag * save = new stencil_tag;
st.name = name;
save->coefs = coefs_tag;
save->elements = elements_tag;
st.kind = 0;
st.link = static_cast<void *>(save);
st.domainmask = domain_mask;
reg_stencils[ret] = st;
return ret;
}
//register stencil that can be got from function
INMOST_DATA_ENUM_TYPE Automatizator::RegisterStencil(std::string name, stencil_callback func, MIDType domain_mask)
{
INMOST_DATA_ENUM_TYPE ret = reg_stencils.size() + AD_STNCL;
stencil_kind_domain st;
st.name = name;
st.kind = 1;
st.link = reinterpret_cast<void *>(func);
st.domainmask = domain_mask;
reg_stencils[ret] = st;
return ret;
}
INMOST_DATA_ENUM_TYPE Automatizator::RegisterTable(std::string name, INMOST_DATA_REAL_TYPE * Arguments, INMOST_DATA_REAL_TYPE * Values, INMOST_DATA_ENUM_TYPE size)
{
INMOST_DATA_ENUM_TYPE ret = reg_tables.size() + AD_TABLE;
table_ptr t = new table;
t->name = name;
t->args = new INMOST_DATA_REAL_TYPE[size];
memcpy(t->args, Arguments, sizeof(INMOST_DATA_REAL_TYPE)*size);
t->vals = new INMOST_DATA_REAL_TYPE[size];
memcpy(t->vals, Values, sizeof(INMOST_DATA_REAL_TYPE)*size);
t->size = size;
reg_tables[ret] = t;
return ret;
}
/// set data of tag t defined on domain_mask to be dynamic data
/// don't register tag twice
INMOST_DATA_ENUM_TYPE Automatizator::RegisterDynamicTag(Tag t, ElementType typemask, MIDType domain_mask)
{
tagpair p;
p.d.domain_mask = domain_mask;
p.d.t = t;
ElementType def = NONE, sparse = NONE;
for (ElementType q = NODE; q <= MESH; q = q << 1) if (q & typemask)
{
if (t.isDefined(q)) def |= q;
if (t.isSparse(q)) sparse |= q;
}
p.indices = m->CreateTag(t.GetTagName() + "_index", DATA_INTEGER, def, sparse, t.GetSize());
INMOST_DATA_ENUM_TYPE ret = reg_tags.size() + AD_TAG;
reg_tags[ret] = p;
index_tags.push_back(p);
return ret;
}
/// set index for every data entry of dynamic tag
void Automatizator::EnumerateDynamicTags()
{
first_num = last_num = 0;
const ElementType paralleltypes = NODE | EDGE | FACE | CELL;
for (index_enum::iterator it = index_tags.begin(); it != index_tags.end(); ++it)
for (ElementType etype = NODE; etype <= MESH; etype = etype << 1)
if (it->indices.isDefined(etype) && it->indices.isSparse(etype))
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
jt->DelData(it->indices);
for (index_enum::iterator it = index_tags.begin(); it != index_tags.end(); ++it)
{
for (ElementType etype = NODE; etype <= MESH; etype = etype << 1)
if (it->indices.isDefined(etype))
{
if (it->indices.GetSize() == ENUMUNDEF)
{
if (!it->indices.isSparse(etype))
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask)))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
indarr.resize(jt->RealArray(it->d.t).size());
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt = last_num++;
}
}
else
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (jt->HaveData(it->d.t) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask))))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
indarr.resize(jt->RealArray(it->d.t).size());
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt = last_num++;
}
}
}
else
{
if (!it->indices.isSparse(etype))
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask)))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt = last_num++;
}
}
else
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (jt->HaveData(it->d.t) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask))))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt = last_num++;
}
}
}
}
}
#if defined(USE_MPI)
if (m->GetProcessorsNumber() > 1)
{
MPI_Scan(&last_num, &first_num, 1, INMOST_MPI_DATA_ENUM_TYPE, MPI_SUM, m->GetCommunicator());
first_num -= last_num;
ElementType exch_mask = NONE;
if (first_num > 0) for (index_enum::iterator it = index_tags.begin(); it != index_tags.end(); ++it)
{
for (ElementType etype = NODE; etype <= MESH; etype = etype << 1)
if (it->indices.isDefined(etype))
{
exch_mask |= etype;
if (it->indices.GetSize() == ENUMUNDEF)
{
if (!it->indices.isSparse(etype))
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask)))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt += first_num;
}
}
else
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (jt->HaveData(it->d.t) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask))))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
indarr.resize(jt->RealArray(it->d.t).size());
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt += first_num;
}
}
}
else
{
if (!it->indices.isSparse(etype))
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask)))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt += first_num;
}
}
else
{
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (jt->HaveData(it->d.t) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask))))
{
Storage::integer_array indarr = jt->IntegerArray(it->indices);
for (Storage::integer_array::iterator qt = indarr.begin(); qt != indarr.end(); ++qt)
*qt += first_num;
}
}
}
}
}
last_num += first_num;
{
std::vector<Tag> exch_tags;
for (index_enum::iterator it = index_tags.begin(); it != index_tags.end(); ++it) exch_tags.push_back(it->indices);
m->ExchangeData(exch_tags, exch_mask);
}
}
#endif
}
/// register tag, data for which don't change through iterations
/// don't register tag twice
INMOST_DATA_ENUM_TYPE Automatizator::RegisterStaticTag(Tag t, MIDType domain_mask)
{
INMOST_DATA_ENUM_TYPE ret = reg_ctags.size() + AD_CTAG;
tagdomain d;
d.t = t;
d.domain_mask = domain_mask;
reg_ctags[ret] = d;
return ret;
}
#if defined(USE_AUTODIFF_ASMJIT)
asmjit::kVarType GetEnumType()
{
switch (sizeof(INMOST_DATA_ENUM_TYPE))
{
case 1: return asmjit::kVarTypeUInt8;
case 2: return asmjit::kVarTypeUInt16;
case 4: return asmjit::kVarTypeUInt32;
case 8: return asmjit::kVarTypeUInt64;
}
assert(0);
return asmjit::kVarTypeInvalid;
}
asmjit::kVarType GetIntegerType()
{
switch (sizeof(INMOST_DATA_INTEGER_TYPE))
{
case 1: return asmjit::kVarTypeInt8;
case 2: return asmjit::kVarTypeInt16;
case 4: return asmjit::kVarTypeInt32;
case 8: return asmjit::kVarTypeInt64;
}
assert(0);
return asmjit::kVarTypeInvalid;
}