def load_data(mesh, mesh_f, dim, data): ''' Represent mesh_f over dim entities of mesh as collection of vertices. Can have mesh as mesh function or (h5_file, data_set) ''' try: h5_file, data_set = mesh_f mf = MeshFunction('size_t', mesh, dim, 0) h5_file.read(mf, data_set) except ValueError: mf = mesh_f data_set = '%d dim entites' % mf.dim() # Mapf for encoding entities as vertices mesh.init(dim, 0) e2v = mesh.topology()(dim, 0) tags = set(mf.array()) # Don't encode zero - we initialize to it if 0 in tags: tags.remove(0) info('%s evolves tags %r' % (data_set, tags)) for tag in tags: data[(dim, tag)] = np.array([e2v(e.index()) for e in SubsetIterator(mf, tag)], dtype='uintp') return data
def laplace( mesh: df.Mesh, markers: Optional[Dict[str, int]], fiber_space: str = "CG_1", ffun: Optional[df.MeshFunction] = None, use_krylov_solver: bool = False, verbose: bool = False, strict: bool = False, ) -> Dict[str, np.ndarray]: """ Solve the laplace equation and project the gradients of the solutions. """ # Create scalar laplacian solutions df.info("Calculating scalar fields") scalar_solutions = scalar_laplacians( mesh=mesh, markers=markers, ffun=ffun, use_krylov_solver=use_krylov_solver, verbose=verbose, strict=strict, ) # Create gradients df.info("\nCalculating gradients") data = project_gradients( mesh=mesh, fiber_space=fiber_space, scalar_solutions=scalar_solutions, ) return data
def verify(self, key, tolerance=0.0): """ Verify data associated with the given key, with the specified tolerance. The key is internally cast to a string. """ key = str(key) if not key in self.__filenames: raise CheckpointException("Missing checkpoint with key %s" % key) if not isinstance(tolerance, float) or tolerance < 0.0: raise InvalidArgumentException( "tolerance must be a non-negative float") handle = open(self.__filename(key), "rb") pickler = pickle.Unpickler(handle) c_cs = pickler.load() try: id_map = self.__id_map[key] for c_id in c_cs: c = id_map[c_id] self._Checkpointer__verify(c, c_cs[c_id], tolerance=tolerance) dolfin.info("Verified checkpoint with key %s" % key) except CheckpointException as e: dolfin.info(str(e)) raise CheckpointException( "Failed to verify checkpoint with key %s" % key) return
def compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters): "Compute size of time residual" info("Computing time residual") global M, W, w # Get data needed to compute residual U0, U1 = read_adaptive_data(primal_series, dual_series, t0, t1, problem, parameters) # Set time step dt = t1 - t0 kn = Constant(dt) # Assemble right-hand side r0, r1 = weak_residual(U0, U1, U1, w, kn, problem) r = assemble(r0 + r1) # Compute norm of functional R = Vector() solve(M, R, r) Rk = sqrt(r.inner(R)) info("Time residual is Rk = %g" % Rk) return Rk
def main(mesh_filename='meshfile', resolution=32): filename = '%s.%s' % (mesh_filename, 'xml') if os.path.exists(filename): print('Mesh file exists, loading from file') mesh_3d = dolfin.Mesh(filename) else: geometry_3d = get_geometry() dolfin.info(geometry_3d, True) print('Creating mesh') mesh_3d = dolfin.Mesh(geometry_3d, resolution) print('Saving to file:') print(filename) data_file = dolfin.File(filename) data_file << mesh_3d # Plot in either case. print('Plotting in interactive mode') fh = dolfin.plot(mesh_3d, '3D mesh', interactive=True, window_width=900, window_height=700)
def verify(self, key, tolerance=0.0): """ Verify data associated with the given key, with the specified tolerance. The key is internally cast to a string. """ key = str(key) if not key in self.__filenames: raise CheckpointException("Missing checkpoint with key %s" % key) if not isinstance(tolerance, float) or tolerance < 0.0: raise InvalidArgumentException("tolerance must be a non-negative float") handle = open(self.__filename(key), "rb") pickler = cPickle.Unpickler(handle) c_cs = pickler.load() try: id_map = self.__id_map[key] for c_id in c_cs: c = id_map[c_id] self._Checkpointer__verify(c, c_cs[c_id], tolerance=tolerance) dolfin.info("Verified checkpoint with key %s" % key) except CheckpointException as e: dolfin.info(str(e)) raise CheckpointException("Failed to verify checkpoint with key %s" % key) return
def __init__(self, A, solver=default_solver, parameters={}): from PyTrilinos import Epetra, Amesos from dolfin import info from time import time self.A = A # Keep reference T = time() self.problem = Epetra.LinearProblem() self.problem.SetOperator(A.down_cast().mat()) self.solver = Amesos.Factory().Create(solver, self.problem) if (self.solver == None): raise RuntimeError('Failed to create Amesos solver: ' + solver) # This prevents a use-after-free crash for the MPI communicator. It # enforces that the solver is destroyed before A. self.solver.A = A self.solver.SetParameters(parameters) if self.solver is None: raise RuntimeError("Unknown solver '%s'" % solver) err = self.solver.SymbolicFactorization() if err != 0: raise RuntimeError("Amesos " + solver + " symbolic factorization failed, err=%d" % err) err = self.solver.NumericFactorization() if err != 0: raise RuntimeError("Amesos " + solver + " numeric factorization failed, err=%d" % err) info('constructed direct solver (using %s) in %.2f s' % (solver, time() - T))
def generate_meshes(N = 5, iterations = 3, refinements = 0.5): mesh1 = UnitSquare(N,N) mesh2 = UnitSquare(N,N) for ref in range(iterations): print "refinement ", ref+1 info(mesh1) info(mesh2) cf1 = CellFunction("bool", mesh1) cf2 = CellFunction("bool", mesh2) cf1.set_all(False) cf2.set_all(False) m1 = round(cf1.size()*refinements) m2 = round(cf2.size()*refinements) mi1 = randint(0,cf1.size(),m1) mi2 = randint(0,cf2.size(),m2) for i in mi1: cf1[i] = True for i in mi2: cf2[i] = True # newmesh1 = adapt(mesh1, cf1) newmesh1 = refine(mesh1, cf1) # newmesh2 = adapt(mesh2, cf2) newmesh2 = refine(mesh2, cf2) mesh1 = newmesh1 mesh2 = newmesh2 return [(0.,0.),(1.,0.),(1.,1.),(0.,1.)], mesh1, mesh2
def collapse(self): '''Return a matrix representation''' # Check cache if hasattr(self, 'matrix_repr'): return self.matrix_repr # Otherwise compute it, but only once x = self.create_vec(dim=1) x_values = x.get_local() columns = [] df.info('Collapsing to %d x %d matrix' % (self.V0.dim(), self.V1.dim())) timer = df.Timer('Collapse') for i in range(self.V1.dim()): # Basis of row space x_values[i] = 1. x.set_local(x_values) column = sparse.csc_matrix((self * x).get_local()) columns.append(column) # Reset x_values[i] = 0. # Alltogether mat = (sparse.vstack(columns).T).tocsr() df.info('\tDone in %g' % timer.stop()) # As PETSc.Mat A = PETSc.Mat().createAIJ(comm=PETSc.COMM_WORLD, size=mat.shape, csr=(mat.indptr, mat.indices, mat.data)) # Finally for dolfin self.matrix_repr = df.PETScMatrix(A) return self.matrix_repr
def __init__(self, grid, fields): timer = Timer('setup'); timer.start() mesh = fields[0].function_space().mesh() # Same meshes for all assert all(mesh.id() == f.function_space().mesh().id() for f in fields) # Locate each point limit = mesh.num_entities_global(mesh.topology().dim()) bbox_tree = mesh.bounding_box_tree() npoints = np.prod(grid.ns) cells_for_x = [None]*npoints for i, x in enumerate(grid.points()): cell = bbox_tree.compute_first_entity_collision(Point(*x)) if -1 < cell < limit: cells_for_x[i] = Cell(mesh, cell) assert not any(c is None for c in cells_for_x) # For each field I want to build a function which which evals # it at all the points self.data = {} self.eval_fields = [] for u in fields: # Alloc key = u.name() self.data[key] = [np.zeros(npoints) for _ in range(u.value_size())] # Attach the eval for u self.eval_fields.append(eval_u(u, grid.points(), cells_for_x, self.data[key])) info('Probe setup took %g' % timer.stop()) self.grid = grid # Get values at construction self.update()
def compute_time_residual(primal_series, dual_series, t0, t1, problem, parameters): "Compute size of time residual" info("Computing time residual") global M, W, w # Get data needed to compute residual U0, U1 = read_adaptive_data(primal_series, dual_series, t0, t1, problem, parameters) # Set time step dt = t1 - t0 kn = Constant(dt) # Assemble right-hand side Rk_F, Rk_S, Rk_M = weak_residuals(U0, U1, U1, w, kn, problem) r = assemble(Rk_F + Rk_S + Rk_M, cell_domains=problem.cell_domains, exterior_facet_domains=problem.fsi_boundary, interior_facet_domains=problem.fsi_boundary) # Compute norm of functional R = Vector() solve(M, R, r) Rk = sqrt(r.inner(R)) info("Time residual is Rk = %g" % Rk) return Rk
def tail(self, t, it, logger): cc = self.cc pv = self.pv # Get div(v) locally div_v = self.div_v if div_v is not None: div_v.assign( df.project(df.div(pv["v"]), div_v.function_space())) # Compute required functionals keys = ["t", "E_kin", "Psi", "mean_p"] vals = {} vals[keys[0]] = t vals[keys[1]] = df.assemble(0.5 * cc["rho"] * df.inner(pv["v"], pv["v"]) * df.dx) vals[keys[2]] = df.assemble(( 0.25 * cc["a"] * cc["eps"] *\ df.inner(df.dot(cc["LA"], df.grad(pv["phi"])), df.grad(pv["phi"])) + (cc["b"] / cc["eps"]) * cc["F"] ) * df.dx) vals[keys[3]] = df.assemble(pv["p"] * df.dx) if it % self.mod == 0: for key in keys: self.functionals[key].append(vals[key]) # Logging and reporting df.info("") df.begin("Reported functionals:") for key in keys[1:]: desc = "{:6s} = %g".format(key) logger.info(desc, (vals[key], ), (key, ), t) df.end() df.info("")
def save_errors(E, E_h, E_k, E_c, E_c0, E_c1, parameters): "Save errors to file" global _refinement_level # Summarize errors summary = """ Estimating error ------------------------- Adaptive loop no. = %d ------------------------- E_h = %g E_k = %g E_c = %g = |%g + %g| E_tot = %g """ % (_refinement_level, E_h, E_k, abs(E_c), E_c0, E_c1, E) # Print summary info(summary) # Save to log file f = open("%s/adaptivity.log" % parameters["output_directory"], "a") f.write(summary) f.close() # Save to file (for plotting) g = open("%s/error_estimates.txt" % parameters["output_directory"], "a") g.write("%d %g %g %g %g %g %g\n" % (_refinement_level, E, E_h, E_k, abs(E_c), E_c0, E_c1)) g.close()
def _create_coefficients(r_dens, r_visc): c = OrderedDict() c[r"r_dens"] = r_dens c[r"r_visc"] = r_visc # Problem parameters c[r"\rho_1"] = 1.0 c[r"\rho_2"] = r_dens * c[r"\rho_1"] c[r"\nu_1"] = 1.0 c[r"\nu_2"] = r_visc * c[r"\nu_1"] c[r"\eps"] = 0.1 c[r"g_a"] = 1.0 # Characteristic quantities c[r"L_0"] = 1.0 c[r"V_0"] = 1.0 c[r"\rho_0"] = c[r"\rho_1"] df.begin("\nDimensionless numbers") At = (c[r"\rho_1"] - c[r"\rho_2"]) / (c[r"\rho_1"] + c[r"\rho_2"]) Re_1 = c[r"\rho_1"] / c[r"\nu_1"] Re_2 = c[r"\rho_2"] / c[r"\nu_2"] df.info("r_dens = {}".format(r_dens)) df.info("r_visc = {}".format(r_visc)) df.info("Re_1 = {}".format(Re_1)) df.info("Re_2 = {}".format(Re_2)) df.info("At = {}".format(At)) df.end() return c
def dump(self, add=0): data_mat = self.probes.array(1) if self.h5fp_str is not None: data_mat_p = self.probes_p.array(1) if self.compute_stress: data_mat_grad_u = dict() for dim in xrange(3): data_mat_grad_u[dim] = self.probes_grad_u[dim].array(1) if add == 0: stepstrout = self.stepstr else: stepstrout = str(int(self.stepstr) + add) if self.mpi_rank == 0: df.info("Saving!") with h5py.File( os.path.join(self.folder_out, "u_" + stepstrout + ".h5"), "w") as h5f_out: h5f_out.create_dataset("/u/" + stepstrout, data=data_mat[:, :3]) if self.h5fp_str is not None: h5f_out.create_dataset("/p/" + stepstrout, data=data_mat_p[:, 0]) if self.compute_stress: h5f_out.create_dataset("/grad_u/" + stepstrout, data=np.hstack( (data_mat_grad_u[0][:, :3], data_mat_grad_u[1][:, :3], data_mat_grad_u[2][:, :3])))
def solve_system( a, L, bcs, u: df.Function, solver_parameters: Optional[Dict[str, str]] = None, use_krylov_solver: bool = False, krylov_solver_atol: Optional[float] = None, krylov_solver_rtol: Optional[float] = None, krylov_solver_max_its: Optional[int] = None, verbose: bool = False, ) -> Optional[df.PETScKrylovSolver]: if use_krylov_solver: try: return solve_krylov( a, L, bcs, u, ksp_atol=krylov_solver_atol, ksp_rtol=krylov_solver_rtol, ksp_max_it=krylov_solver_max_its, verbose=verbose, ) except Exception: df.info( "Failed to solve using Krylov solver. Try a regular solve...") solve_regular(a, L, bcs, u, solver_parameters) return None solve_regular(a, L, bcs, u, solver_parameters) return None
def collapse(x): """Compute an explicit matrix representation of an operator. For example, given a block_ mul object M=A*B, collapse(M) performs the actual matrix multiplication. """ # Since _collapse works recursively, this method is a user-visible wrapper # to print timing, and to check input/output arguments. from time import time from dolfin import PETScMatrix, info, warning T = time() res = _collapse(x) if getattr(res, 'transposed', False): # transposed matrices will normally be converted to a non-transposed # one by matrix multiplication or addition, but if the transpose is the # outermost operation then this doesn't work. res.M.transpose() info('computed explicit matrix representation %s in %.2f s' % (str(res), time() - T)) result = PETScMatrix(res.M) # Sanity check. Cannot trust EpetraExt.Multiply always, it seems. from block import block_vec v = x.create_vec() block_vec([v]).randomize() xv = x * v err = (xv - result * v).norm('l2') / (xv).norm('l2') if (err > 1e-3): raise RuntimeError( 'collapse computed wrong result; ||(a-a\')x||/||ax|| = %g' % err) return result
def setupSolver(self): if type(self.f) == type([]): self.n = len(self.f) if type(d.lhs(self.f[0]).integrals()[0].integrand()) == type( UFL.constantvalue.Zero() ): # Not particularly elegant. Should check for another solution. self.rank = 1 else: self.rank = 2 else: self.n = 1 if type(d.lhs(self.f).integrals()[0].integrand()) == type( UFL.constantvalue.Zero() ): # Not particularly elegant. Should check for another solution. self.rank = 1 else: self.rank = 2 # Set appropriate solver if self.rank == 2: d.info("Using LU-solver to solve linear systems.") self.linear = True self.solver = d.LUSolver() else: d.info("Using Newton-solver to solve nonlinear systems.") self.linear = False self.solver = d.NewtonSolver()
def convert(msh_file, h5_file): '''Temporary version of convert from msh to h5''' root, _ = os.path.splitext(msh_file) assert os.path.splitext(msh_file)[1] == '.msh' assert os.path.splitext(h5_file)[1] == '.h5' # Get the xml mesh xml_file = '.'.join([root, 'xml']) subprocess.call(['dolfin-convert %s %s' % (msh_file, xml_file)], shell=True) # Success? assert os.path.exists(xml_file) mesh = Mesh(xml_file) out = HDF5File(mesh.mpi_comm(), h5_file, 'w') out.write(mesh, 'mesh') info('Mesh has %d cells' % mesh.num_cells()) info('Mesh size %g %g' % (mesh.hmin(), mesh.hmax())) outputs = [mesh] # Save ALL data as facet_functions names = ('surfaces', 'volumes') for name, region in zip(names, ('facet_region.xml', 'physical_region.xml')): r_xml_file = '_'.join([root, region]) f = MeshFunction('size_t', mesh, r_xml_file) out.write(f, name) outputs.append(f) return outputs
def __init__(self, A, overlap=0, params={}): from PyTrilinos.IFPACK import Factory from dolfin import info from time import time self.A = A # Keep reference to avoid delete T = time() prectype = self.prectype if overlap == 0: prectype += ' stand-alone' # Skip the additive Schwarz step self.prec = Factory().Create(prectype, A.down_cast().mat(), overlap) if not self.prec: raise RuntimeError("Unknown IFPACK preconditioner '%s'" % prectype) paramlist = { 'schwartz: combine mode': 'Add' } # Slower than 'Zero', but symmetric paramlist.update(self.params) paramlist.update(params) assert (0 == self.prec.SetParameters(paramlist)) assert (0 == self.prec.Initialize()) err = self.prec.Compute() if err: raise RuntimeError('Compute returned error %d: %s' % (err, self.errcode.get(-err))) info('Constructed %s in %.2f s' % (self.__class__.__name__, time() - T))
def set_solver(self): solver = PETScSNESSolver() snes = solver.snes() snes.setType("newtontr") ksp = snes.getKSP() ksp.setType("preonly") pc = ksp.getPC() pc.setType("lu") snes_solver_parameters = { # "linear_solver": "lu", "linear_solver": "umfpack", # "linear_solver": "mumps", "maximum_iterations": 300, "report": True, # "monitor": True, "line_search": "basic", "method": "newtonls", "absolute_tolerance": 1e-5, "relative_tolerance": 1e-5, "solution_tolerance": 1e-5 } solver.parameters.update(snes_solver_parameters) info(solver.parameters, True) # import pdb; pdb.set_trace() return solver
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 bayer( cases, mesh, markers, ffun, verbose: bool, use_krylov_solver: bool, strict: bool, krylov_solver_atol: Optional[float] = None, krylov_solver_rtol: Optional[float] = None, krylov_solver_max_its: Optional[int] = None, ) -> Dict[str, df.Function]: apex = apex_to_base( mesh, markers["base"], ffun, use_krylov_solver=use_krylov_solver, krylov_solver_atol=krylov_solver_atol, krylov_solver_rtol=krylov_solver_rtol, krylov_solver_max_its=krylov_solver_max_its, verbose=verbose, ) # Find the rest of the laplace soltions V = apex.function_space() u = df.TrialFunction(V) v = df.TestFunction(V) a = df.dot(df.grad(u), df.grad(v)) * df.dx L = v * df.Constant(0) * df.dx solutions = dict((what, df.Function(V)) for what in cases) solutions["apex"] = apex sol = solutions["apex"].vector().copy() sol[:] = 0.0 # Iterate over the three different cases df.info("Solving Laplace equation") solver_parameters = {"linear_solver": "mumps"} if "superlu_dist" in df.linear_solver_methods(): solver_parameters = {"linear_solver": "superlu_dist"} for case in cases: df.info( " {0} = 1, {1} = 0".format( case, ", ".join([c for c in cases if c != case]), ), ) # Solve linear system bcs = [ df.DirichletBC( V, 1 if what == case else 0, ffun, markers[what], "topological", ) for what in cases ]
def _staggered_turbine_layout(self, num_x, num_y, site_x_start, site_x_end, site_y_start, site_y_end): """Adds a staggered, rectangular turbine layout to the farm. A rectangular turbine layout with turbines evenly spread out in each direction across the domain. :param turbine: Defines the type of turbine to add to the farm. :type turbine: Turbine object. :param num_x: The number of turbines placed in the x-direction. :type num_x: int :param num_y: The number of turbines placed in the y-direction (will be one less in each second row). :type num_y: int :param site_x_start: The minimum x-coordinate of the site. :type site_x_start: float :param site_x_end: The maximum x-coordinate of the site. :type site_x_end: float :param site_y_start: The minimum y-coordinate of the site. :type site_y_start: float :param site_y_end: The maximum y-coordinate of the site. :type site_y_end: float :raises: ValueError """ if self._turbine_specification is None: raise ValueError("A turbine specification has not been set.") turbine = self._turbine_specification # Generate the start and end points in the desired layout. start_x = site_x_start + turbine.radius start_y = site_y_start + turbine.radius end_x = site_x_end - turbine.radius end_y = site_y_end - turbine.radius # Check that we can fit enough turbines in each direction. too_many_x = turbine.diameter*num_x > site_x_end - site_x_start too_many_y = turbine.diameter*num_y > site_y_end - site_y_start # Raise exceptions if too many turbines are placed in a certain # direction. if too_many_x and too_many_y: raise ValueError("Too many turbines in the x and y direction") elif too_many_x: raise ValueError("Too many turbines in the x direction") elif too_many_y: raise ValueError("Too many turbines in the y direction") # Iterate over the x and y positions and append them to the turbine # list. for i, x in enumerate(numpy.linspace(start_x, end_x, num_x)): if i % 2 == 0: for y in numpy.linspace(start_y, end_y, num_y): self.add_turbine((x,y)) else: ys = numpy.linspace(start_y, end_y, num_y) for i in range(len(ys)-1): self.add_turbine((x, ys[i] + 0.5*(ys[i+1]-ys[i]))) dolfin.info("Added %i turbines to the site in an %ix%i rectangular " "array." % (num_x*num_y, num_x, num_y))
def _staggered_turbine_layout(self, num_x, num_y, site_x_start, site_x_end, site_y_start, site_y_end): """Adds a staggered, rectangular turbine layout to the farm. A rectangular turbine layout with turbines evenly spread out in each direction across the domain. :param turbine: Defines the type of turbine to add to the farm. :type turbine: Turbine object. :param num_x: The number of turbines placed in the x-direction. :type num_x: int :param num_y: The number of turbines placed in the y-direction (will be one less in each second row). :type num_y: int :param site_x_start: The minimum x-coordinate of the site. :type site_x_start: float :param site_x_end: The maximum x-coordinate of the site. :type site_x_end: float :param site_y_start: The minimum y-coordinate of the site. :type site_y_start: float :param site_y_end: The maximum y-coordinate of the site. :type site_y_end: float :raises: ValueError """ if self._turbine_specification is None: raise ValueError("A turbine specification has not been set.") turbine = self._turbine_specification # Generate the start and end points in the desired layout. start_x = site_x_start + turbine.radius start_y = site_y_start + turbine.radius end_x = site_x_end - turbine.radius end_y = site_y_end - turbine.radius # Check that we can fit enough turbines in each direction. too_many_x = turbine.diameter*num_x > end_x-start_x too_many_y = turbine.diameter*num_y > end_y-start_y # Raise exceptions if too many turbines are placed in a certain # direction. if too_many_x and too_many_y: raise ValueError("Too many turbines in the x and y direction") elif too_many_x: raise ValueError("Too many turbines in the x direction") elif too_many_y: raise ValueError("Too many turbines in the y direction") # Iterate over the x and y positions and append them to the turbine # list. for i, x in enumerate(numpy.linspace(start_x, end_x, num_x)): if i % 2 == 0: for y in numpy.linspace(start_y, end_y, num_y): self.add_turbine((x,y)) else: ys = numpy.linspace(start_y, end_y, num_y) for i in range(len(ys)-1): self.add_turbine((x, ys[i] + 0.5*(ys[i+1]-ys[i]))) dolfin.info("Added %i turbines to the site in an %ix%i rectangular " "array." % (num_x*num_y, num_x, num_y))
def cleanup(files=None, exts=()): '''Get rid of xml''' if files is not None: return map(os.remove, files) else: files = list(filter(lambda f: any(map(f.endswith, exts)), os.listdir('.'))) info('Removing %r' % files) return cleanup(files)
def powers2(num): '''List (descending) of powers of two in the number''' powers = [int(power) for power, value in enumerate(reversed(format(num, 'b'))) if value != '0'] info('Number of binary + %d' % (len(powers) - 1)) info('Largest tile does %d unary +' % (max(powers) - 1)) return powers[::-1]
def save_goal_functional_final(goal_functional, integrated_goal_functional, parameters): "Saving goal functional at final time" global _refinement_level info("Value of goal functional at T: %g" % goal_functional) f = open("%s/goal_functional_final.txt" % parameters["output_directory"], "a") f.write("%d %.16g %.16g\n" % (_refinement_level, goal_functional, integrated_goal_functional)) f.close()
def system_info(): """ Print system information and assorted library versions. """ timestepping.system_info() dolfin.info("dolfin-adjoint version: %s" % dolfin_adjoint.__version__) return
def probe(self): self.probes.clear() df.info("Probing!") self.probes(self.u[0], self.u[1], self.u[2]) if self.h5fp_str is not None: self.probes_p(self.p) if self.compute_stress: for dim in xrange(3): self.probes_grad_u[dim](self.grad_u[dim])
def dolfin_to_hd5(obj, h5name, time="", comm=mpi_comm_world(), name=None): """ Save object to and HDF file. Parameters ---------- obj : dolfin.Mesh or dolfin.Function The object you want to save name : str Name of the object h5group : str The folder you want to save the object withing the HDF file. Default: '' """ name = obj.name() if name is None else name df.info("Save {0} to {1}:{0}/{2}".format(name, h5name, time)) group = name if time == "" else "/".join([name, str(time)]) file_mode = "a" if os.path.isfile(h5name) else "w" if isinstance(obj, df.Function): if value_size(obj) == 1: return save_scalar_function(comm, obj, h5name, group, file_mode) else: return save_vector_function(comm, obj, h5name, group, file_mode) elif isinstance(obj, df.Mesh): with df.HDF5File(comm, h5name, file_mode) as h5file: h5file.write(obj, group) if obj.geometry().dim() == 3: coords = "XYZ" elif obj.geometry().dim() == 2: coords = "XY" else: coords = "X" return { "h5group": group, "cell_indices": "/".join([group, "cell_indices"]), "coordinates": "/".join([group, "coordinates"]), "topology": "/".join([group, "topology"]), "ncells": obj.num_cells(), "nverts": obj.num_vertices(), "coords": coords, "type": "mesh", "cell": str(obj.ufl_cell()).capitalize(), "top_dim": obj.topology().dim() + 1, "geo_dim": obj.geometry().dim(), } else: raise ValueError("Unknown type {}".format(type(obj)))
def save_goal_functional(t1, goal_functional, integrated_goal_functional, parameters): "Saving goal functional at t = t1" global _refinement_level info("Value of goal functional at t = %.16g: %.16g" % (t1, goal_functional)) info("Integrated goal functional at t = %.16g: %.16g" % (t1, integrated_goal_functional)) f = open("%s/goal_functional.txt" % parameters["output_directory"], "a") f.write("%d %.16g %.16g %.16g\n" % (_refinement_level, t1, goal_functional, integrated_goal_functional)) f.close()
def solve_molecular(self,rho_solute=const.rhom): """ Solve the molecular diffusion problem if 'solve_sol_mol' is not in the flags list this will be an instantaneous mixing problem. """ # Solve solution concentration # Diffusivity ramp = dolfin.Expression('x[0] > minR ? 100. : 1.',minR=np.log(self.Rstar)-0.5,degree=1) self.Dstar = dolfin.project(dolfin.Expression('ramp*diff_ratio*exp(-2.*x[0])',degree=1,ramp=ramp,diff_ratio=self.astar_i/self.Lewis),self.sol_V) # calculate solute flux (this is like the Stefan condition for the molecular diffusion problem Dwall = self.Dstar(self.sol_coords[self.sol_idx_wall]) self.solFlux = -(self.C_wall/Dwall)*(self.dR/self.dt) # Set the concentration for points that moved out of the grid to match the solute flux u0_c_hold = self.u0_c.vector()[:].copy() u0_c_hold[~self.sol_idx_extrapolate] = self.C_wall+self.solFlux*(np.exp(self.sol_coords[~self.sol_idx_extrapolate,0])-self.Rstar) u0_c_hold[u0_c_hold<0.]=0. self.u0_c.vector()[:] = u0_c_hold[:] # Variational Problem F_c = (self.u_s-self.u0_c)*self.v_s*dolfin.dx + \ self.dt*dolfin.inner(dolfin.grad(self.u_s), dolfin.grad(self.Dstar*self.v_s))*dolfin.dx - \ self.dt*self.solFlux*self.v_s*self.sds(1) F_c = dolfin.action(F_c,self.C) # First derivative J = dolfin.derivative(F_c, self.C, self.u_s) # handle the bounds lower = dolfin.project(dolfin.Constant(0.0),self.sol_V) upper = dolfin.project(dolfin.Constant(rho_solute),self.sol_V) # set bounds and solve snes_solver_parameters = {"nonlinear_solver": "snes", "snes_solver": {"linear_solver": "lu", "maximum_iterations": 20, "report": True, "error_on_nonconvergence": False}} problem = dolfin.NonlinearVariationalProblem(F_c, self.C, J=J) problem.set_bounds(lower, upper) solver = dolfin.NonlinearVariationalSolver(problem) solver.parameters.update(snes_solver_parameters) dolfin.info(solver.parameters, True) (iter, converged) = solver.solve() self.u0_c.assign(self.C) # Recalculate the freezing temperature self.Tf_last = self.Tf self.Tf = Tf_depression(self.C.vector()[self.sol_idx_wall,0],linear=True) # Get the updated solution properties self.rhos = dolfin.project(dolfin.Expression('C + rhow*(1.-C/rho_solute)', degree=1,C=self.C,rhow=const.rhow,rho_solute=rho_solute),self.sol_V) self.cs = dolfin.project(dolfin.Expression('ce*(C/rho_solute) + cw*(1.-C/rho_solute)', degree=1,C=self.C,cw=const.cw,ce=const.ce,rho_solute=rho_solute),self.sol_V) self.ks = dolfin.project(dolfin.Expression('ke*(C/rho_solute) + kw*(1.-C/rho_solute)', degree=1,C=self.C,kw=const.kw,ke=const.ke,rho_solute=rho_solute),self.sol_V) self.rhos_wall = self.rhos.vector()[self.sol_idx_wall] self.cs_wall = self.cs.vector()[self.sol_idx_wall] self.ks_wall = self.ks.vector()[self.sol_idx_wall]
def cleanup(files=None, exts=(), dir='.'): '''Get rid of xml''' if files is not None: return map(os.remove, files) else: files = [ os.path.join(dir, f) for f in filter( lambda f: any(map(f.endswith, exts)), os.listdir(dir)) ] info('Removing %r' % files) return cleanup(files)
def set_solver(): # "hypre_amg") #"hypre_euclid") # "hypre_amg") # "petsc_amg" "petsc_amg" solver = d.KrylovSolver("cg", "hypre_amg") solver.parameters["maximum_iterations"] = 1000 solver.parameters["absolute_tolerance"] = 1E-8 solver.parameters["error_on_nonconvergence"] = True solver.parameters["monitor_convergence"] = True # solver.parameters["divergence_limit"] = 1E+6 # solver.parameters["nonzero_initial_guess"] = True d.info(solver.parameters, verbose=True) d.set_log_level(d.PROGRESS) return solver
def main(): geometry_3d = get_geometry() dolfin.info(geometry_3d, True) resolution = 32 print "=" * 60 print "Creating mesh" print "=" * 60 mesh_3d = dolfin.Mesh(geometry_3d, resolution) print "=" * 60 print "Plotting in interactive mode" print "=" * 60 dolfin.plot(mesh_3d, "3D mesh", interactive=True)
def create_dirichlet_conditions(values, boundaries, function_spaces): """Create Dirichlet boundary conditions for given boundary values, boundaries and function space.""" # Check that the size matches if len(values) != len(boundaries): error( "The number of Dirichlet values does not match the number of Dirichlet boundaries." ) if len(values) != len(function_spaces): error( "The number of Dirichlet values does not match the number of function spaces." ) if len(boundaries) != len(function_spaces): error( "The number of Dirichlet boundaries does not match the number of function spaces." ) info("Creating %d Dirichlet boundary condition(s)." % len(values)) # Create Dirichlet conditions bcs = [] for (i, value) in enumerate(values): # Get current boundary boundary = boundaries[i] function_space = function_spaces[i] # Case 0: boundary is a string if isinstance(boundary, str): boundary = CompiledSubDomain(boundary) bc = DirichletBC(function_space, value, boundary) # Case 1: boundary is a SubDomain elif isinstance(boundary, SubDomain): bc = DirichletBC(function_space, value, boundary) # Case 2: boundary is defined by a MeshFunction elif isinstance(boundary, tuple): mesh_function, index = boundary bc = DirichletBC(function_space, value, mesh_function, index) # Unhandled case else: error( "Unhandled boundary specification for boundary condition. " "Expecting a string, a SubDomain or a (MeshFunction, int) tuple." ) bcs.append(bc) return bcs
def info(self): """ Print some cache status information. """ counts = [0, 0, 0] for key in self.__cache.keys(): counts[form_rank(key[0])] += 1 dolfin.info("Assembly cache status:") for i in xrange(3): dolfin.info("Pre-assembled rank %i forms: %i" % (i, counts[i])) return
def compute_velocity_correction( ui, p0, p1, u_bcs, rho, mu, dt, rotational_form, my_dx, tol, verbose ): """Compute the velocity correction according to .. math:: U = u_0 - \\frac{dt}{\\rho} \\nabla (p_1-p_0). """ W = ui.function_space() P = p1.function_space() u = TrialFunction(W) v = TestFunction(W) a3 = dot(u, v) * my_dx phi = Function(P) phi.assign(p1) if p0: phi -= p0 if rotational_form: r = SpatialCoordinate(W.mesh())[0] div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1) phi += mu * div_ui L3 = dot(ui, v) * my_dx - dt / rho * (phi.dx(0) * v[0] + phi.dx(1) * v[1]) * my_dx u1 = Function(W) solve( a3 == L3, u1, bcs=u_bcs, solver_parameters={ "linear_solver": "iterative", "symmetric": True, "preconditioner": "hypre_amg", "krylov_solver": { "relative_tolerance": tol, "absolute_tolerance": 0.0, "maximum_iterations": 100, "monitor_convergence": verbose, }, }, ) # u = project(ui - k/rho * grad(phi), V) # div_u = 1/r * div(r*u) r = SpatialCoordinate(W.mesh())[0] div_u1 = 1.0 / r * (r * u1[0]).dx(0) + u1[1].dx(1) info("||u||_div = {:e}".format(sqrt(assemble(div_u1 * div_u1 * my_dx)))) return u1
def create_dirichlet_conditions(values, boundaries, function_space): """Create Dirichlet boundary conditions for given boundary values, boundaries and function space.""" # Check that the size matches if len(values) != len(boundaries): error("The number of Dirichlet values does not match the number of Dirichlet boundaries.") info("Creating %d Dirichlet boundary condition(s)." % len(values)) # Create Dirichlet conditions bcs = [] for (i, value) in enumerate(values): # Get current boundary boundary = boundaries[i] if isinstance(value, tuple): subdim = value[1] value = value[0] temp_function_space = function_space.sub(subdim) else: temp_function_space = function_space # Case 0: boundary is a string if isinstance(boundary, str): boundary = CompiledSubDomain(boundary) bc = DirichletBC(temp_function_space, value, boundary) # Case 1: boundary is a SubDomain elif isinstance(boundary, SubDomain): bc = DirichletBC(temp_function_space, value, boundary) # Case 2: boundary is defined by a MeshFunction elif isinstance(boundary, tuple): mesh_function, index = boundary bc = DirichletBC(temp_function_space, value, mesh_function, index) # Unhandled case else: error("Unhandled boundary specification for boundary condition. " "Expecting a string, a SubDomain or a (MeshFunction, int) tuple.") bcs.append(bc) return bcs
def __init__(self, parameters=None, solver="ipcs"): "Create Navier-Stokes problem" self.parameters = Parameters("problem_parameters") # Create solver if solver == "taylor-hood": info("Using Taylor-Hood based Navier-Stokes solver") self.solver = TaylorHoodSolver(self) elif solver == "ipcs": info("Using IPCS based Navier-Stokes solver") self.solver = NavierStokesSolver(self) else: error("Unknown Navier--Stokes solver: %s" % solver) # Set up parameters self.parameters.add(self.solver.parameters)
def add_turbine(self, coordinates): """Add a turbine to the farm at the given coordinates. Creates a new turbine of the same specification as the prototype turbine and places it at coordinates. :param coordinates: The x-y coordinates where the turbine should be placed. :type coordinates: :func:`list` """ if self._turbine_specification is None: raise ValueError("A turbine specification has not been set.") turbine = self._turbine_specification self._parameters["position"].append(coordinates) self._parameters["friction"].append(turbine.friction) dolfin.info("Turbine added at (%.2f, %.2f)." % (coordinates[0], coordinates[1]))
def read_parameters(): """Read parametrs from file specified on command-line or return default parameters if no file is specified""" # Read parameters from the command-line import sys p = default_parameters() try: file = File(sys.argv[1]) file >> p info("Parameters read from %s." % sys.argv[1]) except: info("No parameters specified, using default parameters.") # Set output directory if p["output_directory"] == "unspecified": p["output_directory"] = "results-%s"%date() return p
def refine_timestep(E_k, parameters): """Refine time steps (for next round) by adjusting the tolerance used to determine the adaptive time steps""" global TOL_k # Get parameters w_k = parameters["w_k"] TOL = parameters["tolerance"] conservation = 1.0 # Compute new tolerance TOL_k_new = w_k * TOL / E_k * TOL_k # Modify tolerance to avoid oscillations TOL_k_new = (1.0 + conservation) * TOL_k * TOL_k_new / (TOL_k + conservation * TOL_k_new) info("Changing TOL_k: %g --> %g" % (TOL_k, TOL_k_new)) TOL_k = TOL_k_new
def _end_time_step(self, t, T): "Call at end of time step" # Record CPU time cpu_time = time() elapsed_time = cpu_time - self._cpu_time self._cpu_time = cpu_time # Write some useful information s = "Time step %d (t = %g) finished in %g seconds." % (self._time_step, t, elapsed_time) info("\n" + s + "\n" + len(s)*"-" + "\n") # Update progress bar if self._progress is None: self._progress = Progress("Time-stepping") self._progress.update(t / T) # Increase time step counter self._time_step += 1
def save_errors(E_0, E_0_F, E_0_S, E_0_M, E, E_h, E_k, E_c, E_c_F, E_c_S, E_c_M, parameters): "Save errors to file" global _refinement_level # Summarize errors summary = """ Estimating error ------------------------- Adaptive loop no. = %d ------------------------- E_0 = %g E_h = %g E_k = %g E_c = %g E_tot = %g """ % (_refinement_level, E_0, E_h, E_k, abs(E_c), E) # Print summary info(summary) # Save to log file f = open("%s/adaptivity.log" % parameters["output_directory"], "a") f.write(summary) f.close() # Save to file (for plotting) g = open("%s/error_estimates.txt" % parameters["output_directory"], "a") if _refinement_level == 0: g.write("level\t E_0\t E_0_F\t E_0_S\t E_0_M\t E\t E_h\t E_k\t |E_c|\t E_c_F\t E_c_S\t E_c_M\n") g.write("%d %g %g %g %g %g %g %g %g %g %g %g\n" % \ (_refinement_level, E_0, E_0_F, E_0_S, E_0_M, E, E_h, E_k, abs(E_c), E_c_F, E_c_S, E_c_M)) g.close()
def _error_estimator(dx, phi, mu, sigma, omega, conv, voltages): '''Simple error estimator from A posteriori error estimation and adaptive mesh-refinement techniques; R. Verfürth; Journal of Computational and Applied Mathematics; Volume 50, Issues 1-3, 20 May 1994, Pages 67-83; <https://www.sciencedirect.com/science/article/pii/0377042794902909>. The strong PDE is - div(1/(mu r) grad(rphi)) + <u, 1/r grad(rphi)> + i sigma omega phi = sigma v_k / (2 pi r). ''' from dolfin import cells mesh = phi.function_space().mesh() # Assemble the cell-wise residual in DG space DG = FunctionSpace(mesh, 'DG', 0) # get residual in DG v = TestFunction(DG) R = _residual_strong(dx, v, phi, mu, sigma, omega, conv, voltages) r_r = assemble(R[0]) r_i = assemble(R[1]) r = r_r * r_r + r_i * r_i visualize = True if visualize: # Plot the cell-wise residual u = TrialFunction(DG) a = zero() * dx(0) subdomain_indices = mu.keys() for i in subdomain_indices: a += u * v * dx(i) A = assemble(a) R2 = Function(DG) solve(A, R2.vector(), r) plot(R2, title='||R||^2') interactive() K = r.array() info('%r' % K) h = numpy.array([c.diameter() for c in cells(mesh)]) eta = h * numpy.sqrt(K) return eta
def init_adaptive_data(problem, parameters): "Initialize data needed for adaptive time stepping" global U0, U1, M, W, w Omega = problem.mesh() # Create primal functions info("Initializing primal variables for time residual") U0 = create_primal_functions(Omega, parameters) U1 = create_primal_functions(Omega, parameters) # Assemble mass matrix W = create_dual_space(Omega, parameters) w = TestFunctions(W) m = inner_product(w, TrialFunctions(W)) M = assemble(m) # note: no cell_domains argument # Remove old saved data f = open("%s/timesteps_final.txt" % parameters["output_directory"], "w") f.close()
def compute_itertol(problem, w_c, TOL, dt, t1, parameters): "Compute tolerance for FSI iterations" if parameters["uniform_timestep"]: tol = parameters["fixedpoint_tolerance"] info("") info_blue(" * Tolerance for (f)-(S)-(M) iteration is fixed to %g" % tol) end() else: S_c = 1.0 # not computed tol = w_c * TOL * dt / S_c info("") info_blue(" * Changing tolerance for (f)-(S)-(M) iteration to %g" % tol) end() # Save FSI iteration tolerance to file save_itertol(t1, tol, parameters) return tol
def verify(self, key, tolerance=0.0): """ Verify data associated with the given key, with the specified tolerance. """ if not key in self.__cache: raise CheckpointException("Missing checkpoint with key %s" % str(key)) if not isinstance(tolerance, float) or tolerance < 0.0: raise InvalidArgumentException("tolerance must be a non-negative float") c_cs = self.__cache[key] try: for c in c_cs: self._Checkpointer__verify(c, c_cs[c], tolerance=tolerance) dolfin.info("Verified checkpoint with key %s" % str(key)) except CheckpointException as e: dolfin.info(str(e)) raise CheckpointException("Failed to verify checkpoint with key %s" % str(key)) return
def compute_time_step(problem, Rk, TOL, dt, t1, T, w_k, parameters): """Compute new time step based on residual R, stability factor S, tolerance TOL, and the previous time step dt. The time step is adjusted so that we will not step beyond the given end time.""" global _refinement_level, TOL_k # Set parameters for adaptive time steps conservation = 1.0 snap = 0.9 # Compute new time step if abs(Rk) > 0.0 and TOL_k is not None: dt_new = TOL_k / Rk else: TOL_k = 1.0 dt_new = 2.0 * dt # Modify time step to avoid oscillations dt_new = (1.0 + conservation) * dt * dt_new / (dt + conservation * dt_new) # Modify time step so we don't step beoynd end time at_end = False if dt_new > snap * (T - t1): info("Close to t = T, snapping time step to end time: %g --> %g" % (dt_new, T - t1)) dt_new = T - t1 at_end = True else: # Store minimum time step (but don't include snapped time steps) global min_timestep if min_timestep is None or dt_new < min_timestep: min_timestep = dt_new # Save time step save_timestep(t1, Rk, dt, TOL_k, parameters) if at_end: save_timestep(T, Rk, dt_new, TOL_k, parameters) info("Changing time step: %g --> %g" % (dt, dt_new)) return dt_new, at_end
def save_goal_functional_final(goal_functional, integrated_goal_functional, reference_value, parameters): "Saving goal functional at final time" global _refinement_level info("Value of goal functional at end time: %.16g" % goal_functional) info("Integrated goal functional final time %.16g" % integrated_goal_functional) if reference_value is not None: info("Reference value for integrated goal functional: %.16g" % reference_value) info("Error in integrated goal functional: %.16g" % (reference_value - integrated_goal_functional)) f = open("%s/goal_functional_final.txt" % parameters["output_directory"], "a") f.write("%d %.16g %.16g\n" % (_refinement_level, goal_functional, integrated_goal_functional)) f.close()
def compute_signs(self, AA, bb): self.signs = [None]*len(self) bb.allocate(AA, dim=0) for i in range(len(self)): if not self[i]: # No BC on this block, sign doesn't matter continue if numpy.isscalar(AA[i,i]): xAx = AA[i,i] else: # Do not use a constant vector, as that may be in the null space # before boundary conditions are applied x = AA[i,i].create_vec(dim=1) ran = numpy.random.random(x.local_size()) x.set_local(ran) Ax = AA[i,i]*x xAx = x.inner(Ax) if xAx == 0: from dolfin import warning warning("block_bc: zero or semi-definite block (%d,%d), using sign +1"%(i,i)) self.signs[i] = -1 if xAx < 0 else 1 dolfin.info('Calculated signs of diagonal blocks:' + str(self.signs))
def compute_itertol(problem, w_c, TOL, dt, t1, parameters): "Compute tolerance for FSI iterations" if parameters["uniform_timestep"]: tol = parameters["iteration_tolerance"] info("") if parameters["primal_solver"] == "fixpoint":itertype = "(f)-(S)-(M)" else:itertype = "Newton" info_blue(" * Tolerance for %s iteration is fixed to %g" %(itertype,tol)) end() else: S_c = 1.0 # not computed tol = w_c * TOL * dt / S_c info("") info_blue(" * Changing tolerance for (f)-(S)-(M) iteration to %g" % tol) end() # Save FSI iteration tolerance to file save_itertol(t1, tol, parameters) return tol
def main(mesh_filename='meshfile', resolution=32): filename = '%s.%s' % (mesh_filename, 'xml') if os.path.exists(filename): print('Mesh file exists, loading from file') mesh_3d = dolfin.Mesh(filename) else: geometry_3d = get_geometry() dolfin.info(geometry_3d, True) print('Creating mesh') mesh_3d = dolfin.Mesh(geometry_3d, resolution) print('Saving to file:'); print(filename) data_file = dolfin.File(filename) data_file << mesh_3d # Plot in either case. print('Plotting in interactive mode') fh = dolfin.plot(mesh_3d, '3D mesh', interactive=True, window_width=900, window_height=700)
def main(): resolution = 32 # 32 * 3 # filename = 'data/mesh_res_%d_boundary.xml' % resolution filename = "data/mesh_res_%d_boundary.xml" % resolution if os.path.exists(filename): print "=" * 60 print "Mesh file exists, loading from file" print "=" * 60 mesh_3d = dolfin.Mesh(filename) else: geometry_3d = get_geometry() dolfin.info(geometry_3d, True) print "=" * 60 print "Creating mesh" print "=" * 60 mesh_3d = dolfin.Mesh(geometry_3d, resolution) print "=" * 60 print "Converting to a boundary mesh" print "=" * 60 mesh_3d = dolfin.BoundaryMesh(mesh_3d, "exterior") # Since much smaller, it's much easier to refine the boundary mesh # as well. It may be worth doing this via: # mesh_3d = dolfin.mesh.refine(mesh_3d) print "=" * 60 print "Saving to file:", filename print "=" * 60 data_file = dolfin.File(filename) data_file << mesh_3d # Plot in either case. print "=" * 60 print "Plotting in interactive mode" print "=" * 60 fh = dolfin.plot(mesh_3d, "3D mesh", interactive=True, window_width=900, window_height=700)