/** * \param[in] rcells * \param[out] adjncy */ template< size_t NDIM > void UnstructuredBlock< NDIM >::build_csr( const LookupTable<index_type, CLMFC> & rcells , LookupTable<index_type, 0> & adjncy) const { // iterators. int icl, ifl, ieg; // fill. index_type const * prcells = reinterpret_cast<index_type const *>(rcells.row(0)); index_type * padjncy = reinterpret_cast<index_type *>(adjncy.row(0)); ieg = 0; for (icl=0; icl<ncell(); icl++) { for (ifl=0; ifl<CLMFC; ifl++) { if (prcells[ifl] != -1) { padjncy[ieg] = prcells[ifl]; ieg += 1; }; }; // advance pointers. prcells += CLMFC; }; };
void PltWin::drawIt(QPainter *p) { QString txt; double x, y, x0, y0, x1, y1, x2, y2, xprev, yprev, shift, ubmin, ubmax, ub, alpha; int n, layer, lay, prev_layer, circDia, i, j, at, ichain, a, istart, iend, icurr, xs, ys; int idx, nmax; bool dum; QPen *pen = new QPen(); QBrush *brush = new QBrush(); QBrush *brush_unrld = new QBrush(); // antialiasing of primitives if ANTIALIASE is set to true if (!paintEPS) p->setRenderHint(QPainter::Antialiasing, ANTIALIASE); // plot the grain boundary line if (isGBfile && showGB) { x0 = ZFact*xyzMin(1) - xPan - (ZFact-1)*xyzCen(1); x1 = ZFact*xyzMax(1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*gbYcoor - yPan - (ZFact-1)*xyzCen(2); DrawLine(p, x0, y, x1, y); } if (AtomPos==COMPOSITE) { if (!paintEPS) { brush_unrld->setColor( Qt::lightGray ); brush_unrld->setStyle( Qt::SolidPattern ); } } // plotting of atomic arrangement in the initial configuration prev_layer = -1; x0 = y0 = x1 = y1 = 0; // need to construct the neighbor list in the relaxed configuration if (plotType == PLOT_ATOM_NEIGHBORS) { if (AtomPos == UNRELAXED && NeighListInit.data == NULL) InitNeighborList(this, NeighListInit, numNeighInit); if ((AtomPos == RELAXED || AtomPos == COMPOSITE) && NeighListRel.data == NULL) RelNeighborList(this, rcut, NeighListRel, numNeighRel); if (AtomPos == UNRELAXED) { nmax = -1; for (at=1; at<=NInit; at++) { n = numNeighInit(at); if (n > nmax) nmax = n; } colormap(nmax+1, cmap); } if (AtomPos == RELAXED) { nmax = -1; for (at=1; at<=NRel; at++) { n = numNeighRel(at); if (n > nmax) nmax = n; } colormap(nmax+1, cmap); } } if (plotType == PLOT_ATOM_TYPES) { nmax = -1; for (at=1; at<=NInit; at++) { n = atomType(at); if (n > nmax) nmax = n; } colormap(nmax, cmap); } // // Plot the atomic configuration such that the atoms in the front (in the top layer) are plotted // at the end. // for (i=1; i<=NInit; i++) { at = aorder(i); if (!zLayerSel(zLayer(at))) continue; layer = zLayer(at); circDia = zDiamLayer(layer); switch(plotType) { case PLOT_ATOM_LAYERS: layer = zLayer(at); if (!paintEPS && layer != prev_layer) { pen->setColor(zColorLayer(layer, 1)); pen->setWidth(zLineThickLayer(layer)); p->setPen(*pen); brush->setColor(zColorLayer(layer, 2)); brush->setStyle(Qt::SolidPattern); p->setBrush(*brush); } break; case PLOT_ATOM_TYPES: lay = layer; layer = atomType(at); if (!paintEPS && layer != prev_layer) { pen->setColor(Qt::black); pen->setWidth(zLineThickLayer(lay)); p->setPen(*pen); if (layer == 0) { brush->setColor(Qt::lightGray); } else { brush->setColor(cmap[layer-1]); } brush->setStyle(Qt::SolidPattern); p->setBrush(*brush); } break; case PLOT_ATOM_NEIGHBORS: lay = layer; if (AtomPos == UNRELAXED) layer = numNeighInit(at); else if (AtomPos == RELAXED || AtomPos == COMPOSITE) layer = numNeighRel(at); if (!paintEPS && layer != prev_layer) { pen->setColor(Qt::black); pen->setWidth(zLineThickLayer(lay)); p->setPen(*pen); if (layer == 0) brush->setColor(Qt::lightGray); else { brush->setColor(QColor(cmap[layer])); } brush->setStyle(Qt::SolidPattern); p->setBrush(*brush); } break; } if (layer != prev_layer) prev_layer = layer; switch(AtomPos) { case UNRELAXED: x = ZFact*xyzInit(at,1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*xyzInit(at,2) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, at, x, y, circDia); break; case RELAXED: x = ZFact*(xyzInit(at,1) + AtomDispScale*aDisp(at,1)) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*(xyzInit(at,2) + AtomDispScale*aDisp(at,2)) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, at, x, y, circDia); break; case COMPOSITE: if (!paintEPS) { p->setBrush( *brush_unrld ); } x = ZFact*xyzInit(at,1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*xyzInit(at,2) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, -1, x, y, circDia); if (!paintEPS) { p->setBrush( *brush ); } x = ZFact*(xyzInit(at,1) + AtomDispScale*aDisp(at,1)) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*(xyzInit(at,2) + AtomDispScale*aDisp(at,2)) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, at, x, y, circDia); break; } if (x < x0) x0 = x; if (x > x1) x1 = x; if (y < y0) y0 = y; if (y > y1) y1 = y; // atom numbers if (AtomNumbers) { txt.sprintf("%d", at); shift = circDia/(2.0*factor); DrawText(p, x+shift, y+shift, txt); } } // plot the inert atoms if (InertAtoms) { if (!paintEPS) { pen->setColor(Qt::black); pen->setWidth(zLineThickLayer(layer)); p->setPen(*pen); brush->setColor(Qt::black); brush->setStyle(Qt::NoBrush); p->setBrush( *brush ); } for (at=1; at<=NInert; at++) { // plot only those atoms which belong to the selected (active) layers // if (!zLayerSel(zLayer(n))) // continue; x = ZFact*xyzInert(at,1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*xyzInert(at,2) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, 0, x, y, circDia); } } // highlight the atoms picked if (!paintEPS && napicked > 0) { pen->setColor(Qt::green); pen->setWidth(2); p->setPen(*pen); brush->setStyle(Qt::NoBrush); p->setBrush(*brush); dum = ATOM_3DSPHERE; ATOM_3DSPHERE = false; for (n=1; n<=napicked; n++) { at = apicked(n); x = ZFact*xyzInit(at,1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*xyzInit(at,2) - yPan - (ZFact-1)*xyzCen(2); DrawAtom(p, at, x, y, circDia+4); if (n > 1) DrawLine(p, xprev, yprev, x, y); xprev = x; yprev = y; } ATOM_3DSPHERE = dum; } // highlight the atoms in selected chains if (!paintEPS && nchain > 0) { pen->setColor(Qt::green); pen->setWidth(2); p->setPen(*pen); for (ichain=1; ichain<=nchain; ichain++) { for (i=1; i<=nachain(ichain); i++) { a = achain(ichain,i); x = ZFact*xyzInit(a,1) - xPan - (ZFact-1)*xyzCen(1); y = ZFact*xyzInit(a,2) - yPan - (ZFact-1)*xyzCen(2); if (i>1) DrawLine(p, x0, y0, x, y); x0 = x; y0 = y; } } if (!paintEPS && nchain >= 2) { QPen *pen2 = new QPen(); pen2->setColor(Qt::green); pen2->setStyle(Qt::DashLine); p->setPen(*pen2); for (i=1; i<nchain; i+=2) { x1 = ZFact*dposchain(i,1) - xPan - (ZFact-1)*xyzCen(1); y1 = ZFact*dposchain(i,2) - yPan - (ZFact-1)*xyzCen(2); x2 = ZFact*dposchain(i+1,1) - xPan - (ZFact-1)*xyzCen(1); y2 = ZFact*dposchain(i+1,2) - yPan - (ZFact-1)*xyzCen(2); DrawLine(p, x1, y1, x2, y2); } } } // plotting the coordinate system centered at the initial position of // the dislocation line if (PlaneTraces) DrawPlaneTraces(p, x0, y0, x1, y1); // plotting of arrows if (arrNeighNum > 0) { if (!paintEPS) { pen->setColor(Qt::black); pen->setWidth(thicknessArrow); p->setPen(*pen); p->setBrush(Qt::black); } switch(DispComponent) { case EDGE: plotEdgeComponent(p); break; case SCREW: plotScrewComponent(p); break; case PROJ: plotScrewComponent(p); // plotted the same way as screw components break; case DIFF_EDGE: case DIFF_SCREW: plotDifference(p); break; } } // position of dislocation center if (DisloCenter) { DrawLine(p, xCore, y0, xCore, y1); DrawLine(p, x0, yCore, x1, yCore); } // small inset to show the active Z-layers if (!paintEPS && showZLayers) ShowActiveZLayers(p); // show color map if (!paintEPS && (plotType == PLOT_ATOM_TYPES || plotType == PLOT_ATOM_NEIGHBORS)) ShowColorMap(p); // lines showing the division of the block into cells (for the linked neighbor list) if (showNeighCells) { if (!paintEPS) { pen->setColor(Qt::black); p->setPen(*pen); } for (i=0; i<=ncell(1); i++) { x = ZFact*(xyzMin(1)+i*cellsize(1)) - xPan - (ZFact-1)*xyzCen(1); y0 = ZFact*xyzMin(2) - yPan - (ZFact-1)*xyzCen(2); y1 = ZFact*xyzMax(2) - yPan - (ZFact-1)*xyzCen(2); DrawLine(p, x, y0, x, y1); for (j=0; j<=ncell(2); j++) { y = ZFact*(xyzMin(2)+j*cellsize(2)) - yPan - (ZFact-1)*xyzCen(2); x0 = ZFact*xyzMin(1) - xPan - (ZFact-1)*xyzCen(1); x1 = ZFact*xyzMax(1) - xPan - (ZFact-1)*xyzCen(1); DrawLine(p, x0, y, x1, y); } } } // coordinate system of the block if (!paintEPS && showCSys) ShowCSys(p); // show the polygon that encompasses the dislocation center if (!paintEPS && ndpoly > 0) { pen->setColor(Qt::green); p->setPen(*pen); for (n=1; n<=ndpoly; n++) { x1 = ZFact*dpoly(n,1) - xPan - (ZFact-1)*xyzCen(1); y1 = ZFact*dpoly(n,2) - yPan - (ZFact-1)*xyzCen(2); if (n<ndpoly) { x2 = ZFact*dpoly(n+1,1) - xPan - (ZFact-1)*xyzCen(1); y2 = ZFact*dpoly(n+1,2) - yPan - (ZFact-1)*xyzCen(2); } else { x2 = ZFact*dpoly(1,1) - xPan - (ZFact-1)*xyzCen(1); y2 = ZFact*dpoly(1,2) - yPan - (ZFact-1)*xyzCen(2); } DrawLine(p, x1, y1, x2, y2); } } if (!paintEPS && ndpath > 0) { pen->setColor(Qt::green); p->setPen(*pen); brush->setColor(Qt::green); brush->setStyle(Qt::NoBrush); p->setBrush(*brush); for (n=1; n<ndpath; n++) { x1 = ZFact*dpath(n,1) - xPan - (ZFact-1)*xyzCen(1); y1 = ZFact*dpath(n,2) - yPan - (ZFact-1)*xyzCen(2); x2 = ZFact*dpath(n+1,1) - xPan - (ZFact-1)*xyzCen(1); y2 = ZFact*dpath(n+1,2) - yPan - (ZFact-1)*xyzCen(2); DrawLine(p, x1, y1, x2, y2); if (n==1) { xyWorldToScreen(x1, y1, xs, ys); xs -= 2; ys -= 2; p->drawEllipse(xs, ys, 4, 4); } xyWorldToScreen(x2, y2, xs, ys); xs -= 2; ys -= 2; p->drawEllipse(xs, ys, 4, 4); } } }
void UnstructuredBlock< NDIM >::build_faces_from_cells() { // pointers. int *pcltpn, *pclnds, *pclfcs, *pfctpn, *pfcnds, *pfccls; int *pifctpn, *pjfctpn, *pifcnds, *pjfcnds; int *pndfcs; // buffers. int *ndnfc, *ndfcs, *map, *map2; // scalars. int tpnicl, ndmfc, cond; // iterator. int icl, ifc, jfc, inf, jnf, ind, nd1, ifl; int it; const index_type mface = calc_max_nface(cltpn()); index_type computed_nface = -1; // create temporary tables. LookupTable<index_type, MAX_CLNFC+1> tclfcs(0, ncell()); LookupTable<index_type, 0> tfctpn(0, mface); LookupTable<index_type, MAX_FCNND+1> tfcnds(0, mface); LookupTable<index_type, FCNCL > tfccls(0, mface); tclfcs.fill(-1); tfcnds.fill(-1); tfccls.fill(-1); index_type * lclfcs = reinterpret_cast<index_type *>(tclfcs.row(0)); index_type * lfctpn = reinterpret_cast<shape_type *>(tfctpn.row(0)); index_type * lfcnds = reinterpret_cast<index_type *>(tfcnds.row(0)); index_type * lfccls = reinterpret_cast<index_type *>(tfccls.row(0)); // extract face definition from the node list of cells. pcltpn = reinterpret_cast<index_type *>(cltpn().row(0)); pclnds = reinterpret_cast<index_type *>(clnds().row(0)); pclfcs = lclfcs; pfctpn = lfctpn; pfcnds = lfcnds; ifc = 0; for (icl=0; icl<ncell(); icl++) { tpnicl = pcltpn[0]; // parse each type of cell. if (tpnicl == 0) { } else if (tpnicl == 1) { // line. // extract 2 points from a line. pclfcs[0] = 2; for (it=0; it<pclfcs[0]; it++) { pfctpn[it] = 0; // face type is point. pfcnds[it*(FCMND+1)] = 1; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 2) { // quadrilateral. // extract 4 lines from a quadrilateral. pclfcs[0] = 4; for (it=0; it<pclfcs[0]; it++) { pfctpn[it] = 1; // face type is line. pfcnds[it*(FCMND+1)] = 2; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[3]; pfcnds[2] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; // face 4. pclfcs[4] = ifc; pfcnds[1] = pclnds[4]; pfcnds[2] = pclnds[1]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 3) { // triangle. // extract 3 lines from a triangle. pclfcs[0] = 3; for (it=0; it<pclfcs[0]; it++) { pfctpn[it] = 1; // face type is line. pfcnds[it*(FCMND+1)] = 2; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[3]; pfcnds[2] = pclnds[1]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 4) { // hexahedron. // extract 6 quadrilaterals from a hexahedron. pclfcs[0] = 6; for (it=0; it<pclfcs[0]; it++) { pfctpn[it] = 2; // face type is quadrilateral. pfcnds[it*(FCMND+1)] = 4; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[4]; pfcnds[3] = pclnds[3]; pfcnds[4] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[3]; pfcnds[3] = pclnds[7]; pfcnds[4] = pclnds[6]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[5]; pfcnds[2] = pclnds[6]; pfcnds[3] = pclnds[7]; pfcnds[4] = pclnds[8]; pfcnds += FCMND+1; ifc += 1; // face 4. pclfcs[4] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[8]; pfcnds[4] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; // face 5. pclfcs[5] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[2]; pfcnds[3] = pclnds[6]; pfcnds[4] = pclnds[5]; pfcnds += FCMND+1; ifc += 1; // face 6. pclfcs[6] = ifc; pfcnds[1] = pclnds[3]; pfcnds[2] = pclnds[4]; pfcnds[3] = pclnds[8]; pfcnds[4] = pclnds[7]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 5) { // tetrahedron. // extract 4 triangles from a tetrahedron. pclfcs[0] = 4; for (it=0; it<pclfcs[0]; it++) { pfctpn[it] = 3; // face type is triangle. pfcnds[it*(FCMND+1)] = 3; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[3]; pfcnds[3] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[2]; pfcnds[3] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[4]; pfcnds[3] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; // face 4. pclfcs[4] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[3]; pfcnds[3] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 6) { // prism. // extract 2 triangles and 3 quadrilaterals from a prism. pclfcs[0] = 5; for (it=0; it<2; it++) { pfctpn[it] = 3; // face type is triangle. pfcnds[it*(FCMND+1)] = 3; // number of nodes per face. }; for (it=2; it<pclfcs[0]; it++) { pfctpn[it] = 2; // face type is quadrilateral. pfcnds[it*(FCMND+1)] = 4; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[2]; pfcnds[3] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[4]; pfcnds[2] = pclnds[6]; pfcnds[3] = pclnds[5]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[4]; pfcnds[3] = pclnds[5]; pfcnds[4] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 4. pclfcs[4] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[3]; pfcnds[3] = pclnds[6]; pfcnds[4] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; // face 5. pclfcs[5] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[6]; pfcnds[4] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; } else if (tpnicl == 7) { // pyramid. // extract 4 triangles and 1 quadrilaterals from a pyramid. pclfcs[0] = 5; for (it=0; it<4; it++) { pfctpn[it] = 3; // face type is triangle. pfcnds[it*(FCMND+1)] = 3; // number of nodes per face. }; for (it=4; it<pclfcs[0]; it++) { pfctpn[it] = 2; // face type is quadrilateral. pfcnds[it*(FCMND+1)] = 4; // number of nodes per face. }; pfctpn += pclfcs[0]; // face 1. pclfcs[1] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[4]; pfcnds += FCMND+1; ifc += 1; // face 2. pclfcs[2] = ifc; pfcnds[1] = pclnds[2]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[1]; pfcnds += FCMND+1; ifc += 1; // face 3. pclfcs[3] = ifc; pfcnds[1] = pclnds[3]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; // face 4. pclfcs[4] = ifc; pfcnds[1] = pclnds[4]; pfcnds[2] = pclnds[5]; pfcnds[3] = pclnds[3]; pfcnds += FCMND+1; ifc += 1; // face 5. pclfcs[5] = ifc; pfcnds[1] = pclnds[1]; pfcnds[2] = pclnds[4]; pfcnds[3] = pclnds[3]; pfcnds[4] = pclnds[2]; pfcnds += FCMND+1; ifc += 1; }; // advance pointers. pcltpn += 1; pclnds += CLMND+1; pclfcs += CLMFC+1; }; // build the hash table, to know what faces connect to each node. /// first pass: get the maximum number of faces. ndnfc = (int *)malloc((size_t)nnode()*sizeof(int)); for (ind=0; ind<nnode(); ind++) { // initialize. ndnfc[ind] = 0; }; pfcnds = lfcnds; // count. for (ifc=0; ifc<mface; ifc++) { for (inf=1; inf<=pfcnds[0]; inf++) { ind = pfcnds[inf]; // node of interest. ndnfc[ind] += 1; // increment counting. }; // advance pointers. pfcnds += FCMND+1; }; ndmfc = 0; // get maximum. for (ind=0; ind<nnode(); ind++) { if (ndnfc[ind] > ndmfc) { ndmfc = ndnfc[ind]; }; }; free(ndnfc); /// second pass: scan again to build hash table. ndfcs = (int *)malloc((size_t)nnode()*(ndmfc+1)*sizeof(int)); pndfcs = ndfcs; // initialize. for (ind=0; ind<nnode(); ind++) { pndfcs[0] = 0; for (it=1; it<=ndmfc; it++) { // <= or < ?? pndfcs[it] = -1; }; // advance pointers; pndfcs += ndmfc+1; }; pfcnds = lfcnds; // build hash table mapping from node to face. for (ifc=0; ifc<mface; ifc++) { for (inf=1; inf<=pfcnds[0]; inf++) { ind = pfcnds[inf]; // node of interest. pndfcs = ndfcs + ind*(ndmfc+1); pndfcs[0] += 1; // increment face count for the node. pndfcs[pndfcs[0]] = ifc; }; // advance pointers. pfcnds += FCMND+1; }; // scan for duplicated faces and build duplication map. map = (int *)malloc((size_t)mface*sizeof(int)); for (ifc=0; ifc<mface; ifc++) { // initialize. map[ifc] = ifc; }; for (ifc=0; ifc<mface; ifc++) { if (map[ifc] == ifc) { pifcnds = lfcnds + ifc*(FCMND+1); nd1 = pifcnds[1]; // take only the FIRST node of a face. pndfcs = ndfcs + nd1*(ndmfc+1); for (it=1; it<=pndfcs[0]; it++) { jfc = pndfcs[it]; // test for duplication. if ((jfc != ifc) && (lfctpn[jfc] == lfctpn[ifc])) { pjfcnds = lfcnds + jfc*(FCMND+1); cond = pjfcnds[0]; // scan all nodes in ifc and jfc to see if all the same. for (jnf=1; jnf<=pjfcnds[0]; jnf++) { for (inf=1; inf<=pifcnds[0]; inf++) { if (pjfcnds[jnf] == pifcnds[inf]) { cond -= 1; break; }; }; }; if (cond == 0) { map[jfc] = ifc; // record duplication. }; }; }; }; }; // use the duplication map to remap nodes in faces, and build renewed map. map2 = (int *)malloc((size_t)mface*sizeof(int)); pifcnds = lfcnds; pjfcnds = lfcnds; pifctpn = lfctpn; pjfctpn = lfctpn; jfc = 0; for (ifc=0; ifc<mface; ifc++) { if (map[ifc] == ifc) { for (inf=0; inf<=FCMND; inf++) { pjfcnds[inf] = pifcnds[inf]; }; pjfctpn[0] = pifctpn[0]; map2[ifc] = jfc; // increment j-face. jfc += 1; pjfcnds += FCMND+1; pjfctpn += 1; } else { map2[ifc] = map2[map[ifc]]; }; // advance pointers; pifcnds += FCMND+1; pifctpn += 1; }; computed_nface = jfc; // record deduplicated number of face. // rebuild faces in cells and build face neighboring, according to the // renewed face map. pfccls = lfccls; // initialize. for (ifc=0; ifc<mface; ifc++) { for (it=0; it<FCREL; it++) { pfccls[it] = -1; }; // advance pointers; pfccls += FCREL; }; pclfcs = lclfcs; for (icl=0; icl<ncell(); icl++) { for (ifl=1; ifl<=pclfcs[0]; ifl++) { ifc = pclfcs[ifl]; jfc = map2[ifc]; // rebuild faces in cells. pclfcs[ifl] = jfc; // build face neighboring. pfccls = lfccls + jfc*FCREL; if (pfccls[0] == -1) { pfccls[0] = icl; } else if (pfccls[1] == -1) { pfccls[1] = icl; }; }; // advance pointers; pclfcs += CLMFC+1; }; free(map2); free(map); free(ndfcs); // recreate member tables. set_nface(computed_nface); create_fctpn(0, nface()); create_fcnds(0, nface()); create_fccls(0, nface()); for (icl=0; icl < ncell(); ++icl) { clfcs().set(icl, tclfcs[icl]); } for (ifc=0; ifc < nface(); ++ifc) { fctpn().set(ifc, tfctpn[ifc]); fcnds().set(ifc, tfcnds[ifc]); fccls().set(ifc, tfccls[ifc]); } create_fccnd(0, nface()); create_fcnml(0, nface()); create_fcara(0, nface()); }