void Foam::faceCracker::detachFaceCracker
(
    polyTopoChange& ref
) const
{
    if (debug)
    {
        Pout<< "void faceCracker::detachFaceCracker("
            << "polyTopoChange& ref) const "
            << " for object " << name() << " : "
            << "Detaching faces" << endl;
    }

    const polyMesh& mesh = topoChanger().mesh();
    const faceZoneMesh& zoneMesh = mesh.faceZones();

    const primitiveFacePatch& masterFaceLayer =
        zoneMesh[crackZoneID_.index()]();
    const pointField& points = mesh.points();
    const labelListList& meshEdgeFaces = mesh.edgeFaces();

    const labelList& mp = masterFaceLayer.meshPoints();
    const edgeList& zoneLocalEdges = masterFaceLayer.edges();

    const labelList& meshEdges = zoneMesh[crackZoneID_.index()].meshEdges();

    // Create the points

    labelList addedPoints(mp.size(), -1);

    // Go through boundary edges of the master patch.  If all the faces from
    // this patch are internal, mark the points in the addedPoints lookup
    // with their original labels to stop duplication
    label nIntEdges = masterFaceLayer.nInternalEdges();

    for
    (
        label curEdgeID = nIntEdges;
        curEdgeID < meshEdges.size();
        curEdgeID++
    )
    {
        const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];

        bool edgeIsInternal = true;

        forAll (curFaces, faceI)
        {
            if (!mesh.isInternalFace(curFaces[faceI]))
            {
                // The edge belongs to a boundary face
                edgeIsInternal = false;
                break;
            }
        }

        if (edgeIsInternal)
        {
            // Reset the point creation
            addedPoints[zoneLocalEdges[curEdgeID].start()] =
                mp[zoneLocalEdges[curEdgeID].start()];

            addedPoints[zoneLocalEdges[curEdgeID].end()] =
                mp[zoneLocalEdges[curEdgeID].end()];
        }
    }
    // Pout << "addedPoints before point creation: " << addedPoints << endl;

    // Create new points for face zone
    forAll (addedPoints, pointI)
    {
        if (addedPoints[pointI] < 0)
        {
            addedPoints[pointI] =
                ref.setAction
                (
                    polyAddPoint
                    (
                        points[mp[pointI]],        // point
                        mp[pointI],                // master point
                        -1,                        // zone ID
                        true                       // supports a cell
                    )
                );
        }
    }

    // Modify faces in the master zone and duplicate for the slave zone

    const labelList& mf = zoneMesh[crackZoneID_.index()];
    const boolList& mfFlip = zoneMesh[crackZoneID_.index()].flipMap();
    const faceList& zoneFaces = masterFaceLayer.localFaces();

    const faceList& faces = mesh.faces();
    const labelList& own = mesh.faceOwner();
    const labelList& nei = mesh.faceNeighbour();

    forAll (mf, faceI)
    {
        const label curFaceID = mf[faceI];

        // Build the face for the slave patch by renumbering
        const face oldFace = zoneFaces[faceI].reverseFace();

        face newFace(oldFace.size());

        forAll (oldFace, pointI)
        {
            newFace[pointI] = addedPoints[oldFace[pointI]];
        }

        if (mfFlip[faceI])
        {
            // Face needs to be flipped for the master patch
            ref.setAction
            (
                polyModifyFace
                (
                    faces[curFaceID].reverseFace(), // modified face
                    curFaceID,                  // label of face being modified
                    nei[curFaceID],                 // owner
                    -1,                             // neighbour
                    true,                           // face flip
                    crackPatchID_.index(),          // patch for face
                    false,                          // remove from zone
                    crackZoneID_.index(),           // zone for face
                    !mfFlip[faceI]                  // face flip in zone
                )
            );

            // Add renumbered face into the slave patch
            ref.setAction
            (
                polyAddFace
                (
                    newFace,                        // face
                    own[curFaceID],                 // owner
                    -1,                             // neighbour
                    -1,                             // master point
                    -1,                             // master edge
                    curFaceID,                      // master face
                    false,                          // flip flux
                    crackPatchID_.index(),          // patch to add the face to
                    -1,                             // zone for face
                    false                           // zone flip
                )
            );
        // Pout << "Flip.  Modifying face: " << faces[curFaceID].reverseFace()
        //<< " next to cell: " << own[curFaceID] << endl;
        }
        else
        {
            // No flip
            ref.setAction
            (
                polyModifyFace
                (
                    faces[curFaceID],         // modified face
                    curFaceID,                // label of face being modified
                    own[curFaceID],           // owner
                    -1,                       // neighbour
                    false,                    // face flip
                    crackPatchID_.index(),    // patch for face
                    false,                    // remove from zone
                    crackZoneID_.index(),     // zone for face
                    mfFlip[faceI]             // face flip in zone
                )
            );

            // Add renumbered face into the slave patch
            ref.setAction
            (
                polyAddFace
                (
                    newFace,                        // face
                    nei[curFaceID],                 // owner
                    -1,                             // neighbour
                    -1,                             // master point
                    -1,                             // master edge
                    curFaceID,                      // master face
                    true,                           // flip flux
                    crackPatchID_.index(),          // patch to add the face to
                    -1,                             // zone for face
                    false                           // face flip in zone
                )
            );
        // Pout << "No flip.  Modifying face: " << faces[curFaceID]
        //<< " next to cell: " << nei[curFaceID] << endl;
        }
    }

    // Modify the remaining faces of the master cells to reconnect to the new
    // layer of faces.

    // Algorithm: Go through all the cells of the master zone and make
    // a map of faces to avoid duplicates.  Do not insert the faces in
    // the master patch (as they have already been dealt with).  Make
    // a master layer point renumbering map, which for every point in
    // the master layer gives its new label. Loop through all faces in
    // the map and attempt to renumber them using the master layer
    // point renumbering map.  Once the face is renumbered, compare it
    // with the original face; if they are the same, the face has not
    // changed; if not, modify the face but keep all of its old
    // attributes (apart from the vertex numbers).

    // Create the map of faces in the master cell layer
    const labelList& mc =
        mesh.faceZones()[crackZoneID_.index()].masterCells();

    labelHashSet masterCellFaceMap(6*mc.size());

    const cellList& cells = mesh.cells();

    forAll (mc, cellI)
    {
        const labelList& curFaces = cells[mc[cellI]];

        forAll (curFaces, faceI)
        {
            // Check if the face belongs to the master patch; if not add it
            if (zoneMesh.whichZone(curFaces[faceI]) != crackZoneID_.index())
            {
                masterCellFaceMap.insert(curFaces[faceI]);
            }
        }
    }

    // Extend the map to include first neighbours of the master cells to
    // deal with multiple corners.
    { // Protection and memory management
        // Make a map of master cells for quick reject
        labelHashSet mcMap(2*mc.size());

        forAll (mc, mcI)
        {
            mcMap.insert(mc[mcI]);
        }

        // Go through all the faces in the masterCellFaceMap.  If the
        // cells around them are not already used, add all of their
        // faces to the map
        const labelList mcf = masterCellFaceMap.toc();

        forAll (mcf, mcfI)
        {
      Info << nl << "mcf[mcfI] " << mcf[mcfI] << endl;
            // Do the owner side
            const label ownCell = own[mcf[mcfI]];

            if (!mcMap.found(ownCell))
            {
          Info << "ownCell " << ownCell << endl;
                // Cell not found. Add its faces to the map
                const cell& curFaces = cells[ownCell];

                forAll (curFaces, faceI)
                {
                    masterCellFaceMap.insert(curFaces[faceI]);
                }
rootpaerror_t executeOneCmpCommand(CMTHANDLE handle, CmpMessage* commandP, CmpMessage* responseP)
{
    LOGD(">>executeOneCmpCommand");
    if (unlikely( bad_write_ptr(handle,sizeof(CMTSTRUCT)))) 
    {
        return ROOTPA_ERROR_INTERNAL;
    }
    if(unlikely (commandP->contentP==NULL || commandP->length< sizeof(cmpCommandId_t)))
    {
        return ROOTPA_ERROR_INTERNAL;
    }

    mcResult_t mcRet=MC_DRV_OK;
    cmpCommandId_t commandId=getCmpCommandId(commandP->contentP);
        
    handle->mappedSize=getTotalMappedBufferSize(commandP);
    if(0==handle->mappedSize)
    {
        LOGE("<<executeOneCmpCommand, command %d not supported", commandId);
        return ROOTPA_COMMAND_NOT_SUPPORTED;
    }

    rootpaerror_t ret=ROOTPA_OK;
    while(true) 
    {
        handle->mappedP=malloc((size_t) handle->mappedSize);
        if(NULL==handle->mappedP)
        {
            ret=ROOTPA_ERROR_OUT_OF_MEMORY;
            break;
        }
        memset(handle->mappedP, 0,handle->mappedSize);
        mcRet=mcMap(&handle->session, handle->mappedP, handle->mappedSize, &handle->mapInfo);
        if(mcRet!=MC_DRV_OK)
        {
            LOGE("executeOneCmpCommand not able to map memory %d", mcRet);
            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
            commandP->hdr.intRet=mcRet;
            responseP->hdr.intRet=mcRet;
            break;
        }

        if((ret = prepareCommand(commandId, commandP, handle, responseP))!=ROOTPA_OK)
        {
            LOGE("prepareCommand failed %d", ret);
            break;
        }

        if (unlikely( !tltChannelTransmit(handle, NOTIFICATION_WAIT_TIMEOUT_MS)))
        {
            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
            commandP->hdr.intRet=handle->lasterror;
            responseP->hdr.intRet=handle->lasterror;
            break;
        }

        uint32_t neededBytes=getNeededBytesFromResponse(handle->wsmP);

        if(0==neededBytes)
        {
            break;
        }

        if(-1==neededBytes)
        {
            ret=ROOTPA_ERROR_MOBICORE_CONNECTION; 
            break;
        }

        if(neededBytes <= handle->mappedSize)
        {
            LOGE("executeOneCmpCommand, there is something wrong. CMTL is requesting smaller buffer than we originally had. Command: %d, original %d requested %d",  
	         commandId, handle->mappedSize, neededBytes);
            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
            break;
        }

        // this is Info level LOGI on purpose
        LOGI("executeOneCmpCommand, updating RootPA recommended (%d bytes was not enough for %d response, allocating %d bytes and retrying)", handle->mappedSize, commandId, neededBytes);
        mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo);
        if(mcRet!=MC_DRV_OK)
        {
            LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet);
            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
            commandP->hdr.intRet=mcRet;
            responseP->hdr.intRet=mcRet;
            break;
        }

        free(handle->mappedP);
        memset(&handle->mapInfo, 0 , sizeof(handle->mapInfo));
        handle->mappedSize=neededBytes;
    }

    if(ROOTPA_OK==ret)
    {
        ret=handleResponse(commandId, responseP, handle);
    }
    else
    {
        responseP->hdr.ret=ret;
    }
    LOGD("cleaning up mapped memory %ld",(long int) handle->mappedP);
    mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo);
    if(mcRet!=MC_DRV_OK)
    {
        LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet);
        ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
    }
    LOGD("freeing mapped memory %ld", (long int) handle->mappedP);    
    free(handle->mappedP);    
    if(commandP->hdr.ret==ROOTPA_OK) commandP->hdr.ret=ret;
    if(responseP->hdr.ret==ROOTPA_OK) responseP->hdr.ret=ret;    
    LOGD("<<executeOneCmpCommand %d %d",commandId, ret);
    return ret;
}
コード例 #3
0
//------------------------------------------------------------------------------
static TEEC_Result _TEEC_SetupOperation(
    _TEEC_TCI           *tci,
    mcSessionHandle_t   *handle,
    TEEC_Operation      *operation,
    uint32_t            *returnOrigin)
{
    uint32_t                    i;
    _TEEC_ParameterInternal     *imp;
    TEEC_Parameter              *ext;
    mcResult_t                  mcRet = MC_DRV_OK;
    TEEC_Result                 teecResult = TEEC_SUCCESS;

    LOG_I(" %s()", __func__);

    tci->operation.isCancelled = false;
    tci->operation.paramTypes = 0;

    //operation can be NULL
    if (operation != NULL) {

        operation->started = 1;

        //This design allows a non-NULL buffer with a size of 0 bytes to allow trivial integration with any
        //implementations of the C library malloc, in which is valid to allocate a zero byte buffer and receive a non-
        //NULL pointer which may not be de-referenced in return.

        for (i = 0; i < _TEEC_PARAMETER_NUMBER; i++) {
            uint8_t paramType = _TEEC_GET_PARAM_TYPE(operation->paramTypes, i);

            imp = &tci->operation.params[i];
            ext = &operation->params[i];

            switch (paramType) {
            case TEEC_VALUE_OUTPUT:
                LOG_I("  cycle %d, TEEC_VALUE_OUTPUT", i);
                break;
            case TEEC_NONE:
                LOG_I("  cycle %d, TEEC_NONE", i);
                break;
            case TEEC_VALUE_INPUT:
            case TEEC_VALUE_INOUT: {
                LOG_I("  cycle %d, TEEC_VALUE_IN*", i);
                imp->value.a = ext->value.a;
                imp->value.b = ext->value.b;
                break;
            }
            case TEEC_MEMREF_TEMP_INPUT:
            case TEEC_MEMREF_TEMP_OUTPUT:
            case TEEC_MEMREF_TEMP_INOUT: {
                //TODO: A Temporary Memory Reference may be null, which can be used to denote a special case for the
                //parameter. Output Memory References that are null are typically used to request the required output size.
                LOG_I("  cycle %d, TEEC_TEMP_IN*", i);
                imp->memref.mapInfo.sVirtualLen = 0;
                if ((ext->tmpref.size) && (ext->tmpref.buffer)) {
                    mcRet = mcMap(handle, ext->tmpref.buffer, ext->tmpref.size, &imp->memref.mapInfo);
                    if (mcRet != MC_DRV_OK) {
                        LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
                        *returnOrigin = TEEC_ORIGIN_COMMS;
                        i = _TEEC_PARAMETER_NUMBER;
                    }
                } else {
                    LOG_I("  cycle %d, TEEC_TEMP_IN*  - zero pointer or size", i);
                }
                break;
            }
            case TEEC_MEMREF_WHOLE: {
                LOG_I("  cycle %d, TEEC_MEMREF_WHOLE", i);
                imp->memref.mapInfo.sVirtualLen = 0;
                if (ext->memref.parent->size) {
                    mcRet = mcMap(handle, ext->memref.parent->buffer, ext->memref.parent->size, &imp->memref.mapInfo);
                    if (mcRet != MC_DRV_OK) {
                        LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
                        *returnOrigin = TEEC_ORIGIN_COMMS;
                        i = _TEEC_PARAMETER_NUMBER;
                    }
                }
                /* We don't transmit that the mem ref is the whole shared mem */
                /* Magic number 4 means that it is a mem ref */
                paramType = ext->memref.parent->flags | 4;
                break;
            }
            case TEEC_MEMREF_PARTIAL_INPUT:
            case TEEC_MEMREF_PARTIAL_OUTPUT:
            case TEEC_MEMREF_PARTIAL_INOUT: {
                LOG_I("  cycle %d, TEEC_PARTIAL_IN*", i);
                //Check data flow consistency
                if ((((ext->memref.parent->flags & (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)) == TEEC_MEM_INPUT) &&
                        (paramType == TEEC_MEMREF_PARTIAL_OUTPUT)) ||
                        (((ext->memref.parent->flags & (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)) == TEEC_MEM_OUTPUT) &&
                         (paramType == TEEC_MEMREF_PARTIAL_INPUT))) {
                    LOG_E("PARTIAL data flow inconsistency");
                    *returnOrigin = TEEC_ORIGIN_API;
                    teecResult = TEEC_ERROR_BAD_PARAMETERS;
                    i = _TEEC_PARAMETER_NUMBER;
                    break;
                }
                /* We don't transmit that the mem ref is partial */
                paramType &= TEEC_MEMREF_TEMP_INOUT;

                if (ext->memref.offset + ext->memref.size > ext->memref.parent->size) {
                    LOG_E("PARTIAL offset/size error");
                    *returnOrigin = TEEC_ORIGIN_API;
                    teecResult = TEEC_ERROR_BAD_PARAMETERS;
                    i = _TEEC_PARAMETER_NUMBER;
                    break;
                }
                imp->memref.mapInfo.sVirtualLen = 0;
                if (ext->memref.size) {
                    mcRet = mcMap(handle, (uint8_t *)ext->memref.parent->buffer + ext->memref.offset, ext->memref.size, &imp->memref.mapInfo);
                    if (mcRet != MC_DRV_OK) {
                        LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
                        *returnOrigin = TEEC_ORIGIN_COMMS;
                        i = _TEEC_PARAMETER_NUMBER;
                    }
                }
                break;
            }
            default:
                LOG_E("cycle %d, default", i);
                *returnOrigin = TEEC_ORIGIN_API;
                teecResult = TEEC_ERROR_BAD_PARAMETERS;
                i = _TEEC_PARAMETER_NUMBER;
                break;
            }
            tci->operation.paramTypes |= (paramType<<i*4);
        }

        if (tci->operation.isCancelled) {
            LOG_E("the operation has been cancelled in COMMS");
            *returnOrigin = TEEC_ORIGIN_COMMS;
            teecResult = TEEC_ERROR_CANCEL;
        }

        if ((mcRet != MC_DRV_OK) || (teecResult != TEEC_SUCCESS)) {
            uint32_t retOrigIgnored;
            _TEEC_UnwindOperation(tci, handle, operation, false, &retOrigIgnored);
            //Zeroing out tci->operation
            memset(&tci->operation, 0, sizeof(tci->operation));
            if (teecResult != TEEC_SUCCESS) return teecResult;
            return TEEC_ERROR_GENERIC;
        }
    }

    //Copy version indicator field
    memcpy(tci->header, "TCIGP000", sizeof(tci->header));

    // Fill in invalid values for secure world to overwrite
    tci->returnStatus = TEEC_ERROR_BAD_STATE;

    // Signal completion of request writing
    tci->ready = 1;

    return teecResult;
}
void Foam::attachDetach::detachInterface
(
    polyTopoChange& ref
) const
{
    // Algorithm:
    // 1. Create new points for points of the master face zone
    // 2. Modify all faces of the master zone, by putting them into the master
    //    patch (look for orientation) and their renumbered mirror images
    //    into the slave patch
    // 3. Create a point renumbering list, giving a new point index for original
    //    points in the face patch
    // 4. Grab all faces in cells on the master side and renumber them 
    //    using the point renumbering list.  Exclude the ones that belong to
    //    the master face zone
    //
    // Note on point creation:
    // In order to take into account the issues related to partial
    // blocking in an attach/detach mesh modifier, special treatment
    // is required for the duplication of points on the edge of the
    // face zone.  Points which are shared only by internal edges need
    // not to be duplicated, as this would propagate the discontinuity
    // in the mesh beyond the face zone.  Therefore, before creating
    // the new points, check the external edge loop.  For each edge
    // check if the edge is internal (i.e. does not belong to a
    // patch); if so, exclude both of its points from duplication.

    if (debug)
    {
        Pout<< "void attachDetach::detachInterface("
            << "polyTopoChange& ref) const "
            << " for object " << name() << " : "
            << "Detaching interface" << endl;
    }

    const polyMesh& mesh = topoChanger().mesh();
    const faceZoneMesh& zoneMesh = mesh.faceZones();

    const primitiveFacePatch& masterFaceLayer = zoneMesh[faceZoneID_.index()]();
    const pointField& points = mesh.points();
    const labelListList& meshEdgeFaces = mesh.edgeFaces();

    const labelList& mp = masterFaceLayer.meshPoints();
    const edgeList& zoneLocalEdges = masterFaceLayer.edges();

    const labelList& meshEdges = zoneMesh[faceZoneID_.index()].meshEdges();

    // Create the points

    labelList addedPoints(mp.size(), -1);

    // Go through boundary edges of the master patch.  If all the faces from
    // this patch are internal, mark the points in the addedPoints lookup
    // with their original labels to stop duplication
    label nIntEdges = masterFaceLayer.nInternalEdges();

    for (label curEdgeID = nIntEdges; curEdgeID < meshEdges.size(); curEdgeID++)
    {
        const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]];

        bool edgeIsInternal = true;

        forAll (curFaces, faceI)
        {
            if (!mesh.isInternalFace(curFaces[faceI]))
            {
                // The edge belongs to a boundary face
                edgeIsInternal = false;
                break;
            }
        }

        if (edgeIsInternal)
        {
// Pout<< "Internal edge found: (" << mp[zoneLocalEdges[curEdgeID].start()] << " " << mp[zoneLocalEdges[curEdgeID].end()] << ")" << endl;

            // Reset the point creation
            addedPoints[zoneLocalEdges[curEdgeID].start()] =
                mp[zoneLocalEdges[curEdgeID].start()];

            addedPoints[zoneLocalEdges[curEdgeID].end()] =
                mp[zoneLocalEdges[curEdgeID].end()];
        }
    }
// Pout << "addedPoints before point creation: " << addedPoints << endl;

    // Create new points for face zone
    forAll (addedPoints, pointI)
    {
        if (addedPoints[pointI] < 0)
        {
            addedPoints[pointI] =
                ref.setAction
                (
                    polyAddPoint
                    (
                        points[mp[pointI]],        // point
                        mp[pointI],                // master point
                        -1,                        // zone ID
                        true                       // supports a cell
                    )
                );
// Pout << "Adding point " << points[mp[pointI]] << " for original point " << mp[pointI] << endl;
        }
    }

    // Modify faces in the master zone and duplicate for the slave zone

    const labelList& mf = zoneMesh[faceZoneID_.index()];
    const boolList& mfFlip = zoneMesh[faceZoneID_.index()].flipMap();
    const faceList& zoneFaces = masterFaceLayer.localFaces();

    const faceList& faces = mesh.faces();
    const labelList& own = mesh.faceOwner();
    const labelList& nei = mesh.faceNeighbour();

    forAll (mf, faceI)
    {
        const label curFaceID = mf[faceI];

        // Build the face for the slave patch by renumbering
        const face oldFace = zoneFaces[faceI].reverseFace();

        face newFace(oldFace.size());

        forAll (oldFace, pointI)
        {
            newFace[pointI] = addedPoints[oldFace[pointI]];
        }

        if (mfFlip[faceI])
        {
            // Face needs to be flipped for the master patch
            // No need to check for nei index: internal face.  HJ, 16/Dec/2008
            ref.setAction
            (
                polyModifyFace
                (
                    faces[curFaceID].reverseFace(), // modified face
                    curFaceID,                   // label of face being modified
                    nei[curFaceID],                 // owner
                    -1,                             // neighbour
                    true,                           // face flip
                    masterPatchID_.index(),         // patch for face
                    false,                          // remove from zone
                    faceZoneID_.index(),            // zone for face
                    !mfFlip[faceI]                  // face flip in zone
                )
            );

            // Add renumbered face into the slave patch
            ref.setAction
            (
                polyAddFace
                (
                    newFace,                        // face
                    own[curFaceID],                 // owner
                    -1,                             // neighbour
                    -1,                             // master point
                    -1,                             // master edge
                    curFaceID,                      // master face
                    false,                          // flip flux
                    slavePatchID_.index(),          // patch to add the face to
                    -1,                             // zone for face
                    false                           // zone flip
                )
            );
// Pout << "Flip.  Modifying face: " << faces[curFaceID].reverseFace() << " next to cell: " << nei[curFaceID] << " and adding face: " << newFace << " next to cell: " << own[curFaceID] << endl;
        }
        else
        {
            // No flip
            ref.setAction
            (
                polyModifyFace
                (
                    faces[curFaceID],         // modified face
                    curFaceID,                // label of face being modified
                    own[curFaceID],           // owner
                    -1,                       // neighbour
                    false,                    // face flip
                    masterPatchID_.index(),   // patch for face
                    false,                    // remove from zone
                    faceZoneID_.index(),      // zone for face
                    mfFlip[faceI]             // face flip in zone
                )
            );

            // Add renumbered face into the slave patch
            // No need to check for nei index: internal face.  HJ, 16/Dec/2008
            ref.setAction
            (
                polyAddFace
                (
                    newFace,                        // face
                    nei[curFaceID],                 // owner
                    -1,                             // neighbour
                    -1,                             // master point
                    -1,                             // master edge
                    curFaceID,                      // master face
                    true,                           // flip flux
                    slavePatchID_.index(),          // patch to add the face to
                    -1,                             // zone for face
                    false                           // face flip in zone
                )
            );
// Pout << "No flip.  Modifying face: " << faces[curFaceID] << " next to cell: " << own[curFaceID] << " and adding face: " << newFace << " next to cell: " << nei[curFaceID] << endl;
        }
    }

    // Modify the remaining faces of the master cells to reconnect to the new
    // layer of faces.

    // Algorithm: Go through all the cells of the master zone and make
    // a map of faces to avoid duplicates.  Do not insert the faces in
    // the master patch (as they have already been dealt with).  Make
    // a master layer point renumbering map, which for every point in
    // the master layer gives its new label. Loop through all faces in
    // the map and attempt to renumber them using the master layer
    // point renumbering map.  Once the face is renumbered, compare it
    // with the original face; if they are the same, the face has not
    // changed; if not, modify the face but keep all of its old
    // attributes (apart from the vertex numbers).

    // Create the map of faces in the master cell layer
    const labelList& mc =
        mesh.faceZones()[faceZoneID_.index()].masterCells();

    labelHashSet masterCellFaceMap(6*mc.size());

    const cellList& cells = mesh.cells();

    forAll (mc, cellI)
    {
        const labelList& curFaces = cells[mc[cellI]];

        forAll (curFaces, faceI)
        {
            // Check if the face belongs to the master patch; if not add it
            if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index())
            {
                masterCellFaceMap.insert(curFaces[faceI]);
            }
        }
    }

    // Extend the map to include first neighbours of the master cells to
    // deal with multiple corners.
    { // Protection and memory management
        // Make a map of master cells for quick reject
        labelHashSet mcMap(2*mc.size());

        forAll (mc, mcI)
        {
            mcMap.insert(mc[mcI]);
        }

        // Go through all the faces in the masterCellFaceMap.  If the
        // cells around them are not already used, add all of their
        // faces to the map
        const labelList mcf = masterCellFaceMap.toc();

        forAll (mcf, mcfI)
        {
            // Do the owner side
            const label ownCell = own[mcf[mcfI]];

            if (!mcMap.found(ownCell))
            {
                // Cell not found. Add its faces to the map
                const cell& curFaces = cells[ownCell];

                forAll (curFaces, faceI)
                {
                    masterCellFaceMap.insert(curFaces[faceI]);
                }
            }

            // Do the neighbour side if face is internal
            if (mesh.isInternalFace(mcf[mcfI]))
            {
                const label neiCell = nei[mcf[mcfI]];

                if (!mcMap.found(neiCell))
                {
                    // Cell not found. Add its faces to the map
                    const cell& curFaces = cells[neiCell];

                    forAll (curFaces, faceI)
                    {
                        masterCellFaceMap.insert(curFaces[faceI]);
                    }
                }
            }