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); } } } } }
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); } } } } }
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; }
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; }
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 }
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; }