def unrotated_center(self): c_lng = rotations.get_center_angle(self.max_longitude, self.min_longitude) c_lat = rotations.colat2lat( rotations.get_center_angle(rotations.lat2colat(self.max_latitude), rotations.lat2colat(self.min_latitude))) Point = collections.namedtuple("CenterPoint", ["longitude", "latitude"]) return Point(longitude=c_lng, latitude=c_lat)
def unrotated_center(self): c_lng = rotations.get_center_angle(self.max_longitude, self.min_longitude) c_lat = rotations.colat2lat(rotations.get_center_angle( rotations.lat2colat(self.max_latitude), rotations.lat2colat(self.min_latitude))) Point = collections.namedtuple("CenterPoint", ["longitude", "latitude"]) return Point(longitude=c_lng, latitude=c_lat)
def _on_button_press(event): if event.button != 1 or not event.inaxes: return lon, lat = m(event.xdata, event.ydata, inverse=True) # Convert to colat to ease indexing. colat = rotations.lat2colat(lat) x_range = (self.setup["physical_boundaries_x"][1] - self.setup["physical_boundaries_x"][0]) x_frac = (colat - self.setup["physical_boundaries_x"][0]) / x_range x_index = int(((self.setup["boundaries_x"][1] - self.setup["boundaries_x"][0]) * x_frac) + self.setup["boundaries_x"][0]) y_range = (self.setup["physical_boundaries_y"][1] - self.setup["physical_boundaries_y"][0]) y_frac = (lon - self.setup["physical_boundaries_y"][0]) / y_range y_index = int(((self.setup["boundaries_y"][1] - self.setup["boundaries_y"][0]) * y_frac) + self.setup["boundaries_y"][0]) plt.figure(1, figsize=(3, 8)) depths = available_depths values = data[x_index, y_index, :] plt.plot(values, depths) plt.grid() plt.ylim(depths[-1], depths[0]) plt.show() plt.close() plt.figure(0)
def write(self, outdir, verbose=True): """Write input files(setup, event_x, event_list, recfile_x, stf) to given directory """ outdir = outdir if not os.path.isdir(outdir): os.makedirs(outdir) self.events.write(outdir, config=self.config) self.stalst.write(outdir) stf_fname = outdir + '/stf' # Note: header is mandatory for stf file!!! np.savetxt(stf_fname, self.config.source_time_function, header='\n \n \n') if self.config.is_dissipative and ( not os.path.isfile(outdir + '/relax')): print outdir raise AttributeError('relax file not exists!') setup_file_template = ( "MODEL ===============================================================" "=================================================================" "=====\n" "{theta_min:<44.6f}! theta_min (colatitude) in degrees\n" "{theta_max:<44.6f}! theta_max (colatitude) in degrees\n" "{phi_min:<44.6f}! phi_min (longitude) in degrees\n" "{phi_max:<44.6f}! phi_max (longitude) in degrees\n" "{z_min:<44.6f}! z_min (radius) in m\n" "{z_max:<44.6f}! z_max (radius) in m\n" "{is_diss:<44d}! is_diss\n" "{model_type:<44d}! model_type\n" "COMPUTATIONAL SETUP (PARALLELISATION) ===============================" "=================================================================" "=====\n" "{nx_global:<44d}! nx_global, " "(nx_global+px = global # elements in theta direction)\n" "{ny_global:<44d}! ny_global, " "(ny_global+py = global # elements in phi direction)\n" "{nz_global:<44d}! nz_global, " "(nz_global+pz = global # of elements in r direction)\n" "{lpd:<44d}! lpd, LAGRANGE polynomial degree\n" "{px:<44d}! px, processors in theta direction\n" "{py:<44d}! py, processors in phi direction\n" "{pz:<44d}! pz, processors in r direction\n" "ADJOINT PARAMETERS ==================================================" "=================================================================" "=====\n" "{adjoint_flag:<44d}! adjoint_flag (0=normal simulation, " "1=adjoint forward, 2=adjoint reverse)\n" "{samp_ad:<44d}! samp_ad, sampling rate of forward field\n" "{adjoint_wavefield_folder}") EARTH_RADIUS = 6371 * 1000. adjointdict = { 'normal simulation': 0, 'adjoint forward': 1, 'adjoint reverse': 2 } setup_file = setup_file_template.format( # Colatitude! Swaps min and max. theta_min=rotations.lat2colat(float( self.config.mesh_max_latitude)), theta_max=rotations.lat2colat(float( self.config.mesh_min_latitude)), phi_min=float(self.config.mesh_min_longitude), phi_max=float(self.config.mesh_max_longitude), # Min/max radius and depth are inverse to each other. z_min=EARTH_RADIUS - (float(self.config.mesh_max_depth_in_km) * 1000.0), z_max=EARTH_RADIUS - (float(self.config.mesh_min_depth_in_km) * 1000.0), is_diss=1 if self.config.is_dissipative else 0, model_type=3, lpd=int(self.config.lagrange_polynomial_degree), # Computation setup. nx_global=self.config.nx_global, ny_global=self.config.ny_global, nz_global=self.config.nz_global, px=self.config.px, py=self.config.py, pz=self.config.pz, adjoint_flag=adjointdict[self.config.simulation_type], samp_ad=self.config.adjoint_forward_sampling_rate, adjoint_wavefield_folder=self.config. adjoint_forward_wavefield_output_folder) setup_fname = outdir + '/setup' with open(setup_fname, 'wb') as f: f.writelines(setup_file) return
def write(self, outdir, config=None, nt=None, dt=None, output_folder=None, ssamp=None, outdisp=None): """Write event file to ouput directory """ try: nt = config.number_of_time_steps dt = config.time_increment_in_s output_folder = config.output_folder ssamp = config.displacement_snapshot_sampling outdisp = config.output_displacement except: if nt == None or dt == None or output_folder == None or ssamp == None or outdisp == None: raise ValueError('Wrong input for events writer!') if not os.path.isdir(outdir): os.makedirs(outdir) eventlst = outdir + '/event_list' L = len(self.events) lst_template = ("{L:<44d}! n_events = number of events\n") lst_file = lst_template.format(L=int(L)) with open(eventlst, 'wb') as f: f.writelines(lst_file) for i in xrange(L): f.writelines('%d \n' % (i + 1)) event_template = ( "SIMULATION PARAMETERS ===============================================" "===================================\n" "{nt:<44d}! nt, number of time steps\n" "{dt:<44.6f}! dt in sec, time increment\n" "SOURCE ==============================================================" "===================================\n" "{xxs:<44.6f}! xxs, theta-coord. center of source in degrees\n" "{yys:<44.6f}! yys, phi-coord. center of source in degrees\n" "{zzs:<44.6f}! zzs, source depth in (m)\n" "{srctype:<44d}! srctype, 1:f_x, 2:f_y, 3:f_z, 10:M_ij\n" "{m_tt:<44.6e}! M_theta_theta\n" "{m_pp:<44.6e}! M_phi_phi\n" "{m_rr:<44.6e}! M_r_r\n" "{m_tp:<44.6e}! M_theta_phi\n" "{m_tr:<44.6e}! M_theta_r\n" "{m_pr:<44.6e}! M_phi_r\n" "OUTPUT DIRECTORY ====================================================" "==================================\n" "{output_folder}\n" "OUTPUT FLAGS ========================================================" "==================================\n" "{ssamp:<44d}! ssamp, snapshot sampling\n" "{output_displacement:<44d}! output_displacement, output displacement " "field (1=yes,0=no)") for i in xrange(L): eventname = outdir + '/event_%d' % (i + 1) with open(eventname, 'wb') as f: lat = self.events[i].origins[0].latitude lon = self.events[i].origins[0].longitude evdp = self.events[i].origins[0].depth * 1000. m_tt = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_tt m_rr = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_rr m_pp = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_pp m_tp = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_tp m_tr = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_rt m_pr = self.events[i].focal_mechanisms[ 0].moment_tensor.tensor.m_rp event_file = event_template.format( nt=int(nt), dt=float(dt), # Colatitude! xxs=rotations.lat2colat(lat), yys=lon, zzs=evdp, srctype=10, m_tt=float(m_tt), m_pp=float(m_pp), m_rr=float(m_rr), m_tp=float(m_tp), m_tr=float(m_tr), m_pr=float(m_pr), output_folder=output_folder, ssamp=int(ssamp), output_displacement=outdisp) f.writelines(event_file) return
def finalize_adjoint_sources(self, iteration_name, event_name): """ Finalizes the adjoint sources. """ from itertools import izip import numpy as np from lasif import rotations all_coordinates = [] _i = 0 window_manager = self.comm.windows.get(event_name, iteration_name) event = self.comm.events.get(event_name) iteration = self.comm.iterations.get(iteration_name) iteration_event_def = iteration.events[event["event_name"]] iteration_stations = iteration_event_def["stations"] event_weight = iteration_event_def["event_weight"] output_folder = self.comm.project.get_output_folder( "adjoint_sources__ITERATION_%s__%s" % (iteration_name, event_name)) l = sorted(window_manager.list()) for station, windows in itertools.groupby( l, key=lambda x: ".".join(x.split(".")[:2])): if station not in iteration_stations: continue station_weight = iteration_stations[station]["station_weight"] channels = {} for w in windows: w = window_manager.get(w) channel_weight = 0 srcs = [] for window in w: ad_src = window.adjoint_source if not ad_src["adjoint_source"].ptp(): continue srcs.append(ad_src["adjoint_source"] * window.weight) channel_weight += window.weight if not srcs: continue # Final adjoint source for that channel and apply all weights. adjoint_source = np.sum(srcs, axis=0) / channel_weight * \ event_weight * station_weight channels[w.channel_id[-1]] = adjoint_source if not channels: continue # Now all adjoint sources of a window should have the same length. length = set(len(v) for v in channels.values()) assert len(length) == 1 length = length.pop() # All missing channels will be replaced with a zero array. for c in ["Z", "N", "E"]: if c in channels: continue channels[c] = np.zeros(length) # Get the station coordinates coords = self.comm.query.get_coordinates_for_station(event_name, station) # Rotate. if needed rec_lat = coords["latitude"] rec_lng = coords["longitude"] domain = self.comm.project.domain if domain["rotation_angle"]: # Rotate the adjoint source location. r_rec_lat, r_rec_lng = rotations.rotate_lat_lon( rec_lat, rec_lng, domain["rotation_axis"], -domain["rotation_angle"]) # Rotate the adjoint sources. channels["N"], channels["E"], channels["Z"] = \ rotations.rotate_data( channels["N"], channels["E"], channels["Z"], rec_lat, rec_lng, domain["rotation_axis"], -domain["rotation_angle"]) else: r_rec_lat = rec_lat r_rec_lng = rec_lng r_rec_depth = 0.0 r_rec_colat = rotations.lat2colat(r_rec_lat) CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"} _i += 1 adjoint_src_filename = os.path.join(output_folder, "ad_src_%i" % _i) all_coordinates.append((r_rec_colat, r_rec_lng, r_rec_depth)) # Actually write the adjoint source file in SES3D specific format. with open(adjoint_src_filename, "wt") as open_file: open_file.write("-- adjoint source ------------------\n") open_file.write("-- source coordinates (colat,lon,depth)\n") open_file.write("%f %f %f\n" % (r_rec_colat, r_rec_lng, r_rec_depth)) open_file.write("-- source time function (x, y, z) --\n") for x, y, z in izip(-1.0 * channels[CHANNEL_MAPPING["X"]], channels[CHANNEL_MAPPING["Y"]], channels[CHANNEL_MAPPING["Z"]]): open_file.write("%e %e %e\n" % (x, y, z)) open_file.write("\n") # Write the final file. with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh: fh.write("%i\n" % _i) for line in all_coordinates: fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2])) fh.write("\n") print "Wrote %i adjoint sources to %s." % ( _i, os.path.relpath(output_folder))
def finalize_adjoint_sources(self, iteration_name, event_name): """ Finalizes the adjoint sources. """ from itertools import izip import numpy as np from lasif import rotations window_manager = self.comm.windows.get(event_name, iteration_name) event = self.comm.events.get(event_name) iteration = self.comm.iterations.get(iteration_name) iteration_event_def = iteration.events[event["event_name"]] iteration_stations = iteration_event_def["stations"] # For now assume that the adjoint sources have the same # sampling rate as the synthetics which in LASIF's workflow # actually has to be true. dt = iteration.get_process_params()["dt"] # Current domain and solver. domain = self.comm.project.domain solver = iteration.solver_settings["solver"].lower() adjoint_source_stations = set() if "ses3d" in solver: ses3d_all_coordinates = [] event_weight = iteration_event_def["event_weight"] output_folder = self.comm.project.get_output_folder( type="adjoint_sources", tag="ITERATION_%s__%s" % (iteration_name, event_name)) l = sorted(window_manager.list()) for station, windows in itertools.groupby( l, key=lambda x: ".".join(x.split(".")[:2])): if station not in iteration_stations: continue print ".", station_weight = iteration_stations[station]["station_weight"] channels = {} try: for w in windows: w = window_manager.get(w) channel_weight = 0 srcs = [] for window in w: ad_src = window.adjoint_source if not ad_src["adjoint_source"].ptp(): continue srcs.append(ad_src["adjoint_source"] * window.weight) channel_weight += window.weight if not srcs: continue # Final adjoint source for that channel and apply all # weights. adjoint_source = np.sum(srcs, axis=0) / channel_weight * \ event_weight * station_weight channels[w.channel_id[-1]] = adjoint_source except LASIFError as e: print("Could not calculate adjoint source for iteration %s " "and station %s. Repick windows? Reason: %s" % ( iteration.name, station, str(e))) continue if not channels: continue # Now all adjoint sources of a window should have the same length. length = set(len(v) for v in channels.values()) assert len(length) == 1 length = length.pop() # All missing channels will be replaced with a zero array. for c in ["Z", "N", "E"]: if c in channels: continue channels[c] = np.zeros(length) # Get the station coordinates coords = self.comm.query.get_coordinates_for_station(event_name, station) # Rotate. if needed rec_lat = coords["latitude"] rec_lng = coords["longitude"] # The adjoint sources depend on the solver. if "ses3d" in solver: # Rotate if needed. if domain.rotation_angle_in_degree: # Rotate the adjoint source location. r_rec_lat, r_rec_lng = rotations.rotate_lat_lon( rec_lat, rec_lng, domain.rotation_axis, -domain.rotation_angle_in_degree) # Rotate the adjoint sources. channels["N"], channels["E"], channels["Z"] = \ rotations.rotate_data( channels["N"], channels["E"], channels["Z"], rec_lat, rec_lng, domain.rotation_axis, -domain.rotation_angle_in_degree) else: r_rec_lat = rec_lat r_rec_lng = rec_lng r_rec_depth = 0.0 r_rec_colat = rotations.lat2colat(r_rec_lat) # Now once again map from ZNE to the XYZ of SES3D. CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"} adjoint_source_stations.add(station) adjoint_src_filename = os.path.join( output_folder, "ad_src_%i" % len(adjoint_source_stations)) ses3d_all_coordinates.append( (r_rec_colat, r_rec_lng, r_rec_depth)) # Actually write the adjoint source file in SES3D specific # format. with open(adjoint_src_filename, "wt") as open_file: open_file.write("-- adjoint source ------------------\n") open_file.write( "-- source coordinates (colat,lon,depth)\n") open_file.write("%f %f %f\n" % (r_rec_colat, r_rec_lng, r_rec_depth)) open_file.write("-- source time function (x, y, z) --\n") # Revert the X component as it has to point south in SES3D. for x, y, z in izip(-1.0 * channels[CHANNEL_MAPPING["X"]], channels[CHANNEL_MAPPING["Y"]], channels[CHANNEL_MAPPING["Z"]]): open_file.write("%e %e %e\n" % (x, y, z)) open_file.write("\n") elif "specfem" in solver: s_set = iteration.solver_settings["solver_settings"] if "adjoint_source_time_shift" not in s_set: warnings.warn("No <adjoint_source_time_shift> tag in the " "iteration XML file. No time shift for the " "adjoint sources will be applied.", LASIFWarning) src_time_shift = 0 else: src_time_shift = float(s_set["adjoint_source_time_shift"]) adjoint_source_stations.add(station) # Write all components. The adjoint sources right now are # not time shifted. for component in ["Z", "N", "E"]: # XXX: M band code could be different. adjoint_src_filename = os.path.join( output_folder, "%s.MX%s.adj" % (station, component)) adj_src = channels[component] l = len(adj_src) to_write = np.empty((l, 2)) to_write[:, 0] = \ np.linspace(0, (l - 1) * dt, l) + src_time_shift # SPECFEM expects non-time reversed adjoint sources and # the sign is different for some reason. to_write[:, 1] = -1.0 * adj_src[::-1] np.savetxt(adjoint_src_filename, to_write) else: raise NotImplementedError( "Adjoint source writing for solver '%s' not yet " "implemented." % iteration.solver_settings["solver"]) if not adjoint_source_stations: print("Could not create a single adjoint source.") return if "ses3d" in solver: with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh: fh.write("%i\n" % len(adjoint_source_stations)) for line in ses3d_all_coordinates: fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2])) fh.write("\n") elif "specfem" in solver: adjoint_source_stations = sorted(list(adjoint_source_stations)) with open(os.path.join(output_folder, "STATIONS_ADJOINT"), "wt") as fh: for station in adjoint_source_stations: coords = self.comm.query.get_coordinates_for_station( event_name, station) fh.write("{sta} {net} {lat} {lng} {ele} {dep}\n".format( sta=station.split(".")[1], net=station.split(".")[0], lat=coords["latitude"], lng=coords["longitude"], ele=coords["elevation_in_m"], dep=coords["local_depth_in_m"])) print "Wrote adjoint sources for %i station(s) to %s." % ( len(adjoint_source_stations), os.path.relpath(output_folder))
def finalize_adjoint_sources(self, iteration_name, event_name): """ Finalizes the adjoint sources. """ import numpy as np from lasif import rotations window_manager = self.comm.windows.get(event_name, iteration_name) event = self.comm.events.get(event_name) iteration = self.comm.iterations.get(iteration_name) iteration_event_def = iteration.events[event["event_name"]] iteration_stations = iteration_event_def["stations"] # For now assume that the adjoint sources have the same # sampling rate as the synthetics which in LASIF's workflow # actually has to be true. dt = iteration.get_process_params()["dt"] # Current domain and solver. domain = self.comm.project.domain solver = iteration.solver_settings["solver"].lower() adjoint_source_stations = set() if "ses3d" in solver: ses3d_all_coordinates = [] event_weight = iteration_event_def["event_weight"] output_folder = self.comm.project.get_output_folder( type="adjoint_sources", tag="ITERATION_%s__%s" % (iteration_name, event_name)) l = sorted(window_manager.list()) for station, windows in itertools.groupby( l, key=lambda x: ".".join(x.split(".")[:2])): if station not in iteration_stations: continue print(".", end=' ') station_weight = iteration_stations[station]["station_weight"] channels = {} try: for w in windows: w = window_manager.get(w) channel_weight = 0 srcs = [] for window in w: ad_src = window.adjoint_source if not ad_src["adjoint_source"].ptp(): continue srcs.append(ad_src["adjoint_source"] * window.weight) channel_weight += window.weight if not srcs: continue # Final adjoint source for that channel and apply all # weights. adjoint_source = np.sum(srcs, axis=0) / channel_weight * \ event_weight * station_weight channels[w.channel_id[-1]] = adjoint_source except LASIFError as e: print(("Could not calculate adjoint source for iteration %s " "and station %s. Repick windows? Reason: %s" % (iteration.name, station, str(e)))) continue if not channels: continue # Now all adjoint sources of a window should have the same length. length = set(len(v) for v in list(channels.values())) assert len(length) == 1 length = length.pop() # All missing channels will be replaced with a zero array. for c in ["Z", "N", "E"]: if c in channels: continue channels[c] = np.zeros(length) # Get the station coordinates coords = self.comm.query.get_coordinates_for_station( event_name, station) # Rotate. if needed rec_lat = coords["latitude"] rec_lng = coords["longitude"] # The adjoint sources depend on the solver. if "ses3d" in solver: # Rotate if needed. if domain.rotation_angle_in_degree: # Rotate the adjoint source location. r_rec_lat, r_rec_lng = rotations.rotate_lat_lon( rec_lat, rec_lng, domain.rotation_axis, -domain.rotation_angle_in_degree) # Rotate the adjoint sources. channels["N"], channels["E"], channels["Z"] = \ rotations.rotate_data( channels["N"], channels["E"], channels["Z"], rec_lat, rec_lng, domain.rotation_axis, -domain.rotation_angle_in_degree) else: r_rec_lat = rec_lat r_rec_lng = rec_lng r_rec_depth = 0.0 r_rec_colat = rotations.lat2colat(r_rec_lat) # Now once again map from ZNE to the XYZ of SES3D. CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"} adjoint_source_stations.add(station) adjoint_src_filename = os.path.join( output_folder, "ad_src_%i" % len(adjoint_source_stations)) ses3d_all_coordinates.append( (r_rec_colat, r_rec_lng, r_rec_depth)) # Actually write the adjoint source file in SES3D specific # format. with open(adjoint_src_filename, "wt") as open_file: open_file.write("-- adjoint source ------------------\n") open_file.write( "-- source coordinates (colat,lon,depth)\n") open_file.write("%f %f %f\n" % (r_rec_colat, r_rec_lng, r_rec_depth)) open_file.write("-- source time function (x, y, z) --\n") # Revert the X component as it has to point south in SES3D. for x, y, z in zip(-1.0 * channels[CHANNEL_MAPPING["X"]], channels[CHANNEL_MAPPING["Y"]], channels[CHANNEL_MAPPING["Z"]]): open_file.write("%e %e %e\n" % (x, y, z)) open_file.write("\n") elif "specfem" in solver: s_set = iteration.solver_settings["solver_settings"] if "adjoint_source_time_shift" not in s_set: warnings.warn( "No <adjoint_source_time_shift> tag in the " "iteration XML file. No time shift for the " "adjoint sources will be applied.", LASIFWarning) src_time_shift = 0 else: src_time_shift = float(s_set["adjoint_source_time_shift"]) adjoint_source_stations.add(station) # Write all components. The adjoint sources right now are # not time shifted. for component in ["Z", "N", "E"]: # XXX: M band code could be different. adjoint_src_filename = os.path.join( output_folder, "%s.MX%s.adj" % (station, component)) adj_src = channels[component] l = len(adj_src) to_write = np.empty((l, 2)) to_write[:, 0] = \ np.linspace(0, (l - 1) * dt, l) + src_time_shift # SPECFEM expects non-time reversed adjoint sources and # the sign is different for some reason. to_write[:, 1] = -1.0 * adj_src[::-1] np.savetxt(adjoint_src_filename, to_write) else: raise NotImplementedError( "Adjoint source writing for solver '%s' not yet " "implemented." % iteration.solver_settings["solver"]) if not adjoint_source_stations: print("Could not create a single adjoint source.") return if "ses3d" in solver: with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh: fh.write("%i\n" % len(adjoint_source_stations)) for line in ses3d_all_coordinates: fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2])) fh.write("\n") elif "specfem" in solver: adjoint_source_stations = sorted(list(adjoint_source_stations)) with open(os.path.join(output_folder, "STATIONS_ADJOINT"), "wt") as fh: for station in adjoint_source_stations: coords = self.comm.query.get_coordinates_for_station( event_name, station) fh.write("{sta} {net} {lat} {lng} {ele} {dep}\n".format( sta=station.split(".")[1], net=station.split(".")[0], lat=coords["latitude"], lng=coords["longitude"], ele=coords["elevation_in_m"], dep=coords["local_depth_in_m"])) print("Wrote adjoint sources for %i station(s) to %s." % (len(adjoint_source_stations), os.path.relpath(output_folder)))
def write(self, outdir, verbose=True): """Write input files(setup, event_x, event_list, recfile_x, stf) to given directory """ outdir=outdir if not os.path.isdir(outdir): os.makedirs(outdir) self.events.write(outdir, config=self.config) self.stalst.write(outdir) stf_fname=outdir+'/stf' # Note: header is mandatory for stf file!!! np.savetxt(stf_fname, self.config.source_time_function, header = '\n \n \n') if self.config.is_dissipative and ( not os.path.isfile(outdir+'/relax') ): print outdir raise AttributeError('relax file not exists!') setup_file_template = ( "MODEL ===============================================================" "=================================================================" "=====\n" "{theta_min:<44.6f}! theta_min (colatitude) in degrees\n" "{theta_max:<44.6f}! theta_max (colatitude) in degrees\n" "{phi_min:<44.6f}! phi_min (longitude) in degrees\n" "{phi_max:<44.6f}! phi_max (longitude) in degrees\n" "{z_min:<44.6f}! z_min (radius) in m\n" "{z_max:<44.6f}! z_max (radius) in m\n" "{is_diss:<44d}! is_diss\n" "{model_type:<44d}! model_type\n" "COMPUTATIONAL SETUP (PARALLELISATION) ===============================" "=================================================================" "=====\n" "{nx_global:<44d}! nx_global, " "(nx_global+px = global # elements in theta direction)\n" "{ny_global:<44d}! ny_global, " "(ny_global+py = global # elements in phi direction)\n" "{nz_global:<44d}! nz_global, " "(nz_global+pz = global # of elements in r direction)\n" "{lpd:<44d}! lpd, LAGRANGE polynomial degree\n" "{px:<44d}! px, processors in theta direction\n" "{py:<44d}! py, processors in phi direction\n" "{pz:<44d}! pz, processors in r direction\n" "ADJOINT PARAMETERS ==================================================" "=================================================================" "=====\n" "{adjoint_flag:<44d}! adjoint_flag (0=normal simulation, " "1=adjoint forward, 2=adjoint reverse)\n" "{samp_ad:<44d}! samp_ad, sampling rate of forward field\n" "{adjoint_wavefield_folder}") EARTH_RADIUS = 6371 * 1000. adjointdict={'normal simulation': 0, 'adjoint forward': 1, 'adjoint reverse': 2} setup_file = setup_file_template.format( # Colatitude! Swaps min and max. theta_min=rotations.lat2colat(float( self.config.mesh_max_latitude)), theta_max=rotations.lat2colat(float( self.config.mesh_min_latitude)), phi_min=float(self.config.mesh_min_longitude), phi_max=float(self.config.mesh_max_longitude), # Min/max radius and depth are inverse to each other. z_min=EARTH_RADIUS - (float(self.config.mesh_max_depth_in_km) * 1000.0), z_max=EARTH_RADIUS - (float(self.config.mesh_min_depth_in_km) * 1000.0), is_diss=1 if self.config.is_dissipative else 0, model_type=3, lpd=int(self.config.lagrange_polynomial_degree), # Computation setup. nx_global=self.config.nx_global, ny_global=self.config.ny_global, nz_global=self.config.nz_global, px=self.config.px, py=self.config.py, pz=self.config.pz, adjoint_flag=adjointdict[self.config.simulation_type], samp_ad=self.config.adjoint_forward_sampling_rate, adjoint_wavefield_folder=self.config.adjoint_forward_wavefield_output_folder) setup_fname=outdir+'/setup' with open(setup_fname, 'wb') as f: f.writelines(setup_file) return