Exemple #1
0
def quadratic(x):
    """A quadratic B-spline.

    This is a special case of `bspline`, and equivalent to ``bspline(x, 2)``.
    """
    ax = abs(asarray(x))
    res = zeros_like(ax)
    cond1 = less(ax, 0.5)
    if cond1.any():
        ax1 = ax[cond1]
        res[cond1] = 0.75 - ax1**2
    cond2 = ~cond1 & less(ax, 1.5)
    if cond2.any():
        ax2 = ax[cond2]
        res[cond2] = (ax2 - 1.5)**2 / 2.0
    return res
Exemple #2
0
def cubic(x):
    """A cubic B-spline.

    This is a special case of `bspline`, and equivalent to ``bspline(x, 3)``.
    """
    ax = abs(asarray(x))
    res = zeros_like(ax)
    cond1 = less(ax, 1)
    if cond1.any():
        ax1 = ax[cond1]
        res[cond1] = 2.0 / 3 - 1.0 / 2 * ax1**2 * (2 - ax1)
    cond2 = ~cond1 & less(ax, 2)
    if cond2.any():
        ax2 = ax[cond2]
        res[cond2] = 1.0 / 6 * (2 - ax2)**3
    return res
Exemple #3
0
    def positive_constrain(self,dn_3D,dF_3D_2):
        n_med = 1.334
        wavelength = 532
        k2 = (2*np.pi*n_med/wavelength)**2
        n_med2 = n_med**2
        # dF_3D = cupy.multiply(cupy.subtract(cupy.divide(cupy.multiply(dn_3D,dn_3D),n_med2),1),-k2)
        # dF_3D = cupy.fft.fftn(dF_3D)
        # dF_3D[cupy.not_equal(dF_3D_2,0)] = dF_3D_2[cupy.not_equal(dF_3D_2,0)]
        # dF_3D   = cupy.fft.ifftn(dF_3D)    
        # dn_3D   = cupy.multiply(cupy.sqrt(cupy.add(cupy.divide(dF_3D,-k2), 1)), n_med)
        
        # dn_3D =  cupy.fft.fftshift(dn_3D);
        dn_3D[cupy.less(cupy.real(dn_3D),n_med)] = n_med+1j*cupy.imag(dn_3D[cupy.less(cupy.real(dn_3D),n_med)])
        dn_3D[cupy.less(cupy.imag(dn_3D),0)]     = cupy.real(dn_3D[cupy.less(cupy.imag(dn_3D), 0)])


        return dn_3D
def voltMeterwStep(ne, ex_mat, step_arr=None, parser=None):
    '''
    
    Returns all measurements with this step_arr and ex_mat

    takes:

    ex_mat - array shape (n_source/sinks, 2) - excitation matrix with source and sink for each measurement
    step_arr - array shape (n_source/sinks) - step between measuring electrodes for each source/sink pair
    parser - string

    returns:

    pair_mat - array shape (n_measurements, 2) - matrix with all possible meas. electrode combinations
    ind_new - array shape (n_measurements) - helper array

    '''        
    if step_arr is None:
        step_arr = 1 + cp.arange((ex_mat.shape[0])) % (ne)
    elif type(step_arr) is int:
    	step_arr = step_arr * cp.ones(ex_mat.shape[0]) % ne

    drv_a = ex_mat[:, 0]
    drv_b = ex_mat[:, 1]
    i0 = drv_a if parser == 'fmmu' else 0
    A = cp.arange(ne)
    
    #M = cp.dot(cp.ones(ex_mat.shape[0])[:,None], A[None, :]) % self.ne
    #N = (M + step_arr[:, None]) % self.ne

    M = cp.arange(ex_mat.shape[0] * ne) % ne
    N = (M.reshape((ex_mat.shape[0], ne)) + step_arr[:, None]) % ne
    pair_mat = cp.stack((N.ravel(), M), axis=-1)

    #ind_new = cp.arange(pair_mat.shape[0]) % ex_mat.shape[0]
    ind_new = cp.arange(ex_mat.shape[0])        
    ind_new = cp.tile(ind_new, (ne, 1)).T.ravel()
    #print('before indtest', ind_new[20:70])
    nz2 = cp.where(pair_mat == drv_a[ind_new, None])
    nz3 = cp.where(pair_mat == drv_b[ind_new, None])
    #print(ind_new)
    ind_ = cp.arange(pair_mat.shape[0])
    ind_fin = cp.sum(ind_[:, None] == nz2[0][None], axis=1)
    ind_fin2 = cp.sum(ind_[:, None] == nz3[0][None], axis=1)

    ind_test = cp.less((ind_fin + ind_fin2), 0.5 * cp.ones(len(ind_fin)))

    pair_mat = pair_mat[ind_test, :]
    ind_new = ind_new[ind_test]
    sort_index = cp.argsort(ind_new)

    #print('after indtest', ind_new[20:70])
    #meas = cp.concatenate((ex_mat[ind_new], pair_mat), axis=1)
    #print(meas[20:70])
    return pair_mat, ex_mat[ind_new], ind_new
def less(x1: Array, x2: Array, /) -> Array:
    """
    Array API compatible wrapper for :py:func:`np.less <numpy.less>`.

    See its docstring for more information.
    """
    if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
        raise TypeError("Only numeric dtypes are allowed in less")
    # Call result type here just to raise on disallowed type combinations
    _result_type(x1.dtype, x2.dtype)
    x1, x2 = Array._normalize_two_args(x1, x2)
    return Array._new(np.less(x1._array, x2._array))
    def voltMeter(self, ex_mat, step_arr=None, parser=None):

        pair_mat = volt_mat(self.ne)
        srcsinkpairs = ex_mat.shape[0]

        pair_mat = cp.tile(pair_mat, (int(ex_mat.shape[0]), 1, 1))
        pair_mat = pair_mat.reshape((pair_mat.shape[0] * pair_mat.shape[1], 2))

        ind_new = cp.arange(pair_mat.shape[0]) // srcsinkpairs

        nz2 = cp.where(pair_mat == ex_mat[:, 0][ind_new, None])
        nz3 = cp.where(pair_mat == ex_mat[:, 1][ind_new, None])

        ind_ = cp.arange(pair_mat.shape[0])
        ind_fin = cp.sum(ind_[:, None] == nz2[0][None], axis=1)
        ind_fin2 = cp.sum(ind_[:, None] == nz3[0][None], axis=1)

        ind_test = cp.less((ind_fin + ind_fin2), 0.5 * cp.ones(len(ind_fin)))

        pair_mat = pair_mat[ind_test, :]
        ind_new = ind_new[ind_test]

        return pair_mat, ex_mat[ind_new], ind_new
Exemple #7
0
 def __lt__(self, other):
     return cupy.less(self, other)
Exemple #8
0
def evaluate_chunks(
        results: [cp.ndarray, cp.ndarray,
                  cp.ndarray],  # closest triangle, distance, projection
        all_pts: cp.ndarray = None,
        vertices: cp.ndarray = None,
        edges: cp.ndarray = None,
        edge_norms: cp.ndarray = None,
        edge_normssq: cp.ndarray = None,
        normals: cp.ndarray = None,
        norms: cp.ndarray = None,
        normssq: cp.ndarray = None,
        zero_tensor: cp.ndarray = None,
        one_tensor: cp.ndarray = None,
        tris: cp.ndarray = None,
        vertex_normals: cp.ndarray = None,
        bounding_box: dict = None,
        chunk_size: int = None,
        num_verts: int = None) -> None:

    #
    # Expand vertex normals if non empty
    if vertex_normals is not None:
        vertex_normals = vertex_normals[tris]
        vertex_normals = cp.tile(cp.expand_dims(vertex_normals, axis=2),
                                 (1, 1, chunk_size, 1))

    # begin = time.time()
    #
    # Load and extend the batch
    num_chunks = all_pts.shape[0] // chunk_size
    for i in range(num_chunks):
        #
        # Get subset of the query points
        start_index = i * chunk_size
        end_index = (i + 1) * chunk_size
        pts = all_pts[start_index:end_index, :]

        #
        # Match the dimensions to those assumed above.
        #    REPEATED       REPEATED
        # [triangle_index, vert_index, querypoint_index, coordinates]
        pts = cp.tile(cp.expand_dims(pts, axis=(0, 1)), (num_verts, 3, 1, 1))

        #
        # Compute the differences between
        # vertices on each triangle and the
        # points of interest
        #
        # [triangle_index, vert_index, querypoint_index, coordinates]
        # ===================
        # [:,0,:,:] = p - p1
        # [:,1,:,:] = p - p2
        # [:,2,:,:] = p - p3
        diff_vectors = pts - vertices

        #
        # Compute alpha, beta, gamma
        barycentric = cp.empty(diff_vectors.shape)

        #
        # gamma = u x (p - p1)
        barycentric[:, 2, :, :] = cp.cross(edges[:, 0, :, :],
                                           diff_vectors[:, 0, :, :])
        # beta = (p - p1) x v
        barycentric[:, 1, :, :] = cp.cross(diff_vectors[:, 0, :, :],
                                           edges[:, 1, :, :])
        # alpha = w x (p - p2)
        barycentric[:, 0, :, :] = cp.cross(edges[:, 2, :, :],
                                           diff_vectors[:, 1, :, :])
        barycentric = cp.divide(
            cp.sum(cp.multiply(barycentric, normals), axis=3), normssq)

        #
        # Test conditions
        less_than_one = cp.less_equal(barycentric, one_tensor)
        more_than_zero = cp.greater_equal(barycentric, zero_tensor)

        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        cond1 = cp.logical_and(less_than_one, more_than_zero)

        #
        #     if gamma <= 0:
        cond2 = cp.logical_not(more_than_zero[:, 2, :])
        cond2 = cp.tile(cp.expand_dims(cond2, axis=1), (1, 3, 1))

        #
        #     if beta <= 0:
        cond3 = cp.logical_not(more_than_zero[:, 1, :])
        cond3 = cp.tile(cp.expand_dims(cond3, axis=1), (1, 3, 1))

        #
        #     if alpha <= 0:
        cond4 = cp.logical_not(more_than_zero[:, 0, :])
        cond4 = cp.tile(cp.expand_dims(cond4, axis=1), (1, 3, 1))

        #
        # Get the projections for each case
        xi = cp.empty(barycentric.shape)
        barycentric_ext = cp.tile(cp.expand_dims(barycentric, axis=3),
                                  (1, 1, 1, 3))
        proj = cp.sum(cp.multiply(barycentric_ext, vertices), axis=1)
        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        xi[cond1] = barycentric[cond1]

        #
        # if gamma <= 0:
        #  x = p - p1
        #  u = p2 - p1
        #  a = p1
        #  b = p2
        t2 = cp.divide(
            #
            # u.dot(x)
            cp.sum(cp.multiply(edges[:, 0, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 0])
        xi2 = cp.zeros((t2.shape[0], 3, t2.shape[1]))
        xi2[:, 0, :] = -t2 + 1
        xi2[:, 1, :] = t2
        #
        t2 = cp.tile(cp.expand_dims(t2, axis=2), (1, 1, 3))
        lz = cp.less(t2, cp.zeros(t2.shape))
        go = cp.greater(t2, cp.ones(t2.shape))
        proj2 = vertices[:, 0, :, :] + cp.multiply(t2, edges[:, 0, :, :])
        proj2[lz] = vertices[:, 0, :, :][lz]
        proj2[go] = vertices[:, 1, :, :][go]
        #
        xi[cond2] = xi2[cond2]
        proj[cp.swapaxes(cond2, 1, 2)] = proj2[cp.swapaxes(cond2, 1, 2)]

        #
        # if beta <= 0:
        #  x = p - p1
        #  v = p3 - p1
        #  a = p1
        #  b = p3
        t3 = cp.divide(
            #
            # v.dot(x)
            cp.sum(cp.multiply(edges[:, 1, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 1])
        xi3 = cp.zeros((t3.shape[0], 3, t3.shape[1]))
        xi3[:, 0, :] = -t3 + 1
        xi3[:, 2, :] = t3
        #
        t3 = cp.tile(cp.expand_dims(t3, axis=2), (1, 1, 3))
        lz = cp.less(t3, cp.zeros(t3.shape))
        go = cp.greater(t3, cp.ones(t3.shape))
        proj3 = vertices[:, 0, :, :] + cp.multiply(t3, edges[:, 1, :, :])
        proj3[lz] = vertices[:, 0, :, :][lz]
        proj3[go] = vertices[:, 2, :, :][go]
        #
        xi[cond3] = xi3[cond3]
        proj[cp.swapaxes(cond3, 1, 2)] = proj3[cp.swapaxes(cond3, 1, 2)]

        #
        #     if alpha <= 0:
        #  y = p - p2
        #  w = p3 - p2
        #  a = p2
        #  b = p3
        t4 = cp.divide(
            #
            # w.dot(y)
            cp.sum(cp.multiply(edges[:, 2, :, :], diff_vectors[:, 1, :, :]),
                   axis=2),
            edge_normssq[:, 2])
        xi4 = cp.zeros((t4.shape[0], 3, t4.shape[1]))
        xi4[:, 1, :] = -t4 + 1
        xi4[:, 2, :] = t4
        #
        t4 = cp.tile(cp.expand_dims(t4, axis=2), (1, 1, 3))
        lz = cp.less(t4, cp.zeros(t4.shape))
        go = cp.greater(t4, cp.ones(t4.shape))
        proj4 = vertices[:, 1, :, :] + cp.multiply(t4, edges[:, 2, :, :])
        proj4[lz] = vertices[:, 1, :, :][lz]
        proj4[go] = vertices[:, 2, :, :][go]
        #
        xi[cond4] = xi4[cond4]
        proj[cp.swapaxes(cond4, 1, 2)] = proj4[cp.swapaxes(cond4, 1, 2)]

        vec_to_point = pts[:, 0, :, :] - proj
        distances = cp.linalg.norm(vec_to_point, axis=2)

        # n = "\n"
        # print(f"{pts[:,0,:,:]=}")
        # print(f"{proj=}")
        # print(f"{pts[:,0,:,:] - proj=}")
        # print(f"{distances=}")

        min_distances = cp.min(distances, axis=0)

        closest_triangles = cp.argmin(distances, axis=0)

        projections = proj[closest_triangles, np.arange(chunk_size), :]

        #
        # Distinguish close triangles
        is_close = cp.isclose(distances, min_distances)

        #
        # Determine sign
        signed_normal = normals[:, 0, :, :]
        if vertex_normals is not None:
            signed_normal = cp.sum(vertex_normals.transpose() * xi.transpose(),
                                   axis=2).transpose()

        is_negative = cp.less_equal(
            cp.sum(cp.multiply(vec_to_point, signed_normal), axis=2), 0.)

        #
        # Combine
        is_close_and_negative = cp.logical_and(is_close, is_negative)

        #
        # Determine if inside
        is_inside = cp.all(cp.logical_or(is_close_and_negative,
                                         cp.logical_not(is_close)),
                           axis=0)

        #
        # Overwrite the signs of points
        # that are outside of the box
        if bounding_box is not None:
            #
            # Extract
            rotation_matrix = cp.asarray(bounding_box['rotation_matrix'])
            translation_vector = cp.asarray(bounding_box['translation_vector'])
            size = cp.asarray(bounding_box['size'])
            #
            # Transform
            transformed_pts = cp.dot(
                all_pts[start_index:end_index, :] - translation_vector,
                rotation_matrix)

            #
            # Determine if outside bbox
            inside_bbox = cp.all(cp.logical_and(
                cp.less_equal(0., transformed_pts),
                cp.less_equal(transformed_pts, size)),
                                 axis=1)

            #
            # Treat points outside bbox as
            # being outside of lumen
            print(f"{inside_bbox=}")
            is_inside = cp.logical_and(is_inside, inside_bbox)

        #
        # Apply sign to indicate whether the distance is
        # inside or outside the mesh.
        min_distances[is_inside] = -1 * min_distances[is_inside]

        #
        # Emplace results
        # [triangle_index, vert_index, querypoint_index, coordinates]
        results[0][start_index:end_index] = closest_triangles
        results[1][start_index:end_index] = min_distances
        results[2][start_index:end_index, :] = projections
Exemple #9
0
        if a[i] == 0:
            print("  ", end="")
        elif a[i] == 1:
            print(" O", end="")
        elif a[i] == -1:
            print(" X", end="")
    print()


k = 0
times = 0
idx = cp.arange(train_datas)
x = list()
y = list()
print("開始訓練...")
while cp.less(k, train_datas):
    times = cp.add(times, 1)
    output = train.TTTG_Network(
        input_data, weight, baise, weight2, baise2, weight3, baise3, weight4, baise4, L, expect_data, True, True)
    if times % 10000 == 0:
        error = cp.sum(output[0])
        result = expect_data[idx, output[1]]
        k = cp.count_nonzero(result)
        # result = cp.equal(expect_data, cp.asarray(output[1]))  # AND閘
        expect_idx = list()
        for i in map(cp.nonzero, expect_data[result == 0]):
            expect_idx.append(i[0].tolist())
        print("輸入棋盤,輸出位置,預計輸出,實際輸出:", *list(zip(input_data[result == 0].tolist(
        ), output[1][result == 0].tolist(), expect_idx, output[2][result == 0].tolist())), sep='\n')
        print("第%d次訓練(學習率:%f):" % (times, L))
        print("總誤差:", error)
def basis_pursuit(A, b, tol=1e-4, niter=100, biter=32):
    """
    solves min |x|_1 s.t. Ax=b using a Primal-Dual Interior Point Method

    Args:
      A: design matrix of size (d, n)
      b: measurement vector of length d
      tol: solver tolerance
      niter: maximum length of central path
      biter: maximum number of steps in backtracking line search

    Returns:
      vector of length n
    """
    A = cp.asarray(A)
    b = cp.asarray(b)
    d, n = A.shape
    alpha = 0.01
    beta = 0.5
    mu = 10
    e = cp.ones(n)
    gradf0 = cp.hstack([cp.zeros(n), e])
    x = (A.T).dot(inv(A.dot(A.T))).dot(b)
    absx = cp.abs(x)
    u = 0.95 * absx + 0.1 * cp.max(absx)

    fu1 = x - u
    fu2 = -x - u
    lamu1 = -1.0 / fu1
    lamu2 = -1.0 / fu2
    v = A.dot(lamu2 - lamu1)
    ATv = (A.T).dot(v)
    sdg = -(cp.inner(fu1, lamu1) + cp.inner(fu2, lamu2))
    tau = 2.0 * n * mu / sdg
    ootau = 1.0 / tau

    rcent = cp.hstack([-lamu1 * fu1, -lamu2 * fu2]) - ootau
    rdual = gradf0 + cp.hstack([lamu1 - lamu2 + ATv, -lamu1 - lamu2])
    rpri = A.dot(x) - b
    resnorm = cp.sqrt(norm(rdual)**2 + norm(rcent)**2 + norm(rpri)**2)
    rdp = cp.empty(2 * n)
    rcp = cp.empty(2 * n)

    for i in range(niter):

        oofu1 = 1.0 / fu1
        oofu2 = 1.0 / fu2
        w1 = -ootau * (oofu2 - oofu1) - ATv
        w2 = -1.0 - ootau * (oofu1 + oofu2)
        w3 = -rpri

        lamu1xoofu1 = lamu1 * oofu1
        lamu2xoofu2 = lamu2 * oofu2
        sig1 = -lamu1xoofu1 - lamu2xoofu2
        sig2 = lamu1xoofu1 - lamu2xoofu2
        sigx = sig1 - sig2**2 / sig1
        if cp.min(cp.abs(sigx)) == 0.0:
            break

        w1p = -(w3 - A.dot(w1 / sigx - w2 * sig2 / (sigx * sig1)))
        H11p = A.dot((A.T) * (e / sigx)[:, cp.newaxis])
        if cp.min(sigx) > 0.0:
            dv = solve(H11p, w1p)
        else:
            dv = solve(H11p, w1p)
        dx = (w1 - w2 * sig2 / sig1 - (A.T).dot(dv)) / sigx
        Adx = A.dot(dx)
        ATdv = (A.T).dot(dv)

        du = (w2 - sig2 * dx) / sig1
        dlamu1 = lamu1xoofu1 * (du - dx) - lamu1 - ootau * oofu1
        dlamu2 = lamu2xoofu2 * (dx + du) - lamu2 - ootau * oofu2

        s = 1.0
        indp = cp.less(dlamu1, 0.0)
        indn = cp.less(dlamu2, 0.0)
        if cp.any(indp):
            s = min(s, cp.min(-lamu1[indp] / dlamu1[indp]))
        if cp.any(indn):
            s = min(s, cp.min(-lamu2[indn] / dlamu2[indn]))
        indp = cp.greater(dx - du, 0.0)
        indn = cp.greater(-dx - du, 0.0)
        if cp.any(indp):
            s = min(s, cp.min(-fu1[indp] / (dx[indp] - du[indp])))
        if cp.any(indn):
            s = min(s, cp.min(-fu2[indn] / (-dx[indn] - du[indn])))
        s = 0.99 * s

        for j in range(biter):
            xp = x + s * dx
            up = u + s * du
            vp = v + s * dv
            ATvp = ATv + s * ATdv
            lamu1p = lamu1 + s * dlamu1
            lamu2p = lamu2 + s * dlamu2
            fu1p = xp - up
            fu2p = -xp - up
            rdp[:n] = lamu1p - lamu2p + ATvp
            rdp[n:] = -lamu1p - lamu2p
            rdp += gradf0
            rcp[:n] = -lamu1p * fu1p
            rcp[n:] = lamu2p * fu2p
            rcp -= ootau
            rpp = rpri + s * Adx
            s *= beta
            if (cp.sqrt(norm(rdp)**2 + norm(rcp)**2 + norm(rpp)**2) <=
                (1 - alpha * s) * resnorm):
                break
        else:
            break

        x = xp
        lamu1 = lamu1p
        lamu2 = lamu2p
        fu1 = fu1p
        fu2 = fu2p
        sdg = -(cp.inner(fu1, lamu1) + cp.inner(fu2, lamu2))
        if sdg < tol:
            return cp.asnumpy(x)

        u = up
        v = vp
        ATv = ATvp
        tau = 2.0 * n * mu / sdg
        rpri = rpp
        rcent[:n] = lamu1 * fu1
        rcent[n:] = lamu2 * fu2
        ootau = 1.0 / tau
        rcent -= ootau
        rdual[:n] = lamu1 - lamu2 + ATv
        rdual[n:] = -lamu1 + lamu2
        rdual += gradf0
        resnorm = cp.sqrt(norm(rdual)**2 + norm(rcent)**2 + norm(rpri)**2)

    return cp.asnumpy(x)
Exemple #11
0
#%% ORIGIN constrain and reconstuct
 
# disp_3Dx = np.fft.fftshift(C_3D)
# print(np.sum(np.isnan(F_3Dx)))
plot_F_domain(np.fft.fftshift(F_3Dx), ffsize, df)
plot_F_domain(np.fft.fftshift(C_3D/C_3D), ffsize, df)

# dF_3Dx = cupy.fft.fftshift(dF_dst)
dF_3Dx = cupy.array(F_3Dx.copy())
dF_3D   = cupy.fft.ifftn(cupy.divide(dF_3Dx,dx))
dF_3D_2 = cupy.divide(dF_3Dx,dx)
dn_3D   = cupy.multiply(cupy.sqrt(cupy.add(cupy.divide(dF_3Dx,-k2), 1)), n_med)


# Positive constraint
dn_3D[cupy.less(cupy.real(dn_3D),n_med)] = cupy.real(n_med)+cupy.imag(dn_3D[cupy.less(cupy.real(dn_3D),n_med)])
dn_3D[cupy.less(cupy.imag(dn_3D),0)]     = cupy.real(dn_3D[cupy.less(cupy.imag(dn_3D), 0)])

n_3D_bi = np.zeros(dn_3D.shape,dtype=int)

# for iter in tqdm(range(0,100)): 
    
#     dF_3D = cupy.multiply(cupy.subtract(cupy.divide(cupy.multiply(dn_3D,dn_3D),n_med2),1),-k2)
#     dF_3D = cupy.fft.fftn(dF_3D)
#     dF_3D[cupy.not_equal(dF_3D_2,0)] = dF_3D_2[cupy.not_equal(dF_3D_2,0)]
#     dF_3D   = cupy.fft.ifftn(dF_3D)    
#     dn_3D   = cupy.multiply(cupy.sqrt(cupy.add(cupy.divide(dF_3D,-k2), 1)), n_med)
#     #Positive constraint
#     dn_3D[cupy.less(cupy.real(dn_3D),n_med)] = cupy.real(n_med)+cupy.imag(dn_3D[cupy.less(cupy.real(dn_3D),n_med)])
#     dn_3D[cupy.less(cupy.imag(dn_3D),0)]     = cupy.real(dn_3D[cupy.less(cupy.imag(dn_3D), 0)])