예제 #1
0
def gen_ifcs_node_mapping(parax_model, node_defs, nodes):
    """Create mapping between composite diagram and interface based diagram.
    
    I think this works only for singlets and mirrors.
    """
    map_to_ifcs = []
    origin = np.array([0., 0.])
    for i, kernel in enumerate(node_defs):
        if len(kernel) == 1:
            idx = kernel[0]
            map_to_ifcs.append((idx, i, 0.))
        elif len(kernel) == 2:
            l1_pt1 = np.array(nodes[i - 1])
            l1_pt2 = np.array(nodes[i])
            l2_pt1 = np.array(nodes[i])
            l2_pt2 = np.array(nodes[i + 1])

            prev_gap_idx, gap_idx = kernel
            for k in range(prev_gap_idx + 1, gap_idx + 1):
                pt_k = np.array(parax_model.get_pt(k))
                new_node1 = np.array(
                    get_intersect(l1_pt1, l1_pt2, origin, pt_k))
                if np.allclose(new_node1, pt_k):
                    t1 = norm(new_node1 - l1_pt1) / norm(l1_pt2 - l1_pt1)
                    map_to_ifcs.append((k, i - 1, t1))
                else:
                    new_node2 = np.array(
                        get_intersect(origin, pt_k, l2_pt1, l2_pt2))
                    if np.allclose(new_node2, pt_k):
                        t2 = norm(new_node2 - l2_pt1) / norm(l2_pt2 - l2_pt1)
                        map_to_ifcs.append((k, i, t2))
    return map_to_ifcs
예제 #2
0
        def on_edit(fig, event):
            buffer = 0.0025
            nonlocal diagram
            shape = diagram.shape
            node = self.node
            if node > 0 and node < (len(shape)-2):
                if event.xdata is not None and event.ydata is not None:
                    inpt = np.array([event.xdata, event.ydata])
                    vertex, edge, perp_edge = self.bundle
                    # project input pt onto perp_edge
                    ppi = np.dot(inpt - vertex, perp_edge)
                    # constrain the input point within the range, if needed
                    if ppi < self.pp_lim[0]:
                        inpt = vertex + (1+buffer)*self.pp_lim[0]*perp_edge
                    elif ppi > self.pp_lim[1]:
                        inpt = vertex + (1-buffer)*self.pp_lim[1]*perp_edge

                    # compute new edge vertices from intersection of adjacent
                    #  edges and line shifted parallel to the initial edge
                    edge_pt = inpt + edge
                    pt1 = np.array(get_intersect(shape[node-1], vertex,
                                                 inpt, edge_pt))
                    diagram.apply_data(self.node, pt1)
                    pt2 = np.array(get_intersect(vertex, shape[node+2],
                                                 inpt, edge_pt))
                    diagram.apply_data(self.node+1, pt2)
                    fig.build = 'update'
                    fig.refresh_gui(build='update')
예제 #3
0
 def on_select(fig, event):
     nonlocal diagram
     if event.xdata is None or event.ydata is None:
         return
     shape = diagram.shape
     self.node = node = dgm_edge.node
     if node > 0 and node < (len(shape)-2):
         inpt = np.array([event.xdata, event.ydata])
         # get the virtual vertex of the combined element surfaces
         vertex = np.array(get_intersect(shape[node-1], shape[node],
                                         shape[node+1], shape[node+2]))
         edge_dir_01 = normalize(shape[node] - shape[node-1])
         edge_dir_23 = normalize(shape[node+2] - shape[node+1])
         # which node is closer to the input point?
         pt1_dist = distance_sqr_2d(shape[node], inpt)
         pt2_dist = distance_sqr_2d(shape[node+1], inpt)
         if pt1_dist < pt2_dist:
             self.filter = calc_coef_fct(vertex, node, edge_dir_01,
                                         node+1, edge_dir_23)
         else:
             self.filter = calc_coef_fct(vertex, node+1, edge_dir_23,
                                         node, edge_dir_01)
         # get direction cosines for the edge
         edge = normalize(shape[node+1] - shape[node])
         # construct perpendicular to the edge. use this to define a
         # range for allowed inputs
         perp_edge = np.array([edge[1], -edge[0]])
         self.bundle = (vertex, edge, perp_edge, edge_dir_01,
                        edge_dir_23)
예제 #4
0
 def on_select(fig, event):
     nonlocal diagram
     shape = diagram.shape
     self.node = node = dgm_edge.node
     if node > 0 and node < (len(shape)-2):
         # get the virtual vertex of the combined element surfaces
         vertex = np.array(get_intersect(shape[node-1], shape[node],
                                         shape[node+1], shape[node+2]))
         # get direction cosines for the edge
         edge = normalize(shape[node+1] - shape[node])
         # construct perpendicular to the edge. use this to define a
         # range for allowed inputs
         perp_edge = np.array([edge[1], -edge[0]])
         self.bundle = vertex, edge, perp_edge
         # measure distances along the perpendicular thru the vertex
         #  and project the 2 outer nodes and the first vertex of the
         #  edge
         pp0 = np.dot(shape[node-1]-vertex, perp_edge)
         pp1 = np.dot(shape[node]-vertex, perp_edge)
         pp3 = np.dot(shape[node+2]-vertex, perp_edge)
         # use the first edge vertex to calculate an allowed input range
         if pp1 > 0:
             self.pp_lim = 0, min(i for i in (pp0, pp3) if i > 0)
         else:
             self.pp_lim = max(i for i in (pp0, pp3) if i < 0), 0
예제 #5
0
def nodes_from_node_defs(parax_model, node_defs):
    """ produce a list of nodes given the parax_model and node_defs.

    `node_defs` is a list of tuples, each with either one or two indices.
    if there is a single index, it is to a node in `parax_model`.
    if there are 2 indices, the first is to the gap preceding the element;
    the second is to the gap following the element (also the last interface
    of the element). The node is calculated from the intersection of the
    diagram edges corresponding to these gaps.
    
    There is no guarentee that the nodes calculated here represent a physically
    realizable system, i.e. there may be virtual airspaces.
    """
    nodes = []
    for i, kernel in enumerate(node_defs):
        if len(kernel) == 1:
            nodes.append(parax_model.get_pt(kernel[0]))
        elif len(kernel) == 2:
            prev_gap_idx, after_gap_idx = kernel
            l1_pt1 = parax_model.get_pt(prev_gap_idx)
            l1_pt2 = parax_model.get_pt(prev_gap_idx + 1)
            l2_pt1 = parax_model.get_pt(after_gap_idx)
            l2_pt2 = parax_model.get_pt(after_gap_idx + 1)
            new_node = get_intersect(l1_pt1, l1_pt2, l2_pt1, l2_pt2)
            nodes.append(new_node)
        elif len(kernel) == 3:
            idx, prev_gap_idx, after_gap_idx = kernel
            nodes.append(parax_model.get_pt(idx))
    return nodes
예제 #6
0
def nodes_from_node_defs(parax_model, node_defs):
    nodes = []
    for i, kernel in enumerate(node_defs):
        if len(kernel) == 1:
            nodes.append(parax_model.get_pt(kernel[0]))
        elif len(kernel) == 2:
            prev_gap_idx, gap_idx = kernel
            l1_pt1 = parax_model.get_pt(prev_gap_idx)
            l1_pt2 = parax_model.get_pt(prev_gap_idx + 1)
            l2_pt1 = parax_model.get_pt(gap_idx)
            l2_pt2 = parax_model.get_pt(gap_idx + 1)
            new_node = get_intersect(l1_pt1, l1_pt2, l2_pt1, l2_pt2)
            nodes.append(new_node)
    return nodes
예제 #7
0
    def replace_node_with_seq(self, node, sys_seq, pp_info):
        """ replaces the data at node with sys_seq """
        sys = self.sys
        ax = self.ax
        pr = self.pr
        if len(sys_seq) == 1:
            sys[node] = sys_seq[0]
        else:
            opt_inv = self.opt_inv
            efl, pp1, ppk, ffl, bfl = pp_info[2]
            sys[node - 1][tau] -= pp1 / sys[node - 1][indx]

            # sys_seq[-1][tau] = sys[node][tau] - ppk/sys_seq[-1][indx]
            p0 = [ax[node][ht], pr[node][ht]]
            pn = [ax[node + 1][ht], pr[node + 1][ht]]
            slp0 = [ax[node][slp], pr[node][slp]]

            for n, ss in enumerate(sys_seq[:-1], start=node):
                sys.insert(n, ss)

                ax_ht = ax[n - 1][ht] + sys[n - 1][tau] * ax[n - 1][slp]
                ax_slp = ax[n - 1][slp] - ax_ht * sys[n][pwr]
                ax.insert(n, [ax_ht, ax_slp, 0.0])

                pr_ht = pr[n - 1][ht] + sys[n - 1][tau] * pr[n - 1][slp]
                pr_slp = pr[n - 1][slp] - pr_ht * sys[n][pwr]
                pr.insert(n, [pr_ht, pr_slp, 0.0])

            # replace the original node data
            ax[n + 1][slp] = slp0[0]
            pr[n + 1][slp] = slp0[1]
            sys[n + 1][pwr] = (ax[n][slp] * pr[n + 1][slp] -
                               ax[n + 1][slp] * pr[n][slp]) / opt_inv
            # sys_seq[-1][pwr]
            p1 = [ax[n][ht], pr[n][ht]]
            p2 = [ax[n][ht] + ax[n][slp], pr[n][ht] + pr[n][slp]]
            p2int = np.array(get_intersect(p1, p2, p0, pn))
            ax[n + 1][ht] = p2int[0]
            pr[n + 1][ht] = p2int[1]
            sys[n][tau] = (
                (ax[n][ht] * pr[n + 1][ht] - ax[n + 1][ht] * pr[n][ht]) /
                opt_inv)
            sys[n + 1][tau] = (p2int[0] * pn[1] - pn[0] * p2int[1]) / opt_inv
예제 #8
0
 def calc_scale_factors(pt1, pt2, pt_k):
     new_node = np.array(get_intersect(pt1, pt2, np.array([0., 0.]), pt_k))
     t1 = norm(new_node - pt1) / norm(pt2 - pt1)
     t2 = norm(pt_k) / norm(new_node)
     return t1, t2