Ejemplo n.º 1
0
def H_offset(info, opts, layerNum, objID, tList=[]):
    """For a given layerNum=n and ObjID=i, compute the deposited object.

    ```latex
    H_{n,i}(t) = C_{n,i}(t) \cap [ B_{n,i}(t) \cup (\cup_{m<n;j} H_{m,j}(t_i+t)) \cup (\cup_k A_k(t_i + t))],
    ```
    where A_k is from the base substrate list. This is computed recursively. The list of integers
    tList determines the offset t; t = the sum of all layer thicknesses ti that appear
    in tList. For example, tList = [1,2,3] -> t = t1+t2+t3.

    Note: this object is returned as a list of objects that need to be unioned together
    in order to form the full H.
    """

    # This is a tuple that encodes the check offset t:
    checkOffsetTuple = tuple(sorted(tList))
    # This is a tuple that encodes the total offset t_i+t:
    offsetTuple = tuple(sorted(tList + [layerNum]))
    # First, check if we have to do anything:
    layers = info.lithoDict['layers']
    if checkOffsetTuple in layers[layerNum]['objIDs'][objID]['HDict']:
        return layers[layerNum]['objIDs'][objID]['HDict'][checkOffsetTuple]
    # First, compute t:
    t = 0.0
    for tIndex in tList:
        t += layers[tIndex]['thickness']
    # thickness of this layer
    ti = layers[layerNum]['thickness']
    # Set the aux. thickness t:
    B = layers[layerNum]['objIDs'][objID][
        'B']  # B prism for this layer & objID
    C = layers[layerNum]['objIDs'][objID][
        'C']  # C prism for this layer & ObjID
    B_t = gen_offset(opts, B, t)  # offset the B prism
    C_t = gen_offset(opts, C, t)  # offset the C prism
    info.trash.append(B_t)
    info.trash.append(C_t)

    # Build up the substrate due to previously deposited gates
    HOffsetList = []
    for m in layers.keys():
        if m < layerNum:  # then this is a lower layer
            for j in layers[m]['objIDs'].keys():
                HOffsetList += screened_H_union_list(info, opts, C_t, m, j,
                                                     offsetTuple,
                                                     checkOffsetTuple)
                # Next, build up the original substrate list:
    AOffsetList = []
    AOffsetList += screened_A_UnionList(info, opts, C_t, t, ti, offsetTuple,
                                        checkOffsetTuple)
    unionList = HOffsetList + AOffsetList
    returnList = [B_t]

    for obj in unionList:
        intObj = intersect([C_t, obj])
        info.trash.append(intObj)
        returnList.append(intObj)
    layers[layerNum]['objIDs'][objID]['HDict'][checkOffsetTuple] = returnList
    return returnList
Ejemplo n.º 2
0
def H_offset(info, opts, layer_num, objID, tList=[]):
    r"""For a given layer_num=n and ObjID=i, compute the deposited object.

    ```latex
    H_{n,i}(t) = C_{n,i}(t) \cap [ B_{n,i}(t) \cup (\cup_{m<n;j} H_{m,j}(t_i+t)) \cup (\cup_k A_k(t_i + t))],
    ```
    where A_k is from the base substrate list. This is computed recursively. The list of integers
    tList determines the offset t; t = the sum of all layer thicknesses ti that appear
    in tList. For example, tList = [1,2,3] -> t = t1+t2+t3.

    Note: this object is returned as a list of objects that need to be unioned together
    in order to form the full H.

    Parameters
    ----------
    info :

    opts : dict
        Options dict in the QMT Geometry3D.__init__ input format.

    layer_num :

    objID :

    tList :
        (Default value = [])

    Returns
    -------


    """

    logging.debug(
        ">>> partname %s",
        info.lithoDict["layers"][layer_num]["objIDs"][objID]["partName"],
    )

    # This is a tuple that encodes the check offset t:
    checkOffsetTuple = tuple(sorted(tList))
    # This is a tuple that encodes the total offset t_i+t:
    offsetTuple = tuple(sorted(tList + [layer_num]))
    # First, check if we have to do anything:
    layers = info.lithoDict["layers"]
    if checkOffsetTuple in layers[layer_num]["objIDs"][objID]["HDict"]:
        return layers[layer_num]["objIDs"][objID]["HDict"][checkOffsetTuple]
    # First, compute t:
    t = sum(layers[layer_num]["thickness"] for layer_num in tList)
    # thickness of this layer
    ti = layers[layer_num]["thickness"]
    # Set the aux. thickness t:
    # B prism for this layer & objID
    B = layers[layer_num]["objIDs"][objID]["B"]
    # C prism for this layer & ObjID
    C = layers[layer_num]["objIDs"][objID]["C"]
    B_t = gen_offset(opts, B, t)  # offset the B prism
    C_t = gen_offset(opts, C, t)  # offset the C prism
    info.trash.append(B_t)
    info.trash.append(C_t)

    # Build up the substrate due to previously deposited gates
    HOffsetList = []
    for m in layers.keys():
        if m < layer_num:  # then this is a lower layer
            for j in layers[m]["objIDs"].keys():
                HOffsetList += screened_H_union_list(info, opts, C_t, m, j,
                                                     offsetTuple,
                                                     checkOffsetTuple)
    # Next, build up the original substrate list:
    AOffsetList = []
    AOffsetList += screened_A_UnionList(info, opts, C_t, t, ti, offsetTuple,
                                        checkOffsetTuple)
    unionList = HOffsetList + AOffsetList
    returnList = [B_t]

    for obj in unionList:
        intObj = intersect([C_t, obj])
        info.trash.append(intObj)
        returnList.append(intObj)
        logging.debug("%s (%s) -> %s (%s)", obj.Name, obj.Label, intObj.Name,
                      intObj.Label)

    layers[layer_num]["objIDs"][objID]["HDict"][checkOffsetTuple] = returnList

    logging.debug("<<< %s", [f"{o.Name} ({o.Label})" for o in returnList])
    return returnList
Ejemplo n.º 3
0
def buildAlShell(sketch,
                 zBottom,
                 width,
                 verts,
                 thickness,
                 depoZone=None,
                 etchZone=None,
                 offset=0.0):
    """Builds a shell on a nanowire parameterized by sketch, zBottom, and width.

    Here, verts describes the vertices that are covered, and thickness describes
    the thickness of the shell. depoZone, if given, is extruded and intersected
    with the shell (for an etch). Note that offset here *is not* a real offset -
    for simplicity we keep this a thin shell that lies cleanly on top of the
    bigger wire offset. There's no need to include the bottom portion since that's
    already taken up by the wire.

    Parameters
    ----------
    sketch :

    zBottom :

    width :

    verts :

    thickness :

    depoZone :
        (Default value = None)
    etchZone :
        (Default value = None)
    offset :
        (Default value = 0.0)

    Returns
    -------


    """
    lineSegments = findSegments(sketch)[0]
    x0, y0, z0 = lineSegments[0]
    x1, y1, z1 = lineSegments[1]
    dx = x1 - x0
    dy = y1 - y0
    rAxis = np.array([-dy, dx, 0])
    # axis perpendicular to the wire in the xy plane
    rAxis /= np.sqrt(np.sum(rAxis**2))
    zAxis = np.array([0, 0, 1.0])
    doc = FreeCAD.ActiveDocument
    shellList = []
    for vert in verts:
        # Make the original wire (including an offset if applicable)
        originalWire = buildWire(sketch, zBottom, width, offset=offset)
        # Now make the shifted wire:
        angle = vert * np.pi / 3.0
        dirVec = rAxis * np.cos(angle) + zAxis * np.sin(angle)
        shiftVec = (thickness) * dirVec
        transVec = FreeCAD.Vector(tuple(shiftVec))
        face = makeHexFace(sketch, zBottom - offset,
                           width + 2 * offset)  # make the bigger face
        shiftedFace = Draft.move(face, transVec, copy=False)
        extendedSketch = extendSketch(sketch, offset)
        # The shell offset is handled manually since we are using faceOverride to
        # input a shifted starting face:
        shiftedWire = buildWire(extendedSketch,
                                zBottom,
                                width,
                                faceOverride=shiftedFace)
        delete(extendedSketch)
        shellCut = doc.addObject("Part::Cut", f"{sketch.Name}_cut_{vert}")
        shellCut.Base = shiftedWire
        shellCut.Tool = originalWire
        doc.recompute()
        shell = Draft.move(shellCut, FreeCAD.Vector(0.0, 0.0, 0.0), copy=True)
        doc.recompute()
        delete(shellCut)
        delete(originalWire)
        delete(shiftedWire)
        shellList.append(shell)
    if len(shellList) > 1:
        coatingUnion = doc.addObject("Part::MultiFuse",
                                     f"{sketch.Name}_coating")
        coatingUnion.Shapes = shellList
        doc.recompute()
        coatingUnionClone = copy_move(coatingUnion)
        doc.removeObject(coatingUnion.Name)
        for shell in shellList:
            doc.removeObject(shell.Name)
    elif len(shellList) == 1:
        coatingUnionClone = shellList[0]
    else:
        raise NameError(
            "Trying to build an empty Al shell. If no shell is desired, omit the AlVerts key from "
            "the json.")
    if (depoZone is None) and (etchZone is None):
        return coatingUnionClone

    elif depoZone is not None:
        coatingBB = getBB(coatingUnionClone)
        zMin = coatingBB[4]
        zMax = coatingBB[5]
        depoVol = extrudeBetween(depoZone, zMin, zMax)
        etchedCoatingUnionClone = intersect(
            [depoVol, coatingUnionClone],
            consumeInputs=True if not DBG_OUT else False)
        return etchedCoatingUnionClone
    else:  # etchZone instead
        coatingBB = getBB(coatingUnionClone)
        zMin = coatingBB[4]
        zMax = coatingBB[5]
        etchVol = extrudeBetween(etchZone, zMin, zMax)
        etchedCoatingUnionClone = subtract(
            coatingUnionClone,
            etchVol,
            consumeInputs=True if not DBG_OUT else False)
        return etchedCoatingUnionClone