Commit 831bfd7c authored by Alexander Danilov's avatar Alexander Danilov
Browse files

Merge branch 'master' of inmost-github

parents f3e4e583 5452e1ea
......@@ -31,7 +31,7 @@ set(HEADER inmost.h
container.hpp
io.hpp
solver_ilu2.hpp
# solver_ddpqiluc2.hpp
solver_ddpqiluc2.hpp
solver_bcgsl.hpp
solver_prototypes.hpp)
......@@ -56,7 +56,7 @@ option(USE_PARTITIONER_PARMETIS "Use ParMetis partitioner" OFF)
option(USE_PARTITIONER_ZOLTAN "Use Zoltan partitioner" OFF)
option(USE_SOLVER_PETSC "Use PETSc solver" OFF)
option(USE_AUTODIFF_OPENCL "Use OpenCL for automatic differentiation (under work)" OFF)
option(USE_AUTODIFF_ASMJIT "Use AsmJit for automatic differentiation" ON)
option(USE_AUTODIFF_ASMJIT "Use AsmJit for automatic differentiation" OFF)
option(USE_AUTODIFF_EXPRESSION_TEMPLATES "Use c++ expression templates for automatic differentiation" OFF)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_find/")
......
......@@ -13,14 +13,216 @@
namespace INMOST
{
#if defined(NEW_VERSION)
//! returns offset from the end of precomputed z
void Automatizator::DerivativeFill(expr & var, INMOST_DATA_ENUM_TYPE element, INMOST_DATA_ENUM_TYPE parent, Solver::Row & entries, INMOST_DATA_REAL_TYPE multval, void * user_data)
{
INMOST_DATA_ENUM_TYPE voffset = var.values_offset(element), doffset = var.derivatives_offset(element);
INMOST_DATA_ENUM_TYPE k = var.data.size()-1;
Storage * e = var.current_stencil[element].first;
INMOST_DATA_REAL_TYPE lval, rval, ret;
var.values[doffset+k] = multval;
expr::expr_data * arr = &var.data[0], *it;
//for (expr::data_type::reverse_iterator it = var.data.rbegin(); it != var.data.rend(); ++it)
do
{
it = arr+k;
switch (it->op)
{
case AD_EXT:
assert(parent != ENUMUNDEF);
it->left.e->values[it->left.e->derivatives_offset(parent)+it->right.i] += var.values[doffset+k];
break;
case AD_COND:
{
expr & next = var.values[voffset+it->left.i] > 0.0 ? *it->right.q->left.e : *it->right.q->right.e;
DerivativeFill(next, 0, element, entries,var.values[doffset+k], user_data);
}
break;
case AD_PLUS:
var.values[doffset+it->left.i] += var.values[doffset+k];
var.values[doffset+it->right.i] += var.values[doffset+k];
break;
case AD_MINUS:
var.values[doffset+it->left.i] += var.values[doffset+k];
var.values[doffset+it->right.i] -= var.values[doffset+k];
break;
case AD_MULT:
rval = var.values[voffset+it->right.i];
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k]*rval;
var.values[doffset+it->right.i] += var.values[doffset+k]*lval;
break;
case AD_DIV:
rval = var.values[voffset+it->right.i];
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k]/rval;
var.values[doffset+it->right.i] -= var.values[doffset+k]*lval/(rval*rval);
break;
case AD_POW:
ret = var.values[voffset+k];
rval = var.values[voffset+it->right.i];
lval = var.values[voffset+it->left.i];
var.values[doffset+it->right.i] += var.values[doffset+k] * ::log(lval);
var.values[doffset+it->left.i] += var.values[doffset+k] * ret * rval / lval;
break;
case AD_SQRT:
ret = var.values[voffset+k];
var.values[doffset+it->left.i] += 0.5 * var.values[doffset+k] / ret;
break;
case AD_ABS:
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k] * (lval > 0.0 ? 1.0 : -1.0);
break;
case AD_EXP:
ret = var.values[voffset+k];
var.values[doffset+it->left.i] += var.values[doffset+k] * ret;
break;
case AD_LOG:
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k] / lval;
break;
case AD_SIN:
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k] * ::cos(lval);
break;
case AD_COS:
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] -= var.values[doffset+k] * ::sin(lval);
break;
case AD_COND_MARK: break;
case AD_COND_TYPE: break;
case AD_CONST: break;
case AD_MES: break;
case AD_VAL:
{
expr & next = *it->right.e;
next.current_stencil.resize(1);
next.current_stencil[0] = stencil_pair(e,1.0);
next.resize_for_stencil();
var.values[doffset+it->left.i] += var.values[doffset+k] * EvaluateSub(next,0,element,user_data);
break;
}
default:
if (it->op >= AD_FUNC) {}
else if (it->op >= AD_TABLE)
{
lval = var.values[voffset+it->left.i];
var.values[doffset+it->left.i] += var.values[doffset+k] * reg_tables[it->op]->get_derivative(lval);
}
else if (it->op >= AD_STNCL)
{
for (INMOST_DATA_ENUM_TYPE j = 0; j < it->left.e->current_stencil.size(); ++j) if( it->left.e->current_stencil[j].first != NULL )
{
DerivativeFill(*it->left.e, j, ENUMUNDEF, entries, var.values[doffset+k] * it->left.e->current_stencil[j].second, user_data);
}
}
else if (it->op >= AD_CTAG) {}
else if (it->op >= AD_TAG)
{
if (isDynamicValid(e, it->op))
{
entries[GetDynamicIndex(e,it->op,it->left.i)] += var.values[doffset+k];
}
}
else assert(false);
}
} while(k-- != 0);
}
INMOST_DATA_REAL_TYPE Automatizator::EvaluateSub(expr & var, INMOST_DATA_ENUM_TYPE element, INMOST_DATA_ENUM_TYPE parent, void * user_data)
{
INMOST_DATA_ENUM_TYPE k = 0, offset = var.values_offset(element);
Storage * e = var.current_stencil[element].first;
expr::expr_data * arr = &var.data[0], *it;
//for (expr::data_type::iterator it = var.data.begin(); it != var.data.end(); ++it)
do
{
it = arr+k;
switch (it->op)
{
case AD_EXT:
assert(parent != ENUMUNDEF);
var.values[offset+k] = it->left.e->values[it->left.e->values_offset(parent)+it->right.i];
break;
case AD_COND:
{
expr & next = var.values[offset+it->left.i] > 0.0 ? *it->right.q->left.e : *it->right.q->right.e;
next.current_stencil.resize(1);
next.current_stencil[0] = stencil_pair(e,1.0);
next.resize_for_stencil();
var.values[offset+k] = EvaluateSub(next, 0,element, user_data);
}
break;
case AD_PLUS: var.values[offset+k] = var.values[offset+it->left.i] + var.values[offset+it->right.i]; break;
case AD_MINUS: var.values[offset+k] = var.values[offset+it->left.i] - var.values[offset+it->right.i]; break;
case AD_MULT: var.values[offset+k] = var.values[offset+it->left.i] * var.values[offset+it->right.i]; break;
case AD_DIV: var.values[offset+k] = var.values[offset+it->left.i] / var.values[offset+it->right.i]; break;
case AD_POW: var.values[offset+k] = ::pow(var.values[offset+it->left.i], var.values[offset+it->right.i]); break;
case AD_SQRT: var.values[offset+k] = ::sqrt(var.values[offset+it->left.i]); break;
case AD_ABS: var.values[offset+k] = ::fabs(var.values[offset+it->left.i]); break;
case AD_EXP: var.values[offset+k] = ::exp(var.values[offset+it->left.i]); break;
case AD_LOG: var.values[offset+k] = ::log(var.values[offset+it->left.i]); break;
case AD_SIN: var.values[offset+k] = ::sin(var.values[offset+it->left.i]); break;
case AD_COS: var.values[offset+k] = ::cos(var.values[offset+it->left.i]); break;
case AD_CONST: var.values[offset+k] = it->left.r; break;
case AD_COND_TYPE: var.values[offset+k] = ((e->GetElementType() & it->left.i)? 1.0 : -1.0); break;
case AD_COND_MARK: var.values[offset+k] = e->GetMarker(it->left.i) ? 1.0 : -1.0; break;
case AD_MES: assert(!(e->GetElementType() & (ESET | MESH))); m->GetGeometricData(static_cast<Element *>(e), MEASURE, &var.values[offset+k]); break;
case AD_VAL: var.values[offset+k] = var.values[offset+it->left.i]; break;
default:
if (it->op >= AD_FUNC) var.values[offset+k] = reg_funcs[it->op].func(e, user_data);
else if (it->op >= AD_TABLE) var.values[offset+k] = reg_tables[it->op]->get_value(var.values[offset+it->left.i]);
else if (it->op >= AD_STNCL)
{
it->left.e->current_stencil.clear();
GetStencil(it->op,e,user_data,it->left.e->current_stencil);
it->left.e->resize_for_stencil();
var.values[offset+k] = 0.0;
for (INMOST_DATA_ENUM_TYPE j = 0; j < it->left.e->current_stencil.size(); ++j) if( it->left.e->current_stencil[j].first != NULL )
var.values[offset+k] += EvaluateSub(*it->left.e,j,ENUMUNDEF,user_data) * it->left.e->current_stencil[j].second;
}
else if (it->op >= AD_CTAG) var.values[offset+k] = GetStaticValue(e, it->op, it->left.i);
else if (it->op >= AD_TAG) var.values[offset+k] = GetDynamicValue(e, it->op, it->left.i);
else assert(false);
}
//k++;
} while(++k != var.data.size());
return var.values[offset+var.data.size()-1];
}
INMOST_DATA_REAL_TYPE Automatizator::Evaluate(expr & var, Storage * e, void * user_data)
{
var.current_stencil.resize(1);
var.current_stencil[0] = stencil_pair(e,1.0);
var.resize_for_stencil();
return EvaluateSub(var,0,ENUMUNDEF,user_data);
}
INMOST_DATA_REAL_TYPE Automatizator::Derivative(expr & var, Storage * e, Solver::Row & out, Storage::real multiply, void * user_data)
{
INMOST_DATA_REAL_TYPE ret;
var.current_stencil.resize(1);
var.current_stencil[0] = stencil_pair(e,1.0);
var.resize_for_stencil();
ret = EvaluateSub(var,0,ENUMUNDEF,user_data);
DerivativeFill(var, 0, ENUMUNDEF, out, multiply, user_data);
return ret*multiply;
}
#else
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_TYPE:
lval = (e->GetElementType() & reinterpret_cast<ElementType>(var.left))? 1.0 : -1.0;
return lval;
case AD_COND_MARK:
lval = e->GetMarker(reinterpret_cast<MIDType>(var.left))? 1.0 : -1.0;
return lval;
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);
......@@ -54,6 +256,11 @@ namespace INMOST
ret = ::pow(lval, rval);
values.push_back(ret);
return ret*var.coef;
case AD_SQRT:
lval = DerivativePrecompute(*var.left, e, values, user_data);
ret = ::sqrt(lval);
values.push_back(ret);
return ret*var.coef;
case AD_INV:
lval = DerivativePrecompute(*var.left, e, values, user_data);
values.push_back(lval);
......@@ -85,6 +292,11 @@ namespace INMOST
assert(!(e->GetElementType() & (ESET | MESH)));
m->GetGeometricData(static_cast<Element *>(e), MEASURE, &ret);
return ret*var.coef;
case AD_VAL:
lval = DerivativePrecompute(*var.left, e, values, user_data);
rval = Evaluate(*var.left,e,user_data);
values.push_back(rval);
return lval*var.coef;
}
if (var.op >= AD_FUNC)
{
......@@ -100,14 +312,14 @@ namespace INMOST
}
else if (var.op >= AD_STNCL)
{
stencil_kind_domain st = reg_stencils[var.op];
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)
for (INMOST_DATA_ENUM_TYPE k = 0; k < elems.size(); ++k) if( elems[k] != NULL )
{
lval = DerivativePrecompute(*var.left, elems[k], values, user_data);
ret += lval * coefs[k];
......@@ -117,7 +329,7 @@ namespace INMOST
{
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)
for (INMOST_DATA_ENUM_TYPE k = 0; k < get_st.size(); ++k) if( get_st[k].first != NULL )
{
lval = DerivativePrecompute(*var.left, get_st[k].first, values, user_data);
ret += lval * get_st[k].second;
......@@ -138,17 +350,18 @@ namespace INMOST
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_MARK:
case AD_COND_TYPE:
return;
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);
......@@ -180,6 +393,10 @@ namespace INMOST
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_SQRT:
ret = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, 0.5 * multval / ret * 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);
......@@ -206,6 +423,10 @@ namespace INMOST
return;
case AD_CONST: return;
case AD_MES: return;
case AD_VAL:
rval = values.back(); values.pop_back();
DerivativeFill(*var.left, e, entries, values, multval * var.coef * rval, user_data);
return;
}
if (var.op >= AD_FUNC)
{
......@@ -219,21 +440,21 @@ namespace INMOST
}
else if (var.op >= AD_STNCL)
{
stencil_kind_domain st = reg_stencils[var.op];
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)
for (INMOST_DATA_ENUM_TYPE k = elems.size(); k > 0; --k) if( elems[k-1] != NULL )
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)
for (INMOST_DATA_ENUM_TYPE k = get_st.size(); k > 0; --k) if( get_st[k-1].first != NULL )
DerivativeFill(*var.left, get_st[k - 1].first, entries, values, var.coef * get_st[k - 1].second*multval, user_data);
}
return;
......@@ -244,74 +465,76 @@ namespace INMOST
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)
assert(var.op != AD_NONE);
switch (var.op)
{
switch (it->op)
case AD_COND_MARK: return e->GetMarker(reinterpret_cast<MIDType>(var.left)) ? 1.0 : -1.0;
case AD_COND_TYPE: return (e->GetElementType() & reinterpret_cast<ElementType>(var.left)) ? 1.0 : -1.0;
case AD_COND: return Evaluate(*(Evaluate(*var.left, e, user_data) > 0.0 ? var.right->left : var.right->right), e, user_data)*var.coef;
case AD_PLUS: return (Evaluate(*var.left, e, user_data) + Evaluate(*var.right, e, user_data))*var.coef;
case AD_MINUS: return (Evaluate(*var.left, e, user_data) - Evaluate(*var.right, e, user_data))*var.coef;
case AD_MULT: return (Evaluate(*var.left, e, user_data) * Evaluate(*var.right, e, user_data))*var.coef;
case AD_DIV: return (Evaluate(*var.left, e, user_data) / Evaluate(*var.right, e, user_data))*var.coef;
case AD_INV: return var.coef / Evaluate(*var.left, e, user_data);
case AD_POW: return ::pow(Evaluate(*var.left, e, user_data), Evaluate(*var.right, e, user_data))*var.coef;
case AD_SQRT: return ::sqrt(Evaluate(*var.left, e, user_data))*var.coef;
case AD_ABS: return ::fabs(Evaluate(*var.left, e, user_data))*var.coef;
case AD_EXP: return ::exp(Evaluate(*var.left, e, user_data))*var.coef;
case AD_LOG: return ::log(Evaluate(*var.left, e, user_data))*var.coef;
case AD_SIN: return ::sin(Evaluate(*var.left, e, user_data))*var.coef;
case AD_COS: return ::cos(Evaluate(*var.left, e, user_data))*var.coef;
case AD_CONST: return var.coef;
case AD_MES: assert(!(e->GetElementType() & (ESET | MESH))); Storage::real ret; m->GetGeometricData(static_cast<Element *>(e), MEASURE, &ret); return ret*var.coef;
case AD_VAL: return Evaluate(*var.left,e,user_data)*var.coef;
}
if (var.op >= AD_FUNC) return reg_funcs[var.op].func(e, user_data);
if (var.op >= AD_TABLE) return reg_tables[var.op]->get_value(Evaluate(*var.left, e, user_data))*var.coef;
if (var.op >= AD_STNCL)
{
INMOST_DATA_REAL_TYPE ret = 0.0;
stencil_kind_domain & st = reg_stencils[var.op];
assert(st.domainmask == 0 || e->GetMarker(st.domainmask));
if (st.kind == 0)
{
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);
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) if( elems[k] != NULL )
ret += var.coef * Evaluate(*var.left, elems[k], user_data) * coefs[k];
}
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) if ( get_st[k].first != NULL )
ret += var.coef * Evaluate(*var.left, get_st[k].first, user_data) * get_st[k].second;
}
return ret;
}
return values[var.data.size()-1];
if (var.op >= AD_CTAG) return GetStaticValue(e, var.op, *(INMOST_DATA_ENUM_TYPE *)(&var.left))*var.coef;
if (var.op >= AD_TAG) return GetDynamicValue(e, var.op, *(INMOST_DATA_ENUM_TYPE *)(&var.left))*var.coef;
assert(false);
return 0.0;
}
INMOST_DATA_REAL_TYPE Automatizator::Derivative(const expr & var, Storage * e, Solver::Row & out, void * user_data)
INMOST_DATA_REAL_TYPE Automatizator::Derivative(const expr & var, Storage * e, Solver::Row & out, Storage::real multiply, 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;
DerivativeFill(var, e, out, values, multiply, user_data);
return ret*multiply;
}
#endif
Automatizator::Automatizator(Mesh * m) :first_num(0), last_num(0), m(m) {}
Automatizator::~Automatizator()
{
......@@ -400,80 +623,23 @@ namespace INMOST
{
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.isDefined(etype) && it->indices.isSparse(etype))
{
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++;
}
}
for (Mesh::base_iterator jt = m->Begin(etype); jt != m->End(); ++jt)
jt->DelData(it->indices);
}
}
}
#if defined(USE_MPI)
if (m->GetProcessorsNumber() > 1)
for (index_enum::iterator it = index_tags.begin(); it != index_tags.end(); ++it)
{
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)
{
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))
......@@ -482,8 +648,9 @@ namespace INMOST
if (((etype & paralleltypes) && static_cast<Element *>(&*jt)->GetStatus() != Element::Ghost) && (it->d.domain_mask == 0 || jt->GetMarker(it->d.domain_mask)))