def get_latlon_mesh(mesh): """Build 2D projected mesh of spherical mesh""" crds_orig = mesh.coordinates mesh_dg_fs = VectorFunctionSpace(mesh, "DG", 1) crds_dg = Function(mesh_dg_fs) crds_latlon = Function(mesh_dg_fs) par_loop( """ for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { dg[i][j] = cg[i][j]; } } """, dx, { 'dg': (crds_dg, WRITE), 'cg': (crds_orig, READ) }) # lat-lon 'x' = atan2(y, x) crds_latlon.dat.data[:, 0] = arctan2(crds_dg.dat.data[:, 1], crds_dg.dat.data[:, 0]) # lat-lon 'y' = asin(z/sqrt(x^2 + y^2 + z^2)) crds_latlon.dat.data[:, 1] = (arcsin( crds_dg.dat.data[:, 2] / np_sqrt(crds_dg.dat.data[:, 0]**2 + crds_dg.dat.data[:, 1]**2 + crds_dg.dat.data[:, 2]**2))) crds_latlon.dat.data[:, 2] = 0.0 kernel = op2.Kernel( """ #define PI 3.141592653589793 #define TWO_PI 6.283185307179586 void splat_coords(double **coords) { double diff0 = (coords[0][0] - coords[1][0]); double diff1 = (coords[0][0] - coords[2][0]); double diff2 = (coords[1][0] - coords[2][0]); if (fabs(diff0) > PI || fabs(diff1) > PI || fabs(diff2) > PI) { const int sign0 = coords[0][0] < 0 ? -1 : 1; const int sign1 = coords[1][0] < 0 ? -1 : 1; const int sign2 = coords[2][0] < 0 ? -1 : 1; if (sign0 < 0) { coords[0][0] += TWO_PI; } if (sign1 < 0) { coords[1][0] += TWO_PI; } if (sign2 < 0) { coords[2][0] += TWO_PI; } } } """, "splat_coords") op2.par_loop(kernel, crds_latlon.cell_set, crds_latlon.dat(op2.RW, crds_latlon.cell_node_map())) return Mesh(crds_latlon)
def test_2D_dirichlet_regions(): # Can't do mesh refinement because MeshHierarchy ruins the domain tags mesh = Mesh("./2D_mesh.msh") dim = mesh.geometric_dimension() x = SpatialCoordinate(mesh) S = VectorFunctionSpace(mesh, "CG", 1) beta = 1.0 reg_solver = RegularizationSolver( S, mesh, beta=beta, gamma=0.0, dx=dx, design_domain=0 ) # Exact solution with free Neumann boundary conditions for this domain u_exact = Function(S) u_exact_component = (-cos(x[0] * pi * 2) + 1) * (-cos(x[1] * pi * 2) + 1) u_exact.interpolate( as_vector(tuple(u_exact_component for _ in range(dim))) ) f = Function(S) f_component = ( -beta * ( 4.0 * pi * pi * cos(2 * pi * x[0]) * (-cos(2 * pi * x[1]) + 1) + 4.0 * pi * pi * cos(2 * pi * x[1]) * (-cos(2 * pi * x[0]) + 1) ) + u_exact_component ) f.interpolate(as_vector(tuple(f_component for _ in range(dim)))) theta = TestFunction(S) rhs_form = inner(f, theta) * dx velocity = Function(S) rhs = assemble(rhs_form) reg_solver.solve(velocity, rhs) assert norm(project(domainify(u_exact, x) - velocity, S)) < 1e-3
def to_2nd_order(mesh, circle_bdy_id=None, rad=1.0): # make new coordinates function V = VectorFunctionSpace(mesh, 'CG', 2) new_coordinates = project(mesh.coordinates, V) # If we have a circle, move any nodes on the circle bdy # onto the circle. Note circle MUST be centered at origin if circle_bdy_id is not None: nodes_on_circle = V.boundary_nodes(circle_bdy_id, 'geometric') #Force all cell nodes to have given radius :arg:`rad` for node in nodes_on_circle: scale = rad / la.norm(new_coordinates.dat.data[node]) new_coordinates.dat.data[node] *= scale # Make a new mesh with given coordinates return Mesh(new_coordinates)
def mesh_from_gmsh_code(geo_code, clscale=1.0, dim=2, comm=COMM_WORLD, name="/tmp/tmp", smooth=0, delete_files=True): if comm.rank == 0: with open("%s.geo" % name, "w") as text_file: text_file.write(geo_code) comm.Barrier() generateGmsh("%s.geo" % name, "%s.msh" % name, dim, clscale, comm=comm, smooth=smooth) mesh = Mesh("%s.msh" % name) if delete_files: try: os.remove("%s.geo" % name) except OSError: pass try: os.remove("%s.msh" % name) except OSError: pass return mesh
def max_mesh_dimension(mesh: fd.Mesh): coords = mesh.coordinates MAXSP = fd.FunctionSpace(mesh, "R", 0) max_y = fd.Function(MAXSP) min_y = fd.Function(MAXSP) max_x = fd.Function(MAXSP) min_x = fd.Function(MAXSP) domain = "{[i, j] : 0 <= i < u.dofs}" def extract_comp(mode, comp, result): instruction = f""" component[0] = abs(u[i, {comp}]) """ fd.par_loop( (domain, instruction), fd.dx, { "u": (coords, fd.READ), "component": (result, mode) }, is_loopy_kernel=True, ) return result max_y_comp = extract_comp(fd.MAX, 1, max_y).dat.data[0] min_y_comp = extract_comp(fd.MIN, 1, min_y).dat.data[0] max_x_comp = extract_comp(fd.MAX, 0, max_x).dat.data[0] min_x_comp = extract_comp(fd.MIN, 0, min_x).dat.data[0] max_dim_x = abs(max_x_comp - min_x_comp) max_dim_y = abs(max_y_comp - min_y_comp) max_dim = max(max_dim_x, max_dim_y) if mesh.geometric_dimension() == 3: max_z = fd.Function(MAXSP) min_z = fd.Function(MAXSP) max_z_comp = extract_comp(fd.MAX, 2, max_z).dat.data[0] min_z_comp = extract_comp(fd.MIN, 2, min_z).dat.data[0] max_dim_z = abs(max_z_comp - min_z_comp) max_dim = max(max_dim, max_dim_z) return max_dim
xc = L/2. x, z = SpatialCoordinate(ext_mesh) hm = 1. zs = hm*a**2/((x-xc)**2 + a**2) smooth_z = True dirname = 'nh_mountain' if smooth_z: dirname += '_smootherz' zh = 5000. xexpr = as_vector([x, conditional(z < zh, z + cos(0.5*pi*z/zh)**6*zs, z)]) else: xexpr = as_vector([x, z + ((H-z)/H)*zs]) new_coords = Function(Vc).interpolate(xexpr) mesh = Mesh(new_coords) # sponge function W_DG = FunctionSpace(mesh, "DG", 2) x, z = SpatialCoordinate(mesh) zc = H-10000. mubar = 0.15/dt mu_top = conditional(z <= zc, 0.0, mubar*sin((pi/2.)*(z-zc)/(H-zc))**2) mu = Function(W_DG).interpolate(mu_top) fieldlist = ['u', 'rho', 'theta'] timestepping = TimesteppingParameters(dt=dt) output = OutputParameters(dirname=dirname, dumpfreq=18, dumplist=['u'], perturbation_fields=['theta', 'rho'],
def test_3D_dirichlet_regions(): # Can't do mesh refinement because MeshHierarchy ruins the domain tags mesh = Mesh("./3D_mesh.msh") dim = mesh.geometric_dimension() x = SpatialCoordinate(mesh) solver_parameters_amg = { "ksp_type": "cg", "ksp_converged_reason": None, "ksp_rtol": 1e-7, "pc_type": "hypre", "pc_hypre_type": "boomeramg", "pc_hypre_boomeramg_max_iter": 5, "pc_hypre_boomeramg_coarsen_type": "PMIS", "pc_hypre_boomeramg_agg_nl": 2, "pc_hypre_boomeramg_strong_threshold": 0.95, "pc_hypre_boomeramg_interp_type": "ext+i", "pc_hypre_boomeramg_P_max": 2, "pc_hypre_boomeramg_relax_type_all": "sequential-Gauss-Seidel", "pc_hypre_boomeramg_grid_sweeps_all": 1, "pc_hypre_boomeramg_truncfactor": 0.3, "pc_hypre_boomeramg_max_levels": 6, } S = VectorFunctionSpace(mesh, "CG", 1) beta = 1.0 reg_solver = RegularizationSolver( S, mesh, beta=beta, gamma=0.0, dx=dx, design_domain=0, solver_parameters=solver_parameters_amg, ) # Exact solution with free Neumann boundary conditions for this domain u_exact = Function(S) u_exact_component = ( (-cos(x[0] * pi * 2) + 1) * (-cos(x[1] * pi * 2) + 1) * (-cos(x[2] * pi * 2) + 1) ) u_exact.interpolate( as_vector(tuple(u_exact_component for _ in range(dim))) ) f = Function(S) f_component = ( -beta * ( 4.0 * pi * pi * cos(2 * pi * x[0]) * (-cos(2 * pi * x[1]) + 1) * (-cos(2 * pi * x[2]) + 1) + 4.0 * pi * pi * cos(2 * pi * x[1]) * (-cos(2 * pi * x[0]) + 1) * (-cos(2 * pi * x[2]) + 1) + 4.0 * pi * pi * cos(2 * pi * x[2]) * (-cos(2 * pi * x[1]) + 1) * (-cos(2 * pi * x[0]) + 1) ) + u_exact_component ) f.interpolate(as_vector(tuple(f_component for _ in range(dim)))) theta = TestFunction(S) rhs_form = inner(f, theta) * dx velocity = Function(S) rhs = assemble(rhs_form) reg_solver.solve(velocity, rhs) error = norm( project( domainify(u_exact, x) - velocity, S, solver_parameters=solver_parameters_amg, ) ) assert error < 5e-2
def get_latlon_mesh(mesh): coords_orig = mesh.coordinates coords_fs = coords_orig.function_space() if coords_fs.extruded: cell = mesh._base_mesh.ufl_cell().cellname() DG1_hori_elt = FiniteElement("DG", cell, 1, variant="equispaced") DG1_vert_elt = FiniteElement("DG", interval, 1, variant="equispaced") DG1_elt = TensorProductElement(DG1_hori_elt, DG1_vert_elt) else: cell = mesh.ufl_cell().cellname() DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced") vec_DG1 = VectorFunctionSpace(mesh, DG1_elt) coords_dg = Function(vec_DG1).interpolate(coords_orig) coords_latlon = Function(vec_DG1) shapes = {"nDOFs": vec_DG1.finat_element.space_dimension(), 'dim': 3} radius = np.min( np.sqrt(coords_dg.dat.data[:, 0]**2 + coords_dg.dat.data[:, 1]**2 + coords_dg.dat.data[:, 2]**2)) # lat-lon 'x' = atan2(y, x) coords_latlon.dat.data[:, 0] = np.arctan2(coords_dg.dat.data[:, 1], coords_dg.dat.data[:, 0]) # lat-lon 'y' = asin(z/sqrt(x^2 + y^2 + z^2)) coords_latlon.dat.data[:, 1] = np.arcsin( coords_dg.dat.data[:, 2] / np.sqrt(coords_dg.dat.data[:, 0]**2 + coords_dg.dat.data[:, 1]**2 + coords_dg.dat.data[:, 2]**2)) # our vertical coordinate is radius - the minimum radius coords_latlon.dat.data[:, 2] = np.sqrt(coords_dg.dat.data[:, 0]**2 + coords_dg.dat.data[:, 1]**2 + coords_dg.dat.data[:, 2]**2) - radius # We need to ensure that all points in a cell are on the same side of the branch cut in longitude coords # This kernel amends the longitude coords so that all longitudes in one cell are close together kernel = op2.Kernel( """ #define PI 3.141592653589793 #define TWO_PI 6.283185307179586 void splat_coords(double *coords) {{ double max_diff = 0.0; double diff = 0.0; for (int i=0; i<{nDOFs}; i++) {{ for (int j=0; j<{nDOFs}; j++) {{ diff = coords[i*{dim}] - coords[j*{dim}]; if (fabs(diff) > max_diff) {{ max_diff = diff; }} }} }} if (max_diff > PI) {{ for (int i=0; i<{nDOFs}; i++) {{ if (coords[i*{dim}] < 0) {{ coords[i*{dim}] += TWO_PI; }} }} }} }} """.format(**shapes), "splat_coords") op2.par_loop(kernel, coords_latlon.cell_set, coords_latlon.dat(op2.RW, coords_latlon.cell_node_map())) return Mesh(coords_latlon)
def run_trial(trial_id): """ (key, output), or *None* if use_cache is *True* and already have this result stored """ # {{{ Get indexes into lists mesh_ndx = trial_id % len(mesh_names) trial_id //= len(mesh_names) mesh_name = mesh_names[mesh_ndx] # If new mesh, delete old mesh and read in new one global current_mesh_name, mesh if current_mesh_name != mesh_name: del mesh mesh = Mesh(mesh_name) if use_2nd_order: mesh = to_2nd_order(mesh) current_mesh_name = mesh_name mesh_h = mesh_h_vals[mesh_ndx] degree_ndx = trial_id % len(degree_list) trial_id //= len(degree_list) degree = degree_list[degree_ndx] kappa_ndx = trial_id % len(kappa_list) trial_id //= len(kappa_list) kappa = kappa_list[kappa_ndx] method_ndx = trial_id % len(method_list) trial_id //= len(method_list) method = method_list[method_ndx] solver_params = method_to_kwargs[method]['solver_parameters'] # Make sure this is a valid iteration index assert trial_id == 0 # }}} kwargs = method_to_kwargs[method] # {{{ Create key holding data of this trial run: setup_info['h'] = str(mesh_h) setup_info['degree'] = str(degree) setup_info['kappa'] = str(kappa) setup_info['method'] = str(method) setup_info['pc_type'] = str(solver_params['pc_type']) if solver_params['ksp_type'] == 'preonly': setup_info['ksp_rtol'] = '' setup_info['ksp_atol'] = '' else: setup_info['ksp_rtol'] = str(solver_params['ksp_rtol']) setup_info['ksp_atol'] = str(solver_params['ksp_atol']) if method == 'nonlocal': fmm_order = get_fmm_order(kappa, mesh_h) setup_info['FMM Order'] = str(fmm_order) kwargs['FMM Order'] = fmm_order else: setup_info['FMM Order'] = '' # Add gamma/beta to setup_info if there, else make sure # it's recorded as absent in special_key for special_key in ['gamma', 'beta']: if special_key in solver_params: setup_info[special_key] = solver_params[special_key] else: setup_info[special_key] = '' key = frozenset(setup_info.items()) if key in cache and use_cache: return None trial = { 'mesh': mesh, 'degree': degree, 'true_sol_expr': get_true_sol_expr(SpatialCoordinate(mesh), kappa) } # {{{ Solve problem and evaluate error output = {} true_sol, comp_sol, snes_or_ksp = \ run_method.run_method(trial, method, kappa, comp_sol_name=method + " Computed Solution", **kwargs) if isinstance(snes_or_ksp, PETSc.SNES): ksp = snes_or_ksp.getKSP() elif isinstance(snes_or_ksp, PETSc.KSP): ksp = snes_or_ksp else: raise ValueError("snes_or_ksp must be of type PETSc.SNES or" " PETSc.KSP") l2_err = norms.l2_norm(true_sol - comp_sol, region=inner_region) h1_err = norms.h1_norm(true_sol - comp_sol, region=inner_region) # }}} # Store err in output and return output['L2 Error'] = l2_err output['H1 Error'] = h1_err ndofs = true_sol.dat.data.shape[0] output['ndofs'] = str(ndofs) if solver_params['ksp_type'] != 'preonly': output['Iteration Number'] = ksp.getIterationNumber() output['Residual Norm'] = ksp.getResidualNorm() output['Converged Reason'] = KSPReasons[ksp.getConvergedReason()] if solver_params['ksp_type'] == 'gmres': emin, emax = ksp.computeExtremeSingularValues() output['Min Extreme Singular Value'] = emin output['Max Extreme Singular Value'] = emax if visualize: plot(comp_sol) plot(true_sol) plt.show() if print_trials: for name, val in sorted(key): if val != '': print('{0: <9}: {1}'.format(name, val)) for name, val in sorted(output.items()): print('{0: <18}: {1}'.format(name, val)) return key, output
str(solver_params[new_special_key]) # Gets computed solution, prints and caches key = frozenset(setup_info.items()) new_result = not use_cache or key not in cache if new_result: # Build mesh if not done so already if mesh is None: logger.info( "Reading Mesh %s with element size %s " + " and mesh order %s...", mesh_file_name, cell_size, order) # read in using open-cascade with 0 refinements, this allows # for order 2 meshes mesh = Mesh(join('meshes/', mesh_file_name)) if order == 2: if mesh_name not in [ 'circle_in_square', 'ball_in_cube', 'circle_in_square_no_pml' ]: raise NotImplementedError( "2nd order mesh only avaiilbale" + " for circle_in_square, circle_in_square_no_pml, or ball_in_cube. " + " Not available for '%s'" % mesh_name) mesh = to_2nd_order(mesh, inner_bdy_id, mesh_options['radius']) logger.info("Mesh read in") if visualize: from firedrake import triplot
if options_prefix[-1] != '_': options_prefix += '_' new_special_key = options_prefix + special_key # FIXME: CHECK FROM COMMAND LINE if new_special_key in solver_params: setup_info[special_key] = str( solver_params[new_special_key]) # Gets computed solution, prints and caches key = frozenset(setup_info.items()) if not use_cache or key not in cache: # {{{ Read in mesh if haven't already if mesh is None: print("\nReading Mesh...") mesh = Mesh(mesh_name) if use_2nd_order: mesh = to_2nd_order(mesh, circle_bdy_id=inner_bdy_id) spatial_coord = SpatialCoordinate(mesh) trial['mesh'] = mesh print("Mesh Read in.\n") if true_sol_expr is None: true_sol_expr = get_true_sol_expr(spatial_coord) trial['true_sol_expr'] = true_sol_expr # }}} kwargs = method_to_kwargs[method] true_sol, comp_sol, snes_or_ksp = run_method.run_method(
N = mesh.num_vertices() ground_truth = np.zeros((N)) period = 2 * np.pi / 0.3 * 2 for i in range(N): ground_truth[i] = 2 * np.sin(geodesics.get(i) * period + 0.3) return ground_truth if __name__ == '__main__': parser = argument_parser() args = parser.parse_args() mesh = Mesh('resources/meshes/dragon_connected.msh', dim=3) num_eigenpairs = args.num_eigenpairs print('Constructing ground truth. It may take a while') ground_truth = construct_ground_truth(mesh) mayavi_installed = False if args.mayavi: try: import manifold_matern.plotting mayavi_installed = True except ImportError: import warnings warnings.warn( 'Mayavi does not seem to be installed.\n' 'No mayavi-based plotting will occur.', RuntimeWarning)
if mesh_dim == 3: x, y, z = spatial_coord norm = sqrt(x**2 + y**2 + z**2) return Constant(1j / (4 * pi)) / norm * exp(1j * wave_number * norm) elif mesh_dim == 2: x, y = spatial_coord return Constant(1j / 4) * hankel_function( wave_number * sqrt(x**2 + y**2), n=80) raise ValueError("Only meshes of dimension 2, 3 supported") # Get the mesh and appropriate boundary tags mesh_file_name = 'meshes/circle_in_square/max0%25.msh' h = mesh_file_name[mesh_file_name.find('%') - 1:mesh_file_name.find('.')] mesh = Mesh(mesh_file_name) if mesh.geometric_dimension() == 2: scatterer_bdy_id = 1 outer_bdy_id = 2 else: scatterer_bdy_id = 1 outer_bdy_id = 3 # build fspace and bilinear forms fspace = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(fspace) v = TestFunction(fspace) wave_number = 0.1 # one of [0.1, 1.0, 5.0, 10.0] true_sol = get_true_sol_expr(SpatialCoordinate(mesh), wave_number)