def test_grid_vs_anal_L_lfm_grid(res=9): test_re = np.linspace(start=4.0, stop=10.0, num=20) med_error = col.OrderedDict() filename = "test_data/lfm_dipole_test.vts" data = pv.OpenDataFile(filename=filename) fl1 = fl.fieldLine(data=data, start=[2.5, 0.0, 0.0]) for re in test_re: print "Running on L*={}".format(re) fl1.recompute_field_line(new_start_location=[re, 0.0, 0.0]) int_grid = ih.get_lat(fl1.get_location_for_RE(RE=2.5)) int_anal = ih.analytic_dipole_line_lat_crossing(L=re, r=2.5) int_err = np.abs(int_anal - int_grid) med_error[re] = int_err X3, Y3 = ih.dict_to_x_y(med_error) fig1 = plt.figure() ax1 = fig1.add_subplot(111) ax1.semilogy(X3, Y3, 'k.-', label="Error") ax1.set_title( "$\lambda$ Intersection Error Rates for Field Line Tracing (by $L^*$)\nLFM True Double grid Dipole Field" ) ax1.set_xlabel("$L^*$") ax1.set_ylabel("Absolute Error") # ax1.legend(handles=[line1, line2, line3], loc='best') fig1.tight_layout() fig1.savefig("out/error_analysis/Lambda_error_rates_by_re_lfm.pdf")
import fieldLine as fl import numpy as np from prototype import driftShell as ds from ghostpy.prototype import inv_common as ih fl1 = fl.fieldLine(start=[8., 0, 0]) x_f = [a[0] for a in fl1.fieldLinePoints_f] y_f = [a[1] for a in fl1.fieldLinePoints_f] z_f = [a[2] for a in fl1.fieldLinePoints_f] x_b = [a[0] for a in fl1.fieldLinePoints_b] y_b = [a[1] for a in fl1.fieldLinePoints_b] z_b = [a[2] for a in fl1.fieldLinePoints_b] print "B(K=0): {} nT".format(fl1.get_B_mirror_for_K(K=0)) divs = 1000 calcTimes = np.linspace(0, 24, num=4, endpoint=False) ds1 = ds.driftShell(local_times=calcTimes, start_line=[2.5, 0.0, 0.0], K=0, mode='analytic_K') ideal_RE = ih.mag(ds1.field_lines[0].fieldLinePoints_f[0]) print "Ideal L*: {}".format(ideal_RE) test_grids = np.arange(start=100, stop=100, step=50, dtype=np.int) L_star = ds1.calculate_L_star(RE=1.0, lat_divs=divs, lon_divs=divs) diff = ideal_RE - L_star
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()
def add_field_line_from_K(self, local_time): """ Adds a field line object to the drift shell list, based on an iteration over space for K to match B_mirror :local_time: the local time for which to search for a field line :return: True for success, False for failure """ start_unit = ih.get_location_from_localtime(local_time) start_location = list(start_unit * self.start_RE) # print start_location if not self.analytic: newLine = fl.fieldLine(self.data, start=start_location, error_tol=self.error_tol) else: newLine = fl.fieldLine(start=start_location, error_tol=self.error_tol) B_nl = newLine.get_B_mirror_for_K(self.K) new_RE = self.start_RE low_RE = 1.0 hi_RE = 3 * new_RE # TODO: This is a source of problems. needs to fix to outer boundary of grid. # print "start_unit: ", start_unit # print "start_location: ", start_location # print "newLine: ", newLine # print "B_nl: ", B_nl # print "new_RE: ", new_RE # print "low_RE: ", low_RE # print "hi_RE: ", hi_RE # # print "Start RE: ", self.start_RE if B_nl is None: print "Line Not Found" print "Is Bifurcated? ", newLine.is_bifurcated b_values, K_values = ih.dict_to_x_y(newLine.get_k_integrals()) print "self.K", self.K print "Line K Range: ", K_values[0], ":" ,K_values[-1] print "Line B_m Range: ", b_values[0], ":", b_values[-1] return False while not np.isclose(B_nl, self.b_mirror, atol=self.error_tol, rtol=0.0) and not np.isclose(hi_RE,low_RE, atol=self.error_tol, rtol=0.0): dist = np.float64(self.b_mirror-B_nl) sep_orig = np.abs((self.b_mirror-B_nl)/self.b_mirror) sep = 1.08*sep_orig if sep > 1.0 or sep < 0.1: print "Fixing SEP: {}".format(sep) sep = 0.5 if B_nl < self.b_mirror or B_nl is None: print "Reducing RE" hi_RE = new_RE new_RE = hi_RE - sep*(hi_RE-low_RE) else: print "Increasing RE" low_RE = new_RE new_RE = low_RE + sep*(hi_RE-low_RE) print "SEP: {}".format(sep) print "DIST: {}".format(dist) print "HI - LO: {}-{} = {}".format(hi_RE, low_RE, hi_RE - low_RE) print "New RE: {}".format(new_RE) new_start = start_unit * new_RE if not self.analytic: newLine.recompute_field_line(new_start_location=tuple(new_start)) else: newLine.recompute_field_line_analytic(new_start_location=tuple(new_start)) B_nl = newLine.get_B_mirror_for_K(self.K) if B_nl is None: print "Re-Adjusting..." if new_RE < self.start_RE: while B_nl is None: redux = 0.5 * (hi_RE - new_RE) new_RE += redux new_start = start_unit * new_RE if not self.analytic: newLine.recompute_field_line(new_start_location=tuple(new_start)) else: newLine.recompute_field_line_analytic(new_start_location=tuple(new_start)) B_nl = newLine.get_B_mirror_for_K(self.K) else: while B_nl is None: redux = 0.5 * (new_RE - low_RE) new_RE -= redux new_start = start_unit * new_RE if not self.analytic: newLine.recompute_field_line(new_start_location=tuple(new_start)) else: newLine.recompute_field_line_analytic(new_start_location=tuple(new_start)) B_nl = newLine.get_B_mirror_for_K(self.K) if np.isclose(new_RE, low_RE, atol=self.error_tol, rtol=0.0) or np.isclose(new_RE, self.start_RE, atol=self.error_tol, rtol=0.0): print "ERROR: None Value found" B_nl = None self.is_valid = False break else: continue if B_nl is None: self.field_lines[local_time] = None return False else: self.field_lines[local_time] = newLine return True
def test_grid_vs_anal(): print "Conducting grid vs. analytic dipole test" # files_res = [3,5,7,9] #,11,13] #,15,17] files_res = [9] test_re = np.linspace(start=2, stop=10, num=16) min_error = col.OrderedDict() max_error = col.OrderedDict() med_error = col.OrderedDict() for re in test_re: print "Running on L*={}".format(re) int_anal = col.OrderedDict() int_grid = col.OrderedDict() int_err = col.OrderedDict() for res in files_res: print "Executing resolution {}".format(res) filename = "../../out/fields/dipole_dp0_{}_grid.vts".format(res) data = pv.OpenDataFile(filename=filename) fl1 = fl.fieldLine(data=data, start=[re, 0.0, 0.0]) int_grid[res] = ih.get_lat(fl1.get_location_for_RE(RE=1.0)) int_anal[res] = ih.analytic_dipole_line_lat_crossing(L=re, r=1.0) int_err[res] = np.abs(int_anal[res] - int_grid[res]) # X1,Y1 = ih.dict_to_x_y(int_grid) # X2,Y2 = ih.dict_to_x_y(int_anal) # X3,Y3 = ih.dict_to_x_y(int_err) # # fig1 = plt.figure() # ax1 = fig1.add_subplot(111) # ax2 = ax1.twinx() # # line1, = ax1.plot(X1,Y1, 'bo-', label="Grid Trace") # line2, = ax1.plot(X2,Y2, 'r*-', label="Analytic Solution") # line3, = ax2.semilogy(X3,Y3, 'k.-', label="Error") # # ax1.set_title("Convergence of $\lambda$ Intersection in a Gridded Dipole Field\nfor $^* =\ {}$".format(re)) # ax1.set_xlabel("Grid Cells per $R_E$") # ax1.set_ylabel("$\lambda$ Intersection") # ax2.set_ylabel("Absolute Error") # # ax1.legend(handles=[line1, line2, line3], loc=4) # fig1.tight_layout() # fig1.savefig("out/error_analysis/Lambda_intersection_{}_grid.pdf".format(re)) # plt.close(fig1) min_error[re] = np.min(int_err.values()) max_error[re] = np.max(int_err.values()) med_error[re] = np.median(int_err.values()) #X1, Y1 = ih.dict_to_x_y(min_error) #X2, Y2 = ih.dict_to_x_y(max_error) X3, Y3 = ih.dict_to_x_y(med_error) fig1 = plt.figure() ax1 = fig1.add_subplot(111) #line1, = ax1.plot(X1, Y1, 'bo-', label="Min Error") #line2, = ax1.plot(X2, Y2, 'r*-', label="Max Error") line3, = ax1.plot(X3, Y3, 'k.-', label="Error") ax1.set_title( "Error Rates for Field Line Tracing by $L^*$\nGrid Cells per $\\text{R_E = 9$ " ) ax1.set_xlabel("$L^*$") ax1.set_ylabel("Absolute Error") # ax1.legend(handles=[line1, line2, line3], loc='best') fig1.tight_layout() fig1.savefig("out/error_analysis/Lambda_error_rates_by_re.pdf")