Example #1
0
    def process(self, timestep=1):
        '''    
        Processes the surface depending whether par.ETCHING is set or not.
        
        When the initialTime is specified 
    
        par.ETCHING = True -> etching
        par.ETCHING = False-> Sputtern

        When a file is specified, the process is written to a file after each step.
        >>>surface.process(time, step)
        '''
                
        if par.ETCHING:
            vn = par.ETCH_RATE
        else:
            vn = sputterVelocity(self)
            assert len(vn) > 0, 'Error: vn could not be calculated!'
                    
        self.movePointsByDirection(vn*timestep)
                
        if not par.NUMPY:
            #Umwandlung da delopping ein Liste für korrekte Funktion braucht, wenn par.NUMPY=False
            self.xvals, self.yvals = np.array(deloop(list(self.xvals), list(self.yvals)))
        else:
            self.xvals, self.yvals = deloop(self.xvals, self.yvals)
            
        #Berechne neue Winkelsymmetralen für die neuen x & y werte
        self.xs, self.ys = anglebisect(self.xvals, self.yvals)

        #Falls die Funktion Adaptive Gitter erwünscht ist, passe Knoten (und Winkelsymmetralen) an
        if par.ADAPTIVE_GRID:
            adapt(self)
Example #2
0
 def __init__(self):
     interval_start = par.XMIN
     interval_end = par.XMAX
     period = interval_start - interval_end
     assert period != 0, 'Error period is 0.'
     interval_step = par.DELTA_X
     amplitudePP = par.FUN_PEAK_TO_PEAK
     self.surfaceType = par.INITIAL_SURFACE_TYPE
     self.surfaceFile = par.INITIAL_SURFACE_FILE
     #arange() creates a half-open interval, which excludes the endpoint
     self.xvals = np.arange(interval_start, interval_end + interval_step, interval_step)
     self.yvals = np.zeros_like(self.xvals)
     
     func = functions.default
     if par.INITIAL_SURFACE_TYPE == 'Cosine':
         func = functions.cosine
     elif par.INITIAL_SURFACE_TYPE == 'DoubleCosine':
         func = functions.doubleCosine
     elif par.INITIAL_SURFACE_TYPE == 'Step':
         func = functions.step
     elif par.INITIAL_SURFACE_TYPE == 'V-Shape':
         func = functions.vShape        
     
     for i, x in enumerate(self.xvals):
         self.yvals[i] = amplitudePP * (1 + func(x * 2*pi / period) )
     #Berechne Winkelsymmetralen
     self.xs, self.ys = anglebisect(self.xvals, self.yvals)
     #Falls Adaptives Grid gewünscht, passe Werte an
     if par.ADAPTIVE_GRID:
         adapt(self)
Example #3
0
def adapt_grid(self, method='linear'):
    """Adapts surface so that the distance of adjacent points is not too
        large or too small (as defined by MAX_SEGLEN) and angles between normal
        vectors of adjacent knots do not exceed MAX_ANGLE.
        
        method : str, optional
            Method of 
            Possible values are 'linear', 'quadratic'. 'cubic' """
    x, y = self.vertices

    # Check if x-values are monotonically increasing
    if np.any(x[1:] - x[:-1] < 0):
        print('Error: X-Values are not monotonically increasing!')
        sys.exit()

    # Check if the segments are too short and remove knot if so
    max_angle = np.deg2rad(par.MAX_ANGLE)

    status = True
    while (status):
        dx = x[2:] - x[:-2]
        dy = y[2:] - y[:-2]
        double_seglen = np.hypot(dx, dy)

        remove_indices, = np.where(double_seglen < par.MAX_SEGLEN)

        if remove_indices.size == 0:
            break

        for remove_index in remove_indices:
            if abs(self.angles[remove_index + 2] -
                   self.angles[remove_index]) < max_angle:
                x = np.delete(x, remove_index + 1)
                y = np.delete(y, remove_index + 1)
                self.vertices = np.array((x, y))
                self.__directions()
                break
        else:
            status = False

    plt.plot(x, y, 'b+')

    # Check if the segments are too long and insert knot if so
    dx = x[1:] - x[:-1]
    dy = y[1:] - y[:-1]
    seglen = np.hypot(dx, dy)

    long_seg_index, = np.where(seglen > par.MAX_SEGLEN)

    if long_seg_index.size > 0:
        split_value = seglen[long_seg_index] / par.MAX_SEGLEN
        split_value = np.ceil(split_value)

        f = interpolate.interp1d(x, y, method)

        index_insert = list()
        x_insert = list()

        for i in range(long_seg_index.size):
            index_local = long_seg_index[i]
            index_new = np.ones(split_value[i] - 1) * (index_local + 1)
            index_insert.append(index_new)

            x_new = np.linspace(x[index_local],
                                x[index_local + 1],
                                num=split_value[i],
                                endpoint=False)
            x_insert.append(x_new[1:])

        x_insert = np.hstack(x_insert)
        y_insert = f(x_insert)
        index_insert = np.hstack(index_insert)

        x = np.insert(x, index_insert, x_insert)
        y = np.insert(y, index_insert, y_insert)

    self.vertices = np.array((x, y))
    self.__directions()

    # Check if angle between normal vectors of adjacent knots is too large
    # and insert additional knots (same coordinates, different normal vec)
    x, y = self.vertices
    nvx, nvy = self.directions

    # Calculate angles between segments
    dx = x[1:] - x[:-1]
    dy = y[1:] - y[:-1]
    seglen = np.hypot(dx, dy)

    seg_angles_diff = dx[:-1] * dx[1:] + dy[:-1] * dy[1:]
    seg_angles_diff /= (seglen[:-1] * seglen[1:])
    seg_angles_diff = np.clip(seg_angles_diff, -1., 1.)
    seg_angles_diff = np.arccos(seg_angles_diff)

    max_angle = np.deg2rad(par.MAX_ANGLE)

    large_angles, = np.where(seg_angles_diff > max_angle)

    if large_angles.size > 0:
        index_insert = list()
        x_insert = list()
        y_insert = list()
        nvx_insert = list()
        nvy_insert = list()

        for i in range(large_angles.size):
            index_local = large_angles[i]

            delta_angle_left = self.angles[index_local +
                                           1] - self.angles[index_local]
            local_split = np.ceil(abs(delta_angle_left / max_angle))
            local_split = int(local_split)

            rot_angle = delta_angle_left / local_split

            nvx_new = list()
            nvy_new = list()

            for k in range(local_split):
                nvx_local = nvx[index_local] * np.cos(k * rot_angle)
                nvx_local -= nvy[index_local] * np.sin(k * rot_angle)

                nvy_local = nvx[index_local] * np.sin(k * rot_angle)
                nvy_local += nvy[index_local] * np.cos(k * rot_angle)

                nvx_new.append(nvx_local)
                nvy_new.append(nvy_local)

            index_new = np.array(np.ones(local_split) * index_local + 1,
                                 dtype=int)

            index_insert.append(index_new)
            x_new = np.ones(local_split) * x[index_local + 1]
            x_insert.append(x_new)
            y_new = np.ones(local_split) * y[index_local + 1]
            y_insert.append(y_new)

            nvx_insert.append(nvx_new)
            nvy_insert.append(nvy_new)

            delta_angle_right = self.angles[index_local +
                                            2] - self.angles[index_local + 1]

            local_split = np.ceil(abs(delta_angle_right / max_angle))
            local_split = int(local_split)

            rot_angle = delta_angle_right / local_split

            nvx_new = list()
            nvy_new = list()

            for k in range(1, local_split + 1):
                nvx_local = nvx[index_local + 1] * np.cos(k * rot_angle)
                nvx_local -= nvy[index_local + 1] * np.sin(k * rot_angle)

                nvy_local = nvx[index_local + 1] * np.sin(k * rot_angle)
                nvy_local += nvy[index_local + 1] * np.cos(k * rot_angle)

                nvx_new.append(nvx_local)
                nvy_new.append(nvy_local)

            index_new = np.array(np.ones(local_split) * index_local + 2,
                                 dtype=int)

            index_insert.append(index_new)
            x_new = np.ones(local_split) * x[index_local + 1]
            x_insert.append(x_new)
            y_new = np.ones(local_split) * y[index_local + 1]
            y_insert.append(y_new)

            nvx_insert.append(nvx_new)
            nvy_insert.append(nvy_new)

        x_insert = np.hstack(x_insert)
        y_insert = np.hstack(y_insert)
        nvx_insert = np.hstack(nvx_insert)
        nvy_insert = np.hstack(nvy_insert)
        index_insert = np.hstack(index_insert)

        x = np.insert(x, index_insert, x_insert)
        y = np.insert(y, index_insert, y_insert)
        nvx = np.insert(nvx, index_insert, nvx_insert)
        nvy = np.insert(nvy, index_insert, nvy_insert)

        self.vertices = np.array((x, y))
        self.directions = np.array((nvx, nvy))
        self.angles = np.arctan(
            (self.directions[0] / (-1 * self.directions[1])))

#Berechne Winkelsymmetralen
    self.xs, self.ys = anglebisect(self.xvals, self.yvals)
    #Falls Adaptives Grid gewünscht, passe Werte an
    if par.ADAPTIVE_GRID:
        adapt(self)

#Berechne neue Winkelsymmetralen für die neuen x & y werte
    self.xs, self.ys = anglebisect(self.xvals, self.yvals)

    #Falls die Funktion Adaptive Gitter erwünscht ist, passe Knoten (und Winkelsymmetralen) an
    if par.ADAPTIVE_GRID:
        adapt(self)