def test_multi_ps_matrix(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a matrix for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) A = assemble(Constant(0.0)*dot(u, v)*dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks b sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2*len(c_ids)*10) == 0
def test_pointsource_matrix_second_constructor(mesh, point): """Tests point source when given different constructor PointSource(V1, V2, point, mag) with a matrix and when placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. Currently only implemented if V1=V2. """ V1 = FunctionSpace(mesh, "CG", 1) V2 = FunctionSpace(mesh, "CG", 1) rank = MPI.rank(mesh.mpi_comm()) u, v = TrialFunction(V1), TestFunction(V2) w = Function(V1) A = assemble(Constant(0.0)*u*v*dx) if rank == 0: ps = PointSource(V1, V2, point, 10.0) else: ps = PointSource(V1, V2, []) ps.apply(A) # Checks array sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 10.0) == 0 # Checks point source is added to correct part of the array A.get_diagonal(w.vector()) v2d = vertex_to_dof_map(V1) for v in vertices(mesh): if near(v.midpoint().distance(point), 0.0): ind = v2d[v.index()] if ind < len(A.array()): assert np.round(w.vector()[ind] - 10.0) == 0
def test_Probes_vectorfunctionspace_3D(VF3, dirpath): u0 = interpolate(Expression(('x[0]', 'x[1]', 'x[2]'), degree=1), VF3) x = array([[0.5, 0.5, 0.5], [0.4, 0.4, 0.4], [0.3, 0.3, 0.3]]) p = Probes(x.flatten(), VF3) # Probe twice p(u0) p(u0) # Check both snapshots p0 = p.array(N=0) if MPI.rank(MPI.comm_world) == 0: assert round(p0[0, 0] - 0.5, 7) == 0 assert round(p0[1, 1] - 0.4, 7) == 0 assert round(p0[2, 2] - 0.3, 7) == 0 p0 = p.array(N=1) if MPI.rank(MPI.comm_world) == 0: assert round(p0[0, 0] - 0.5, 7) == 0 assert round(p0[1, 1] - 0.4, 7) == 0 assert round(p0[2, 2] - 0.3, 7) == 0 p0 = p.array(filename=dirpath+'dumpvector3D') if MPI.rank(MPI.comm_world) == 0: assert round(p0[0, 0, 0] - 0.5, 7) == 0 assert round(p0[1, 1, 0] - 0.4, 7) == 0 assert round(p0[2, 1, 0] - 0.3, 7) == 0 p1 = load(dirpath+'dumpvector3D_all.npy') assert round(p1[0, 0, 0] - 0.5, 7) == 0 assert round(p1[1, 1, 0] - 0.4, 7) == 0 assert round(p1[2, 1, 1] - 0.3, 7) == 0
def _adaptive_mesh_refinement(dx, phi, mu, sigma, omega, conv, voltages): from dolfin import cells, refine eta = _error_estimator(dx, phi, mu, sigma, omega, conv, voltages) mesh = phi.function_space().mesh() level = 0 TOL = 1.0e-4 E = sum([e * e for e in eta]) E = sqrt(MPI.sum(E)) info('Level %d: E = %g (TOL = %g)' % (level, E, TOL)) # Mark cells for refinement REFINE_RATIO = 0.5 cell_markers = MeshFunction('bool', mesh, mesh.topology().dim()) eta_0 = sorted(eta, reverse=True)[int(len(eta) * REFINE_RATIO)] eta_0 = MPI.max(eta_0) for c in cells(mesh): cell_markers[c] = eta[c.index()] > eta_0 # Refine mesh mesh = refine(mesh, cell_markers) # Plot mesh plot(mesh) interactive() exit() ## Compute error indicators #K = array([c.volume() for c in cells(mesh)]) #R = array([abs(source([c.midpoint().x(), c.midpoint().y()])) for c in cells(mesh)]) #gam = h*R*sqrt(K) return
def test_Probes_vectorfunctionspace_2D(VF2, dirpath): u0 = interpolate(Expression(('x[0]', 'x[1]')), VF2) x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]]) p = Probes(x.flatten(), VF2) # Probe twice p(u0) p(u0) # Check both snapshots p0 = p.array(N=0) if MPI.rank(mpi_comm_world()) == 0: assert round(p0[0, 0] - 0.5, 7) == 0 assert round(p0[1, 1] - 0.4, 7) == 0 assert round(p0[2, 1] - 0.3, 7) == 0 p0 = p.array(N=1) if MPI.rank(mpi_comm_world()) == 0: assert round(p0[0, 0] - 0.5, 7) == 0 assert round(p0[1, 0] - 0.4, 7) == 0 assert round(p0[2, 1] - 0.3, 7) == 0 p0 = p.array(filename=dirpath+'dumpvector2D') if MPI.rank(mpi_comm_world()) == 0: assert round(p0[0, 0, 0] - 0.5, 7) == 0 assert round(p0[1, 1, 1] - 0.4, 7) == 0 assert round(p0[2, 0, 1] - 0.3, 7) == 0 f = open(dirpath+'dumpvector2D_all.probes', 'r') p1 = load(f) assert round(p1[0, 0, 0] - 0.5, 7) == 0 assert round(p1[1, 1, 0] - 0.4, 7) == 0 assert round(p1[2, 1, 1] - 0.3, 7) == 0
def __init__(self, V, options=None): # See if we have dofmap if not is_function_space(V): raise ValueError("V is not a function space.") # Only allow 2d and 3d meshes if V.mesh().geometry().dim() == 1: raise ValueError("Only 2d and 3d meshes are supported.") # Get MPI info try: from dolfin import mpi_comm_world self.mpi_size = MPI.size(mpi_comm_world()) self.mpi_rank = MPI.rank(mpi_comm_world()) except ImportError: self.mpi_size = MPI.num_processes() self.mpi_rank = MPI.process_number() # Analyze the space V self.V = V self.dofmaps = extract_dofmaps(self.V) self.bounds = bounds(self.V) # Rewrite default plotting options if they are provided by user self.options = {"colors": {"mesh_entities": "hsv", "mesh": "Blues"}, "xkcd": False, "markersize": 40} if options is not None: self.options.update(options) # Keep track of the plots self.plots = []
def test_Probes_vectorfunctionspace_2D(): mesh = UnitSquareMesh(4, 4) V = VectorFunctionSpace(mesh, 'CG', 1) u0 = interpolate(Expression(('x[0]', 'x[1]')), V) x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]]) p = Probes(x.flatten(), V) # Probe twice p(u0) p(u0) # Check both snapshots p0 = p.array(N=0) if MPI.rank(mpi_comm_world()) == 0: nose.tools.assert_almost_equal(p0[0, 0], 0.5) nose.tools.assert_almost_equal(p0[1, 1], 0.4) nose.tools.assert_almost_equal(p0[2, 1], 0.3) p0 = p.array(N=1) if MPI.rank(mpi_comm_world()) == 0: nose.tools.assert_almost_equal(p0[0, 0], 0.5) nose.tools.assert_almost_equal(p0[1, 0], 0.4) nose.tools.assert_almost_equal(p0[2, 1], 0.3) p0 = p.array(filename='dumpvector2D') if MPI.rank(mpi_comm_world()) == 0: nose.tools.assert_almost_equal(p0[0, 0, 0], 0.5) nose.tools.assert_almost_equal(p0[1, 1, 1], 0.4) nose.tools.assert_almost_equal(p0[2, 0, 1], 0.3) f = open('dumpvector2D_all.probes', 'r') p1 = load(f) nose.tools.assert_almost_equal(p1[0, 0, 0], 0.5) nose.tools.assert_almost_equal(p1[1, 1, 0], 0.4) nose.tools.assert_almost_equal(p1[2, 1, 1], 0.3)
def apply_noise(UD, noisepercent, mycomm=None): """ WARNING: SUPERCEDED BY CLASS OBSERVATIONOPERATOR Apply Gaussian noise to data. noisepercent = 0.02 => 2% noise level, i.e., || u - ud || / || ud || = || noise || / || ud || = 0.02 """ UDnoise = [] objnoise = 0.0 for ud in UD: noisevect = randn(len(ud)) # Get norm of entire random vector: try: normrand = sqrt(MPI.sum(mycomm, norm(noisevect)**2)) except: normrand = norm(noisevect) noisevect /= normrand # Get norm of entire vector ud (not just local part): try: normud = sqrt(MPI.sum(mycomm, norm(ud)**2)) except: normud = norm(ud) noisevect *= noisepercent * normud objnoise += norm(noisevect)**2 UDnoise.append(ud + noisevect) return UDnoise, objnoise
def gc_barrier(): """Internal utility to easily switch on and off calls to gc.collect() and MPI.barrier(world) in all fixtures here. Helps make the tests deterministic when debugging. """ gc.collect() if MPI.size(mpi_comm_world()) > 1: MPI.barrier(mpi_comm_world())
def check_if_kill(folder): """Check if user has put a file named killoasis in folder.""" found = 0 if 'killoasis' in listdir(folder): found = 1 collective = MPI.sum(mpi_comm_world(), found) if collective > 0: if MPI.rank(mpi_comm_world()) == 0: remove(path.join(folder, 'killoasis')) info_red('killoasis Found! Stopping simulations cleanly...') return True else: return False
def check_if_reset_statistics(folder): """Check if user has put a file named resetoasis in folder.""" found = 0 if 'resetoasis' in listdir(folder): found = 1 collective = MPI.sum(mpi_comm_world(), found) if collective > 0: if MPI.rank(mpi_comm_world()) == 0: remove(path.join(folder, 'resetoasis')) info_red('resetoasis Found!') return True else: return False
def pytest_runtest_teardown(item): """Collect garbage after every test to force calling destructors which might be collective""" # Do the normal teardown item.teardown() # Collect the garbage (call destructors collectively) del item # NOTE: How are we sure that 'item' does not hold references # to temporaries and someone else does not hold a reference # to 'item'?! Well, it seems that it works... gc.collect() MPI.barrier(MPI.comm_world)
def save_tstep_solution_h5(tstep, q_, u_, newfolder, tstepfiles, constrained_domain, output_timeseries_as_vector, u_components, AssignedVectorFunction, scalar_components, NS_parameters, NS_expressions): """Store solution on current timestep to XDMF file.""" timefolder = path.join(newfolder, 'Timeseries') if output_timeseries_as_vector: # project or store velocity to vector function space for comp, tstepfile in six.iteritems(tstepfiles): if comp == "u": V = q_['u0'].function_space() # First time around create vector function and assigners if "uv" not in NS_expressions.keys(): NS_expressions["uv"] = AssignedVectorFunction(u_) # Assign solution to vector NS_expressions["uv"]() # Store solution vector tstepfile.write(NS_expressions["uv"], float(tstep)) elif comp in q_: tstepfile.write(q_[comp], float(tstep)) else: tstepfile.write(tstepfile.function, float(tstep)) else: for comp, tstepfile in six.iteritems(tstepfiles): tstepfile.write(q_[comp], float(tstep)) if MPI.rank(MPI.comm_world) == 0: if not path.exists(path.join(timefolder, "params.dat")): f = open(path.join(timefolder, 'params.dat'), 'wb') pickle.dump(NS_parameters, f)
def test_multi_ps_vector(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a vector for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0)*v*dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(c_ids)*10.0) == 0
def save_tstep_solution_h5(tstep, q_, u_, newfolder, tstepfiles, constrained_domain, output_timeseries_as_vector, u_components, AssignedVectorFunction, scalar_components, NS_parameters): """Store solution on current timestep to XDMF file.""" timefolder = path.join(newfolder, 'Timeseries') if output_timeseries_as_vector: # project or store velocity to vector function space for comp, tstepfile in tstepfiles.iteritems(): if comp == "u": V = q_['u0'].function_space() # First time around create vector function and assigners if not hasattr(tstepfile, 'uv'): tstepfile.uv = AssignedVectorFunction(u_) # Assign solution to vector tstepfile.uv() # Store solution vector tstepfile << (tstepfile.uv, float(tstep)) elif comp in q_: tstepfile << (q_[comp], float(tstep)) else: tstepfile << (tstepfile.function, float(tstep)) else: for comp, tstepfile in tstepfiles.iteritems(): tstepfile << (q_[comp], float(tstep)) if MPI.rank(mpi_comm_world()) == 0: if not path.exists(path.join(timefolder, "params.dat")): f = open(path.join(timefolder, 'params.dat'), 'w') cPickle.dump(NS_parameters, f)
def mat_to_csr(mat): '''Convert any dolfin.Matrix to csr matrix in scipy.''' assert MPI.size(mpi_comm_world()) == 1, 'mat_to_csr assumes single process' # We can handle blocks if isinstance(mat, (list, ndarray, block_mat)): return [mat_to_csr(mat_) for mat_ in mat] # Number block can anly be zero and for bmat these are None elif isinstance(mat, (int, float)): assert abs(mat) < 1E-15 return None # Actual matrix else: rows = [0] cols = [] values = [] for row in range(mat.size(0)): cols_, values_ = mat.getrow(row) rows.append(len(cols_)+rows[-1]) cols.extend(cols_) values.extend(values_) shape = mat.size(0), mat.size(1) return csr_matrix((asarray(values, dtype='float'), asarray(cols, dtype='int'), asarray(rows, dtype='int')), shape)
def __init__(self, Ys, fs, init_t = 0.0, init_dt = 1.0, dt_max = 2.0, tol = 1e-3, verbose = False): # Fenics functions for each of the unknowns self.Ys = Ys # The number of unknowns self.num_unknowns = len(self.Ys) # Slope functions corresponding to each unknown self.fs = fs # Current time self.t = init_t # Initial time step self.dt = init_dt # Maximum time step self.dt_max = dt_max # Tolerance self.tol = tol # List of lists. Each sublist stores the slope functions evaluated at the # last 5 solutions for the ith unknown self.f_ns = [[] for i in range(self.num_unknowns)] # List of solution vectors at last time step self.prev_ys = None # Flag for first step self.first = True # Output stuff? self.verbose = verbose # Store the last five solution times self.ts = [] # An object for computing integrals of basis functions for Lagrange # polynomials. This is used to determine the coefficients for the AB # and AM methods given the last five solution times self.l_int = LagrangeInt() # Process rank self.MPI_rank = MPI.rank(mpi_comm_world())
def test_pointsource_mixed_space(mesh, point): """Tests point source when given constructor PointSource(V, point, mag) with a vector for a mixed function space that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ rank = MPI.rank(mesh.mpi_comm()) ele1 = FiniteElement("CG", mesh.ufl_cell(), 1) ele2 = FiniteElement("DG", mesh.ufl_cell(), 2) ele3 = VectorElement("CG", mesh.ufl_cell(), 2) V = FunctionSpace(mesh, MixedElement([ele1, ele2, ele3])) value_dimension = V.element().value_dimension(0) v = TestFunction(V) b = assemble(dot(Constant([0.0]*value_dimension), v)*dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0*value_dimension) == 0
def save_results(problem, solver, num_dofs, mesh_size, time_step, functional, error): 'Save results to file.' # Print summary if MPI.process_number() == 0 : print '' print 'Problem |', problem print 'Solver |', solver print 'Unknowns |', num_dofs print 'Mesh size |', mesh_size print 'Time step |', time_step print 'Functional |', functional print 'Error |', error # Print DOLFIN summary set_log_active(True) list_timings() # Append to file, let each dx, dt have its own log file results_dir = problem.options['results_dir'] dx = problem.options['refinement_level'] dt = problem.options['dt_division'] name = '%s_%s_results_dx%d_dt%d.log' % (str(problem), str(solver), dx, dt) filename = os.path.join(results_dir, name) # create the dir for results if needed if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) with open(filename, 'a') as f: f.write('%s, %s, %s, %d, %.15g, %.15g, %.15g, %s\n' % (time.asctime(), problem, solver, num_dofs, mesh_size, time_step, functional, str(error)))
def csr_to_petsc4py(csr_matrix): '''Convert Scipy's csr matrix to PETSc matrix.''' assert MPI.size(mpi_comm_world()) == 1, 'mat_to_csr assumes single process' if isinstance(csr_matrix, list): return [csr_to_pets4py(mat) for mat in csr_matrix] # None is zero block elif csr_matrix is None: return None else: A = csr_matrix csr = (A.indptr, A.indices, A.data) # Convert to PETSc n_rows, n_cols = A.shape A_petsc = PETSc.Mat().createAIJ(size=A.shape, csr=csr) # Now set local to global mapping for indices. This is supposed to run in # serial only so these are identities. row_lgmap = PETSc.LGMap().create(list(arange(n_rows, dtype=int))) if not n_rows == n_cols: col_lgmap = PETSc.LGMap().create(list(arange(n_cols, dtype=int))) else: col_lgmap = row_lgmap A_petsc.setLGMap(row_lgmap, col_lgmap) A_petsc.assemble() return A_petsc
def test_convert_diffpack(self): from dolfin import Mesh, MPI, MeshFunction if MPI.num_processes() != 1: return fname = os.path.join("data", "diffpack_tet") dfname = fname+".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.diffpack2xml(fname+".grid", dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 27) self.assertEqual(mesh.num_cells(), 48) self.assertEqual(mesh.domains().markers(3).size(), 48) self.assertEqual(mesh.domains().markers(2).size(), 16) mf_basename = dfname.replace(".xml", "_marker_%d.xml") for marker, num in [(3, 9), (6, 9), (7, 3), (8, 1)]: mf_name = mf_basename % marker mf = MeshFunction("uint", mesh, mf_name) self.assertEqual(sum(mf.array()==marker), num) os.unlink(mf_name) # Clean up os.unlink(dfname)
def test_compute_first_entity_collision_3d(self): reference = [876, 877, 878, 879, 880, 881] p = Point(0.3, 0.3, 0.3) mesh = UnitCubeMesh(8, 8, 8) tree = BoundingBoxTree() tree.build(mesh) first = tree.compute_first_entity_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference) tree = mesh.bounding_box_tree() first = tree.compute_first_entity_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference)
def test_compute_collisions_tree_1d(self): references = [[set([8, 9, 10, 11, 12, 13, 14, 15]), set([0, 1, 2, 3, 4, 5, 6, 7])], [set([14, 15]), set([0, 1])]] points = [Point(0.52), Point(0.9)] for i, point in enumerate(points): mesh_A = UnitIntervalMesh(16) mesh_B = UnitIntervalMesh(16) mesh_B.translate(point) tree_A = BoundingBoxTree() tree_A.build(mesh_A) tree_B = BoundingBoxTree() tree_B.build(mesh_B) entities_A, entities_B = tree_A.compute_collisions(tree_B) if MPI.size(mesh_A.mpi_comm()) == 1: self.assertEqual(set(entities_A), references[i][0]) self.assertEqual(set(entities_B), references[i][1])
def test_compute_collisions_tree_2d(self): references = [[[20, 21, 22, 23, 28, 29, 30, 31], [0, 1, 2, 3, 8, 9, 10, 11]], [[6, 7], [24, 25]]] points = [Point(0.52, 0.51), Point(0.9, -0.9)] for i, point in enumerate(points): mesh_A = UnitSquareMesh(4, 4) mesh_B = UnitSquareMesh(4, 4) mesh_B.translate(point) tree_A = BoundingBoxTree() tree_A.build(mesh_A) tree_B = BoundingBoxTree() tree_B.build(mesh_B) entities_A, entities_B = tree_A.compute_collisions(tree_B) if MPI.num_processes() == 1: self.assertEqual(sorted(entities_A), references[i][0]) self.assertEqual(sorted(entities_B), references[i][1])
def test_compute_first_entity_collision_1d(self): reference = [4] p = Point(0.3) mesh = UnitIntervalMesh(16) tree = BoundingBoxTree() tree.build(mesh) first = tree.compute_first_entity_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference) tree = mesh.bounding_box_tree() first = tree.compute_first_entity_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference)
def test_compute_entity_collisions_tree_3d(self): references = [[set([18, 19, 20, 21, 22, 23, 42, 43, 44, 45, 46, 47]), set([0, 1, 2, 3, 4, 5, 24, 25, 26, 27, 28, 29])], [set([7, 8, 30, 31, 32]), set([15, 16, 17, 39, 41])]] points = [Point(0.52, 0.51, 0.3), Point(0.9, -0.9, 0.3)] for i, point in enumerate(points): mesh_A = UnitCubeMesh(2, 2, 2) mesh_B = UnitCubeMesh(2, 2, 2) mesh_B.translate(point) tree_A = BoundingBoxTree() tree_A.build(mesh_A) tree_B = BoundingBoxTree() tree_B.build(mesh_B) entities_A, entities_B = tree_A.compute_entity_collisions(tree_B) if MPI.size(mesh_A.mpi_comm()) == 1: self.assertEqual(set(entities_A), references[i][0]) self.assertEqual(set(entities_B), references[i][1])
def setgradxdir(self, valueloc): """Sum all local results for Grad . Srch_dir""" try: valueglob = MPI.sum(self.mycomm, valueloc) except: valueglob = valueloc self.gradxdir = valueglob
def test_pointsource_vector_fs(mesh, point): """Tests point source when given constructor PointSource(V, point, mag) with a vector for a vector function space that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(dot(Constant([0.0]*mesh.geometry().dim()), v)*dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0*V.num_sub_spaces()) == 0 # Checks point source is added to correct part of the array v2d = vertex_to_dof_map(V) for v in vertices(mesh): if near(v.midpoint().distance(point), 0.0): for spc_idx in range(V.num_sub_spaces()): ind = v2d[v.index()*V.num_sub_spaces() + spc_idx] if ind < len(b.get_local()): assert np.round(b.get_local()[ind] - 10.0) == 0
def test_compute_entity_collisions_tree_2d(self): references = [[set([20, 21, 22, 23, 28, 29, 30, 31]), set([0, 1, 2, 3, 8, 9, 10, 11])], [set([6]), set([25])]] points = [Point(0.52, 0.51), Point(0.9, -0.9)] for i, point in enumerate(points): mesh_A = UnitSquareMesh(4, 4) mesh_B = UnitSquareMesh(4, 4) mesh_B.translate(point) tree_A = BoundingBoxTree() tree_A.build(mesh_A) tree_B = BoundingBoxTree() tree_B.build(mesh_B) entities_A, entities_B = tree_A.compute_entity_collisions(tree_B) if MPI.size(mesh_A.mpi_comm()) == 1: self.assertEqual(set(entities_A), references[i][0]) self.assertEqual(set(entities_B), references[i][1])
def test_compute_first_collision_1d(self): reference = {1: [4]} p = Point(0.3) mesh = UnitIntervalMesh(16) for dim in range(1, 2): tree = BoundingBoxTree() tree.build(mesh, dim) first = tree.compute_first_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference[dim]) tree = mesh.bounding_box_tree() first = tree.compute_first_collision(p) if MPI.size(mesh.mpi_comm()) == 1: self.assertIn(first, reference[mesh.topology().dim()])
def gather_vector(u): x = dolfin.Vector() comm = mpi_comm_world() size = MPI.size(comm) * MPI.sum(comm, u.size()) u.gather(x, np.arange(size, dtype="intc")) return x.get_local()
""" Test possibility to save and load Fenics function in parallel with different number of processes. Status: works well; file can be saved and loaded with different nb of processes """ import dolfin as dl from dolfin import MPI mpicomm = dl.mpi_comm_world() mpirank = MPI.rank(mpicomm) mpisize = MPI.size(mpicomm) # save == 1 -> create function and save it to file # save == 2 -> load file and plot function save = 2 mesh = dl.UnitSquareMesh(20, 20) V = dl.FunctionSpace(mesh, 'Lagrange', 2) if save == 1: # Save file b_expr = dl.Expression(\ '1.0 + 1.0*(x[0]<=0.7)*(x[0]>=0.3)*(x[1]<=0.7)*(x[1]>=0.3)') b = dl.interpolate(b_expr, V) dl.plot(b, interactive=True) fhdf5 = dl.HDF5File(mpicomm, 'Outputs/b.h5', 'w') fhdf5.write(b, 'b') else: # Load file b_in = dl.Function(V) fhdf5 = dl.HDF5File(mpicomm, 'Outputs/b.h5', 'r')
def test_mesh_construction_pygmsh(): import pygmsh if MPI.rank(MPI.comm_world) == 0: geom = pygmsh.opencascade.Geometry() geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2) pygmsh_mesh = pygmsh.generate_mesh(geom) points, cells = pygmsh_mesh.points, pygmsh_mesh.cells else: points = numpy.zeros([0, 3]) cells = { "tetra": numpy.zeros([0, 4], dtype=numpy.int64), "triangle": numpy.zeros([0, 3], dtype=numpy.int64), "line": numpy.zeros([0, 2], dtype=numpy.int64) } mesh = dolfin.cpp.mesh.Mesh(MPI.comm_world, dolfin.cpp.mesh.CellType.Type.tetrahedron, points, cells['tetra'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 3 mesh = dolfin.cpp.mesh.Mesh(MPI.comm_world, dolfin.cpp.mesh.CellType.Type.triangle, points, cells['triangle'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 2 mesh = dolfin.cpp.mesh.Mesh(MPI.comm_world, dolfin.cpp.mesh.CellType.Type.interval, points, cells['line'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 1 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 1 if MPI.rank(MPI.comm_world) == 0: print("Generate mesh") geom = pygmsh.opencascade.Geometry() geom.add_ball([0.0, 0.0, 0.0], 1.0, char_length=0.2) pygmsh_mesh = pygmsh.generate_mesh( geom, extra_gmsh_arguments=['-order', '2']) points, cells = pygmsh_mesh.points, pygmsh_mesh.cells print("End Generate mesh", cells.keys()) else: points = numpy.zeros([0, 3]) cells = { "tetra10": numpy.zeros([0, 10], dtype=numpy.int64), "triangle6": numpy.zeros([0, 6], dtype=numpy.int64), "line3": numpy.zeros([0, 3], dtype=numpy.int64) } mesh = dolfin.cpp.mesh.Mesh(MPI.comm_world, dolfin.cpp.mesh.CellType.Type.tetrahedron, points, cells['tetra10'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 2 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 3 mesh = dolfin.cpp.mesh.Mesh(MPI.comm_world, dolfin.cpp.mesh.CellType.Type.triangle, points, cells['triangle6'], [], cpp.mesh.GhostMode.none) assert mesh.degree() == 2 assert mesh.geometry.dim == 3 assert mesh.topology.dim == 2
def solution(values, x): values[:, 0] = A * np.cos(k0 * x[:, 0]) * np.cos(k0 * x[:, 1]) # Function space for exact solution - need it to be higher than deg V_exact = FunctionSpace(mesh, ("Lagrange", deg + 3)) u_exact = Function(V_exact) u_exact.interpolate(lambda x: A * np.cos(k0 * x[:, 0]) * np.cos(k0 * x[:, 1])) # best approximation from V # u_BA = project(u_exact, V) # H1 errors diff = u - u_exact # diff_BA = u_BA - u_exact H1_diff = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(grad(diff), grad(diff)) * dx)) # H1_BA = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(grad(diff_BA), grad(diff_BA)) * dx)) H1_exact = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(grad(u_exact), grad(u_exact)) * dx)) # print("Relative H1 error of best approximation:", abs(np.sqrt(H1_BA) / np.sqrt(H1_exact))) print("Relative H1 error of FEM solution:", abs(np.sqrt(H1_diff) / np.sqrt(H1_exact))) # L2 errors L2_diff = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(diff, diff) * dx)) # L2_BA = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(diff_BA, diff_BA) * dx)) L2_exact = MPI.sum(mesh.mpi_comm(), assemble_scalar(inner(u_exact, u_exact) * dx)) # print("Relative L2 error of best approximation:", abs(np.sqrt(L2_BA) / np.sqrt(L2_exact))) print("Relative L2 error of FEM solution:", abs(np.sqrt(L2_diff) / np.sqrt(L2_exact)))
def info_style(message, check=True, style=NORMAL): if MPI.rank(mpi_comm_world()) == 0 and check: print style.format(s=message)
def invalid_config(encoding): return (not has_hdf5() and encoding == XDMFFile.Encoding.HDF5) \ or (encoding == XDMFFile.Encoding.ASCII and MPI.size(MPI.comm_world) > 1) \ or (not has_hdf5_parallel() and MPI.size(MPI.comm_world) > 1)
import pytest from dolfin import MPI from dolfin.common import (has_debug, has_petsc4py, has_petsc_complex, has_slepc) # Skips with dependencies skip_if_not_petsc4py = pytest.mark.skipif( not has_petsc4py, reason="Skipping unit test(s) depending on petsc4py.") skip_if_not_SLEPc = pytest.mark.skipif( not has_slepc, reason="Skipping unit test(s) depending on SLEPc.") # Skips with respect to parallel or serial xfail_in_parallel = pytest.mark.xfail( MPI.size(MPI.comm_world) > 1, reason="This test does not yet work in parallel.") skip_in_parallel = pytest.mark.skipif( MPI.size(MPI.comm_world) > 1, reason="This test should only be run in serial.") skip_in_serial = pytest.mark.skipif( MPI.size(MPI.comm_world) <= 1, reason="This test should only be run in parallel.") # Skips with respect to linear algebra index type # skip_64bit_int = pytest.mark.skipif(cpp.common.sizeof_la_index() == 8, # reason="This test does not work with 64-bit linear algebra indices.") # Skips with respect to the scalar type skip_if_complex = pytest.mark.skipif( has_petsc_complex, reason="This test does not work in complex mode.")
def xtest_cffi_assembly(): mesh = UnitSquareMesh(MPI.comm_world, 13, 13) V = FunctionSpace(mesh, ("Lagrange", 1)) if MPI.rank(mesh.mpi_comm()) == 0: from cffi import FFI ffibuilder = FFI() ffibuilder.set_source( "_cffi_kernelA", r""" #include <math.h> #include <stdalign.h> void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* restrict coordinate_dofs, int cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE3_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE3_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE3_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE3_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE3_C0_D01_Q1[0][0][1]; alignas(32) double sp[20]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = J_c0 / sp[2]; sp[4] = -1 * J_c1 / sp[2]; sp[5] = sp[3] * sp[3]; sp[6] = sp[3] * sp[4]; sp[7] = sp[4] * sp[4]; sp[8] = J_c3 / sp[2]; sp[9] = -1 * J_c2 / sp[2]; sp[10] = sp[9] * sp[9]; sp[11] = sp[8] * sp[9]; sp[12] = sp[8] * sp[8]; sp[13] = sp[5] + sp[10]; sp[14] = sp[6] + sp[11]; sp[15] = sp[12] + sp[7]; sp[16] = fabs(sp[2]); sp[17] = sp[13] * sp[16]; sp[18] = sp[14] * sp[16]; sp[19] = sp[15] * sp[16]; // UFLACS block mode: preintegrated A[0] = 0.5 * sp[19] + 0.5 * sp[18] + 0.5 * sp[18] + 0.5 * sp[17]; A[1] = -0.5 * sp[19] + -0.5 * sp[18]; A[2] = -0.5 * sp[18] + -0.5 * sp[17]; A[3] = -0.5 * sp[19] + -0.5 * sp[18]; A[4] = 0.5 * sp[19]; A[5] = 0.5 * sp[18]; A[6] = -0.5 * sp[18] + -0.5 * sp[17]; A[7] = 0.5 * sp[18]; A[8] = 0.5 * sp[17]; } void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* restrict coordinate_dofs, int cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE4_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE4_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE4_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE4_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE4_C0_D01_Q1[0][0][1]; alignas(32) double sp[4]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = fabs(sp[2]); // UFLACS block mode: preintegrated A[0] = 0.1666666666666667 * sp[3]; A[1] = 0.1666666666666667 * sp[3]; A[2] = 0.1666666666666667 * sp[3]; } """) ffibuilder.cdef(""" void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* restrict coordinate_dofs, int cell_orientation); void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* restrict coordinate_dofs, int cell_orientation); """) ffibuilder.compile(verbose=True) MPI.barrier(mesh.mpi_comm()) from _cffi_kernelA import ffi, lib a = cpp.fem.Form([V._cpp_object, V._cpp_object]) ptrA = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonA")) a.set_cell_tabulate(0, ptrA) L = cpp.fem.Form([V._cpp_object]) ptrL = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonL")) L.set_cell_tabulate(0, ptrL) assembler = cpp.fem.Assembler([[a]], [L], []) A = assembler.assemble_matrix(cpp.fem.Assembler.BlockType.monolithic) b = assembler.assemble_vector(cpp.fem.Assembler.BlockType.monolithic) Anorm = A.norm(cpp.la.Norm.frobenius) bnorm = b.norm(cpp.la.Norm.l2) assert (np.isclose(Anorm, 56.124860801609124)) assert (np.isclose(bnorm, 0.0739710713711999)) list_timings([TimingType.wall])
def block_assemble(lhs, rhs=None, bcs=None, symmetric=False, signs=None, symmetric_mod=None): """ Assembles block matrices, block vectors or block systems. Input can be arrays of variational forms or block matrices/vectors. Arguments: symmetric : Boundary conditions are applied so that symmetry of the system is preserved. If only the left hand side of the system is given, then a matrix represententing the rhs corrections is returned along with a symmetric matrix. symmetric_mod : Matrix describing symmetric corrections for assembly of the of the rhs of a variational system. signs : An array to specify the signs of diagonal blocks. The sign of the blocks are computed if the argument is not provided. """ error_msg = { 'incompatibility': 'A and b do not have compatible dimensions.', 'symm_mod error': 'symmetric_mod argument only accepted when assembling a vector', 'not square': 'A must be square for symmetric assembling', 'invalid bcs': 'Expecting a list or list of lists of DirichletBC.', 'invalid signs': 'signs should be a list of length n containing only 1 or -1', 'mpi and symm': 'Symmetric application of BC not yet implemented in parallel' } # Check arguments from numpy import ndarray has_rhs = True if isinstance(rhs, ndarray) else rhs != None has_lhs = True if isinstance(rhs, ndarray) else rhs != None if symmetric: from dolfin import MPI, mpi_comm_world if MPI.size(mpi_comm_world()) > 1: raise NotImplementedError(error_msg['mpi and symm']) if has_lhs and has_rhs: A, b = list(map(block_tensor, [lhs, rhs])) n, m = A.blocks.shape if not (isinstance(b, block_vec) and len(b.blocks) is m): raise TypeError(error_msg['incompatibility']) else: A, b = block_tensor(lhs), None if isinstance(A, block_vec): A, b = None, A n, m = 0, len(b.blocks) else: n, m = A.blocks.shape if A and symmetric and (m is not n): raise RuntimeError(error_msg['not square']) if symmetric_mod and (A or not b): raise RuntimeError(error_msg['symmetric_mod error']) # First assemble everything needing assembling. from dolfin import assemble assemble_if_form = lambda x: assemble(x, keep_diagonal=True) if _is_form( x) else x if A: A.blocks.flat[:] = list(map(assemble_if_form, A.blocks.flat)) if b: #b.blocks.flat[:] = map(assemble_if_form, b.blocks.flat) b = block_vec(list(map(assemble_if_form, b.blocks.flat))) # If there are no boundary conditions then we are done. if bcs is None: if A: return [A, b] if b else A else: return b # check if arguments are forms, in which case bcs have to be split from ufl import Form if isinstance(lhs, Form): from .splitting import split_bcs bcs = split_bcs(bcs, m) # Otherwise check that boundary conditions are valid. if not hasattr(bcs, '__iter__'): raise TypeError(error_msg['invalid bcs']) if len(bcs) is not m: raise TypeError(error_msg['invalid bcs']) from dolfin import DirichletBC for bc in bcs: if isinstance(bc, DirichletBC) or bc is None: pass else: if not hasattr(bc, '__iter__'): raise TypeError(error_msg['invalid bcs']) else: for bc_i in bc: if isinstance(bc_i, DirichletBC): pass else: raise TypeError(error_msg['invalid bcs']) bcs = [bc if hasattr(bc, '__iter__') else [bc] if bc else bc for bc in bcs] # Apply BCs if we are only assembling the righ hand side if not A: if symmetric_mod: b.allocate(symmetric_mod) for i in range(m): if bcs[i]: if isscalar(b[i]): b[i], val = create_vec_from(bcs[i][0]), b[i] b[i][:] = val for bc in bcs[i]: bc.apply(b[i]) if symmetric_mod: b.allocate(symmetric_mod) b -= symmetric_mod * b return b # If a signs argument is passed, check if it is valid. # Otherwise guess. if signs and symmetric: if (hasattr(signs, '__iter__') and len(signs) == m): for sign in signs: if sign not in (-1, 1): raise TypeError(error_msg['invalid signs']) else: raise TypeError(error_msg['invalid signs']) elif symmetric: from numpy.random import random signs = [0] * m for i in range(m): if isscalar(A[i, i]): signs[i] = -1 if A[i, i] < 0 else 1 else: x = A[i, i].create_vec(dim=1) x.set_local(random(x.local_size())) signs[i] = -1 if x.inner(A[i, i] * x) < 0 else 1 # Now apply boundary conditions. if b: b.allocate(A) elif symmetric: # If we are preserving symmetry but don't have the rhs b, # then we need to store the symmetric corretions to b # as a matrix which we call A_mod b, A_mod = A.create_vec(), A.copy() for i in range(n): if bcs[i]: for bc in bcs[i]: # Apply BCs to the diagonal block. if isscalar(A[i, i]): A[i, i] = _new_square_matrix(bc, A[i, i]) if symmetric: A_mod[i, i] = A[i, i].copy() if symmetric: bc.zero_columns(A[i, i], b[i], signs[i]) bc.apply(A_mod[i, i]) elif b: bc.apply(A[i, i], b[i]) else: bc.apply(A[i, i]) # Zero out the rows corresponding to BC dofs. for j in list(range(i)) + list(range(i + 1, n)): if A[i, j] is 0: continue assert not isscalar(A[i, j]) bc.zero(A[i, j]) # If we are not preserving symmetry then we are done at this point. # Otherwise, we need to zero out the columns as well if symmetric: for j in list(range(i)) + list(range(i + 1, n)): if A[j, i] is 0: continue assert not isscalar(A[j, i]) bc.zero_columns(A[j, i], b[j]) bc.zero(A_mod[i, j]) result = [A] if symmetric: for i in range(n): for j in range(n): A_mod[i, j] -= A[i, j] result += [A_mod] if b: result += [b] return result[0] if len(result) == 1 else result
def info_split_style(msg_1, msg_2, style_1=BLUE, style_2=NORMAL, check=True): if MPI.rank(mpi_comm_world()) == 0 and check: print style_1.format(s=msg_1) + " " + style_2.format(s=msg_2)
def test_GetCells(): """Get cells of mesh""" mesh = UnitSquareMesh(MPI.comm_world, 5, 5) assert MPI.sum(mesh.mpi_comm(), len(mesh.cells())) == 50
""" Gammut of low melt shutoff time tests. """ from dolfin import * from constants import * from sheet_model import * from dolfin import MPI, mpi_comm_world from scale_functions import * MPI_rank = MPI.rank(mpi_comm_world()) ### Load the input file input_file = '../inputs_sheet/steady/real_low_steady.hdf5' k_min = 5e-5 k_max = 5e-3 scale_functions = ScaleFunctions(input_file, k_min, k_max, u_b_max=100.0) ### Setup the model prm = NonlinearVariationalSolver.default_parameters() prm['newton_solver']['relaxation_parameter'] = 1.0 prm['newton_solver']['relative_tolerance'] = 1e-6 prm['newton_solver']['absolute_tolerance'] = 1e-6 prm['newton_solver']['error_on_nonconvergence'] = False prm['newton_solver']['maximum_iterations'] = 30 # Seconds per day spd = pcs['spd'] model_inputs = {}
import numpy import pytest from dolfin import (MPI, Function, FunctionSpace, Mesh, MeshFunction, MeshValueCollection, TensorFunctionSpace, UnitCubeMesh, UnitIntervalMesh, UnitSquareMesh, VectorFunctionSpace, cpp, has_petsc_complex, interpolate) from dolfin.cpp.mesh import CellType from dolfin.io import XDMFFile from dolfin_utils.test.fixtures import tempdir from ufl import FiniteElement, VectorElement assert (tempdir) # Supported XDMF file encoding if MPI.size(MPI.comm_world) > 1: encodings = (XDMFFile.Encoding.HDF5, ) else: encodings = (XDMFFile.Encoding.HDF5, XDMFFile.Encoding.ASCII) # Data types supported in templating data_types = (('int', int), ('size_t', int), ('double', float)) # Finite elements tested fe_1d_shapes = ["interval"] fe_2d_shapes = ["triangle"] fe_3d_shapes = ["tetrahedron"] fe_families = ["CG", "DG"] fe_degrees = [0, 1, 3] topological_dim = [1, 2, 3] number_cells = [6, 10]
def save_checkpoint_solution_h5(tstep, q_, q_1, newfolder, u_components, NS_parameters): """Overwrite solution in Checkpoint folder. For safety reasons, in case the solver is interrupted, take backup of solution first. Must be restarted using the same mesh-partitioning. This will be fixed soon. (MM) """ checkpointfolder = path.join(newfolder, "Checkpoint") NS_parameters["num_processes"] = MPI.size(mpi_comm_world()) if MPI.rank(mpi_comm_world()) == 0: if path.exists(path.join(checkpointfolder, "params.dat")): system('cp {0} {1}'.format( path.join(checkpointfolder, "params.dat"), path.join(checkpointfolder, "params_old.dat"))) f = open(path.join(checkpointfolder, "params.dat"), 'w') cPickle.dump(NS_parameters, f) MPI.barrier(mpi_comm_world()) for ui in q_: h5file = path.join(checkpointfolder, ui + '.h5') oldfile = path.join(checkpointfolder, ui + '_old.h5') # For safety reasons... if path.exists(h5file): if MPI.rank(mpi_comm_world()) == 0: system('cp {0} {1}'.format(h5file, oldfile)) MPI.barrier(mpi_comm_world()) ### newfile = HDF5File(mpi_comm_world(), h5file, 'w') newfile.flush() newfile.write(q_[ui].vector(), '/current') if ui in u_components: newfile.write(q_1[ui].vector(), '/previous') if path.exists(oldfile): if MPI.rank(mpi_comm_world()) == 0: system('rm {0}'.format(oldfile)) MPI.barrier(mpi_comm_world()) if MPI.rank(mpi_comm_world()) == 0 and path.exists( path.join(checkpointfolder, "params_old.dat")): system('rm {0}'.format(path.join(checkpointfolder, "params_old.dat")))
""" Static wave corresponding to an eigenmode of the wave operator """ import sys from os.path import splitext, isdir from shutil import rmtree import numpy as np import matplotlib.pyplot as plt from fenicstools.plotfenics import PlotFenics from fenicstools.acousticwave import AcousticWave try: from dolfin import UnitSquareMesh, FunctionSpace, Constant, DirichletBC, \ interpolate, Expression, Function, MPI, mpi_comm_world mycomm = mpi_comm_world() myrank = MPI.rank(mycomm) except: from dolfin import UnitSquareMesh, FunctionSpace, Constant, DirichletBC, \ interpolate, Expression, Function mycomm = None myrank = 0 NN = np.array((10, 20, 50, 100)) ERROR = [] tf = 1./(8.*np.sqrt(2)) # Final time u0_expr = Expression('sin(2*pi*x[0])*sin(2*pi*x[1])') def u0_boundary(x, on_boundary): return on_boundary ubc = Constant("0.0")