Source code for UM2N.generator.rand_source_generator

# Author: Chunyang Wang
# GitHub Username: chunyang-w

import random

import firedrake as fd

__all__ = ["RandSourceGenerator"]


[docs] class RandSourceGenerator: """ Class for generating a random Helmholtz equation based on a Gaussian distribution. Attributes: simple_u (bool): Flag for using simpler form of u. dist_params (dict): Parameters for Gaussian distribution. u_exact: Analytical Helmholtz equation solution. f: Simulated source function. function_space: Function space for problem. LHS: Left-hand side of Helmholtz equation. RHS: Right-hand side of Helmholtz equation. bc: Dirichlet boundary condition. """ def __init__( self, use_iso=False, dist_params={ "max_dist": 10, "n_dist": None, # if None, then random "x_start": 0, "x_end": 1, "y_start": 0, "y_end": 1, "z_max": 1, "z_min": 0, "w_min": 0.05, "w_max": 0.2, "c_min": 0.2, "c_max": 0.8, "sigma_mean_scaler": 1 / 4, "sigma_sigma_scaler": 1 / 6, "sigma_eps": 1 / 8, }, ): """ Initialize RandomHelmholtzGenerator. Parameters: simple_u (bool): Use simpler form of u (isotripic dataset) if True. Default False. dist_params (dict): Parameters for Gaussian distribution. """ self.use_iso = use_iso self.dist_params = dist_params self.σ_dict = {"x": [], "y": []} self.μ_dict = {"x": [], "y": []} self.z_list = [] self.w_list = [] self.set_dist_params(eps=self.dist_params["sigma_eps"]) self.u_exact = 0 # analytical solution self.f = 0 # simulated source function self.function_space = None self.LHS = None self.RHS = None self.bc = None # boundary conditions
[docs] def set_dist_params(self, eps=1 / 20): """ Set parameters for Gaussian distribution from dist_params. """ if self.dist_params["n_dist"] is None: self.n_dist = random.randint(1, self.dist_params["max_dist"]) else: self.n_dist = self.dist_params["n_dist"] print("Generating {} Gaussian distributions".format(self.n_dist)) for i in range(self.n_dist): σ_mean = ( self.dist_params["x_end"] - self.dist_params["x_start"] ) * self.dist_params["sigma_mean_scaler"] σ_sigma = ( self.dist_params["x_end"] - self.dist_params["x_start"] ) * self.dist_params["sigma_sigma_scaler"] self.μ_dict["x"].append( round( random.uniform( self.dist_params["c_min"], self.dist_params["c_max"] ), 3, ) ) # noqa self.μ_dict["y"].append( round( random.uniform( self.dist_params["c_min"], self.dist_params["c_max"] ), 3, ) ) # noqa self.σ_dict["x"].append(max(round(random.gauss(σ_mean, σ_sigma), 3), eps)) self.σ_dict["y"].append(max(round(random.gauss(σ_mean, σ_sigma), 3), eps)) self.z_list.append( round( random.uniform( self.dist_params["z_min"], self.dist_params["z_max"] ), 3, ) ) self.w_list.append( round( random.uniform( self.dist_params["w_min"], self.dist_params["w_max"] ), 3, ) )
# for i in range(self.n_dist): # σ_mean = random.gauss( # (self.dist_params["x_end"] - self.dist_params["x_start"]) / 24, 1 # ) # σ_sigma = random.gauss( # (self.dist_params["y_end"] - self.dist_params["y_start"]) / 48, 1 # ) # self.μ_dict["x"].append( # round( # random.uniform( # self.dist_params["c_min"], self.dist_params["c_max"] # ), # 4, # ) # ) # noqa # self.μ_dict["y"].append( # round( # random.uniform( # self.dist_params["c_min"], self.dist_params["c_max"] # ), # 4, # ) # ) # noqa # self.σ_dict["x"].append(round(random.gauss(σ_mean, σ_sigma), 4)) # self.σ_dict["y"].append(round(random.gauss(σ_mean, σ_sigma), 4)) # self.z_list.append( # round( # random.uniform( # self.dist_params["z_min"], self.dist_params["z_max"] # ), # 4, # ) # ) # self.w_list.append( # round( # random.uniform( # self.dist_params["w_min"], self.dist_params["w_max"] # ), # 4, # ) # )
[docs] def get_dist_params(self): """ Return dictionary containing distribution parameters. Returns: dict: Dictionary of distribution parameters. """ dist = { "n_dist": self.n_dist, "σ_x": self.σ_dict["x"], "σ_y": self.σ_dict["y"], "μ_x": self.μ_dict["x"], "μ_y": self.μ_dict["y"], "z": self.z_list, "w": self.w_list, "use_iso": self.use_iso, } return dist
[docs] def get_u_exact( self, params={ "x": None, "y": None, "V": None, "u": None, "v": None, }, ): """ Return analytical solution field. Returns: firedrake.Function: Analytical solution. """ x, y = (params[key] for key in ("x", "y")) self.u_exact = 0 if self.use_iso: # use simpler form of u for i in range(self.n_dist): μ_x = self.μ_dict["x"][i] μ_y = self.μ_dict["y"][i] w = self.w_list[i] self.u_exact += fd.exp(-1 * ((((x - μ_x) ** 2) + ((y - μ_y) ** 2)) / w)) else: # use more complex form of u for i in range(self.n_dist): σ_x = self.σ_dict["x"][i] σ_y = self.σ_dict["y"][i] μ_x = self.μ_dict["x"][i] μ_y = self.μ_dict["y"][i] z = self.z_list[i] self.u_exact += z * fd.exp( -1 * ((((x - μ_x) ** 2) / (σ_x**2)) + (((y - μ_y) ** 2) / (σ_y**2))) ) return self.u_exact