def shape(self, mesh, size=50): """Build mesh.""" vf = np.vectorize(self.f) x = mesh.coordinates()[:, 0] y = mesh.coordinates()[:, 1] a = np.arctan2(y, x) x, y = [x * vf(a), y * vf(a)] mesh.coordinates()[:] = np.array([x, y]).transpose() boundary = BoundaryMesh(mesh, 'exterior') boundary.init() lst = [0] vs = list(vertices(boundary)) while True: v = vs[lst[-1]] neighbors = set() for e in edges(v): neighbors.update(e.entities(0)) neighbors.remove(v.index()) neighbors = list(neighbors) k = 0 if len(lst) > 1: if neighbors[0] == lst[-2]: k = 1 lst.append(neighbors[k]) if lst[-1] == lst[0]: break lst = lst[:-1] points = boundary.coordinates()[lst] points = [Point(*p) for p in points] try: polygon = Polygon(points) except: polygon = Polygon(points[::-1]) return generate_mesh(polygon, size)
def test_HarmonicSmoothing(self): print "" print "Testing HarmonicSmoothing::move(Mesh& mesh, " \ "const BoundaryMesh& new_boundary)" # Create some mesh and its boundary mesh = UnitSquareMesh(10, 10) boundary = BoundaryMesh(mesh, 'exterior') # Move boundary disp = Expression(("0.3*x[0]*x[1]", "0.5*(1.0-x[1])")) boundary.move(disp) # Move mesh according to given boundary mesh.move(boundary) # Check that new boundary topology corresponds to given one boundary_new = BoundaryMesh(mesh, 'exterior') self.assertEqual(boundary.topology().hash(), boundary_new.topology().hash()) # Check that coordinates are almost equal err = sum(sum(abs(boundary.coordinates() \ - boundary_new.coordinates()))) / mesh.num_vertices() print "Current CG solver produced error in boundary coordinates", err self.assertAlmostEqual(err, 0.0, places=5) # Check mesh quality magic_number = 0.35 rmin = MeshQuality.radius_ratio_min_max(mesh)[0] self.assertTrue(rmin > magic_number)
def HiptmairMatrixSetupBoundary(mesh, N, M,dim): def boundary(x, on_boundary): return on_boundary # mesh.geometry().dim() path = os.path.abspath(os.path.join(inspect.getfile(inspect.currentframe()), "..")) # if __version__ == '1.6.0': gradient_code = open(os.path.join(path, 'DiscreteGradientSecond.cpp'), 'r').read() # else: # gradient_code = open(os.path.join(path, 'DiscreteGradient.cpp'), 'r').read() compiled_gradient_module = compile_extension_module(code=gradient_code) tic() if dim == 3: EdgeBoundary = BoundaryEdge(mesh) EdgeBoundary = numpy.sort(EdgeBoundary)[::2].astype("float_","C") else: B = BoundaryMesh(mesh,"exterior",False) EdgeBoundary = numpy.sort(B.entity_map(1).array().astype("float_","C")) end = toc() MO.StrTimePrint("Compute edge boundary indices, time: ",end) row = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") #, dtype="intc") column = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") #, dtype="intc") data = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") #, dtype="intc") dataX = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") dataY = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") dataZ = numpy.zeros(2*(mesh.num_edges()-EdgeBoundary.size), order="C") # print 2*(mesh.num_edges()-EdgeBoundary.size) tic() # c = compiled_gradient_module.ProlongationGrad(mesh, EdgeBoundary, dataX,dataY,dataZ, data, row, column) c = compiled_gradient_module.ProlongationGradBoundary(mesh, EdgeBoundary, dataX,dataY,dataZ, data, row, column) # u, indices = numpy.unique(row, return_index=True) # indices = numpy.concatenate((indices,indices+1),axis=1) # # print VertexBoundary # print row # # print numpy.concatenate((indices,indices+1),axis=1) # # print data # row = row[indices] # column = column[indices] # data = data[indices] # print row end = toc() MO.StrTimePrint("Data for C and P created, time: ",end) C = coo_matrix((data,(row,column)), shape=(N, M)).tocsr() Px = coo_matrix((dataX,(row,column)), shape=(N, M)).tocsr() Py = coo_matrix((dataY,(row,column)), shape=(N, M)).tocsr() Pz = coo_matrix((dataZ,(row,column)), shape=(N, M)).tocsr() del dataX, dataY, dataZ, row,column, mesh, EdgeBoundary return C, [Px,Py,Pz]
def BoundaryEdge(mesh): path = os.path.abspath(os.path.join(inspect.getfile(inspect.currentframe()), "..")) # if __version__ == '1.6.0': gradient_code = open(os.path.join(path, 'DiscreteGradientSecond.cpp'), 'r').read() # else: # gradient_code = open(os.path.join(path, 'DiscreteGradient.cpp'), 'r').read() compiled_gradient_module = compile_extension_module(code=gradient_code) B = BoundaryMesh(mesh,"exterior",False) FaceBoundary = numpy.sort(B.entity_map(2).array().astype("float_","C")) EdgeBoundary = numpy.zeros(3*FaceBoundary.size, order="C") c = compiled_gradient_module.FaceToEdgeBoundary(mesh, FaceBoundary, FaceBoundary.size, EdgeBoundary) return EdgeBoundary #numpy.sort(EdgeBoundary)[::2].astype("float_","C")
def HiptmairBCsetupBoundary(C, P, mesh): dim = mesh.geometry().dim() tic() if dim == 3: EdgeBoundary = BoundaryEdge(mesh) else: B = BoundaryMesh(mesh,"exterior",False) EdgeBoundary = numpy.sort(B.entity_map(1).array().astype("int","C")) B = BoundaryMesh(mesh,"exterior",False) NodalBoundary = B.entity_map(0).array()#.astype("int","C") onelagrange = numpy.ones(mesh.num_vertices()) onelagrange[NodalBoundary] = 0 Diaglagrange = spdiags(onelagrange,0,mesh.num_vertices(),mesh.num_vertices()) onemagnetiic = numpy.ones(mesh.num_edges()) onemagnetiic[EdgeBoundary.astype("int","C")] = 0 Diagmagnetic = spdiags(onemagnetiic,0,mesh.num_edges(),mesh.num_edges()) del mesh tic() C = Diagmagnetic*C*Diaglagrange # C = C G = PETSc.Mat().createAIJ(size=C.shape,csr=(C.indptr, C.indices, C.data)) end = toc() MO.StrTimePrint("BC applied to gradient, time: ",end) if dim == 2: tic() # Px = P[0] # Py = P[1] Px = Diagmagnetic*P[0]*Diaglagrange Py = Diagmagnetic*P[1]*Diaglagrange end = toc() MO.StrTimePrint("BC applied to Prolongation, time: ",end) P = [PETSc.Mat().createAIJ(size=Px.shape,csr=(Px.indptr, Px.indices, Px.data)),PETSc.Mat().createAIJ(size=Py.shape,csr=(Py.indptr, Py.indices, Py.data))] else: tic() # Px = P[0] # Py = P[1] # Pz = P[2] Px = Diagmagnetic*P[0]*Diaglagrange Py = Diagmagnetic*P[1]*Diaglagrange Pz = Diagmagnetic*P[2]*Diaglagrange end = toc() MO.StrTimePrint("BC applied to Prolongation, time: ",end) P = [PETSc.Mat().createAIJ(size=Px.shape,csr=(Px.indptr, Px.indices, Px.data)),PETSc.Mat().createAIJ(size=Py.shape,csr=(Py.indptr, Py.indices, Py.data)),PETSc.Mat().createAIJ(size=Pz.shape,csr=(Pz.indptr, Pz.indices, Pz.data))] del Px, Py, Diaglagrange return G, P
def test_HarmonicSmoothing(): # Create some mesh and its boundary mesh = UnitSquareMesh(10, 10) boundary = BoundaryMesh(mesh, 'exterior') # Move boundary disp = Expression(("0.3*x[0]*x[1]", "0.5*(1.0-x[1])")) ALE.move(boundary, disp) # Move mesh according to given boundary ALE.move(mesh, boundary) # Check that new boundary topology corresponds to given one boundary_new = BoundaryMesh(mesh, 'exterior') assert boundary.topology().hash() == boundary_new.topology().hash() # Check that coordinates are almost equal err = sum(sum(abs(boundary.coordinates() \ - boundary_new.coordinates()))) / mesh.num_vertices() print("Current CG solver produced error in boundary coordinates", err) assert round(err - 0.0, 5) == 0 # Check mesh quality magic_number = 0.35 rmin = MeshQuality.radius_ratio_min_max(mesh)[0] assert rmin > magic_number
def test_HarmonicSmoothing(): #print("Testing HarmonicSmoothing::move(Mesh& mesh, "const BoundaryMesh& new_boundary)") # Create some mesh and its boundary mesh = UnitSquareMesh(10, 10) boundary = BoundaryMesh(mesh, 'exterior') # Move boundary disp = Expression(("0.3*x[0]*x[1]", "0.5*(1.0-x[1])")) boundary.move(disp) # Move mesh according to given boundary mesh.move(boundary) # Check that new boundary topology corresponds to given one boundary_new = BoundaryMesh(mesh, 'exterior') assert boundary.topology().hash() == boundary_new.topology().hash() # Check that coordinates are almost equal err = sum(sum(abs(boundary.coordinates() \ - boundary_new.coordinates()))) / mesh.num_vertices() print("Current CG solver produced error in boundary coordinates", err) assert round(err - 0.0, 5) == 0 # Check mesh quality magic_number = 0.35 rmin = MeshQuality.radius_ratio_min_max(mesh)[0] assert rmin > magic_number
def test_HarmonicSmoothing(self): print "" print "Testing HarmonicSmoothing::move(Mesh& mesh, " \ "const BoundaryMesh& new_boundary)" # Create some mesh and its boundary mesh = UnitSquareMesh(10, 10) boundary = BoundaryMesh(mesh, 'exterior') # Move boundary disp = Expression(("0.3*x[0]*x[1]", "0.5*(1.0-x[1])")) boundary.move(disp) # Move mesh according to given boundary mesh.move(boundary) # Check that new boundary topology corresponds to given one boundary_new = BoundaryMesh(mesh, 'exterior') self.assertEqual(boundary.topology().hash(), boundary_new.topology().hash()) # Check that coordinates are almost equal err = sum(sum(abs(boundary.coordinates() \ - boundary_new.coordinates()))) / mesh.num_vertices() print "Current CG solver produced error in boundary coordinates", err self.assertAlmostEqual(err, 0.0, places=5) # Check mesh quality magic_number = 0.35 self.assertTrue(mesh.radius_ratio_min()>magic_number)
cell_vtx = cell_vtx[:, :2] vertices = np.vstack([old_vtx, facet_vtx, cell_vtx]) return vertices, cells, macro_map # -------------------------------------------------------------------- if __name__ == '__main__': from dolfin import (UnitCubeMesh, MeshFunction, File, BoundaryMesh, UnitSquareMesh) import matplotlib.pyplot as plt import operator mesh = BoundaryMesh(UnitCubeMesh(4, 4, 4), 'exterior') dual_mesh = DualMesh(mesh) mapping = dual_mesh.macro_map # We kept the mesh area unchanged old = sum(c.volume() for c in df.cells(mesh)) dual = sum(c.volume() for c in df.cells(dual_mesh)) assert abs(old - dual) < 1E-13 # The overlap vertex of the patch has to be the same geometrical # point as the corresponding old mesh vertex x_old = mesh.coordinates() x_new = dual_mesh.coordinates() patch_vertices = []
def steepest_descent(): o_u = [File("output/u_mesh%d.pvd" % i) for i in range(solver.N)] search = moola.linesearch.ArmijoLineSearch(start_stp=1) outmesh = File("output/steepest.pvd") extra_opts = 0 r_step = 8 max_it = 3 * r_step opts = 0 rel_tol = 1e-4 solver.solve() solver.eval_J() plot(solver.multimesh.part(1), color=colors[0], linewidth=0.75, zorder=0) b_mesh = BoundaryMesh(solver.multimesh.part(1), "exterior", True) plot(b_mesh, color=colors[0], linestyle="None", markersize=1, marker=markers[0], label="Iteration {}".format(0), zorder=1) J_it = [solver.J] J_i = J_it[0] i = 1 while i <= max_it: outmesh << solver.multimesh.part(1) for k in range(solver.N): o_u[k] << solver.u.part(k) print("-" * 10) print("It: {0:1d}, J: {1:.5f}".format(i, J_it[-1])) solver.recompute_dJ() solver.generate_mesh_deformation() #solver.generate_H1_deformation() dJ_i = 0 for j in range(1, solver.N): dJ_i += assemble( action(solver.dJ_form[j - 1], solver.deformation[j - 1])) print("Gradient at current iteration {0:.2e}".format(dJ_i)) def J_steepest(step): solver.update_multimesh(step) solver.solve() solver.eval_J() solver.get_checkpoint() return float(solver.J) def dJ0_steepest(): return float(J_it[-1]), dJ_i def increase_opt_number(): solver.vfac *= 2 solver.bfac *= 2 if opts < extra_opts: return True else: print("{0:d} optimizations done, exiting".format(opts + 1)) return False try: step_a = search.search(J_steepest, None, dJ0_steepest()) print( "Linesearch found decreasing step: {0:.2e}".format(step_a)) # Backup in case step is too large backup_coordinates = [ solver.multimesh.part(k).coordinates().copy() for k in range(1, solver.N) ] solver.update_multimesh(step_a) solver.set_checkpoint() solver.solve() solver.eval_J() J_it.append(solver.J) J_i = J_it[-1] if J_i > 0: if i % r_step == 0: print("Increasing volume and barycenter penalty") solver.vfac *= 2 solver.bfac *= 2 solver.eval_J() J_it.append(solver.J) if i % r_step == 0: b_mesh = BoundaryMesh(solver.multimesh.part(1), "exterior", True) plot(b_mesh, color=colors[i // r_step], linestyle="None", markersize=1, marker=markers[i // r_step], label="Iteration {}".format(i), zorder=i // r_step + 2) i += 1 search.start_stp = 1 else: # If Armjio linesearch returns an unfeasible # functional value, literally deforming too much. # We know that J in our problem has to be positive # Decrease initial stepsize and retry search.start_stp = 0.5 * step_a for k in range(1, solver.N): solver.multimesh.part( k).coordinates()[:] = backup_coordinates[k - 1] solver.multimesh.build() for key in solver.cover_points.keys(): solver.multimesh.auto_cover(key, solver.cover_points[key]) solver.set_checkpoint() solver.solve() solver.eval_J() J_it[-1] = solver.J rel_reduction = abs(J_it[-1] - J_it[-2]) / abs(J_it[-2]) if rel_reduction < rel_tol and solver.move_norm < rel_tol: raise ValueError( "Relative reduction less than {0:1e1}".format(rel_tol)) except Warning: print("Linesearch could not find descent direction") print("Restart with stricter penalty") print("*" * 15) if not increase_opt_number(): break else: # Reset linesearch opts += 1 # In new optimization run, the deformed geometry # should not have a higher functional value than the first # iteration J_i = J_it[0] except ValueError: print("Stopping criteria met") print("abs((J_k-J_k-1)/J_k)={0:.2e}<{1:.2e}".format( rel_reduction, rel_tol)) print("L^2(Gamma)(s)={0:.2e}<{1:.2e}".format( solver.move_norm, rel_tol)) print("Increase volume and barycenter penalty") print("*" * 15) if not increase_opt_number(): break else: opts += 1 solver.solve() solver.eval_J() print("V_r {0:.2e}, Bx_r {1:.2e}, By_r {2:.2e}".format( float(solver.Voloff / solver.Vol0), float(solver.bxoff / solver.bx0), float(solver.byoff / solver.by0))) J_i = solver.J # Old solution with new penalization print("V_r {0:.2e}, Bx_r {1:.2e}, By_r {2:.2e}".format( float(solver.Voloff / solver.Vol0) * 100, float(solver.bxoff / solver.bx0) * 100, float(solver.byoff / solver.by0) * 100)) plot(solver.multimesh.part(1), zorder=2, color=colors[i // r_step], linewidth=1) plt.legend(prop={'size': 10}, markerscale=2) manager = plt.get_current_fig_manager() plt.tight_layout() manager.resize(*manager.window.maxsize()) plt.axis("off") plt.savefig("StokesRugbyMeshes.png", dpi=300) import os os.system("convert StokesRugbyMeshes.png -trim StokesRugbyMeshes.png")
def BoundaryMesh(self): if self._boundary is None: self._boundary = BoundaryMesh(self.mesh, "exterior") return self._boundary