예제 #1
0
    def trap_int(self, dataValue, dataLoc, start, stop):
        """
        function utilizes trapezoidal integration to integrate from start Index to stop Index
        :param dataValue: Array Values to integrate
        :param dataLoc: Array of Locations corresponding to Values
        :param start: index to start integration
        :param stop: index to stop integration
        :param f: function to integrate
        :param f_const_args: constant argument list to be passed to function f
        :return: value of 1/2 SUM[k = 1 : N] ( f(k+1) + f(k) ds )
        """
        i_list = []
        for x in range(start, stop):
            try:
                if not self.is_bifurcated:
                    i_list.append((ih.mag(
                        np.array(dataLoc[x + 1]) - np.array(dataLoc[x]))) *
                                  (np.sqrt(1 - ih.mag(dataValue[x + 1]) /
                                           ih.mag(dataValue[stop])) +
                                   np.sqrt(1 - ih.mag(dataValue[x]) /
                                           ih.mag(dataValue[stop]))))
            except:
                print "ERROR OF SOME KIND"
                print "start: ", start
                print "stop:  ", stop
                print "Current: ", x
                print "Current+1: ", x + 1
                print "Size of Data: ", len(dataValue)
                print "Size of Points: ", len(dataLoc)
                # sys.exit(10)

                break

        return 0.5 * np.sum(i_list)
예제 #2
0
    def get_new_phi_for_localtime(self, localtime, RE=1):
        """
        returns the intersection location of RE and field line searched for from localtime
        :param localtime:
        :param RE:
        :return:
        """
        # TODO: change this to work with spherical rotation interpolation (great circle)
        start_lines_old = self.get_phi_locations(RE=RE)
        start_lines = dict()
        start_lt = sorted(start_lines.keys())

        # normalize the starting vectors (so we have unit vectors to work with)
        # TODO: Basing this off the keys is wrong, as the field line might be found on a localtime,
        # TODO: but may not intersect anywhere near that line.

        for key in start_lines_old:
            # Need to build new keys based on actual local-time of intersection
            mag_start = start_lines_old[key]/ih.mag(start_lines_old[key])
            new_key = ih.get_local_time_from_location(mag_start)
            start_lines[new_key] = mag_start
            if np.isclose(new_key, 24.0, rtol=0.0, atol=self.error_tol):
                # print "Found 2400: ", new_key
                start_lines[0.0] = mag_start
            elif np.isclose(new_key, 0.0, rtol=0.0, atol=self.error_tol):
                # print "Found 0000: ", new_key
                start_lines[24.0] = mag_start

        # TODO: How to loop if we dont have 2400/0000 as a key?

        start_lt = sorted(start_lines.keys())
        # print start_lt
        index_high = bs.bisect_left(start_lt, localtime)
        index_low = index_high -1

        # adjust to circular
        if index_high is len(start_lt):
            index_high = 0

        latitude_high = np.arcsin(start_lines[start_lt[index_high]][2])
        latitude_low = np.arcsin(start_lines[start_lt[index_low]][2])

        w = (float(localtime) - float(start_lt[index_low])) / (float(start_lt[index_high]) - float(start_lt[index_low]))

        latitude_new = latitude_low + (latitude_high - latitude_low) * w

        loc_localtime = ih.get_location_from_localtime(localtime)

        longitude_new = (np.arctan2(loc_localtime[1],loc_localtime[0]))
        ret = tuple([np.cos(longitude_new) * np.cos(latitude_new)*RE, np.sin(longitude_new) * np.cos(latitude_new)*RE, np.sin(latitude_new)*RE])
        return ret
예제 #3
0
    def _integrate_i(self, B_mirror):
        """
        integrates a specific I for a given B_mirror
        :param B_mirror:
        :return: Value of I
        """
        if not self.is_bifurcated:
            if B_mirror in self.get_b_mag_values():
                # 1) locate B_mirror index
                b_f_mag = [ih.mag(x) for x in self.fieldLineData_f]
                b_mir_ind = b_f_mag.index(B_mirror)

                # 2) Integrate FORWARD to B_mirror
                int_forward = self.trap_int(dataValue=self.fieldLineData_f,
                                            dataLoc=self.fieldLinePoints_f,
                                            start=0,
                                            stop=b_mir_ind)

                # 3) Integrate BACKWARD to B_mirror
                int_backward = self.trap_int(dataValue=self.fieldLineData_b,
                                             dataLoc=self.fieldLinePoints_b,
                                             start=0,
                                             stop=b_mir_ind)

                # 4) Return BACKWARD + FORWARD
                return int_forward + int_backward

            else:
                b_mags = self.get_b_mag_values()
                hi_ind = bs.bisect_left(b_mags, B_mirror)
                if hi_ind == len(b_mags) or hi_ind == 0:
                    return None
                else:
                    bmir, Iall = ih.dict_to_x_y(self.get_i_integrals())

                    return ih.cub_interp(Iall, bmir, B_mirror)
        else:
            return None
예제 #4
0
    def build_grid(self):
        # Dimensions

        nx, ny, nz = self._dims_[0], self._dims_[1], self._dims_[
            2]  # Grid Extent resolution
        lx, ly, lz = self._extents_[0], self._extents_[2], self._extents_[4]
        ux, uy, uz = self._extents_[1], self._extents_[3], self._extents_[5]

        # Coordinates
        X = np.linspace(lx, ux, nx)
        Y = np.linspace(ly, uy, ny)
        Z = np.linspace(lz, uz, nz)

        # Build the Grid
        x = np.zeros((nx, ny, nz))
        y = np.zeros((nx, ny, nz))
        z = np.zeros((nx, ny, nz))

        for k in range(len(Z)):
            for j in range(len(Y)):
                for i in range(len(X)):
                    x[i, j, k] = X[i]
                    y[i, j, k] = Y[j]
                    z[i, j, k] = Z[k]
                    if (-self._exclusion_distance_ < X[i] <
                            self._exclusion_distance_) and (
                                -self._exclusion_distance_ < Y[j] <
                                self._exclusion_distance_) and (
                                    -self._exclusion_distance_ < Z[k] <
                                    self._exclusion_distance_):
                        if ih.mag([X[i], Y[j], Z[k]
                                   ]) < self._exclusion_distance_:
                            self.origin_exclusion.append((i, j, k))
                            print "Excluding: ", (i, j, k)

        return x, y, z
예제 #5
0
    def __init__(self, PV_dataObject=None, local_times=None, K=None, b_mirror=None, start_line=None, mode='K', error_tol=None):
        """
        Initialization routine for driftShell class. Sets up the intial configuration of a drift shell
        :param PV_dataObject: Paraview Data object that contains the grid
        :param local_times: array like object of starting local times for finding starting lines (mode='K', K, b_mirror) required.
        :param K: value of K used to define the particle
        :param b_mirror: b_mirror (nT) used to define the particle
        :param start_line: (x,y,z) coordinates for starting line (requires b_mirror)
        :param mode: 'location' or 'K'.
                     'location': starts with a specific location and traces first line there. Uses the given b_mirror.
                     'K': utilizes local time and K to itterate and find the requested b_mirror
        """

        self.data = PV_dataObject
        self.is_valid = True
        self.analytic = False

        if error_tol is None:
            self.error_tol = 1e-5
        else:
            self.error_tol = error_tol

        if mode is 'location_k':
            print "Location (K) based mode"

            if start_line is None or K is None:
                print "ERROR: start_line and K are both required in this mode"
                sys.exit()
            self.start_location = start_line
            self.start_RE = ih.mag(start_line)
            self.K = K
            self.field_lines = col.OrderedDict()
            localtime2 = ih.get_local_time_from_location(start_line)
            self.field_lines[localtime2] = fl.fieldLine(self.data, start=start_line)
            self.b_mirror = self.field_lines[localtime2].get_B_mirror_for_K(self.K)
            for lt in local_times:
                print "Processing Local Time: ", lt
                self.add_field_line_from_K(local_time=lt)
                if not self.field_lines[lt] is None:
                    self.start_RE = ih.mag(self.field_lines[lt].startLoc)

        elif mode is 'location_b':
            print "Location (b_mirror) based mode"

            if start_line is None or b_mirror is None:
                print "ERROR: start_line and b_mirror are both required in this mode"
                sys.exit()
            self.start_location = start_line
            self.start_RE = ih.mag(start_line)
            self.b_mirror = b_mirror
            self.field_lines = col.OrderedDict()
            localtime2 = ih.get_local_time_from_location(start_line)
            self.field_lines[localtime2] = fl.fieldLine(self.data, start=start_line)
            self.K = self.field_lines[localtime2].get_K(self.b_mirror)
            for lt in local_times:
                print "Processing Local Time: ", lt
                self.add_field_line_from_K(local_time=lt)
                if not self.field_lines[lt] is None:
                    self.start_RE = ih.mag(self.field_lines[lt].startLoc)

        elif mode is 'K':
            print "K search based mode"
            if K is None or b_mirror is None or local_times is None:
                print "ERROR: local_times, K, and b_mirror are all required in this mode"
                sys.exit()

            self.start_RE = 5.0
            self.b_mirror = b_mirror
            self.K = K

            self.field_lines = col.OrderedDict()
            for lt in local_times:
                print "Processing Local Time: ", lt
                self.add_field_line_from_K(local_time=lt)
                if not self.field_lines[lt] is None:
                    self.start_RE = ih.mag(self.field_lines[lt].startLoc)

        elif mode is 'analytic_K':
            print "Analytic (K) based mode"
            self.analytic = True
            if start_line is None or K is None:
                print "ERROR: start_line and K are both required in this mode"
                sys.exit()
            self.start_location = start_line
            self.start_RE = ih.mag(start_line)
            self.K = K
            self.field_lines = col.OrderedDict()
            localtime2 = ih.get_local_time_from_location(start_line)
            self.field_lines[localtime2] = fl.fieldLine(start=start_line, error_tol=self.error_tol)
            self.b_mirror = self.field_lines[localtime2].get_B_mirror_for_K(self.K)
            for lt in local_times:
                print "Processing Local Time: ", lt
                self.add_field_line_from_K(local_time=lt)
                if not self.field_lines[lt] is None:
                    self.start_RE = ih.mag(self.field_lines[lt].startLoc)

        else:
            print "Mode ", mode, " is not understood. Exiting."
            sys.exit()
예제 #6
0
    def get_location_for_RE(self, RE):
        """
        Return the coordinates on the Line where it crosses the given RE distance from Earth.  Returns None if
        no such crossing occurs.
        :param RE: Distance (in RE) for where we want the coordinates on the line.
        :return: list of x,y,z coordinates for where the line crosses the RE distance specified. None otherwise.
        """

        # Get the line in RE format
        RE_f = [ih.mag(x) for x in self.fieldLinePoints_f]

        #if was registerd as bifrucated, we have to do a little extra work
        if self.is_bifurcated:
            print "Caution: This line is registering as bifurcated.\nAttempting to find the intersection point"
            print "monotonically decreasing test: {}".format(ih.mon_dec(RE_f))
            if not ih.mon_dec(RE_f):
                print "Need to adjust trace"
                print "exporting Data Dump"
                pos = np.asarray(self.fieldLinePoints_f)
                dat = np.asarray(self.fieldLineData_f)
                dpos = np.diff(self.fieldLinePoints_f, axis=0)
                ddat = np.diff(self.fieldLineData_f, axis=0)

                np.savetxt("errors/pos_{}.csv".format(self.startLoc),
                           pos,
                           delimiter=",")
                np.savetxt("errors/dat_{}.csv".format(self.startLoc),
                           dat,
                           delimiter=",")
                np.savetxt("errors/dpos_{}.csv".format(self.startLoc),
                           dpos,
                           delimiter=",")
                np.savetxt("errors/ddat_{}.csv".format(self.startLoc),
                           dpos,
                           delimiter=",")

        ind_f = None
        loc_f = None

        # reverse the list
        RE_f.reverse()

        if RE < RE_f[0] or RE > RE_f[-1]:
            print "Out of bounds:"
            print "RE: ", RE
            print "RE_f: ", RE_f[0], ":", RE_f[-1]
        else:
            ind_f = bs.bisect_left(RE_f, RE)
            # print "Index: ", ind_f

            bound_f = vb.valBounds(
                lowerVal=RE_f[ind_f - 1],
                lowerLoc=self.fieldLinePoints_f[-ind_f],
                upperVal=RE_f[ind_f],
                upperLoc=self.fieldLinePoints_f[-(ind_f + 1)])

            wa = 0.0
            loc_f = bound_f.get_location(RE, weight_adjust=wa)
            loc_RE = ih.mag(loc_f)

            # TODO: make this a percentage... or don't do it at all, as this can cause an infinite loop like behaviour.
            # while not np.isclose(loc_RE, RE):
            #     if loc_RE < RE:
            #         wa += 0.0001
            #         loc_f = bound_f.get_location(RE, weight_adjust=wa)
            #         loc_RE = ih.mag(loc_f)
            #         print "Adjusting: ", wa,
            #         print "new RE: ", loc_RE
            #
            #     if loc_RE > RE:
            #         wa -= 0.0001
            #         loc_f = bound_f.get_location(RE, weight_adjust=wa)
            #         loc_RE = ih.mag(loc_f)
            #         print "Adjusting: ", wa,
            #         print "new RE: ", loc_RE

        # print "Location for ", RE, " RE: ",loc_f
        # print "Verification: ", RE, " = ", ih.mag(loc_f)

        # TODO: calculate and return the backward location as well. (if needed)

        return loc_f
예제 #7
0
 def get_b_mag_backward(self):
     return [ih.mag(x) for x in self.fieldLineData_b]
예제 #8
0
 def get_b_mag_values(self):
     """
     returns a list of discreete b_mag values in the field trace
     :return: list containing [|B|] contained in trace.
     """
     return [ih.mag(x) for x in self.fieldLineData_f]