def init_parent_edge_indices(submesh, mesh): "Initialize data 'parent_edge_indices' for submesh." # Check arguments if not isinstance(submesh, Mesh): raise TypeError, "expected 'Mesh' as argument" if not isinstance(mesh, Mesh): raise TypeError, "expected 'Mesh' as argument" # Check if edge map has already been computed if not submesh.data().mesh_function("parent_edge_indices") is None: info("Edge map 'parent_edge_indices' already computed, not computing again.") # Get parent vertex numbers parent_vertex_indices = submesh.data().mesh_function("parent_vertex_indices") if parent_vertex_indices is None: cpp.dolfin_error("ale.py", "initialize parent edge indices", "Parent vertex indice are missing") # Make sure that we have edges for both meshes submesh.init(1) mesh.init(1) # Make sure we have vertex-edge connectivity for parent mesh mesh.init(0, 1) # Create the edge map parent_edge_indices = submesh.data().create_mesh_function("parent_edge_indices") parent_edge_indices.init(1) # Iterate over the edges and figure out their parent number for local_edge in edges(submesh): # Get parent indices for edge vertices v0, v1 = local_edge.entities(0) V0 = Vertex(mesh, parent_vertex_indices[int(v0)]) V1 = Vertex(mesh, parent_vertex_indices[int(v1)]) # Get outgoing edges from the two parent vertices edges0 = set(V0.entities(1)) edges1 = set(V1.entities(1)) # Check intersection common_edges = edges0.intersection(edges1) if not len(common_edges) == 1: cpp.dolfin_error("ale.py", "initialize parent edge indices", "Parent vertices do not share exactly one common edge") parent_edge_index = list(common_edges)[0] # Set value parent_edge_indices[local_edge.index()] = parent_edge_index
def _solve_varproblem_adaptive(*args, **kwargs): "Solve variational problem a == L or F == 0 adaptively" # Extract arguments eq, u, bcs, J, tol, M, form_compiler_parameters, \ solver_parameters = _extract_args(*args, **kwargs) # Check that we received the goal functional if M is None: cpp.dolfin_error("solving.py", "solve variational problem adaptively", "Missing goal functional") # Solve linear variational problem if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form): # Create problem problem = LinearVariationalProblem( eq.lhs, eq.rhs, u, bcs, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = AdaptiveLinearVariationalSolver(problem, M) solver.parameters.update(solver_parameters) solver.solve(tol) # Solve nonlinear variational problem else: # Create Jacobian if missing if J is None: cpp.info( "No Jacobian form specified for nonlinear variational problem." ) cpp.info( "Differentiating residual form F to obtain Jacobian J = F'.") F = eq.lhs J = derivative(F, u) # Create problem problem = NonlinearVariationalProblem( eq.lhs, u, bcs, J, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = AdaptiveNonlinearVariationalSolver(problem, M) solver.parameters.update(solver_parameters) solver.solve(tol)
def init_parent_edge_indices(submesh, mesh): "Initialize data 'parent_edge_indices' for submesh." # Check arguments if not isinstance(submesh, Mesh): raise TypeError("expected 'Mesh' as argument") if not isinstance(mesh, Mesh): raise TypeError("expected 'Mesh' as argument") # Check if edge map has already been computed if not submesh.data().exists("parent_edge_indices", 1): info( "Edge map 'parent_edge_indices' already computed, not computing again." ) # Get parent vertex numbers parent_vertex_indices = submesh.data().array("parent_vertex_indices", 0) if parent_vertex_indices is None: cpp.dolfin_error("ale.py", "initialize parent edge indices", "Parent vertex indice are missing") # Make sure that we have edges for both meshes submesh.init(1) mesh.init(1) # Make sure we have vertex-edge connectivity for parent mesh mesh.init(0, 1) # Create the edge map parent_edge_indices = submesh.data().create_array("parent_edge_indices", 1) # Iterate over the edges and figure out their parent number for local_edge in edges(submesh): # Get parent indices for edge vertices v0, v1 = local_edge.entities(0) V0 = Vertex(mesh, parent_vertex_indices[int(v0)]) V1 = Vertex(mesh, parent_vertex_indices[int(v1)]) # Get outgoing edges from the two parent vertices edges0 = set(V0.entities(1)) edges1 = set(V1.entities(1)) # Check intersection common_edges = edges0.intersection(edges1) if not len(common_edges) == 1: cpp.dolfin_error( "ale.py", "initialize parent edge indices", "Parent vertices do not share exactly one common edge") parent_edge_index = list(common_edges)[0] # Set value parent_edge_indices[local_edge.index()] = parent_edge_index
def _solve_varproblem(*args, **kwargs): "Solve variational problem a == L or F == 0" # Extract arguments eq, u, bcs, J, tol, M, form_compiler_parameters, solver_parameters \ = _extract_args(*args, **kwargs) # Solve linear variational problem if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form): # Create problem problem = LinearVariationalProblem( eq.lhs, eq.rhs, u, bcs, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = LinearVariationalSolver(problem) solver.parameters.update(solver_parameters) solver.solve() # Solve nonlinear variational problem else: # Create Jacobian if missing if J is None: cpp.info( "No Jacobian form specified for nonlinear variational problem." ) cpp.info( "Differentiating residual form F to obtain Jacobian J = F'.") F = eq.lhs J = derivative(F, u) # Create problem problem = NonlinearVariationalProblem( eq.lhs, u, bcs, J, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = NonlinearVariationalSolver(problem) solver.parameters.update(solver_parameters) solver.solve()
def _solve_varproblem_adaptive(*args, **kwargs): "Solve variational problem a == L or F == 0 adaptively" # Extract arguments eq, u, bcs, J, tol, M, form_compiler_parameters, solver_parameters \ = _extract_args(*args, **kwargs) # Check that we received the goal functional if M is None: cpp.dolfin_error("solving.py", "solve variational problem adaptively", "Missing goal functional") # Solve linear variational problem if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form): # Create problem problem = LinearVariationalProblem(eq.lhs, eq.rhs, u, bcs, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = AdaptiveLinearVariationalSolver(problem, M) solver.parameters.update(solver_parameters) solver.solve(tol) # Solve nonlinear variational problem else: # Create Jacobian if missing if J is None: cpp.info("No Jacobian form specified for nonlinear variational problem.") cpp.info("Differentiating residual form F to obtain Jacobian J = F'.") F = eq.lhs J = derivative(F, u) # Create problem problem = NonlinearVariationalProblem(eq.lhs, u, bcs, J, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = AdaptiveNonlinearVariationalSolver(problem, M) solver.parameters.update(solver_parameters) solver.solve(tol)
def generate_error_control_forms(problem, goal): """ Create UFL forms required for initializing an ErrorControl object *Arguments* problem (:py:class:`LinearVariationalProblem <dolfin.fem.solving.LinearVariationalProblem>` or :py:class:`NonlinearVariationalProblem <dolfin.fem.solving.NonlinearVariationalProblem>`) The (primal) problem goal (:py:class:`Form <dolfin.fem.form.Form>`) The goal functional *Returns* (tuple of forms, bool) """ msg = "Generating forms required for error control, this may take some time..." cpp.info(msg) # Extract primal forms from problem is_linear = True if isinstance(problem, LinearVariationalProblem): primal = (problem.a_ufl, problem.L_ufl) elif isinstance(problem, NonlinearVariationalProblem): is_linear = False primal = problem.F_ufl else: cpp.dolfin_error("adaptivesolving.py", "generate forms required for error control", "Unknown problem type (\"%s\")" % str(problem)) # Extract unknown Function from problem u = problem.u_ufl # Get DOLFIN's error control generator to generate all forms generator = DOLFINErrorControlGenerator(primal, goal, u) forms = generator.generate_all_error_control_forms() return (forms, is_linear)
def _solve_varproblem(*args, **kwargs): "Solve variational problem a == L or F == 0" # Extract arguments eq, u, bcs, J, tol, M, form_compiler_parameters, solver_parameters \ = _extract_args(*args, **kwargs) # Solve linear variational problem if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form): # Create problem problem = LinearVariationalProblem(eq.lhs, eq.rhs, u, bcs, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = LinearVariationalSolver(problem) solver.parameters.update(solver_parameters) solver.solve() # Solve nonlinear variational problem else: # Create Jacobian if missing if J is None: cpp.info("No Jacobian form specified for nonlinear variational problem.") cpp.info("Differentiating residual form F to obtain Jacobian J = F'.") F = eq.lhs J = derivative(F, u) # Create problem problem = NonlinearVariationalProblem(eq.lhs, u, bcs, J, form_compiler_parameters=form_compiler_parameters) # Create solver and call solve solver = NonlinearVariationalSolver(problem) solver.parameters.update(solver_parameters) solver.solve()
def plot(object, *args, **kwargs): """ Plot given object. *Arguments* object a :py:class:`Mesh <dolfin.cpp.Mesh>`, a :py:class:`MeshFunction <dolfin.cpp.MeshFunction>`, a :py:class:`Function <dolfin.functions.function.Function>`, a :py:class:`Expression` <dolfin.cpp.Expression>, a :py:class:`DirichletBC` <dolfin.cpp.DirichletBC> or a :py:class:`FiniteElement <ufl.FiniteElement>`. *Examples of usage* In the simplest case, to plot only e.g. a mesh, simply use .. code-block:: python mesh = UnitSquare(4,4) plot(mesh) Use the ``title`` argument to specify title of the plot .. code-block:: python plot(mesh, tite="Finite element mesh") It is also possible to plot an element .. code-block:: python element = FiniteElement("BDM", tetrahedron, 3) plot(element) Vector valued functions can be visualized with an alternative mode .. code-block:: python plot(u, mode = "glyphs") A more advanced example .. code-block:: python plot(u, wireframe = True, # use wireframe rendering interactive = False, # do not hold plot on screen scalarbar = False, # hide the color mapping bar hardcopy_prefix = "myplot", # default plotfile name scale = 2.0 # scale the warping/glyphs title = "Fancy plot" # Set your own title ) """ mesh = kwargs.get('mesh') p = cpp.Parameters() for key in kwargs: # If there is a "mesh" kwarg it should not be added to the parameters if key != "mesh": try: p.add(key, kwargs[key]) except TypeError: cpp.warning("Incompatible type for keyword argument \"%s\". Ignoring." % key) # Plot element if isinstance(object, ufl.FiniteElementBase): if os.environ.get("DOLFIN_NOPLOT", "0") != "0": return import ffc return ffc.plot(object, *args, **kwargs) if mesh is None and len(args) == 1 and isinstance(args[0], cpp.Mesh): mesh = args[0] # Plot expression if isinstance(object, cpp.Expression): if mesh is None: raise TypeError, "expected a mesh when plotting an expression." return cpp.plot(object, mesh, p) # Try to project if object is not a standard plottable type if not isinstance(object, (cpp.Function, cpp.Expression, cpp.Mesh, cpp.DirichletBC, cpp.MeshFunction, cpp.MeshFunctionBool, cpp.MeshFunctionInt, cpp.MeshFunctionDouble, cpp.MeshFunctionSizet, cpp.DirichletBC, cpp.CSGGeometry)): from dolfin.fem.projection import project try: cpp.info("Object cannot be plotted directly, projecting to"\ " piecewise linears.") object = project(object, mesh=mesh) except Exception as e: msg = ("Don't know how to plot given object:\n %s\n"\ "and projection failed:\n %s") % (str(object), str(e)) #raise RuntimeError(msg) raise plot_object = cpp.plot(object, p) plot_object.write_ps = _VTKPlotter_write_ps # Avoid premature deletion of plotted objects if they go out of scope # before the plot window is closed. The plotter itself is safe, since it's # created in the plot() C++ function, not directly from Python. But the # Python plotter proxy may disappear, so we can't store the references # there. global _objects_referenced_from_plot_windows _objects_referenced_from_plot_windows[plot_object.key()] = (object, mesh, p) return plot_object
def plot(object, *args, **kwargs): """ Plot given object. *Arguments* object a :py:class:`Mesh <dolfin.cpp.Mesh>`, a :py:class:`MeshFunction <dolfin.cpp.MeshFunction>`, a :py:class:`Function <dolfin.functions.function.Function>`, a :py:class:`Expression` <dolfin.cpp.Expression>, a :py:class:`DirichletBC` <dolfin.cpp.DirichletBC> or a :py:class:`FiniteElement <ufl.FiniteElement>`. *Examples of usage* In the simplest case, to plot only e.g. a mesh, simply use .. code-block:: python mesh = UnitSquare(4,4) plot(mesh) Use the ``title`` argument to specify title of the plot .. code-block:: python plot(mesh, tite="Finite element mesh") It is also possible to plot an element .. code-block:: python element = FiniteElement("BDM", tetrahedron, 3) plot(element) Vector valued functions can be visualized with an alternative mode .. code-block:: python plot(u, mode = "glyphs") A more advanced example .. code-block:: python plot(u, wireframe = True, # use wireframe rendering interactive = False, # do not hold plot on screen scalarbar = False, # hide the color mapping bar hardcopy_prefix = "myplot", # default plotfile name scale = 2.0 # scale the warping/glyphs title = "Fancy plot" # Set your own title ) """ # Plot element if isinstance(object, ufl.FiniteElementBase): if os.environ.get("DOLFIN_NOPLOT", "0") != "0": return import ffc return ffc.plot(object, *args, **kwargs) # Get mesh from explicit mesh kwarg, only positional arg, or via object mesh = kwargs.pop('mesh', None) if isinstance(object, cpp.Mesh): if mesh is not None and mesh.id() != object.id(): cpp.dolfin_error("plotting.py", "plot mesh", "Got different mesh in plot object and keyword argument") mesh = object if mesh is None: if isinstance(object, cpp.Function): mesh = object.function_space().mesh() elif hasattr(object, "mesh"): mesh = object.mesh() # Expressions do not carry their own mesh if isinstance(object, cpp.Expression) and mesh is None: cpp.dolfin_error("plotting.py", "plot expression", "Expecting a mesh as keyword argument") # Try to project if object is not a standard plottable type if not isinstance(object, _plottable_types): from dolfin.fem.projection import project try: cpp.info("Object cannot be plotted directly, projecting to"\ " piecewise linears.") object = project(object, mesh=mesh) except Exception as e: msg = "Don't know how to plot given object:\n %s\n" \ "and projection failed:\n %s" % (str(object), str(e)) cpp.dolfin_error("plotting.py", "plot object", msg) # Select backend backend = cpp.parameters["plotting_backend"] if backend == "vtk": return _plot_cpp(object, mesh, kwargs) elif backend == "matplotlib": return _plot_matplotlib(object, mesh, kwargs)
def plot(object, *args, **kwargs): """ Plot given object. *Arguments* object a :py:class:`Mesh <dolfin.cpp.Mesh>`, a :py:class:`MeshFunction <dolfin.cpp.MeshFunction>`, a :py:class:`Function <dolfin.functions.function.Function>`, a :py:class:`Expression` <dolfin.cpp.Expression>, a :py:class:`DirichletBC` <dolfin.cpp.DirichletBC> or a :py:class:`FiniteElement <ufl.FiniteElement>`. *Examples of usage* In the simplest case, to plot only e.g. a mesh, simply use .. code-block:: python mesh = UnitSquare(4,4) plot(mesh) Use the ``title`` argument to specify title of the plot .. code-block:: python plot(mesh, tite="Finite element mesh") It is also possible to plot an element .. code-block:: python element = FiniteElement("BDM", tetrahedron, 3) plot(element) Vector valued functions can be visualized with an alternative mode .. code-block:: python plot(u, mode = "glyphs") A more advanced example .. code-block:: python plot(u, wireframe = True, # use wireframe rendering interactive = False, # do not hold plot on screen scalarbar = False, # hide the color mapping bar hardcopy_prefix = "myplot", # default plotfile name scale = 2.0 # scale the warping/glyphs title = "Fancy plot" # Set your own title ) """ # Plot element if isinstance(object, ufl.FiniteElementBase): if os.environ.get("DOLFIN_NOPLOT", "0") != "0": return import ffc return ffc.plot(object, *args, **kwargs) # Get mesh from explicit mesh kwarg, only positional arg, or via object mesh = kwargs.pop('mesh', None) if isinstance(object, cpp.Mesh): if mesh is not None and mesh.id() != object.id(): cpp.dolfin_error( "plotting.py", "plot mesh", "Got different mesh in plot object and keyword argument") mesh = object if mesh is None: if isinstance(object, cpp.Function): mesh = object.function_space().mesh() elif hasattr(object, "mesh"): mesh = object.mesh() # Expressions do not carry their own mesh if isinstance(object, cpp.Expression) and mesh is None: cpp.dolfin_error("plotting.py", "plot expression", "Expecting a mesh as keyword argument") # Try to project if object is not a standard plottable type if not isinstance(object, _plottable_types): from dolfin.fem.projection import project try: cpp.info("Object cannot be plotted directly, projecting to"\ " piecewise linears.") object = project(object, mesh=mesh) except Exception as e: msg = "Don't know how to plot given object:\n %s\n" \ "and projection failed:\n %s" % (str(object), str(e)) cpp.dolfin_error("plotting.py", "plot object", msg) # Select backend backend = cpp.parameters["plotting_backend"] if backend == "vtk": return _plot_cpp(object, mesh, kwargs) elif backend == "matplotlib": return _plot_matplotlib(object, mesh, kwargs)
def plot(object, *args, **kwargs): """ Plot given object. *Arguments* object a :py:class:`Mesh <dolfin.cpp.Mesh>`, a :py:class:`MeshFunction <dolfin.cpp.MeshFunction>`, a :py:class:`Function <dolfin.functions.function.Function>`, a :py:class:`Expression` <dolfin.cpp.Expression>, a :py:class:`DirichletBC` <dolfin.cpp.DirichletBC> or a :py:class:`FiniteElement <ufl.FiniteElement>`. *Examples of usage* In the simplest case, to plot only e.g. a mesh, simply use .. code-block:: python mesh = UnitSquare(4,4) plot(mesh) Use the ``title`` argument to specify title of the plot .. code-block:: python plot(mesh, tite="Finite element mesh") It is also possible to plot an element .. code-block:: python element = FiniteElement("BDM", tetrahedron, 3) plot(element) Vector valued functions can be visualized with an alternative mode .. code-block:: python plot(u, mode = "glyphs") A more advanced example .. code-block:: python plot(u, wireframe = True, # use wireframe rendering interactive = False, # do not hold plot on screen scalarbar = False, # hide the color mapping bar hardcopy_prefix = "myplot", # default plotfile name scale = 2.0 # scale the warping/glyphs title = "Fancy plot" # Set your own title ) """ mesh = kwargs.get('mesh') p = cpp.Parameters() for key in kwargs: # If there is a "mesh" kwarg it should not be added to the parameters if key != "mesh": try: p.add(key, kwargs[key]) except TypeError: cpp.warning( "Incompatible type for keyword argument \"%s\". Ignoring." % key) # Plot element if isinstance(object, ufl.FiniteElementBase): if os.environ.get("DOLFIN_NOPLOT", "0") != "0": return import ffc return ffc.plot(object, *args, **kwargs) if mesh is None and len(args) == 1 and isinstance(args[0], cpp.Mesh): mesh = args[0] # Plot expression if isinstance(object, cpp.Expression): if mesh is None: raise TypeError, "expected a mesh when plotting an expression." return cpp.plot(object, mesh, p) # Try to project if object is not a standard plottable type if not isinstance( object, (cpp.Function, cpp.Expression, cpp.Mesh, cpp.DirichletBC, cpp.MeshFunction, cpp.MeshFunctionBool, cpp.MeshFunctionInt, cpp.MeshFunctionDouble, cpp.MeshFunctionSizet, cpp.DirichletBC, cpp.CSGGeometry)): from dolfin.fem.projection import project try: cpp.info("Object cannot be plotted directly, projecting to"\ " piecewise linears.") object = project(object, mesh=mesh) except Exception as e: msg = ("Don't know how to plot given object:\n %s\n"\ "and projection failed:\n %s") % (str(object), str(e)) #raise RuntimeError(msg) raise plot_object = cpp.plot(object, p) plot_object.write_ps = _VTKPlotter_write_ps # Avoid premature deletion of plotted objects if they go out of scope # before the plot window is closed. The plotter itself is safe, since it's # created in the plot() C++ function, not directly from Python. But the # Python plotter proxy may disappear, so we can't store the references # there. global _objects_referenced_from_plot_windows _objects_referenced_from_plot_windows[plot_object.key()] = (object, mesh, p) return plot_object
def generate_error_control_forms(problem, goal): """ Create UFL forms required for initializing an ErrorControl object *Arguments* problem (:py:class:`LinearVariationalProblem <dolfin.fem.solving.LinearVariationalProblem>` or :py:class:`NonlinearVariationalProblem <dolfin.fem.solving.NonlinearVariationalProblem>`) The (primal) problem goal (:py:class:`Form <dolfin.fem.form.Form>`) The goal functional *Returns* (tuple of forms, bool) """ msg = "Generating forms required for error control, this may take some time..." cpp.info(msg) # Paranoid checks added after introduction of multidomain features in ufl: for form in [goal]: assert len(form.ufl_domains()) > 0, "Error control got as input a form with no domain!" assert len(form.ufl_domains()) == 1, "Error control got as input a form with more than one domain!" # Extract primal forms from problem is_linear = True if isinstance(problem, LinearVariationalProblem): primal = (problem.a_ufl, problem.L_ufl) # Paranoid checks added after introduction of multidomain features in ufl: for form in primal: assert len(form.ufl_domains()) > 0, "Error control got as input a form with no domain!" assert len(form.ufl_domains()) == 1, "Error control got as input a form with more than one domain!" elif isinstance(problem, NonlinearVariationalProblem): is_linear = False primal = problem.F_ufl # Paranoid checks added after introduction of multidomain features in ufl: for form in [primal]: assert len(form.ufl_domains()) > 0, "Error control got as input a form with no domain!" assert len(form.ufl_domains()) == 1, "Error control got as input a form with more than one domain!" else: cpp.dolfin_error("adaptivesolving.py", "generate forms required for error control", "Unknown problem type (\"%s\")" % str(problem)) # Extract unknown Function from problem u = problem.u_ufl # Get DOLFIN's error control generator to generate all forms generator = DOLFINErrorControlGenerator(primal, goal, u) forms = generator.generate_all_error_control_forms() # Paranoid checks added after introduction of multidomain features in ufl: for form in forms: assert len(form.ufl_domains()) > 0, "Error control produced a form with no domain!" assert len(form.ufl_domains()) == 1, "Error control produced a form with more than one domain!" return (forms, is_linear)