Example #1
0
bool
LEPlicElementInterface :: isBoundary()
{
    int i, nneighbr, ineighbr;
    double fvk, fvi = this->giveTempVolumeFraction();
    IntArray currCell(1), neighborList;
    LEPlicElementInterface *ineghbrInterface;
    Domain *domain = this->giveElement()->giveDomain();
    ConnectivityTable *contable = domain->giveConnectivityTable();
    if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) {
        // potentially boundary cell
        if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) {
            return true;
        }

        currCell.at(1) = this->giveElement()->giveNumber();
        contable->giveElementNeighbourList(neighborList, currCell);
        // loop over neighbors to assemble normal equations
        nneighbr = neighborList.giveSize();
        for ( i = 1; i <= nneighbr; i++ ) {
            ineighbr = neighborList.at(i);
            if ( ( ineghbrInterface =
                      ( LEPlicElementInterface * ) ( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
                fvk = ineghbrInterface->giveTempVolumeFraction();
                if ( fvk < 1.0 ) {
                    return true;
                }
            }
        }
    }

    return false;
}
void
FastMarchingMethod :: solve(FloatArray &dmanValues,
                            const std :: list< int > &bcDofMans,
                            double F)
{
    int candidate;
    ConnectivityTable *ct = domain->giveConnectivityTable();


    this->dmanValuesPtr = & dmanValues;
    // tag points with boundary value as known
    // then tag as trial all points that are one grid point away
    // finally tag as far all other grid points
    this->initialize(dmanValues, bcDofMans, F);

    // let candidate be the thrial point with smallest T value
    while ( ( candidate = this->getSmallestTrialDofMan() ) ) {
        // add the candidate to known, remove it from trial
        dmanRecords.at(candidate - 1).status = FMM_Status_KNOWN;
        // tag as trial all neighbors of candidate that are not known
        // if the neighbor is in far, remove and add it to the trial set
        // and recompute the values of T at all trial neighbors of candidate
        for ( int neighborElem: *ct->giveDofManConnectivityArray(candidate) ) {
            Element *ie = domain->giveElement( neighborElem );
            for ( int jn: ie->giveDofManArray() ) {
                if ( dmanRecords.at(jn - 1).status != FMM_Status_KNOWN ) {
                    // recompute the value of T at candidate trial neighbor
                    this->updateTrialValue(dmanValues, jn, F);
                }
            }
        }
    }
}
Example #3
0
int
EIPrimaryUnknownMapper :: mapAndUpdate(FloatArray &answer, ValueModeType mode,
                                       Domain *oldd, Domain *newd,  TimeStep *tStep)
{
    int inode, nd_nnodes = newd->giveNumberOfDofManagers();
    int nsize = newd->giveEngngModel()->giveNumberOfDomainEquations( newd->giveNumber(), EModelDefaultEquationNumbering() );
    FloatArray unknownValues;
    IntArray dofidMask, locationArray;
    IntArray reglist;
#ifdef OOFEM_MAPPING_CHECK_REGIONS
    ConnectivityTable *conTable = newd->giveConnectivityTable();
    const IntArray *nodeConnectivity;
#endif

    answer.resize(nsize);
    answer.zero();

    for ( inode = 1; inode <= nd_nnodes; inode++ ) {
        DofManager *node = newd->giveNode(inode);
        /* HUHU CHEATING */
#ifdef __PARALLEL_MODE
        if ( ( node->giveParallelMode() == DofManager_null ) ||
            ( node->giveParallelMode() == DofManager_remote ) ) {
            continue;
        }

#endif

#ifdef OOFEM_MAPPING_CHECK_REGIONS
        // build up region list for node
        nodeConnectivity = conTable->giveDofManConnectivityArray(inode);
        reglist.resize( nodeConnectivity->giveSize() );
        reglist.clear();
        for ( int indx = 1; indx <= nodeConnectivity->giveSize(); indx++ ) {
            reglist.insertSortedOnce( newd->giveElement( nodeConnectivity->at(indx) )->giveRegionNumber() );
        }

#endif
        ///@todo Shouldn't we pass a primary field or something to this function?
        if ( this->evaluateAt(unknownValues, dofidMask, mode, oldd, * node->giveCoordinates(), reglist, tStep) ) {
            ///@todo This doesn't respect local coordinate systems in nodes. Supporting that would require major reworking.
            for ( int ii = 1; ii <= dofidMask.giveSize(); ii++ ) {
                // exclude slaves; they are determined from masters
                auto it = node->findDofWithDofId((DofIDItem)dofidMask.at(ii));
                if ( it != node->end() ) {
                    Dof *dof = *it;
                    if ( dof->isPrimaryDof() ) {
                        int eq = dof->giveEquationNumber(EModelDefaultEquationNumbering());
                        answer.at( eq ) += unknownValues.at(ii);
                    }
                }
            }
        } else {
            OOFEM_ERROR("evaluateAt service failed for node %d", inode);
        }
    }

    return 1;
}
void
FastMarchingMethod :: initialize(FloatArray &dmanValues,
                                 const std :: list< int > &bcDofMans,
                                 double F)
{
    // tag points with boundary value as known
    // then tag as trial all points that are one grid point away
    // finally tag as far all other grid points
    int i, k, l;
    int jnode, neighborNode, nnode = domain->giveNumberOfDofManagers();
    Element *neighborElem;
    const IntArray *neighborElemList;
    ConnectivityTable *ct = domain->giveConnectivityTable();

    // all points are far by default
    dmanRecords.resize(nnode);
    for ( i = 0; i < nnode; i++ ) {
        dmanRecords [ i ].status = FMM_Status_FAR;
    }

    // first tag all boundary points
    std :: list< int > :: const_iterator it;

    for ( it = bcDofMans.begin(); it != bcDofMans.end(); ++it ) {
        if ( ( jnode = * it ) > 0 ) {
            dmanRecords.at(jnode - 1).status = FMM_Status_KNOWN;
        } else {
            dmanRecords.at(-jnode - 1).status = FMM_Status_KNOWN_BOUNDARY;
        }
    }

    // tag as trial all points that are one grid point away
    for ( it = bcDofMans.begin(); it != bcDofMans.end(); ++it ) {
        jnode = abs(* it);

        neighborElemList = ct->giveDofManConnectivityArray(jnode);
        for ( k = 1; k <= neighborElemList->giveSize(); k++ ) {
            if ( neighborElemList->at(k) == i ) {
                continue;
            }

            neighborElem = domain->giveElement( neighborElemList->at(k) );
            for ( l = 1; l <= neighborElem->giveNumberOfDofManagers(); l++ ) {
                neighborNode = neighborElem->giveDofManagerNumber(l);
                if ( ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN ) &&
                    ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN_BOUNDARY ) &&
                    ( dmanRecords.at(neighborNode - 1).status != FMM_Status_TRIAL ) ) {
                    this->updateTrialValue(dmanValues, neighborNode, F);
                }
            }
        }
    }
}
void
FastMarchingMethod :: initialize(FloatArray &dmanValues,
                                 const std :: list< int > &bcDofMans,
                                 double F)
{
    // tag points with boundary value as known
    // then tag as trial all points that are one grid point away
    // finally tag as far all other grid points
    int i;
    int nnode = domain->giveNumberOfDofManagers();
    ConnectivityTable *ct = domain->giveConnectivityTable();

    // all points are far by default
    dmanRecords.resize(nnode);
    for ( i = 0; i < nnode; i++ ) {
        dmanRecords [ i ].status = FMM_Status_FAR;
    }

    // first tag all boundary points

    for ( int jnode: bcDofMans ) {
        if ( jnode > 0 ) {
            dmanRecords.at(jnode - 1).status = FMM_Status_KNOWN;
        } else {
            dmanRecords.at(-jnode - 1).status = FMM_Status_KNOWN_BOUNDARY;
        }
    }

    // tag as trial all points that are one grid point away
    for ( int jnode: bcDofMans ) {
        jnode = abs(jnode);

        for ( int neighbor: *ct->giveDofManConnectivityArray(jnode) ) {
            ///@todo This uses "i" which will always be equal to "node" from the earlier loop. Unsafe coding.
            if ( neighbor == i ) {
                continue;
            }

            Element *neighborElem = domain->giveElement( neighbor );
            for ( int neighborNode: neighborElem->giveDofManArray() ) {
                if ( ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN ) &&
                    ( dmanRecords.at(neighborNode - 1).status != FMM_Status_KNOWN_BOUNDARY ) &&
                    ( dmanRecords.at(neighborNode - 1).status != FMM_Status_TRIAL ) ) {
                    this->updateTrialValue(dmanValues, neighborNode, F);
                }
            }
        }
    }
}
Example #6
0
double
ZZRemeshingCriteria :: giveDofManDensity(int num)
{
    int isize;
    bool init = false;
    ConnectivityTable *ct = domain->giveConnectivityTable();
    const IntArray *con;
    double density;

    con = ct->giveDofManConnectivityArray(num);
    isize = con->giveSize();

#if 0
    // Minimum density
    for ( int i = 1; i <= isize; i++ ) {
        Element *ielem = domain->giveElement( con->at(i) );
        if (i==1)
            density = ielem->computeMeanSize();
        else
            density = min(density, ielem->computeMeanSize());
    }
#endif

    // Average density

    density = 0.0;
    for ( int i = 1; i <= isize; i++ ) {
        Element *ielem = domain->giveElement( con->at(i) );
        init = true;
        density += ielem->computeMeanSize();
    }
    if ( init ) {
        density /= isize;
    } else {
        // the nodal mesh density could not be determined
        density = -1;
    }

    return density;
}
Example #7
0
double
CombinedZZSIRemeshingCriteria :: giveDofManDensity(int num)
{
    int isize;
    ConnectivityTable *ct = domain->giveConnectivityTable();
    const IntArray *con;
    double density = 0.0;

    con = ct->giveDofManConnectivityArray(num);
    isize = con->giveSize();

    for ( int i = 1; i <= isize; i++ ) {
        Element *element = domain->giveElement( con->at(i) );

        if ( i == 1 ) {
            density = element->computeMeanSize();
        } else {
            density = min( density, element->computeMeanSize() );
        }
    }

    return density;
}
Example #8
0
void
LEPlic :: doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool vof_temp_flag)
{
    int i, ineighbr, nneighbr;
    double fvi, fvk, wk, dx, dy;
    bool isBoundaryCell = false;
    LEPlicElementInterface *interface, *ineghbrInterface;
    FloatMatrix lhs(2, 2);
    FloatArray rhs(2), xi(2), xk(2);
    IntArray currCell(1), neighborList;
    ConnectivityTable *contable = domain->giveConnectivityTable();

    if ( ( interface = ( LEPlicElementInterface * ) ( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
        if ( vof_temp_flag ) {
            fvi = interface->giveTempVolumeFraction();
        } else {
            fvi = interface->giveVolumeFraction();
        }

        if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) {
            // potentially boundary cell

            if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) {
                isBoundaryCell = true;
            }

            /* DLS (Differential least square reconstruction)
             *
             * In the DLS method, volume fraction Taylor series expansion of vf (volume fraction)
             * is formed from each reference cell volume fraction vf at element center x(i) to each
             * cell neighbor at point x(k). The sum (vf(i)-vf(k))^2 over all immediate neighbors
             * is then minimized inthe least square sense.
             */
            // get list of neighbours to current cell including current cell
            currCell.at(1) = ie;
            contable->giveElementNeighbourList(neighborList, currCell);
            // loop over neighbors to assemble normal equations
            nneighbr = neighborList.giveSize();
            interface->giveElementCenter(this, xi, coord_upd);
            lhs.zero();
            rhs.zero();
            for ( i = 1; i <= nneighbr; i++ ) {
                ineighbr = neighborList.at(i);
                if ( ineighbr == ie ) {
                    continue;         // skip itself
                }

                if ( ( ineghbrInterface =
                          ( LEPlicElementInterface * ) ( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) {
                    if ( vof_temp_flag ) {
                        fvk = ineghbrInterface->giveTempVolumeFraction();
                    } else {
                        fvk = ineghbrInterface->giveVolumeFraction();
                    }

                    if ( fvk < 1.0 ) {
                        isBoundaryCell = true;
                    }

                    ineghbrInterface->giveElementCenter(this, xk, coord_upd);
                    wk = xk.distance(xi);
                    dx = ( xk.at(1) - xi.at(1) ) / wk;
                    dy = ( xk.at(2) - xi.at(2) ) / wk;
                    lhs.at(1, 1) += dx * dx;
                    lhs.at(1, 2) += dx * dy;
                    lhs.at(2, 2) += dy * dy;

                    rhs.at(1) += ( fvi - fvk ) * dx / wk;
                    rhs.at(2) += ( fvi - fvk ) * dy / wk;
                }
            }

            if ( isBoundaryCell ) {
                // symmetry
                lhs.at(2, 1) = lhs.at(1, 2);

                // solve normal equation for volume fraction gradient
                lhs.solveForRhs(rhs, fvgrad);

                // compute unit normal
                fvgrad.normalize();
                fvgrad.negated();
#ifdef __OOFEG
                /*
                 * EASValsSetLayer(OOFEG_DEBUG_LAYER);
                 * WCRec p[2];
                 * double tx = -fvgrad.at(2), ty=fvgrad.at(1);
                 * p[0].x=xi.at(1)-tx*0.1;
                 * p[0].y=xi.at(2)-ty*0.1;
                 * p[1].x=xi.at(1)+tx*0.1;
                 * p[1].y=xi.at(2)+ty*0.1;
                 * p[0].z = p[1].z = 0.0;
                 * GraphicObj *go = CreateLine3D(p);
                 * EGWithMaskChangeAttributes(LAYER_MASK, go);
                 * EMAddGraphicsToModel(ESIModel(), go);
                 * ESIEventLoop (YES, "Cell DLS finished; Press Ctrl-p to continue");
                 */
#endif
            } else {
                fvgrad.zero();
            }
        }
    }
}
void
ParmetisLoadBalancer :: labelDofManagers()
{
    int idofman, ndofman = domain->giveNumberOfDofManagers();
    ConnectivityTable *ct = domain->giveConnectivityTable();
    const IntArray *dofmanconntable;
    DofManager *dofman;
    Element *ielem;
    dofManagerParallelMode dmode;
    std :: set< int, std :: less< int > >__dmanpartitions;
    int myrank = domain->giveEngngModel()->giveRank();
    int nproc = domain->giveEngngModel()->giveNumberOfProcesses();
    int ie, npart;

    // resize label array
    dofManState.resize(ndofman);
    dofManState.zero();
    // resize dof man partitions
    dofManPartitions.clear();
    dofManPartitions.resize(ndofman);

 #ifdef ParmetisLoadBalancer_DEBUG_PRINT
    int _cols = 0;
    fprintf(stderr, "[%d] DofManager labels:\n", myrank);
 #endif

    // loop over local dof managers
    for ( idofman = 1; idofman <= ndofman; idofman++ ) {
        dofman = domain->giveDofManager(idofman);
        dmode = dofman->giveParallelMode();
        if ( ( dmode == DofManager_local ) || ( dmode == DofManager_shared ) ) {
            dofmanconntable = ct->giveDofManConnectivityArray(idofman);
            __dmanpartitions.clear();
            for ( ie = 1; ie <= dofmanconntable->giveSize(); ie++ ) {
                ielem = domain->giveElement( dofmanconntable->at(ie) );
                // assemble list of partitions sharing idofman dofmanager
                // set is used to include possibly repeated partition only once
                if ( ielem->giveParallelMode() == Element_local ) {
                    __dmanpartitions.insert( giveElementPartition( dofmanconntable->at(ie) ) );
                }
            }

            npart = __dmanpartitions.size();
            dofManPartitions [ idofman - 1 ].resize( __dmanpartitions.size() );
            int i = 1;
            for ( auto &dm: __dmanpartitions ) {
                dofManPartitions [ idofman - 1 ].at(i++) = dm;
            }
        }
    }

    // handle master slave links between dofmans (master and slave required on same partition)
    this->handleMasterSlaveDofManLinks();


    /* Exchange new partitions for shared nodes */
    CommunicatorBuff cb(nproc, CBT_dynamic);
    Communicator com(domain->giveEngngModel(), &cb, myrank, nproc, CommMode_Dynamic);
    com.packAllData(this, & ParmetisLoadBalancer :: packSharedDmanPartitions);
    com.initExchange(SHARED_DOFMAN_PARTITIONS_TAG);
    com.unpackAllData(this, & ParmetisLoadBalancer :: unpackSharedDmanPartitions);
    com.finishExchange();

    /* label dof managers */
    for ( idofman = 1; idofman <= ndofman; idofman++ ) {
        dofman = domain->giveDofManager(idofman);
        dmode = dofman->giveParallelMode();
        npart = dofManPartitions [ idofman - 1 ].giveSize();
        if ( ( dmode == DofManager_local ) || ( dmode == DofManager_shared ) ) {
            // determine its state after balancing -> label
            dofManState.at(idofman) = this->determineDofManState(idofman, myrank, npart, & dofManPartitions [ idofman - 1 ]);
        } else {
            dofManState.at(idofman) = DM_NULL;
        }
    }


 #ifdef ParmetisLoadBalancer_DEBUG_PRINT
    for ( idofman = 1; idofman <= ndofman; idofman++ ) {
        fprintf(stderr, " | %d: ", idofman);
        if ( dofManState.at(idofman) == DM_NULL ) {
            fprintf(stderr, "NULL  ");
        } else if ( dofManState.at(idofman) == DM_Local ) {
            fprintf(stderr, "Local ");
        } else if ( dofManState.at(idofman) == DM_Shared ) {
            fprintf(stderr, "Shared");
        } else if ( dofManState.at(idofman) == DM_Remote ) {
            fprintf(stderr, "Remote");
        } else {
            fprintf(stderr, "Unknown");
        }

        //else if (dofManState.at(idofman) == DM_SharedExclude)fprintf (stderr, "ShdExc");
        //else if (dofManState.at(idofman) == DM_SharedNew)    fprintf (stderr, "ShdNew");
        //else if (dofManState.at(idofman) == DM_SharedUpdate) fprintf (stderr, "ShdUpd");

        if ( ( ( ++_cols % 4 ) == 0 ) || ( idofman == ndofman ) ) {
            fprintf(stderr, "\n");
        }
    }

 #endif
}
Example #10
0
void XfemManager :: updateNodeEnrichmentItemMap()
{
    Domain *domain = giveDomain();
    int nDMan = domain->giveNumberOfDofManagers();
    mNodeEnrichmentItemIndices.clear();
    mNodeEnrichmentItemIndices.resize(nDMan);

    int nElem = domain->giveNumberOfElements();
    mElementEnrichmentItemIndices.clear();

    for ( int i = 1; i <= nElem; i++ ) {
        int elIndex = domain->giveElement(i)->giveGlobalNumber();
        int elPlaceInArray = domain->giveElementPlaceInArray(elIndex);
        if ( i != elPlaceInArray ) {
            printf("i != elPlaceInArray.\n");
            exit(0);
        }
        mElementEnrichmentItemIndices [ elPlaceInArray ].clear();
    }

    int nEI = giveNumberOfEnrichmentItems();

    for ( int eiIndex = 1; eiIndex <= nEI; eiIndex++ ) {
        EnrichmentItem *ei = giveEnrichmentItem(eiIndex);

        const std :: unordered_map< int, NodeEnrichmentType > &enrNodeInd = ei->giveEnrNodeMap();

        //for(size_t i = 0; i < enrNodeInd.size(); i++) {
        for ( auto &nodeEiPair: enrNodeInd ) {
            mNodeEnrichmentItemIndices [ nodeEiPair.first - 1 ].push_back(eiIndex);

            ConnectivityTable *ct = domain->giveConnectivityTable();
            //const IntArray *nodeElements = ct->giveDofManConnectivityArray(nodeEiPair.first);
            IntArray nodeElements;
            IntArray nodeList = {
                nodeEiPair.first
            };
            ct->giveNodeNeighbourList(nodeElements, nodeList);

            for ( int i = 1; i <= nodeElements.giveSize(); i++ ) {
                int elInd = nodeElements.at(i);

                bool found = false;
                for ( size_t j = 0; j < mElementEnrichmentItemIndices [ elInd ].size(); j++ ) {
                    if ( mElementEnrichmentItemIndices [ elInd ] [ j ] == eiIndex ) {
                        found = true;
                        break;
                    }
                }

                if ( !found ) {
                    mElementEnrichmentItemIndices [ elInd ].push_back(eiIndex);
                }
            }
        }
    }




    mMaterialModifyingEnrItemIndices.clear();
    for ( int eiIndex = 1; eiIndex <= nEI; eiIndex++ ) {
        EnrichmentItem *ei = giveEnrichmentItem(eiIndex);

        if ( ei->canModifyMaterial() ) {
            mMaterialModifyingEnrItemIndices.push_back(eiIndex);
        }
    }
}
void
FastMarchingMethod :: updateTrialValue(FloatArray &dmanValues, int id, double F)
{
    int ai, bi, ci, h, nroot, _ind = 0;
    double at, bt, ht, a, b, u, cos_fi, sin_fi, _a, _b, _c, r1, r2, r3, t = 0.0, _h;
    bool reg_upd_flag;
    FloatArray *ac, *bc, *cc, cb, ca;
    ConnectivityTable *ct = domain->giveConnectivityTable();


    // first look for suitable element that can produce admissible value
    // algorithm limited to non-obtuse 2d triangulations
    for ( int neighborElem: *ct->giveDofManConnectivityArray(id) ) {
        // test element if admissible
        Element *ie = domain->giveElement( neighborElem );
        if ( ie->giveGeometryType() == EGT_triangle_1 ) {
            for ( int j = 1; j <= 3; j++ ) {
                if ( ie->giveDofManagerNumber(j) == id ) {
                    _ind = j;
                }
            }

            ci = ie->giveDofManagerNumber(_ind);
            ai = ie->giveDofManagerNumber(1 + ( _ind ) % 3);
            bi = ie->giveDofManagerNumber(1 + ( _ind + 1 ) % 3);

            if ( ( dmanRecords.at(ai - 1).status == FMM_Status_KNOWN ) &&
                ( dmanRecords.at(bi - 1).status == FMM_Status_KNOWN ) ) {
                at = dmanValues.at(ai);
                bt = dmanValues.at(bi);
                if ( fabs(at) > fabs(bt) ) {
                    h = ai;
                    ai = bi;
                    bi = h;
                    ht = at;
                    at = bt;
                    bt = ht;
                }

                // get nodal coordinates
                ac = domain->giveNode(ai)->giveCoordinates();
                bc = domain->giveNode(bi)->giveCoordinates();
                cc = domain->giveNode(ci)->giveCoordinates();

                // a = distance of BC
                a = cc->distance(bc);
                // b = distance of AC
                b = cc->distance(ac);
                // compute fi angle
                cb.beDifferenceOf(* bc, * cc);
                cb.normalize();
                ca.beDifferenceOf(* ac, * cc);
                ca.normalize();
                cos_fi = cb.dotProduct(ca);
                sin_fi = sqrt(1.0 - cos_fi * cos_fi);
                u = fabs(bt);
                // compute quadratic equation coefficients for t
                _a = ( a * a + b * b - 2.0 * a * b * cos_fi );
                _b = 2.0 * b * u * ( a * cos_fi - b );
                _c = b * b * ( u * u - F * F * a * a * sin_fi * sin_fi );
                cubic3r(0.0, _a, _b, _c, & r1, & r2, & r3, & nroot);
                reg_upd_flag = true;

                if ( nroot == 0 ) {
                    reg_upd_flag = false;
                } else if ( nroot == 1 ) {
                    t = r1;
                } else if ( r1 >= 0.0 ) {
                    t = r1;
                } else if ( r2 >= 0.0 ) {
                    t = r2;
                } else {
                    reg_upd_flag = false;
                }

                if ( reg_upd_flag ) {
                    _h = b * ( t - u ) / t;
                    if ( ( t > u ) && ( _h > a * cos_fi ) && ( _h < a / cos_fi ) ) {
                        if ( dmanRecords.at(ci - 1).status == FMM_Status_FAR ) {
                            dmanValues.at(ci) = sgn(F) * t + at;
                        } else if ( F > 0. ) {
                            dmanValues.at(ci) = min(dmanValues.at(ci), sgn(F) * t + at);
                        } else {
                            dmanValues.at(ci) = max(dmanValues.at(ci), sgn(F) * t + at);
                        }
                    } else {
                        reg_upd_flag = false;
                    }
                }

                if ( !reg_upd_flag ) {
                    if ( F > 0. ) {
                        _h = min(b * F + at, a * F + bt);
                    } else {
                        _h = max(b * F + at, a * F + bt);
                    }

                    if ( dmanRecords.at(ci - 1).status == FMM_Status_FAR ) {
                        dmanValues.at(ci) = _h;
                    } else if ( F > 0. ) {
                        dmanValues.at(ci) = min(dmanValues.at(ci), _h);
                    } else {
                        dmanValues.at(ci) = max(dmanValues.at(ci), _h);
                    }
                }

                // if not yet in queue (trial for the first time), put it there
                if ( dmanRecords.at(ci - 1).status != FMM_Status_TRIAL ) {
                    dmanTrialQueue.push(ci);
                }

                dmanRecords.at(ci - 1).status = FMM_Status_TRIAL;
            } // admissible triangle
        } // end EGT_triangle_1 element type
    }
}
int
EIPrimaryUnknownMapper :: mapAndUpdate(FloatArray &answer, ValueModeType mode,
                                       Domain *oldd, Domain *newd,  TimeStep *tStep)
{
    int inode, nd_nnodes = newd->giveNumberOfDofManagers();
    int nsize = newd->giveEngngModel()->giveNumberOfDomainEquations(newd->giveNumber(), EModelDefaultEquationNumbering());
    FloatArray unknownValues;
    IntArray dofMask, locationArray;
    IntArray reglist;
#ifdef OOFEM_MAPPING_CHECK_REGIONS
    ConnectivityTable *conTable = newd->giveConnectivityTable();
    const IntArray *nodeConnectivity;
#endif

    answer.resize(nsize);
    answer.zero();

    for ( inode = 1; inode <= nd_nnodes; inode++ ) {
        /* HUHU CHEATING */
#ifdef __PARALLEL_MODE
        if ( ( newd->giveNode(inode)->giveParallelMode() == DofManager_null ) ||
            ( newd->giveNode(inode)->giveParallelMode() == DofManager_remote ) ) {
            continue;
        }

#endif

#ifdef OOFEM_MAPPING_CHECK_REGIONS
        // build up region list for node
        nodeConnectivity = conTable->giveDofManConnectivityArray(inode);
        reglist.resize( nodeConnectivity->giveSize() );
        reglist.resize(0);
        for ( int indx = 1; indx <= nodeConnectivity->giveSize(); indx++ ) {
            reglist.insertSortedOnce( newd->giveElement( nodeConnectivity->at(indx) )->giveRegionNumber() );
        }

#endif

        if ( this->evaluateAt(unknownValues, dofMask, mode, oldd, * newd->giveNode(inode)->giveCoordinates(), reglist, tStep) ) {
            //
            //  WARNING !! LIMITED IMPLEMENTATION HERE !!
            //
            // possible source of error -> general service allowing to request all DOFs interpolated by element
            // should be there, but newNode can accommodate only certain dofs.
            //
            //
            newd->giveNode(inode)->giveLocationArray( dofMask, locationArray, EModelDefaultEquationNumbering() );
            if ( newd->giveNode(inode)->hasAnySlaveDofs() ) {
                for ( int ii = 1; ii <= dofMask.giveSize(); ii++ ) { ///@todo How should be deal with slave dofs and such? dofMask.size() != locationArray.size() will happen
                    // exclude slaves; they are determined from masters
                    if ( newd->giveNode(inode)->giveDof(ii)->isPrimaryDof() ) {
                        answer.at( locationArray.at(ii) ) += unknownValues.at(ii);
                    }
                }
            } else {
                // assemble the interpolated values to global vector using locationArray of new node
                answer.assemble(unknownValues, locationArray);
            }
        } else {
            OOFEM_ERROR2("EIPrimaryUnknownMapper :: mapAndUpdate - evaluateAt service failed for node %d", inode);
        }
    }

    return 1;
}