def __init__(self, mesh, Vh_STATE, x0): """ Constructor. INPUTS: - mesh: the mesh - Vh_STATE: the finite element space for the state variable - x0: location at which we want to compute the jet-thickness """ Vh_help = dl.FunctionSpace(mesh, "CG", 1) xfun = dl.interpolate(dl.Expression("x[0]", degree=1), Vh_help) x_coord = xfun.vector().gather_on_zero() mpi_comm = mesh.mpi_comm() rank = dl.MPI.rank(mpi_comm) nproc = dl.MPI.size(mpi_comm) # round x0 so that it is aligned with the mesh if nproc > 1: from mpi4py import MPI comm = MPI.COMM_WORLD if rank == 0: idx = (np.abs(x_coord - x0)).argmin() self.x0 = x_coord[idx] else: self.x0 = None self.x0 = comm.bcast(self.x0, root=0) else: idx = (np.abs(x_coord - x0)).argmin() self.x0 = x_coord[idx] line_segment = dl.AutoSubDomain(lambda x: dl.near(x[0], self.x0)) markers_f = dl.FacetFunction("size_t", mesh) markers_f.set_all(0) line_segment.mark(markers_f, 1) dS = dl.dS[markers_f] x_test = dl.TestFunctions(Vh_STATE) u_test = x_test[0] e1 = dl.Constant(("1.", "0.")) self.int_u = dl.assemble(dl.avg(dl.dot(u_test, e1)) * dS(1)) #self.u_cl = dl.assemble( dl.dot(u_test,e1)*dP(1) ) self.u_cl = dl.Function(Vh_STATE).vector() ps = dl.PointSource(Vh_STATE.sub(0).sub(0), dl.Point(self.x0, 0.), 1.) ps.apply(self.u_cl) scaling = self.u_cl.sum() if np.abs(scaling - 1.) > 1e-6: print scaling raise ValueError() self.state = dl.Function(Vh_STATE).vector() self.help = dl.Function(Vh_STATE).vector()
def mark_facets(self, facet_func, id): """ Marks the surface facets of the object This function is needed for calculating the capacitance matrix """ object_boundary = df.AutoSubDomain(lambda x: self.inside(x, True)) object_boundary.mark(facet_func, id) return facet_func
def generate_polygonal_mesh(resolution, ampothem, nedges, radius, plot_mesh=False): """ Sometimes segault is thrown when mshr.generate_mesh() is called. This is because resolution is to low to resolve smaller inner-most circle. """ import mshr vertices = get_vertices_of_polygon(ampothem, nedges) domain_vertices = [] for vertex in vertices.T: domain_vertices.append(dl.Point(vertex[0], vertex[1])) domain = mshr.Polygon(domain_vertices) cx1, cy1 = 0.0, 0.0 circle1 = mshr.Circle(dl.Point(cx1, cy1), radius) domain.set_subdomain(1, circle1) cx2, cy2 = cx1 - radius / np.sqrt(8), cy1 - radius / np.sqrt(8) circle2 = mshr.Circle(dl.Point(cx2, cy2), radius / 2) domain.set_subdomain(2, circle2) mesh = mshr.generate_mesh(domain, resolution) if plot_mesh: subdomains = dl.MeshFunction('size_t', mesh, mesh.topology().dim(), 2) subdomains.set_all(0) subdomain1 = dl.AutoSubDomain(lambda x: np.sqrt( (x[0] - cx1)**2 + (x[1] - cy1)**2) < radius + 1e-8) subdomain1.mark(subdomains, 1) subdomain2 = dl.AutoSubDomain(lambda x: np.sqrt( (x[0] - cx2)**2 + (x[1] - cy2)**2) < radius / 2 + 1e-8) subdomain2.mark(subdomains, 2) dl.plot(mesh) dl.plot(subdomains) plt.show() return mesh
def solve_tr_dir__const_rheo(mesh_name, hol_cyl, deg_choice, T_in_expr, T_inf_expr, HTC, T_old_v, k_mesh, cp_mesh, rho_mesh, k_mesh_old, cp_mesh_old, rho_mesh_old, dt, time_v, theta, bool_plot, bool_solv, savings_do, logger_f): ''' mesh_name: a proper XML file. bool_plot: plots if bool_plot = 1. Solves a direct, steady-state heat conduction problem, and returns A_np, b_np, D_np, T_np, bool_ex, bool_in. A_np: stiffness matrix, ordered by vertices. b_np: integrated volumetric heat sources and surface heat fluxes, ordered by vertices. The surface heat fluxes come from the solution to the direct problem; hence, these terms will not be there in a real IHCP. D_np: integrated Laplacian of T, ordered by vertices. Option 2. The Laplacian of q is properly assembled from D_np. If do.dx(domain = hol_cyl) -> do.Measure('ds')[boundary_faces] and do.Measure('ds')[boundary_faces] -> something representative of Gamma, I would get option 1. T_np: solution to the direct heat conduction problem, ordered by vertices. bool_ex: boolean array declaring which vertices lie on the outer boundary. bool_in: boolean array indicating which vertices lie on the inner boundary. T_sol: solution to the direct heat conduction problem. deg_choice: degree in FunctionSpace. hol_cyl: mesh. ''' #comm1 = MPI.COMM_WORLD #current proc #rank1 = comm1.Get_rank() V = do.FunctionSpace(hol_cyl, 'CG', deg_choice) if 'hollow' in mesh_name and 'cyl' in mesh_name: from hollow_cyl_inv_mesh import geo_fun as geo_fun_hollow_cyl geo_params_d = geo_fun_hollow_cyl()[1] #x_c is a scalar here #y_c is a scalar here elif 'four' in mesh_name and 'cyl' in mesh_name: from four_hole_cyl_inv_mesh import geo_fun as geo_fun_four_hole_cyl geo_params_d = geo_fun_four_hole_cyl()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0_{}'.format(itera)] for itera in xrange(4)] y_c_l = [geo_params_d['y_0_{}'.format(itera)] for itera in xrange(4)] elif 'one_hole_cir' in mesh_name: from one_hole_cir_adj_mesh import geo_fun as geo_fun_one_hole_cir geo_params_d = geo_fun_one_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0']] y_c_l = [geo_params_d['y_0']] elif 'reinh_cir' in mesh_name: from reinh_cir_adj_mesh import geo_fun as geo_fun_one_hole_cir geo_params_d = geo_fun_one_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0']] y_c_l = [geo_params_d['y_0']] elif 'small_circle' in mesh_name: from four_hole_small_cir_adj_mesh import geo_fun as geo_fun_four_hole_cir geo_params_d = geo_fun_four_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0_{}'.format(itera)] for itera in xrange(4)] y_c_l = [geo_params_d['y_0_{}'.format(itera)] for itera in xrange(4)] #center of the cylinder base x_c = geo_params_d['x_0'] y_c = geo_params_d['y_0'] R_in = geo_params_d['R_in'] R_ex = geo_params_d['R_ex'] #define variational problem T = do.TrialFunction(V) g = do.Function(V) v = do.TestFunction(V) T_old = do.Function(V) T_inf = do.Function(V) #scalar T_old.vector()[:] = T_old_v T_inf.vector()[:] = T_inf_expr #solution T_sol = do.Function(V) #scalar T_sol.vector()[:] = T_old_v # Create boundary markers mark_all = 3 mark_in = 4 mark_ex = 5 #x_c is an array here #y_c is an array here g_in = g_in_mesh(mesh_name, x_c_l, y_c_l, R_in) g_ex = g_ex_mesh(mesh_name, x_c, y_c, R_ex) in_boundary = do.AutoSubDomain(g_in) ex_boundary = do.AutoSubDomain(g_ex) #normal unitNormal = do.FacetNormal(hol_cyl) boundary_faces = do.MeshFunction('size_t', hol_cyl, hol_cyl.topology().dim() - 1) boundary_faces.set_all(mark_all) in_boundary.mark(boundary_faces, mark_in) ex_boundary.mark(boundary_faces, mark_ex) bc_in = do.DirichletBC(V, T_in_expr, boundary_faces, mark_in) #bc_ex = do.DirichletBC(V, T_ex_expr, boundary_faces, mark_ex) bcs = [bc_in] #k = do.Function(V) #W/m/K #k.vector()[:] = k_mesh #A0 = k * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) A = dt / 2. * k_mesh * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + \ rho_mesh * cp_mesh * T * v * do.dx(domain = hol_cyl) A_full = A + dt / 2. * HTC * T * v * do.ds( mark_ex, domain=hol_cyl, subdomain_data=boundary_faces) L = -dt / 2. * k_mesh_old * do.dot(do.grad(T_old), do.grad(v)) * \ do.dx(domain = hol_cyl) + \ rho_mesh_old * cp_mesh_old * T_old * v * do.dx(domain = hol_cyl) - \ dt / 2. * HTC * (T_old) * v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) + \ dt * HTC * T_inf * v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) #numpy version of A, T, and (L + int_fluxT) #A_np__not_v2d = do.assemble(A).array() #before applying BCs - needs v2d #L_np__not_v2d = do.assemble(L).array() #before applying BCs - needs v2d #Laplacian of T, without any -1/k int_S q*n*v dS ''' Approximated integral of the Laplacian of T. Option 2. The Laplacian of q is properly assembled from D_np. If do.dx(domain = hol_cyl) -> do.Measure('ds')[boundary_faces] and do.Measure('ds')[boundary_faces] -> something representative of Gamma, I would get option 1. ''' #D_np__not_v2d = do.assemble(-do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + # do.dot(unitNormal, do.grad(T)) * v * # do.Measure('ds')[boundary_faces]).array() #print np.max(D_np__not_v2d)#, np.max(A_np__not_v2d) #logger_f.warning('shape of D_np = {}, {}'.format(D_np__not_v2d.shape[0], #D_np__not_v2d.shape[1])) #nonzero_entries = [] #for row in D_np__not_v2d: # nonzero_entries += [len(np.where(abs(row) > 1e-16)[0])] #logger_f.warning('max, min, and mean of nonzero_entries = {}, {}, {}'.format( # max(nonzero_entries), min(nonzero_entries), np.mean(nonzero_entries))) #solver parameters #linear solvers from #list_linear_solver_methods() #preconditioners from #do.list_krylov_solver_preconditioners() solver = do.KrylovSolver('gmres', 'ilu') do.info(solver.parameters, True) #prints default values solver.parameters['relative_tolerance'] = 1e-16 solver.parameters['maximum_iterations'] = 20000000 solver.parameters['monitor_convergence'] = True #on the screen #http://fenicsproject.org/qa/1124/is-there-a-way-to-set-the-inital-guess-in-the-krylov-solver '''solver.parameters['nonzero_initial_guess'] = True''' solver.parameters['absolute_tolerance'] = 1e-15 #uses whatever in q_v as my initial condition #the next lines are used for CHECK 3 only #A_sys, b_sys = do.assemble_system(A, L, bcs) do.File( os.path.join(savings_do, '{}__markers.pvd'.format( mesh_name.split('.')[0]))) << boundary_faces if bool_plot: do.plot(boundary_faces, '3D mesh', title='boundary markers') #storage T_sol_d = {} g_d = {} if bool_solv == 1: xdmf_DHCP_T = do.File(os.path.join(savings_do, 'DHCP', 'T.pvd')) xdmf_DHCP_q = do.File(os.path.join(savings_do, 'DHCP', 'q.pvd')) for count_t_i, t_i in enumerate(time_v[1:]): #T_in_expr.ts = t_i #T_ex_expr.ts = t_i #storage T_sol_d[count_t_i] = do.Function(V) T_sol_d[count_t_i].vector()[:] = T_sol.vector().array() do.solve(A_full == L, T_sol, bcs) ''' TO BE UPDATED: rheology is not updated ''' #updates L T_old.assign(T_sol) T_sol.rename('DHCP_T', 'temperature from DHCP') #write solution to file #paraview format xdmf_DHCP_T << (T_sol, t_i) #plot solution if bool_plot: do.plot(T_sol, title='T') #, interactive = True) logger_f.warning('len(T) = {}'.format(len(T_sol.vector().array()))) print 'T: count_t = {}, min(T_DHCP) = {}'.format( count_t_i, min(T_sol_d[count_t_i].vector().array())) print 'T: count_t = {}, max(T_DHCP) = {}'.format( count_t_i, max(T_sol_d[count_t_i].vector().array())), '\n' #save flux - required for solving IHCP #same result if do.ds(mark_ex, subdomain_data = boundary_faces) #instead of do.Measure('ds')[boundary_faces] #Langtangen, p. 37: #either do.dot(do.nabla_grad(T), unitNormal) #or do.dot(unitNormal, do.grad(T)) #int_fluxT = do.assemble(-k * do.dot(unitNormal, do.grad(T_sol)) * v * # do.Measure('ds')[boundary_faces]) fluxT = do.project( -k_mesh * do.grad(T_sol), do.VectorFunctionSpace(hol_cyl, 'CG', deg_choice, dim=2)) if bool_plot: do.plot(fluxT, title='flux at iteration = {}'.format(count_t_i)) fluxT.rename('DHCP_flux', 'flux from DHCP') xdmf_DHCP_q << (fluxT, t_i) print 'DHCP: iteration = {}'.format(count_t_i) #################################################### #full solution #T_sol_full = do.Vector() #T_sol.vector().gather(T_sol_full, np.array(range(V.dim()), 'intc')) #################################################### count_t_i += 1 #copy previous lines #storage T_sol_d[count_t_i] = do.Function(V) T_sol_d[count_t_i].vector()[:] = T_sol.vector().array() for count_t_i, t_i in enumerate(time_v): #storage g_d[count_t_i] = do.Function(V) g_d[count_t_i].vector()[:] = g.vector().array() gdim = hol_cyl.geometry().dim() dofmap = V.dofmap() dofs = dofmap.dofs() #Get coordinates as len(dofs) x gdim array dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim)) #booleans corresponding to the outer boundary -> ints since they are sent to root = 0 bool_ex = 1. * np.array([g_ex(dof_x) for dof_x in dofs_x]) #booleans corresponding to the inner boundary -> ints since they are sent to root = 0 bool_in = 1. * np.array([g_in(dof_x) for dof_x in dofs_x]) T_np_ex = [] T_np_in = [] for i_coor, coor in enumerate(dofs_x): if g_ex(coor): T_np_ex += [T_sol.vector().array()[i_coor]] if g_in(coor): T_np_in += [T_sol.vector().array()[i_coor]] print 'CHECK: mean(T) on the outer boundary = ', np.mean(np.array(T_np_ex)) print 'CHECK: mean(T) on the inner boundary = ', np.mean(np.array(T_np_in)) print 'CHECK: mean(HTC) = ', np.mean(do.project(HTC, V).vector().array()) #v2d = do.vertex_to_dof_map(V) #orders by hol_cyl.coordinates() if deg_choice == 1: print 'len(dof_to_vertex_map) = ', len(do.dof_to_vertex_map(V)) print 'min(dofs) = ', min(dofs), ', max(dofs) = ', max(dofs) print 'len(bool ex) = ', len(bool_ex) print 'len(bool in) = ', len(bool_in) print 'bool ex[:10] = ', repr(bool_ex[:10]) print 'type(T) = ', type(T_sol.vector().array()) #first global results, then local results return A, L, g_d, \ V, v, k_mesh, \ mark_in, mark_ex, \ boundary_faces, bool_ex, \ R_in, R_ex, T_sol_d, deg_choice, hol_cyl, \ unitNormal, dofs_x
import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) import dolfin import numpy import sa_thesis import sa_thesis.helpers.io as io import sa_thesis.computation.problems as problems mesh = dolfin.UnitSquareMesh(4, 4) domains = dolfin.MeshFunction('size_t', mesh, 2, 0) half = dolfin.AutoSubDomain(lambda xx, on: xx[0] > 0.5) half.mark(domains, 1) facets = dolfin.MeshFunction('size_t', mesh, 1, 0) left = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[0], 0)) right = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[0], 1)) front = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[1], 0)) back = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[1], 1)) left.mark(facets, 1) right.mark(facets, 2) front.mark(facets, 3) back.mark(facets, 4) h5file = io.H5File('square', 'w') h5file.set_mesh(mesh) h5file.add_attribute(domains, 'sides') problem = problems.PoissonProblem(mesh, domains=domains, facets=facets) ff = dolfin.Constant(-1.)
def spreadFunction(u, mesh, x_max=None): """ This routine computes the following quantities as a function of the distance x from the inflow: - The centerline velocity: u_cl - The integral jet thickness: L - The spread function (derivative of jet thickness): S - The jet thickness: y_1/2 INPUTS: - the velocity u - the mesh mesh """ boundary_mesh = dl.BoundaryMesh(mesh, "exterior") x = boundary_mesh.coordinates() x_coord = x[np.abs(x[:, 1]) < 1e-9, 0] if x_max is not None: x_coord = x_coord[x_coord <= x_max] e1 = dl.Expression(("1.", "0.")) u1, u2 = u.split(deepcopy=True) Vh_grad = dl.FunctionSpace(mesh, 'RT', 1) grad_u1 = dl.Function(Vh_grad) test = dl.TestFunction(Vh_grad) n = dl.FacetNormal(mesh) dl.solve( dl.inner(grad_u1, test) * dl.dx + u1 * dl.div(test) * dl.dx - u1 * dl.dot(test, n) * dl.ds == 0, grad_u1) axis = dl.AutoSubDomain(lambda x: dl.near(x[1], 0.)) axis_mesh = dl.SubMesh(boundary_mesh, axis) Vh_axis = dl.FunctionSpace(axis_mesh, "CG", 2) u1_axis = dl.interpolate(u1, Vh_axis) Vh_axis_grad = dl.FunctionSpace(axis_mesh, 'CG', 1) du1_dx = dl.Function(Vh_axis_grad) test_axis = dl.TestFunction(Vh_axis_grad) left_point = dl.AutoSubDomain( lambda x, on_boundary: dl.near(x[0], x_coord[0]) and on_boundary) right_point = dl.AutoSubDomain( lambda x, on_boundary: dl.near(x[0], x_coord[-1]) and on_boundary) bb_marker = dl.FacetFunction("size_t", axis_mesh) bb_marker.set_all(0) left_point.mark(bb_marker, 1) right_point.mark(bb_marker, 2) dss = dl.Measure("ds")[bb_marker] dl.solve( du1_dx * test_axis * dl.dx + u1_axis * test_axis.dx(0) * dl.dx + u1_axis * test_axis * dss(1) - u1_axis * test_axis * dss(2) == 0, du1_dx) u_cl = np.zeros(x_coord.shape) L = np.zeros(x_coord.shape) S = np.zeros(x_coord.shape) y_half = np.zeros(x_coord.shape) i = 0 for xi in x_coord: line_segment = dl.AutoSubDomain(lambda x: dl.near(x[0], xi)) markers = dl.FacetFunction("size_t", mesh) markers.set_all(0) line_segment.mark(markers, 1) if i == 0 or (i == (x_coord.shape[0] - 1) and x_max is None): ds = dl.ds[markers] int_u1 = dl.assemble(u1 * ds(1)) int_du1_dx = dl.assemble(dl.dot(grad_u1, e1) * ds(1)) else: dS = dl.dS[markers] int_u1 = dl.assemble(dl.avg(u1) * dS(1)) int_du1_dx = dl.assemble(dl.avg(dl.dot(grad_u1, e1)) * dS(1)) u_cl[i] = u1((xi, 0.)) du_cl_dx = du1_dx((xi, 0.)) L[i] = int_u1 / u_cl[i] S[i] = (int_du1_dx * u_cl[i] - int_u1 * du_cl_dx) / (u_cl[i] * u_cl[i]) y_half[i] = _bisection(u1, 9., 0., .5 * u_cl[i], xi) i += 1 out = np.zeros((x_coord.shape[0], 5), dtype=x_coord.dtype) out[:, 0] = x_coord out[:, 1] = u_cl out[:, 2] = L out[:, 3] = S out[:, 4] = y_half return out
cb = plt.colorbar(c, ax=ax2) ax2.set_xlabel(r"$x$", fontsize=18) ax2.set_ylabel(r"$y$", fontsize=18) cb.set_label(r"$u(x, y)$", fontsize=18) cb.set_ticks([0.0, 5, 10, 15]) fig.savefig("ch11-fdm-2d-ex4.pdf") fig.savefig("ch11-fdm-2d-ex4.png") fig.tight_layout() # ### Post processing # In[117]: outer_boundary = dolfin.AutoSubDomain(lambda x, on_bnd: on_bnd and abs(np.sqrt(x[0]**2 + x[1]**2) - r_outer) < 5e-2) # In[118]: bc_outer = dolfin.DirichletBC(V, 1, outer_boundary) # In[119]: mask_outer = dolfin.Function(V) # In[120]: bc_outer.apply(mask_outer.vector())
import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) import dolfin import numpy import sa_thesis import sa_thesis.helpers.io as io import sa_thesis.computation.problems as problems mesh = dolfin.UnitCubeMesh(4, 4, 4) domains = dolfin.MeshFunction('size_t', mesh, 3, 0) half = dolfin.AutoSubDomain(lambda xx, on: xx[0] > 0.5) half.mark(domains, 1) facets = dolfin.MeshFunction('size_t', mesh, 2, 0) left = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[0], 0)) right = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[0], 1)) front = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[1], 0)) back = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[1], 1)) bottom = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[2], 0)) top = dolfin.AutoSubDomain(lambda xx, on: on and dolfin.near(xx[2], 1)) left.mark(facets, 1) right.mark(facets, 2) front.mark(facets, 3) back.mark(facets, 4) bottom.mark(facets, 5) top.mark(facets, 6) coeff = problems.PoissonProblem.default_coefficient problem = problems.PoissonProblem(mesh,
def create_patches(box=np.array([0, 0, 0, 1, 1, 1]), patch_num=3, patch_nums=None, alpha=1.25, beta=2.0, max_resolution=0.5, num=6, create_inclusions=False, skip_patches=[], prefix='test', logger=None, ldomain=False, corner_refine=3, hole=False, hole_radius=None, layers=1, max_refines=1, elem_per_layer=3): if logger is not None: info = logger.info else: info = print basedim = 3 low = box[:basedim].copy() high = box[basedim:].copy() lengths = high - low diameter = np.sqrt(lengths @ lengths) myeps = sa_utils.myeps * diameter center = (high + low) * .5 info('low {:s}, high {:s}, lengths {:s}, center {:s}, diameter {:.2e}'. format(str(low), str(high), str(lengths), str(center), diameter)) layer_bricks = [] layer_hz = lengths[2] / layers layer_low = np.array( [low[0] - lengths[0], low[1] - lengths[1], low[2] - lengths[2]]) layer_high = np.array( [low[0] + lengths[0], low[1] + lengths[1], low[2] + 2 * lengths[2]]) for ii in range(layers - 1): for jj in range(1, elem_per_layer + 1): layer_bricks.append( OrthoBrick( Pnt(*layer_low), Pnt(low[0] + lengths[0], low[1] + lengths[1], low[2] + (ii + jj * 1. / elem_per_layer) * layer_hz))) info('layer [{:d}/{:d}], {:s}, {:s}'.format( ii, layers, str(layer_low), str( np.array([ low[0] + lengths[0], low[1] + lengths[1], low[2] + ii * layer_hz ])))) for jj in range(1, elem_per_layer): layer_bricks.append( OrthoBrick( Pnt(*layer_low), Pnt( low[0] + lengths[0], low[1] + lengths[1], low[2] + (layers - 1 + jj * 1. / elem_per_layer) * layer_hz))) layer_bricks.append(OrthoBrick(Pnt(*layer_low), Pnt(*layer_high))) sublayers = len(layer_bricks) info('layer [{:d}/{:d}], {:s}, {:s}'.format(layers, layers, str(layer_low), str(layer_high))) info('{:d} layers, {:d} sublayers, {:d} bricks'.format( layers, sublayers, len(layer_bricks))) bc_dict = dict() left = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[0], low[0], eps=myeps)) bc_dict[1] = left right = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[0], high[0], eps=myeps)) bc_dict[2] = right front = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[1], low[1], eps=myeps)) bc_dict[3] = front back = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[1], high[1], eps=myeps)) bc_dict[4] = back bottom = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[2], low[2], eps=myeps)) bc_dict[5] = bottom top = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[2], high[2], eps=myeps)) bc_dict[6] = top border = dolfin.AutoSubDomain(lambda xx, on: on) if ldomain: corner_lr = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[0], center[0], eps=myeps)) bc_dict[7] = corner_lr corner_fb = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[1], center[1], eps=myeps)) bc_dict[8] = corner_fb corner_bt = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[2], center[2], eps=myeps)) bc_dict[9] = corner_bt corner_subdomains = [] corner_close = 0.1 * diameter + myeps for ii in range(corner_refine): corner_subdomains.append( dolfin.AutoSubDomain( (lambda what: lambda xx, on: np.sqrt(xx @ xx) < what )(corner_close))) corner_close *= 0.5 if create_inclusions and num: info('random inclusions') if num: number = num * num * num info('n = ' + str(number)) inc_radius = 0.5 / num info('r = ' + str(inc_radius)) nodes = [] radii = [] rnd_low = low - 0.5 * inc_radius rnd_high = high + 0.5 * inc_radius width = rnd_high - rnd_low while (len(nodes) < number): notok = True while (notok): new = rnd.rand(3) * width + rnd_low radius = (0.5 + rnd.rand()) * inc_radius notok = False for old, rr in zip(nodes, radii): diff = new - old if np.sqrt(diff.dot(diff)) < 1.3 * (radius + rr): notok = True break nodes.append(new.copy()) radii.append(radius) nodes = np.array(nodes) radii = np.array(radii) info('found locations for ' + str(len(nodes)) + ' inclusions') np.savetxt(prefix + '/' + prefix + '_inclusions.csv', np.hstack((nodes, radii.reshape(len(nodes), 1))), fmt='%.15e', delimiter=', ') del nodes, radii, number, inc_radius nohole_whole = OrthoBrick(Pnt(*low), Pnt(*high)) if ldomain is True: nohole_whole = nohole_whole - OrthoBrick( Pnt(*center), Pnt(*(center + 2 * (high - center)))) if num: data = np.loadtxt(prefix + '/' + prefix + '_inclusions.csv', delimiter=', ') number = len(data) else: number = 0 if number: nodes = data[:, :3] radii = data[:, 3] inclusions = Sphere(Pnt(*nodes[0]), radii[0]) for kk in range(1, len(nodes)): inclusions += Sphere(Pnt(*nodes[kk]), radii[kk]) nohole_matrix = nohole_whole - inclusions nohole_incs = nohole_whole * inclusions if hole_radius is not None: hole = True if hole: if hole_radius is None: hole_radius = lengths[1] / 9. near_hole = dolfin.AutoSubDomain(lambda xx, on: on and np.sqrt( (xx[0] - center[0]) * (xx[0] - center[0]) + (xx[1] - center[1]) * (xx[1] - center[1])) < hole_radius + 1e4 * myeps) bc_dict[10] = near_hole if patch_nums is None: hh = lengths[0] / float(patch_num) patch_nums = np.array(np.ceil(lengths / hh), dtype=int) hs = lengths / patch_nums hs_alpha = hs * alpha * 0.5 hs_beta = hs_alpha * beta patches = [] patches_ext = [] for kk in range(patch_nums[2]): pt_z = low[0] + (0.5 + kk) * hs[2] for jj in range(patch_nums[1]): pt_y = low[1] + (0.5 + jj) * hs[1] for ii in range(patch_nums[0]): pt_x = low[2] + (0.5 + ii) * hs[0] pt_center = np.array([pt_x, pt_y, pt_z]) pt_low = pt_center - hs_alpha if ldomain and (p_low >= center - myeps).all(): print('[{:d}, {:d}, {:d}] skipped'.format(ii, jj, kk)) continue patches.append( OrthoBrick(Pnt(*(pt_center - hs_alpha)), Pnt(*(pt_center + hs_alpha)))) patches_ext.append( OrthoBrick(Pnt(*(pt_center - hs_beta)), Pnt(*(pt_center + hs_beta))) - patches[-1]) patch_num = len(patches) print('[{:d}] patches total'.format(patch_num)) patch_fill = int(np.log(patch_num) / np.log(10.)) + 1 pt_low = dict() pt_high = dict() pt_inside = dict() info('Patch size computations') sa_utils.makedirs_norace(prefix + '/' + prefix + '_patch_descriptors') ff = open(prefix + '/' + prefix + '_patch_descriptors/0.csv', 'w') ff.write('idx, left, right, front, back, bottom, top\n') for kk in range(patch_num): info(str(kk + 1) + '/' + str(patch_num)) geo = CSGeometry() geo.Add(nohole_whole * patches[kk]) mesh = geo.GenerateMesh(maxh=max_resolution) del geo mesh.Export('tmp.msh', 'Gmsh2 Format') del mesh meshconvert.convert2xml('tmp.msh', 'tmp.xml') os.remove('tmp.msh') os.remove('tmp_facet_region.xml') os.remove('tmp_physical_region.xml') mesh = dolfin.Mesh('tmp.xml') os.remove('tmp.xml') nodes = mesh.coordinates() del mesh pt_low[kk] = np.min(nodes, axis=0) pt_high[kk] = np.max(nodes, axis=0) ff.write('%d, %.15e, %.15e, %.15e, %.15e, %.15e, %.15e\n' % (kk, pt_low[kk][0], pt_high[kk][0], pt_low[kk][1], pt_high[kk][1], pt_low[kk][2], pt_high[kk][2])) del nodes pt_inside[kk] = dolfin.AutoSubDomain(lambda xx, on: (pt_low[ kk] - myeps <= xx).all() and (xx <= pt_high[kk] + myeps).all()) ff.close() info('Patch size computations finished') hole_ratio = hole_radius / lengths[1] for ref in range(max_refines): info('Start meshing resolution {:d}/{:d}'.format(ref + 1, max_refines)) res = max_resolution * 0.5**ref if hole: hole_maxh = res * hole_ratio # hole_maxh = np.min([res*hole_ratio, lengths[2]/layers]) if number: matrix = nohole_matrix - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) incs = nohole_matrix - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) else: whole = nohole_whole - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) dirname = '{:s}/{:s}_{:d}_patches/0/'.format(prefix, prefix, ref) sa_utils.makedirs_norace(dirname) basename = '{:s}/{:s}_{:d}'.format(prefix, prefix, ref) info('Global CSG') geo = CSGeometry() if number: geo.Add(matrix * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1])) geo.Add(incs * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1])) else: geo.Add(whole * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1])) info('Global CSG constructed') mesh = geo.GenerateMesh(maxh=res) info('Global surface meshed') del geo gc.collect() mesh.GenerateVolumeMesh() mesh.Export(basename + '.msh', 'Gmsh2 Format') meshconvert.convert2xml(basename + '.msh', basename + '.xml') del mesh os.remove(basename + '.msh') os.remove(basename + '_facet_region.xml') info('Global volume meshed') gc.collect() global_mesh = dolfin.Mesh(basename + '.xml') tmp_nodes = global_mesh.coordinates() tmp_low = np.min(tmp_nodes, axis=0) tmp_high = np.max(tmp_nodes, axis=0) info('global mesh: {:s}, {:s}, {:s}'.format( str(tmp_low), str(tmp_high), str(top.inside(tmp_high, True)))) os.remove(basename + '.xml') info('Correcting cell markers') global_domains_tmp = dolfin.MeshFunction( 'size_t', global_mesh, basename + '_physical_region.xml') os.remove(basename + '_physical_region.xml') global_domains_tmp.array()[:] -= np.min(global_domains_tmp.array()) global_domains_tmp.array()[:] //= elem_per_layer global_domains = dolfin.MeshFunction('size_t', global_mesh, basedim, 0) if number: where = np.where(global_domains_tmp.array() < layers) global_domains.array( )[where] = 4 * global_domains_tmp.array()[where] where = np.where(layers <= global_domains_tmp.array()) global_domains.array( )[where] = 4 * (global_domains_tmp.array()[where] - layers) + 1 del where else: global_domains.array()[:] = 4 * global_domains_tmp.array() del global_domains_tmp if ldomain: for ii in range(corner_refine): mf = dolfin.CellFunction('bool', global_mesh, False) corner_subdomains[ii].mark(mf, True) global_mesh = dolfin.refine(global_mesh, mf) global_domains = dolfin.adapt(global_domains, global_mesh) del mf inside_fun = dolfin.MeshFunction('bool', global_mesh, basedim, True) global_mesh = dolfin.refine(global_mesh, inside_fun) global_domains = dolfin.adapt(global_domains, global_mesh) info('Correcting facet markers') global_facets = dolfin.MeshFunction('size_t', global_mesh, basedim - 1, 0) for key in bc_dict: bc_dict[key].mark(global_facets, key) sa_hdf5.write_dolfin_mesh(global_mesh, basename, cell_function=global_domains, facet_function=global_facets) del global_facets, global_mesh, global_domains, basename gc.collect() for kk in range(patch_num): if kk in skip_patches: continue info(str(kk) + '/' + str(patch_num)) basename = 'patch_' + str(kk).zfill(patch_fill) extname = basename + '_' + str(beta) info(' csg') geo = CSGeometry() if number: geo.Add(matrix * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(incs * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(matrix * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) geo.Add(incs * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) else: geo.Add(whole * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(whole * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) info(' csg done') mesh = geo.GenerateMesh(maxh=res) info(' surface meshed') del geo gc.collect() mesh.GenerateVolumeMesh() info(' volume meshed') mesh.Export(dirname + '/' + basename + '.msh', 'Gmsh2 Format') meshconvert.convert2xml(dirname + '/' + basename + '.msh', dirname + '/' + basename + '.xml') del mesh os.remove(dirname + '/' + basename + '.msh') os.remove(dirname + '/' + basename + '_facet_region.xml') gc.collect() ext_mesh = dolfin.Mesh(dirname + '/' + basename + '.xml') os.remove(dirname + '/' + basename + '.xml') info(' cell function') ext_domains_tmp = dolfin.MeshFunction( 'size_t', ext_mesh, dirname + '/' + basename + '_physical_region.xml') os.remove(dirname + '/' + basename + '_physical_region.xml') ext_domains_tmp.array()[:] -= np.min(ext_domains_tmp.array()) ext_domains_tmp.array()[:] //= elem_per_layer ext_domains = dolfin.MeshFunction('size_t', ext_mesh, basedim, 0) if number: where = np.where(ext_domains_tmp.array() < layers) ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where] where = np.where( layers <= ext_domains_tmp.array() < 2 * layers) ext_domains.array( )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 1 where = np.where( 2 * layers <= ext_domains_tmp.array() < 3 * layers) ext_domains.array()[where] = 4 * ( ext_domains_tmp.array()[where] - 2 * layers) + 2 where = np.where(3 * layers <= ext_domains_tmp.array()) ext_domains.array()[where] = 4 * ( ext_domains_tmp.array()[where] - 3 * layers) + 3 del where else: where = np.where(ext_domains_tmp.array() < layers) ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where] where = np.where(layers <= ext_domains_tmp.array()) ext_domains.array( )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 2 del ext_domains_tmp if ldomain: for ii in range(corner_refine): mf = dolfin.CellFunction('bool', ext_mesh, False) corner_subdomains[ii].mark(mf, True) ext_mesh = dolfin.refine(ext_mesh, mf) ext_domains = dolfin.adapt(ext_domains, ext_mesh) del mf inside_fun = dolfin.MeshFunction('bool', ext_mesh, basedim, False) pt_inside[kk].mark(inside_fun, True) ext_mesh = dolfin.refine(ext_mesh, inside_fun) del inside_fun ext_domains = dolfin.adapt(ext_domains, ext_mesh) info(' cell function done') pt_mesh = dolfin.SubMesh(ext_mesh, pt_inside[kk]) pt_domains = dolfin.MeshFunction('size_t', pt_mesh, basedim, 0) tree = ext_mesh.bounding_box_tree() for cell in dolfin.cells(pt_mesh): global_index = tree.compute_first_entity_collision( cell.midpoint()) pt_domains[cell] = ext_domains[dolfin.Cell( ext_mesh, global_index)] del tree pt_facets = dolfin.MeshFunction('size_t', pt_mesh, basedim - 1, 0) border.mark(pt_facets, 100) for key in bc_dict: bc_dict[key].mark(pt_facets, key) sa_hdf5.write_dolfin_mesh(pt_mesh, '{:s}/{:s}'.format(dirname, basename), cell_function=pt_domains, facet_function=pt_facets) tmp_nodes = ext_mesh.coordinates() tmp_low = np.min(tmp_nodes, axis=0) tmp_high = np.max(tmp_nodes, axis=0) is_part = (tmp_low > low + myeps).any() or (tmp_high < high - myeps).any() del tmp_low, tmp_high, tmp_nodes info('patch [{:d}/{:d}], beta [{:.2e}] is real subdomain [{:}]'. format(kk + 1, patch_num, beta, is_part)) if is_part: vals = np.arange(1, 11) else: vals = np.unique(pt_facets.array()) vals = vals[np.where(vals > 0)] patch_dict = dict() for key in bc_dict: if key in vals: patch_dict[key] = bc_dict[key] else: patch_dict[key] = dolfin.AutoSubDomain( (lambda what: (lambda xx, on: bc_dict[what].inside( xx, on) and pt_inside[kk].inside(xx, on)))(key)) ext_facets = dolfin.MeshFunction('size_t', ext_mesh, basedim - 1, 0) border.mark(ext_facets, 100) for key in patch_dict: patch_dict[key].mark(ext_facets, key) del patch_dict, vals sa_hdf5.write_dolfin_mesh(ext_mesh, dirname + '/' + basename + '_' + str(beta), cell_function=ext_domains, facet_function=ext_facets) del ext_mesh, ext_domains, ext_facets, pt_mesh, pt_domains, pt_facets gc.collect() del pt_low, pt_high, pt_inside
def navier_stokes_IPCS_cavity(mesh, dt, parameter): """ fenics code: weak form of the problem. """ dx, ds = df.dx, df.ds dot, inner, outer, div = df.dot, df.inner, df.outer, df.div nabla_grad, grad = df.nabla_grad, df.grad test_f, trial_f = df.TestFunction, df.TrialFunction U0, D, mu_solid = parameter g = 9.81/1.0000000000 # function space V = df.VectorFunctionSpace(mesh, 'P', 2) Q = df.FunctionSpace(mesh, 'P', 1) T = df.FunctionSpace(mesh, 'P', 1) ASD1 = df.AutoSubDomain(top) ASD2 = df.AutoSubDomain(left) ASD3 = df.AutoSubDomain(bottom) ASD4 = df.AutoSubDomain(right) mf = df.MeshFunction("size_t", mesh, 1) mf.set_all(9999) ASD1.mark(mf, 1) ASD2.mark(mf, 2) ASD3.mark(mf, 3) ASD4.mark(mf, 4) ds_ = ds(subdomain_data=mf, domain=mesh) print(np.unique(ds_(3).subdomain_data().array())) vu, vp, vt = test_f(V), test_f(Q), test_f(T) u_, p_, t_ = df.Function(V), df.Function(Q), df.Function(T) # solution mu_k, rho_k = df.Function(T), df.Function(T) u_1, p_1, t_1, rho_1 = df.Function(V), df.Function(Q), df.Function(T), df.Function(T) # solution1 u, p, t = trial_f(V), trial_f(Q), trial_f(T) # unknown! u_k = df.Function(V) # boundary conditions no_slip = df.Constant((0., 0)) topflow = df.Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"), m=U0, degree=2) bc0 = df.DirichletBC(V, topflow, top) bc1 = df.DirichletBC(V, no_slip, left) bc2 = df.DirichletBC(V, no_slip, bottom) bc3 = df.DirichletBC(V, no_slip, right) # bc4 = df.DirichletBC(Q, df.Constant(0), top) # bc3 = df.DirichletBC(T, df.Constant(800), top) bcu = [bc0, bc1, bc2, bc3] # no boundary conditions for the pressure bcp = [] # bcp = [df.DirichletBC(Q, df.Constant(0), top)] bct = [] # set initial temp: 500°C y=0, 800°C at y=1 x, y = np.split(T.tabulate_dof_coordinates(), 2, 1) u_1.vector().vec().array[:] = 1e-6 u_k.vector().vec().array[:] = 1e-6 p_.vector().vec().array[:] = -rho(750)*g*y.ravel() p_1.vector().vec().array[:] = -rho(750)*g*y.ravel() t_1.vector().vec().array = (y.ravel())*100 + 700 t_.assign(t_1) mu_k.vector().vec().array = mu(t_1.vector().vec().array, mu_solid) rho_k.vector().vec().array = rho(t_1.vector().vec().array) rho_1.vector().vec().array = rho(t_1.vector().vec().array) n = df.FacetNormal(mesh) # implicit: acceleration = inner((rho_k*u - rho_1*u_1)/dt, vu) * dx convection = dot(div(rho_k*outer(u_k, u)), vu) * dx pressure = inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds # integrated by parts diffusion = -inner(mu_k * (grad(u) + grad(u).T), grad(vu))*dx \ + dot(mu_k * (grad(u) + grad(u).T)*n, vu)*ds # integrated by parts body_force = dot(df.Constant((0.0, -g))*rho_k, vu)*dx \ + dot(df.Constant((0.0, 0.0)), vu) * ds F1 = -acceleration - convection + diffusion + pressure + body_force a1, L1 = df.lhs(F1), df.rhs(F1) # Define variational problem for step 2 F2 = rho_k / dt * dot(div(u_), vp) * dx + dot(grad(p-p_1), grad(vp)) * dx # grad(p-p_1)/2 * grad(vp) * dx does not work a2, L2 = df.lhs(F2), df.rhs(F2) # Define variational problem for step 3, where u_ = u* from step 1 F3 = -rho_k / dt * dot(u-u_, vu) * dx - dot(grad(p_-p_1), vu) * dx a3, L3 = df.lhs(F3), df.rhs(F3) # Step 4: Transport of rho / Convection-diffusion and SUPG # vr = vr + tau_SUPG * inner(u_, grad(vr)) # SUPG stabilization # F4 = dot((t - t_1) / dt, vt)*dx + dot(div(t*u_), vt) * dx + D*dot(grad(t), grad(vt)) * dx # above does not work, below works fine, but is mathematically not correct, since d/dt (rho) is not 0 F4 = dot((t - t_1) / dt, vt)*dx + dot(dot(grad(t), u_), vt)*dx \ + D*dot(grad(t), grad(vt)) * dx a4, L4 = df.lhs(F4), df.rhs(F4) # Robin BC: HT on the walls. ht coefficient k is arbitray t_amb, t_feeder = 100., 800. k_top, k_lft, k_btm, k_rgt = (1e-3, 3.33e-4, 3.33e-4, 3.33e-4) F4 += k_top*(t - t_feeder)*vt*ds_(1) F4 += k_lft*(t - t_amb)*vt*ds_(2) F4 += k_btm*(t - t_amb)*vt*ds_(3) F4 += k_rgt*(t - t_amb)*vt*ds_(4) # Assemble matrices A1 = df.assemble(a1) A2 = df.assemble(a2) A3 = df.assemble(a3) # A4 = assemble(a4) # Apply boundary conditions to matrices [bc.apply(A1) for bc in bcu] [bc.apply(A2) for bc in bcp] [bc.apply(A3) for bc in bcu] return (u_1, p_1, t_1, mu_k, rho_k, u_, p_, t_, u_k, D, L1, a1, L2, A2, L3, A3, L4, a4, bcu, bcp, bct)
#define a mesh with a finder resolution along the boundary mesh = df.RectangleMesh(df.Point(0., -Ly / 2), df.Point(Lx, Ly / 2), Nx, Ny) x = mesh.coordinates()[:] x[:, 1] = (np.arctan(2. * np.pi * x[:, 1] / Ly) / np.arctan(1. * np.pi) ) #the stretching of a finer resolution close to the boundary x[:, 1] *= (1 + eps * np.cos(2 * np.pi * x[:, 0] / Lx)) Eu = df.VectorElement("Lagrange", mesh.ufl_cell(), 2) Ep = df.FiniteElement("Lagrange", mesh.ufl_cell(), 1) Echi = df.FiniteElement("Lagrange", mesh.ufl_cell(), 1) #define walls and periodicity pbc = PBC(Lx) walls = Walls(Lx, Ly, eps) inlet = df.AutoSubDomain(inlet) #define a descrete function on the mesh, zero on fluid, 1 on boundary, and 2 on inlet subd = df.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) subd.set_all(0) walls.mark(subd, 1) inlet.mark(subd, 2) #make folders if rank == 0 and not os.path.exists(folder): os.makedirs(folder) with df.XDMFFile(mesh.mpi_comm(), "{}/subd.xdmf".format(folder)) as xdmff: xdmff.write(subd) #define variational functions for velocity field and Pressure (Eu, Ep) and Brenner field (Echi)
def __init__(self, mesh, hh, *, domains = None, boundaries = None, alpha = 0.25, oversampling = 2., rel_eps = 1e-7, weight_degree = 1): self.mesh = mesh self.basedim = mesh.geometric_dimension() if domains is None: self.domains = dolfin.MeshFunction('size_t', mesh, self.basedim, 0) else: self.domains = domains if boundaries is None: self.boundaries = dolfin.MeshFunction('size_t', mesh, self.basedim-1, 0) else: self.boundaries = boundaries coordinates = mesh.coordinates() low = numpy.min(coordinates, 0) high = numpy.max(coordinates, 0) diag = numpy.linalg.norm(high-low) eps = diag*rel_eps center = (low+high)*0.5 subdivisions = numpy.int64(numpy.round((high-center-eps)/hh)) alpha_hh = alpha*hh flattop_hh = hh-alpha_hh overlapping_hh = hh+alpha_hh oversampled_hh = oversampling*overlapping_hh index_list = numpy.vstack(map(numpy.ravel, numpy.meshgrid(*map(lambda ll: range(-ll,ll+1), subdivisions)))).T flat_top_indices = numpy.zeros(mesh.num_vertices(), dtype=int) space = dolfin.FunctionSpace(mesh, 'CG', 1) dof_to_vertex_map = dolfin.dof_to_vertex_map(space) self.markers = [] self.pu = [] poly = WeightPolynomial(weight_degree) weight = numpy.zeros(mesh.num_vertices()) for index in index_list: box_center = center+index*hh box_low = box_center-0.5*hh box_high = box_center+0.5*hh # ignore patches which don't contain points from the mesh (without the overlapping part) if not (((box_low-eps) < coordinates).all(1)*(coordinates < (box_high+eps)).all(1)).any(): continue flattop_low = box_center-0.5*flattop_hh flattop_high = box_center+0.5*flattop_hh overlapping_low = box_center-0.5*overlapping_hh overlapping_high = box_center+0.5*overlapping_hh oversampled_low = box_center-0.5*oversampled_hh oversampled_high = box_center+0.5*oversampled_hh flattop_domain = dolfin.AutoSubDomain(lambda xx, on: (flattop_low-eps < xx).all()*(xx < flattop_high+eps).all()) patch_domain = dolfin.AutoSubDomain(lambda xx, on: (overlapping_low-eps < xx).all()*(xx < overlapping_high+eps).all()) oversampled_domain = dolfin.AutoSubDomain(lambda xx, on: (oversampled_low-eps < xx).all()*(xx < oversampled_high+eps).all()) marker = dolfin.MeshFunction('size_t', mesh, self.basedim, 0) oversampled_domain.mark(marker, 1) patch_domain.mark(marker, 2) #flattop_domain.mark(marker, 3) self.markers.append(marker) inside_flattop = ((flattop_low-eps) < coordinates).all(1)*(coordinates < (flattop_high+eps)).all(1) inside_overlapping = ((overlapping_low-eps) < coordinates).all(1)*(coordinates < (overlapping_high+eps)).all(1) overlapping = numpy.where((inside_overlapping > 0)*(inside_flattop == 0)) overlapping_coords = coordinates[overlapping] dd = numpy.max([flattop_low-overlapping_coords, numpy.zeros_like(overlapping_coords), overlapping_coords-flattop_high], 0) dist = numpy.sqrt(numpy.sum(dd*dd, 1)) / alpha_hh dist[numpy.where(dist > 1)] = 1. coeff = numpy.zeros(mesh.num_vertices()) coeff[overlapping] = poly(dist) coeff[numpy.where(inside_flattop > 0)] = 1. pu = dolfin.Function(space) pu.vector().set_local(coeff[dof_to_vertex_map]) weight += pu.vector().get_local() self.pu.append(pu) self.init_submeshes()