Ejemplo n.º 1
0
def test_form_splitter_matrices(shape):
    mesh = UnitSquareMesh(dolfin.MPI.comm_self, 3, 3)
    Vu = FunctionSpace(mesh, 'DG', 2)
    Vp = FunctionSpace(mesh, 'DG', 1)

    def define_eq(u, v, p, q):
        "A simple Stokes-like coupled weak form"
        eq = Constant(2) * dot(u, v) * dx
        eq += dot(grad(p), v) * dx
        eq -= dot(Constant([1, 1]), v) * dx
        eq += dot(grad(q), u) * dx
        eq -= dot(Constant(0.3), q) * dx
        return eq

    if shape == (2, 2):
        eu = MixedElement([Vu.ufl_element(), Vu.ufl_element()])
        ew = MixedElement([eu, Vp.ufl_element()])
        W = FunctionSpace(mesh, ew)

        u, p = TrialFunctions(W)
        v, q = TestFunctions(W)
        u = as_vector([u[0], u[1]])
        v = as_vector([v[0], v[1]])

    elif shape == (3, 3):
        ew = MixedElement(
            [Vu.ufl_element(),
             Vu.ufl_element(),
             Vp.ufl_element()])
        W = FunctionSpace(mesh, ew)

        u0, u1, p = TrialFunctions(W)
        v0, v1, q = TestFunctions(W)
        u = as_vector([u0, u1])
        v = as_vector([v0, v1])
        eq = define_eq(u, v, p, q)

    # Define coupled problem
    eq = define_eq(u, v, p, q)

    # Split the weak form into a saddle point block matrix system
    mat, vec = split_form_into_matrix(eq, W, W)

    # Check shape and that appropriate elements are none
    assert mat.shape == shape
    assert mat[-1, -1] is None
    for i in range(shape[0] - 1):
        for j in range(shape[1] - 1):
            if i != j:
                assert mat[i, j] is None

    # Check that the split matrices are identical with the
    # coupled matrix when reassembled into a single matrix
    compare_split_matrices(eq, mat, vec, W, W)
Ejemplo n.º 2
0
def _test_linear_solver_sparse(callback_type):
    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2 * pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2*pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2 * pi - 10 * DOLFIN_EPS

    # Define exact solution
    exact_solution_expression = Expression("x[0] + sin(2*x[0])",
                                           element=V.ufl_element())
    exact_solution = project(exact_solution_expression, V)

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    g = Expression("4*sin(2*x[0])", element=V.ufl_element())
    a = inner(grad(u), grad(v)) * dx
    f = g * v * dx
    x = inner(u, v) * dx

    # Assemble inner product matrix
    X = assemble(x)

    # Define boundary condition
    bc = [DirichletBC(V, exact_solution_expression, boundary)]

    # Defin solution
    sparse_solution = Function(V)

    # Define linear solver depending on callback type, and solve the problem
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        A = None
        F = None
        sparse_solver = SparseLinearSolver(a, sparse_solution, f, bc)
    elif callback_type == "tensor callbacks":
        A = assemble(a)
        F = assemble(f)
        sparse_solver = SparseLinearSolver(A, sparse_solution, F, bc)
    sparse_solver.solve()

    # Compute the error
    sparse_error = Function(V)
    sparse_error.vector().add_local(+sparse_solution.vector().get_local())
    sparse_error.vector().add_local(-exact_solution.vector().get_local())
    sparse_error.vector().apply("")
    sparse_error_norm = sparse_error.vector().inner(X * sparse_error.vector())
    print("SparseLinearSolver error (" + callback_type + "):",
          sparse_error_norm)
    assert isclose(sparse_error_norm, 0., atol=1.e-5)
    return (sparse_error_norm, V, A, F, X, exact_solution)
Ejemplo n.º 3
0
def mk_scheme(N, Vname, Vorder, cpp_expr, expr_args, convection_inp, dim=2, comm=None):
    if comm is None:
        comm = MPI.comm_world

    parameters['ghost_mode'] = 'shared_vertex'
    if dim == 2:
        mesh = UnitSquareMesh(comm, N, N)
    else:
        mesh = UnitCubeMesh(comm, N, N, N)

    V = FunctionSpace(mesh, Vname, Vorder)
    C = Function(V)
    e = Expression(cpp_expr, element=V.ufl_element(), **expr_args)
    C.interpolate(e)

    D = Function(V)
    D.assign(C)

    sim = Simulation()
    sim.set_mesh(mesh)
    sim.data['constrained_domain'] = None
    sim.data['C'] = C
    for key, value in convection_inp.items():
        sim.input.set_value('convection/C/%s' % key, value)

    scheme_name = convection_inp['convection_scheme']
    return get_convection_scheme(scheme_name)(sim, 'C')
Ejemplo n.º 4
0
def mk_vel(sim, Vname, Vorder, cpp_exprs):
    mesh = sim.data['mesh']
    V = FunctionSpace(mesh, Vname, Vorder)

    vel = []
    for cpp in cpp_exprs:
        u = Function(V)
        u.interpolate(Expression(cpp, element=V.ufl_element()))
        vel.append(u)

    return as_vector(vel)
Ejemplo n.º 5
0
def test_estimator():
    # setup solution multi vector
    mis = [Multiindex([0]),
           Multiindex([1]),
           Multiindex([0, 1]),
           Multiindex([0, 2])]
    mesh = UnitSquare(4, 4)
    fs = FunctionSpace(mesh, "CG", 1)
    F = [interpolate(Expression("*".join(["x[0]"] * i)), fs) for i in range(1, 5)]
    vecs = [FEniCSVector(f) for f in F]

    w = MultiVectorWithProjection()
    for mi, vec in zip(mis, vecs):
        w[mi] = vec
        #    v = A * w

    # define coefficient field
    aN = 4
    a = [Expression('2.+sin(20.*pi*I*x[0]*x[1])', I=i, degree=3, element=fs.ufl_element())
         for i in range(1, aN)]
    rvs = [UniformRV(), NormalRV(mu=0.5)]
    coeff_field = ListCoefficientField(a[0], a[1:], rvs)

    # define source term
    f = Constant("1.0")

    # evaluate residual and projection error estimators
    resind, reserr = ResidualEstimator.evaluateResidualEstimator(w, coeff_field, f)
    projind, projerr = ResidualEstimator.evaluateProjectionError(w, coeff_field)
    print resind[mis[0]].as_array().shape, projind[mis[0]].as_array().shape
    print "RESIDUAL:", resind[mis[0]].as_array()
    print "PROJECTION:", projind[mis[0]].as_array()
    print "residual error estimate for mu"
    for mu in reserr:
        print "\t eta", mu, " is ", reserr[mu]
        print "\t delta", mu, " is ", projerr[mu]

    assert_equal(w.active_indices(), resind.active_indices())
    print "active indices are ", resind.active_indices()
Ejemplo n.º 6
0
def test_local_assembler_on_facet_integrals():
    mesh = UnitSquareMesh(MPI.comm_world, 4, 4, 'right')
    Vdg = FunctionSpace(mesh, 'DG', 0)
    Vdgt = FunctionSpace(mesh, 'DGT', 1)

    v = TestFunction(Vdgt)

    # Initialize DG function "w" in discontinuous pattern
    w = Expression('(1.0 + pow(x[0], 2.2) + 1/(0.1 + pow(x[1], 3)))*300.0',
                   element=Vdg.ufl_element())

    # Define form that tests that the correct + and - values are used
    L = w('-') * v('+') * dS

    # Compile form. This is collective
    L = Form(L)

    # Get global cell 10. This will return a cell only on one of the
    # processes
    c = get_cell_at(mesh, 5 / 12, 1 / 3, 0)

    if c:
        # Assemble locally on the selected cell
        b_e = assemble_local(L, c)

        # Compare to values from phonyx (fully independent
        # implementation)
        b_phonyx = numpy.array(
            [266.55210302, 266.55210302, 365.49000122, 365.49000122, 0.0, 0.0])
        error = sum((b_e - b_phonyx)**2)**0.5
        error = float(error)  # MPI.max does strange things to numpy.float64

    else:
        error = 0.0

    error = MPI.max(MPI.comm_world, float(error))
    assert error < 1e-8
Ejemplo n.º 7
0
    def test_funvec2img_pb(self):
        m, n = 10, 20

        # Define mesh.
        mesh = UnitSquareMesh(m - 1, n - 1)

        # Define function spaces
        V = FunctionSpace(mesh,
                          'CG',
                          1,
                          constrained_domain=dh.PeriodicBoundary())

        class MyUserExpression(UserExpression):
            def eval(self, value, x):
                value[0] = x[0]

            def value_shape(self):
                return (1, )

        f = interpolate(MyUserExpression(element=V.ufl_element()), V)

        v = dh.funvec2img_pb(f.vector().get_local(), m, n)
        np.testing.assert_allclose(v.shape, (m, n))
        np.testing.assert_allclose(v[:, 0], v[:, -1])
Ejemplo n.º 8
0
class State(object):
  def __init__(self, mesh, celldomains = {'magnetic': 1, 'conducting': 1}, facetdomains = {'outermagnet': 1}, material = None, scale = 1.0, t = 0.0, **kwargs):
    """
    This class holds the complete state of the simulation and provides some
    convenience wrappers for the handling of multiple domains. Furthermore
    it provides an interface for attribute handling and caching.

    *Domain/Material Examples*
      .. code-block:: python

        state = State(mesh,
          celldomains = {'magnetic': (1,3), 'conducting': 2, 'iron': 1, 'cobalt': 3}
          m = Expression(...)
        )

        # Set materials for different regions
        state.material['iron']       = Material(...)
        state.material['cobalt']     = Material(...)
        state.material['conducting'] = Material(...)

        # Use integration measures with named domains
        assemble(Constant(1.0) * state.dx('all'))       # All named domains
        assemble(Constant(1.0) * state.dx('magnetic'))  # Magnetic region
        assemble(Constant(1.0) * state.dx('!magnetic')) # Nonmagnetic region
        assemble(Constant(1.0) * state.dx(1))           # Region by ID

        # Compute average of magnetization m
        state.m.average()       # Over whole space
        state.m.average('iron') # Over iron region

        # Crop magnetization to subdomain and save as PVD
        f = File("m_iron.pvd")
        f << state.m.crop('iron')

        # Normalize the magnetization
        state.m.normalize()

    *Attribute Examples*
      .. code-block:: python

        # initialize state with constant magnetization. m is automatically
        # interpolated on a suitable discrete function space.
        state = State(mesh,
          m = Constant((1.0, 0.0, 0.0)),
        )

        # define a current as function of the time
        state.j = lambda state: Constant((state.t * 1e12, 0.0, 0.0))

        # define some functional depending on m
        state.E = lambda state: (assemble(inner(state.m, state.m)*state.dx()), "m")

        # dependencies can be arbirtrarily nested
        state.E_times_2 = lambda state: (2*state.E, "E")

        # all values are cached according to their dependencies
        state.E_times_2  # triggers computation of E_times_2
        state.E_times_2  # taken from cache, no computation

        state.m = Constant((0.0, 1.0, 0.0))

        state.E_times_2  # triggers computation of E_times_2

    *Arguments*
      mesh (:class:`dolfin.Mesh`)
        The mesh including all subdomains as :class:`dolfin.MeshDomains`
      celldomains (:class:`dict`)
        naming of the cell subdomains, at least the subdomains 'magnetic' and 'conducting' should be defined.
      facetdomains (:class:`dict`)
        naming of the facet subdomains
      material (:class:`Material`)
        the material of the sample. If material differs from subdomain to subdomain, use material setters instead.
      scale (:class:`float`)
        the spatial scaling of the mesh. Use 1e-9 if you use nanometers as length measure.
      t (:class:`float`)
        the time
      **kwargs (:class:`dict`)
        add any state variables like magnetization (m) or spin diffusion (s).
        Expressions are automatically interpolated on the corresponding discrete spaces.
        
    """

    self._uuid  = uuid.uuid4()
    self.mesh  = mesh
    self.scale = scale
    self.t = t
    self.set_celldomains(celldomains)
    self.set_facetdomains(facetdomains)

    # TODO add args to set domains via mesh functions directly
    self.cell_domains  = MeshFunction('size_t', mesh, 3, mesh.domains())
    self.facet_domains = MeshFunction('size_t', mesh, 2, mesh.domains())

    self._dx = Measure('dx', mesh)[self.cell_domains]
    self._ds = Measure('ds', mesh)[self.facet_domains]
    self._dS = Measure('dS', mesh)[self.facet_domains]
    self._dP = {}

    self._VS = FunctionSpace(self.mesh, 'CG', 1)          # TODO lazy initialize
    self._VV = VectorFunctionSpace(self.mesh, 'CG', 1, 3) # TODO lazy initialize

    self.material = material

    self._wrapped_meshes  = {}
    self._volumes         = {}
    self._func_attributes = {}
    self._M_inv_diag      = {}

    for key, value in kwargs.iteritems():
      setattr(self, key, value)

  def _decorate_attr(self, name, value):
    if isinstance(value, GenericFunction):
      value._state      = self
      value.update_uuid = types.MethodType(_update_uuid, value)
      value.crop        = types.MethodType(_crop, value)
      value.average     = types.MethodType(_average, value)
      value.normalize   = types.MethodType(_normalize, value)
      value.rename(name, value.label())
      value.update_uuid()
    return value

  def __setattr__(self, name, value):
    # handle lambda attributes
    if isfunction(value):
      self._func_attributes[name] = Cache(
          func  = value,
          uuid  = None,
          value = None,
          keys  = None,
          in_process = False
      )
      return

    if isinstance(value, GenericFunction):
      # always interpolate
      value = self.interpolate(value)

      # use assign if object exists
      if hasattr(self, name):
        attr = getattr(self, name)
        attr.assign(value)
        attr.update_uuid()
        return

      # decorate if object does not exist
      else:
        self._decorate_attr(name, value)

    super(State, self).__setattr__(name, value)

  def __getattr__(self, name):
    # handle lambda attributes
    if self._func_attributes.has_key(name):
      attr = self._func_attributes[name]

      # return uncached attribute
      if attr.keys == (): return attr.func(self)

      # check cycle dependency
      if attr.in_process:
        raise AttributeCycleDependency("Attribute dependency cycle detected.")

      # check cache hit
      if attr.keys is not None:
        uuid = self.uuid(*attr.keys)
        if uuid == attr.uuid: return attr.value

      # update cache
      attr.in_process = True
      value = attr.func(self)
      attr.in_process = False

      # set default hash keys
      if not isinstance(value, tuple):
        # primitives default to their value
        if isinstance(value, (int, float, str)):
          value = (value,)
        # others default to the time
        else:
          value = (value, "t")

      # XXX this seems to create a memory leak
      if isinstance(attr.value, Function):
        attr.value.assign(value[0])
        attr.value.update_uuid()
      else:
        attr.value = self._decorate_attr(name, value[0])

      attr.keys  = value[1:]
      if attr.keys != ():
        attr.uuid = self.uuid(*attr.keys)

      return attr.value

    raise AttributeError("'State' object has no attribute '%s'" % name)

  def uuid(self, *names):
    """
    Returns a uuid for a given list of attributes. The uuid changes if the
    attribute if reset.

    *Arguments*
      names ([:class:`string`])
        list of attribute names

    *Returns*
      the uuid
    """
    if len(names) == 0:
      return self._uuid
    elif len(names) == 1:
      name = names[0]
      # lambda attribute
      if self._func_attributes.has_key(name):
        attr = self._func_attributes[name]
        if attr.keys == None: getattr(self, name)
        if attr.keys == ():
          return getattr(self, name)
        else:
          return self.uuid(*attr.keys)

      # no lambda attribute
      else:
        attr = getattr(self, name)

        # object attribute (e.g. Function)
        if hasattr(attr, "uuid"):
          return attr.uuid

        # primitive attribute
        else:
          return attr
    else:
      return map(lambda x: self.uuid(x), names)

  def wrapped_mesh_for(self, domain):
    """
    Creates a :class:`WrappedMesh` object for a certain domain. This can be
    used to crop certain state values like the magnetization to a region of
    interest.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        domain identifier (either string or id)

    *Returns*
      :class:`WrappedMesh`
        the wrapped mesh
    """
    if not self._wrapped_meshes.has_key(domain):
      self._wrapped_meshes[domain] = WrappedMesh.create(self.mesh, self.domain_ids(domain))

    return self._wrapped_meshes[domain]

  def volume(self, domain = 'all'):
    """
    Computes the volume of a certain domain.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        domain identifier (either string or id)

    *Returns*
      :class:`float`
        the volume of the region
    """
    if not self._volumes.has_key(domain):
      self._volumes[domain] = assemble(Constant(1.0)*self.dx(domain))

    return self._volumes[domain]

  @property
  def material(self):
    return self._material

  @material.setter
  def material(self, value):
    if value is None:
      self._material = CompositeMaterial(self, Material())
    elif isinstance(value, Material):
      self._material = CompositeMaterial(self, value)
    else:
      raise AttributeError("Type not supported.")

  def set_celldomains(self, celldomains):
    self.celldomains = {}
    for material in celldomains:
      ids = celldomains[material]
      if isinstance(ids, int):  ids = (ids,)
      if isinstance(ids, list): ids = tuple(ids)
      self.celldomains[material] = ids

  def set_facetdomains(self, facetdomains):
    self.facetdomains = {}
    for material in facetdomains:
      ids = facetdomains[material]
      if isinstance(ids, int):  ids = (ids,)
      if isinstance(ids, list): ids = tuple(ids)
      self.facetdomains[material] = ids

  def domain_ids(self, domain, domaintype = 'cell'):
    """
    Get the domain IDs for a named domain.

    *Arguments*
      domain (:class:`string`/ :class:`int`)
        name or ID of domain
      domaintype (:class:`string`)
        domain type, (cell, facet)

    *Returns*
      :class:`[int]`
        List of domain IDs
    """
    if isinstance(domain, int):
      return [domain]

    domains = {
        'cell':  self.celldomains,
        'facet': self.facetdomains
      }[domaintype]

    if domain == 'all':
      ids = tuple()
      for material in domains:
        ids = ids + domains[material]
      return tuple(set(ids))
    elif domain[0] == '!':
      ids = set(self.domain_ids('all', domaintype))
      for id in self.domain_ids(domain[1:], domaintype):
        ids.remove(id)
      return tuple(ids)
    else:
      try:
        return domains[domain]
      except KeyError:
        raise KeyError("Unknown domain '%s'." % domain)

  def dx(self, domain = "all", dx = None):
    """
    Convenience wrapper for integral-cell measure. If the mesh does not contain
    any cell domains, the measure for the whole mesh is returned.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        name or ID of domain
      dx (:class:`dolfin:Measure`)
        alternative measure

    *Returns*
      :class:`dolfin:Measure`
        the measure


        # Compute volume of magnetic domain
        assemble(Constant(1.0) * state.dx('magnetic'))

        # Compute volume of domain with ID 3
        assemble(Constant(1.0) * state.dx(3))
    """
    # return measure for whole mesh if no domains are defined
    if not self.mesh_has_domains(): return self._dx

    domain_ids = self.domain_ids(domain)
    # XXX fall back to zero measure
    if len(domain_ids) == 0: domain_ids = (999999,)

    if dx == None: dx = self._dx

    return reduce(lambda x,y: x+y, map(lambda i: dx(i), domain_ids))
 
  def dP(self, domain = "all"):
    """
    Convenience wrapper for integral-point measure. If the mesh does not contain
    any cell domains, the measure for the whole mesh is returned.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        name or ID of domain

    *Returns*
      :class:`dolfin:Measure`
        the measure
    """
    if not self.mesh_has_domains(): return Measure('dP', self.mesh)

    if not self._dP.has_key(domain):
      v = TestFunction(self.FunctionSpace())
      values = assemble(v*self.dx(domain)).array()
      # TODO improve this?
      markers = ((np.sign(np.ceil(values) - 0.5) + 1.0) / 2.0).astype(np.uint64)

      vertex_domains = MeshFunction('size_t', self.mesh, 0)
      vertex_domains.array()[:] = markers

      self._dP[domain] = Measure('dP', self.mesh)[vertex_domains](1)

    return self._dP[domain]

  def ds(self, domain = "all", ds = None, intersect = None):
    """
    Convenience wrapper for integral-facet measure. If the mesh does not
    contain any cell domains, the measure for the whole mesh is returned.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        name or ID of domain
      ds (:class:`dolfin:Measure`)
        alternative measure
      intersect (:class:`string` / :class:`int`)
        name or ID of anothe domain to intersect with

    *Returns*
      :class:`dolfin:Measure`
        the measure
    """
    # return measure for whole mesh if no domains are defined
    if not self.mesh_has_domains(): return self._ds

    domain_ids = self.domain_ids(domain, 'facet')
    if intersect is not None:
      domain_ids = list(set(self.domain_ids(intersect, 'facet')).intersection(domain_ids))
    # XXX fall back to zero measure
    if len(domain_ids) == 0: domain_ids = (999999,)

    if ds == None: ds = self._ds

    measure = ds(domain_ids[0])
    for domain_id in domain_ids[1:]:
      measure += ds(domain_id)

    return reduce(lambda x,y: x+y, map(lambda i: ds(i), domain_ids))

  def dS(self, domain = "all", dS = None):
    """
    Convenience wrapper for integral-interior-facet measure. If the mesh does
    not contain any cell domains, the measure for the whole mesh is returned.

    *Arguments*
      domain (:class:`string` / :class:`int`)
        name or ID of domain
      dS (:class:`dolfin:Measure`)
        alternative measure

    *Returns*
      :class:`dolfin:Measure`
        the measure
    """
    if dS == None:
      return self.ds(domain, self._dS)
    else:
      return self.ds(domain, dS)

  def mesh_has_domains(self):
    """
    Returns True if mesh contains cell-domain data.

    *Returns*
      :class:`bool`
        True if mesh contains cell-domain data
    """
    return self.mesh.domains().num_marked(3) != 0

  def interpolate(self, expressions):
    """
    Interpolates a collection of expressions, each defined for a specific domain,
    on a suitable function space. Also works for a single expression.

    *Arguments*
      expressions (:class:`dict`)
        Expressions to be interpolated.

    *Returns*
      :class:`dolfin.Function`
        Interpolated function

    *Example*
      .. code-block:: python

        f1 = state.interpolate({
          'magnetic':  Constant((1.0, 0.0, 0.0)),
          '!magnetic': Constant((0.0, 1.0, 0.0))
        })

        f2 = state.interpolate(Constant(1.0))
    """
    # single expression
    if isinstance(expressions, GenericFunction):
      if isinstance(expressions, Function):
        # TODO check if function spaces match
        return expressions
      else:
        return interpolate(
          expressions,
          self.FunctionSpace(rank = expressions.rank())
        )
    # multiple expressions (dict)
    else:
      result = Function(self.FunctionSpace(rank = expressions.itervalues().next().rank()))
      result.vector().zero()
      for domain in expressions:
        wmesh = self.wrapped_mesh_for(domain)
        expression = expressions[domain]
        f = interpolate(expression, self.FunctionSpace(wmesh, expression.rank()))
        wmesh.expand(f, result)
      return result

  def step(self, integrators, dt):
    """
    Calls the step method on every integrator and increases :code:`t`.

    *Arguments*
      integrators (:class:`list` or :class:`Integrator`)
        Integrator on which the step method is called.
        Can be either a list of integrators or a single integrator.
    """
    if not isinstance(integrators, collections.Iterable):
      integrators = [integrators]

    for integrator in integrators:
      integrator.step(self, dt)

    self.t += dt

  def VectorFunctionSpace(self, mesh = None):
    """
    Returns the vector-function space for a mesh.

    *Arguments*
      mesh (:class:`dolfin.Mesh`)
        the mesh, defaults to mesh of the state if set to :code:`None`

    *Returns*
      :class:`dolfin.FunctionSpace`
        the function space
    """
    if mesh == None: return self._VV
    element = self._VS.ufl_element()
    return VectorFunctionSpace(mesh, element.family(), element.degree())

  def FunctionSpace(self, mesh = None, rank = 0):
    """
    Returns a function space for a mesh.

    *Arguments*
      mesh (:class:`dolfin.Mesh`)
        the mesh, defaults to mesh of the state if set to :code:`None`
      rank (:class:`int`)
        the rank of the function space (0 for scalar space, 1 for vector space)

    *Returns*
      :class:`dolfin.FunctionSpace`
        the function space
    """
    if rank == 0:
      if mesh == None: return self._VS
      element = self._VS.ufl_element()
      return FunctionSpace(mesh, element.family(), element.degree())
    elif rank == 1:
      return self.VectorFunctionSpace(mesh)
    else:
      raise Exception("Rank > 1 not supported.")

  def M_inv_diag(self, domain = "all"):
    """
    Returns the inverse lumped mass matrix for the vector function space.
    The result ist cached.

    .. note:: This method requires the PETSc Backend to be enabled.

    *Returns*
      :class:`dolfin.Matrix`
        the matrix
    """
    if not self._M_inv_diag.has_key(domain):
      v = TestFunction(self.VectorFunctionSpace())
      u = TrialFunction(self.VectorFunctionSpace())

      mass_form = inner(v, u) * self.dx(domain)
      mass_action_form = action(mass_form, Constant((1.0, 1.0, 1.0)))
      diag = assemble(mass_action_form)
      as_backend_type(diag).vec().reciprocal()

      result = assemble(inner(v, u) * dP)
      result.zero()
      result.set_diagonal(diag)
      self._M_inv_diag[domain] = result

    return self._M_inv_diag[domain]

  @property
  def full(self):
    return self

  def expand(self, func):
    return func

  def cut(self, func):
    return func

  def mask(self, domain):
    # TODO also check if domain spans the whole mesh
    if self.mesh_has_domains():
      return MaskedState(self, domain)
    else:
      return self
class Data(object):
    def __init__(self, Th, callback_type):
        # Create mesh and define function space
        mesh = UnitSquareMesh(Th, Th)
        self.V = FunctionSpace(mesh, "Lagrange", 1)
        # Define variational problem
        du = TrialFunction(self.V)
        v = TestFunction(self.V)
        self.u = Function(self.V)
        self.r = lambda u, g: inner(grad(u), grad(v)) * dx + inner(
            u + u**3, v) * dx - g * v * dx
        self.j = lambda u, r: derivative(r, u, du)
        # Define initial guess
        self.initial_guess_expression = Expression(
            "0.1 + 0.9*x[0]*x[1]", element=self.V.ufl_element())
        # Define callback function depending on callback type
        assert callback_type in ("form callbacks", "tensor callbacks")
        if callback_type == "form callbacks":

            def callback(arg):
                return arg
        elif callback_type == "tensor callbacks":

            def callback(arg):
                return assemble(arg)

        self.callback_type = callback_type
        self.callback = callback

    def generate_random(self):
        # Generate random forcing
        g = RandomDolfinFunction(self.V)
        # Generate correspondingly residual and jacobian forms
        r = self.r(self.u, g)
        j = self.j(self.u, r)

        # Prepare problem wrapper
        class ProblemWrapper(NonlinearProblemWrapper):
            # Residual and jacobian functions
            def residual_eval(self_, solution):
                return self.callback(r)

            def jacobian_eval(self_, solution):
                return self.callback(j)

            # Define boundary condition
            def bc_eval(self_):
                return None

            # Empty solution monitor
            def monitor(self_, solution):
                pass

        problem_wrapper = ProblemWrapper()
        # Return
        return (r, j, problem_wrapper)

    def evaluate_builtin(self, r, j, problem_wrapper):
        project(self.initial_guess_expression, self.V, function=self.u)
        solve(r == 0,
              self.u,
              J=j,
              solver_parameters={
                  "nonlinear_solver": "snes",
                  "snes_solver": {
                      "linear_solver": "mumps",
                      "maximum_iterations": 20,
                      "relative_tolerance": 1e-9,
                      "absolute_tolerance": 1e-9,
                      "maximum_residual_evaluations": 10000,
                      "report": True
                  }
              })
        return self.u.copy(deepcopy=True)

    def evaluate_backend(self, r, j, problem_wrapper):
        project(self.initial_guess_expression, self.V, function=self.u)
        solver = NonlinearSolver(problem_wrapper, self.u)
        solver.set_parameters({
            "linear_solver": "mumps",
            "maximum_iterations": 20,
            "relative_tolerance": 1e-9,
            "absolute_tolerance": 1e-9,
            "report": True
        })
        solver.solve()
        return self.u.copy(deepcopy=True)

    def assert_backend(self, r, j, problem_wrapper, result_backend):
        result_builtin = self.evaluate_builtin(r, j, problem_wrapper)
        error = Function(self.V)
        error.vector().add_local(+result_backend.vector().get_local())
        error.vector().add_local(-result_builtin.vector().get_local())
        error.vector().apply("add")
        relative_error = error.vector().norm(
            "l2") / result_builtin.vector().norm("l2")
        assert isclose(relative_error, 0., atol=1e-12)
Ejemplo n.º 10
0
mesh = UnitSquareMesh(200, 200)
# mesh = create_dolfin_mesh(*meshzoo.triangle(1500, corners=[[0, 0], [1, 0], [0, 1]]))


V = FunctionSpace(mesh, "CG", 1)

u = TrialFunction(V)
v = TestFunction(V)

n = FacetNormal(mesh)
# A = assemble(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds)
A = assemble(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds)
M = assemble(u * v * dx)

f = Expression("sin(pi * x[0]) * sin(pi * x[1])", element=V.ufl_element())
x = project(f, V)

Ax = A * x.vector()
Minv_Ax = Function(V).vector()
solve(M, Minv_Ax, Ax)
val = Ax.inner(Minv_Ax)

print(val)


# Exact value
x = sympy.Symbol("x")
y = sympy.Symbol("y")
f = sympy.sin(sympy.pi * x) * sympy.sin(sympy.pi * y)
f2 = sympy.diff(f, x, x) + sympy.diff(f, y, y)
Ejemplo n.º 11
0
def _test_nonlinear_solver_sparse(callback_type):
    from dolfin import Function
    from rbnics.backends.dolfin import NonlinearSolver

    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2 * pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2 * pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2 * pi - 10 * DOLFIN_EPS

    # Define exact solution
    exact_solution_expression = Expression("x[0] + sin(2*x[0])",
                                           element=V.ufl_element())
    exact_solution = project(exact_solution_expression, V)

    # Define variational problem
    du = TrialFunction(V)
    v = TestFunction(V)
    u = Function(V)
    g = Expression(
        "4 * sin(2 * x[0]) * (pow(x[0] + sin(2 * x[0]), 2) + 1)" +
        " - 2 * (x[0] + sin(2 * x[0])) * pow(2 * cos(2 * x[0]) + 1," + " 2)",
        element=V.ufl_element())
    r = inner((1 + u**2) * grad(u), grad(v)) * dx - g * v * dx
    j = derivative(r, u, du)
    x = inner(du, v) * dx

    # Assemble inner product matrix
    X = assemble(x)

    # Define initial guess
    def initial_guess():
        initial_guess_expression = Expression("0.1 + 0.9 * x[0]",
                                              element=V.ufl_element())
        return project(initial_guess_expression, V)

    # Define boundary condition
    bc = [DirichletBC(V, exact_solution_expression, boundary)]

    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":

        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":

        def callback(arg):
            return assemble(arg)

    # Define problem wrapper
    class ProblemWrapper(NonlinearProblemWrapper):
        # Residual function
        def residual_eval(self, solution):
            return callback(r)

        # Jacobian function
        def jacobian_eval(self, solution):
            return callback(j)

        # Define boundary condition
        def bc_eval(self):
            return bc

        # Define custom monitor to plot the solution
        def monitor(self, solution):
            if matplotlib.get_backend() != "agg":
                plot(solution, title="u")
                plt.show(block=False)
                plt.pause(1)
            else:
                print("||u|| = " + str(solution.vector().norm("l2")))

    # Solve the nonlinear problem
    problem_wrapper = ProblemWrapper()
    solution = u
    assign(solution, initial_guess())
    solver = NonlinearSolver(problem_wrapper, solution)
    solver.set_parameters({
        "linear_solver": "mumps",
        "maximum_iterations": 20,
        "report": True
    })
    solver.solve()

    # Compute the error
    error = Function(V)
    error.vector().add_local(+solution.vector().get_local())
    error.vector().add_local(-exact_solution.vector().get_local())
    error.vector().apply("")
    error_norm = error.vector().inner(X * error.vector())
    print("Sparse error (" + callback_type + "):", error_norm)
    assert isclose(error_norm, 0., atol=1.e-5)
    return (error_norm, V, u, r, j, X, initial_guess, exact_solution)
Ejemplo n.º 12
0
def RunJob(Tb, mu_value, path):
    runtimeInit = clock()

    tfile = File(path + '/t6t.pvd')
    mufile = File(path + "/mu.pvd")
    ufile = File(path + '/velocity.pvd')
    gradpfile = File(path + '/gradp.pvd')
    pfile = File(path + '/pstar.pvd')
    parameters = open(path + '/parameters', 'w', 0)
    vmeltfile = File(path + '/vmelt.pvd')
    rhofile = File(path + '/rhosolid.pvd')

    for name in dir():
        ev = str(eval(name))
        if name[0] != '_' and ev[0] != '<':
            parameters.write(name + ' = ' + ev + '\n')

    temp_values = [27. + 273, Tb + 273, 1300. + 273, 1305. + 273]
    dTemp = temp_values[3] - temp_values[0]
    temp_values = [x / dTemp for x in temp_values]  # non dimensionalising temp

    mu_a = mu_value  # this was taken from the blankenbach paper, can change..

    Ep = b / dTemp

    mu_bot = exp(-Ep * (temp_values[3] * dTemp - 1573) + cc) * mu_a

    Ra = rho_0 * alpha * g * dTemp * h**3 / (kappa_0 * mu_a)
    w0 = rho_0 * alpha * g * dTemp * h**2 / mu_a
    tau = h / w0
    p0 = mu_a * w0 / h

    print(mu_a, mu_bot, Ra, w0, p0)

    vslipx = 1.6e-09 / w0
    vslip = Constant((vslipx, 0.0))  # nondimensional
    noslip = Constant((0.0, 0.0))

    dt = 3.E11 / tau
    tEnd = 3.E13 / tau  # non-dimensionalising times

    class PeriodicBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return left(x, on_boundary)

        def map(self, x, y):
            y[0] = x[0] - MeshWidth
            y[1] = x[1]

    pbc = PeriodicBoundary()

    class TempExp(Expression):
        def eval(self, value, x):
            if x[1] >= LAB(x):
                value[0] = temp_values[0] + (temp_values[1] - temp_values[0]
                                             ) * (MeshHeight -
                                                  x[1]) / (MeshHeight - LAB(x))
            else:
                value[0] = temp_values[3] - (
                    temp_values[3] - temp_values[2]) * (x[1]) / (LAB(x))

    class FluidTemp(Expression):
        def eval(self, value, x):
            if value[0] < 1295:
                value[0] = 1295

    mesh = RectangleMesh(Point(0.0, 0.0), Point(MeshWidth, MeshHeight), nx, ny)

    Svel = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Spre = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Stemp = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Smu = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Sgradp = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Srho = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    S0 = MixedFunctionSpace([Svel, Spre, Stemp])

    u = Function(S0)
    v, p, T = split(u)
    v_t, p_t, T_t = TestFunctions(S0)

    T0 = interpolate(TempExp(), Stemp)

    muExp = Expression(
        'exp(-Ep * (T_val * dTemp - 1573) + cc * x[2] / meshHeight)',
        Smu.ufl_element(),
        Ep=Ep,
        dTemp=dTemp,
        cc=cc,
        meshHeight=MeshHeight,
        T_val=T0)

    mu = interpolate(muExp, Smu)

    rhosolid = Function(Srho)
    deltarho = Function(Srho)

    v0 = Function(Svel)
    vmelt = Function(Svel)

    v_theta = (1. - theta) * v0 + theta * v

    T_theta = (1. - theta) * T + theta * T0

    r_v = (inner(sym(grad(v_t)), 2.*mu*sym(grad(v))) \
        - div(v_t)*p \
        - T*v_t[1] )*dx

    r_p = p_t * div(v) * dx

    r_T = (T_t*((T - T0) \
        + dt*inner(v_theta, grad(T_theta))) \
        + (dt/Ra)*inner(grad(T_t), grad(T_theta)) )*dx
    #           + k_s*(Tf-T_theta)*dt

    Tf = T0.interpolate(FluidTemp())
    # Tf = T0.interpolate(Expression('value[0] >= 1295.0 ? value[0] : 1295.0'))

    # Tf.interpolate(Expression('value[0] >= 1295 ? value[0] : 1295'))
    # project(Expression('value[0] >= 1295 ? value[0] : 1295'), Tf)
    # Alex, a question for you:
    # can you see if there is a way to set Tf = T in regions where T >=1295 celsius
    #
    # 1295 celsius is my arbitrary choice for the LAB isotherm.  In regions
    # where T < 1295 C, set Tf to be some constant for now, such as 1295 C.
    # Once we do this, then we can add in a term like that last line above where
    # it will only be non-zero when the solid temperature, T, is cooler than 1295
    # can you do this? After this is done, we will then worry about a calculation
    # where we solve for Tf as a function of time in the regions cooler than 1295 C
    # Makes sense?  If not, we can skype soon -- email me with questions
    # 3/19/16
    r = r_v + r_p + r_T

    bcv0 = DirichletBC(S0.sub(0), noslip, top)
    bcv1 = DirichletBC(S0.sub(0), vslip, bottom)
    bcp0 = DirichletBC(S0.sub(1), Constant(0.0), bottom)
    bct0 = DirichletBC(S0.sub(2), Constant(temp_values[0]), top)
    bct1 = DirichletBC(S0.sub(2), Constant(temp_values[3]), bottom)

    bcs = [bcv0, bcv1, bcp0, bct0, bct1]

    t = 0
    count = 0
    while (t < tEnd):
        solve(r == 0, u, bcs)
        t += dt
        nV, nP, nT = u.split()
        gp = grad(nP)
        rhosolid = rho_0 * (1 - alpha * (nT * dTemp - 1573))
        deltarho = rhosolid - rhomelt
        yvec = Constant((0.0, 1.0))
        vmelt = nV * w0 - darcy * (gp * p0 / h - deltarho * yvec * g)
        if (count % 100 == 0):
            pfile << nP
            ufile << nV
            tfile << nT
            mufile << mu
            gradpfile << project(grad(nP), Sgradp)
            mufile << project(mu * mu_a, Smu)
            rhofile << project(rhosolid, Srho)
            vmeltfile << project(vmelt, Svel)
        count += 1
        assign(T0, nT)
        assign(v0, nV)
        mu.interpolate(muExp)

    print('Case mu=%g, Tb=%g complete.' % (mu_a, Tb), ' Run time =',
          clock() - runtimeInit, 's')
Ejemplo n.º 13
0
    if edgefields:
        fh.write("CELL_DATA {0}\n".format(elems.shape[0]))
        for n,f in edgefields:
            PUTFIELD(n,f)
            
    fh.close()





if __name__=="__main__":
    from dolfin import UnitSquareMesh, Function, FunctionSpace, VectorFunctionSpace, TensorFunctionSpace, Expression

    mesh = UnitSquareMesh(10,10)
    S=FunctionSpace(mesh,"DG",0)
    V=VectorFunctionSpace(mesh,"DG",0)
    T=TensorFunctionSpace(mesh,"DG",0)
    Tsym = TensorFunctionSpace(mesh,"DG",0,symmetry=True)

    s = Function(S)
    s.interpolate(Expression('x[0]',element=S.ufl_element()))
    v = Function(V)
    v.interpolate(Expression(('x[0]','x[1]'),element=V.ufl_element()))
    t = Function(T)
    t.interpolate(Expression(( ('x[0]','1.0'),('2.0','x[1]')),element=T.ufl_element()))
    ts = Function(Tsym)
    ts.interpolate(Expression(( ('x[0]','1.0'),('x[1]',)),element=Tsym.ufl_element()))
    
    write_vtk_f("test.vtk",cellfunctions={'s':s,'v':v,'t':t,'tsym':ts})
Ejemplo n.º 14
0
def _test_time_stepping_1_sparse(callback_type, integrator_type):
    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2*pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2*pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2*pi - 10*DOLFIN_EPS
        
    # Define time step
    dt = 0.01
    T = 1.

    # Define exact solution
    exact_solution_expression = Expression("sin(x[0]+t)", t=0, element=V.ufl_element())
    # ... and interpolate it at the final time
    exact_solution_expression.t = T
    exact_solution = project(exact_solution_expression, V)

    # Define exact solution dot
    exact_solution_dot_expression = Expression("cos(x[0]+t)", t=0, element=V.ufl_element())
    # ... and interpolate it at the final time
    exact_solution_dot_expression.t = T
    exact_solution_dot = project(exact_solution_dot_expression, V)

    # Define variational problem
    du = TrialFunction(V)
    du_dot = TrialFunction(V)
    v = TestFunction(V)
    u = Function(V)
    u_dot = Function(V)
    g = Expression("sin(x[0]+t) + cos(x[0]+t)", t=0., element=V.ufl_element())
    r_u = inner(grad(u), grad(v))*dx
    j_u = derivative(r_u, u, du)
    r_u_dot = inner(u_dot, v)*dx
    j_u_dot = derivative(r_u_dot, u_dot, du_dot)
    r = r_u_dot + r_u - g*v*dx
    x = inner(du, v)*dx
    def bc(t):
        exact_solution_expression.t = t
        return [DirichletBC(V, exact_solution_expression, boundary)]

    # Assemble inner product matrix
    X = assemble(x)
    
    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":
        def callback(arg):
            return assemble(arg)
            
    # Define problem wrapper
    class SparseProblemWrapper(TimeDependentProblem1Wrapper):
        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            g.t = t
            return callback(r)
        def jacobian_eval(self, t, solution, solution_dot, solution_dot_coefficient):
            return callback(Constant(solution_dot_coefficient)*j_u_dot + j_u)
            
        # Define boundary condition
        def bc_eval(self, t):
            return bc(t)
            
        # Define initial condition
        def ic_eval(self):
            exact_solution_expression.t = 0.
            return project(exact_solution_expression, V)
            
        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            if matplotlib.get_backend() != "agg":
                plt.subplot(1, 2, 1).clear()
                plot(solution, title="u at t = " + str(t))
                plt.subplot(1, 2, 2).clear()
                plot(solution_dot, title="u_dot at t = " + str(t))
                plt.show(block=False)
                plt.pause(DOLFIN_EPS)
            else:
                print("||u|| at t = " + str(t) + ": " + str(solution.vector().norm("l2")))
                print("||u_dot|| at t = " + str(t) + ": " + str(solution_dot.vector().norm("l2")))

    # Solve the time dependent problem
    sparse_problem_wrapper = SparseProblemWrapper()
    (sparse_solution, sparse_solution_dot) = (u, u_dot)
    sparse_solver = SparseTimeStepping(sparse_problem_wrapper, sparse_solution, sparse_solution_dot)
    sparse_solver.set_parameters({
        "initial_time": 0.0,
        "time_step_size": dt,
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "monitor": sparse_problem_wrapper.monitor,
        "report": True
    })
    all_sparse_solutions_time, all_sparse_solutions, all_sparse_solutions_dot = sparse_solver.solve()
    assert len(all_sparse_solutions_time) == int(T/dt + 1)
    assert len(all_sparse_solutions) == int(T/dt + 1)
    assert len(all_sparse_solutions_dot) == int(T/dt + 1)

    # Compute the error
    sparse_error = Function(V)
    sparse_error.vector().add_local(+ sparse_solution.vector().get_local())
    sparse_error.vector().add_local(- exact_solution.vector().get_local())
    sparse_error.vector().apply("")
    sparse_error_norm = sparse_error.vector().inner(X*sparse_error.vector())
    sparse_error_dot = Function(V)
    sparse_error_dot.vector().add_local(+ sparse_solution_dot.vector().get_local())
    sparse_error_dot.vector().add_local(- exact_solution_dot.vector().get_local())
    sparse_error_dot.vector().apply("")
    sparse_error_dot_norm = sparse_error_dot.vector().inner(X*sparse_error_dot.vector())
    print("SparseTimeStepping error (" + callback_type + ", " + integrator_type + "):", sparse_error_norm, sparse_error_dot_norm)
    assert isclose(sparse_error_norm, 0., atol=1.e-4)
    assert isclose(sparse_error_dot_norm, 0., atol=1.e-4)
    return ((sparse_error_norm, sparse_error_dot_norm), V, dt, T, u, u_dot, g, r, j_u, j_u_dot, X, exact_solution_expression, exact_solution, exact_solution_dot)
Ejemplo n.º 15
0
def RunJob(Tb, mu_value, path):
    runtimeInit = clock()

    tfile = File(path + '/t6t.pvd')
    mufile = File(path + "/mu.pvd")
    ufile = File(path + '/velocity.pvd')
    gradpfile = File(path + '/gradp.pvd')
    pfile = File(path + '/pstar.pvd')
    parameters = open(path + '/parameters', 'w', 0)
    vmeltfile = File(path + '/vmelt.pvd')
    rhofile = File(path + '/rhosolid.pvd')

    for name in dir():
        ev = str(eval(name))
        if name[0] != '_' and ev[0] != '<':
            parameters.write(name + ' = ' + ev + '\n')

    temp_values = [27. + 273, Tb + 273, 1300. + 273, 1305. + 273]
    dTemp = temp_values[3] - temp_values[0]
    temp_values = [x / dTemp for x in temp_values]  # non dimensionalising temp

    mu_a = mu_value  # this was taken from the blankenbach paper, can change..
    
    Ep = b / dTemp

    mu_bot = exp(-Ep * (temp_values[3] * dTemp - 1573) + cc) * mu_a

    Ra = rho_0 * alpha * g * dTemp * h**3 / (kappa_0 * mu_a)
    w0 = rho_0 * alpha * g * dTemp * h**2 / mu_a
    tau = h / w0
    p0 = mu_a * w0 / h

    print(mu_a, mu_bot, Ra, w0, p0)

    vslipx = 1.6e-09 / w0
    vslip = Constant((vslipx, 0.0))  # nondimensional
    noslip = Constant((0.0, 0.0))

    dt = 3.E11 / tau
    tEnd = 3.E13 / tau  # non-dimensionalising times

    class PeriodicBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return left(x, on_boundary)

        def map(self, x, y):
            y[0] = x[0] - MeshWidth
            y[1] = x[1]

    pbc = PeriodicBoundary()

    class TempExp(Expression):
        def eval(self, value, x):
            if x[1] >= LAB(x):
                value[0] = temp_values[0] + (temp_values[1] - temp_values[0]) * (MeshHeight - x[1]) / (MeshHeight - LAB(x))
            else:
                value[0] = temp_values[3] - (temp_values[3] - temp_values[2]) * (x[1]) / (LAB(x))

    class FluidTemp(Expression):
        def eval(self, value, x):
            if value[0] < 1295:
                value[0] = 1295

    mesh = RectangleMesh(Point(0.0, 0.0), Point(MeshWidth, MeshHeight), nx, ny)

    Svel = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Spre = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Stemp = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Smu = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Sgradp = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Srho = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    S0 = MixedFunctionSpace([Svel, Spre, Stemp])

    u = Function(S0)
    v, p, T = split(u)
    v_t, p_t, T_t = TestFunctions(S0)

    T0 = interpolate(TempExp(), Stemp)

    muExp = Expression('exp(-Ep * (T_val * dTemp - 1573) + cc * x[2] / meshHeight)', Smu.ufl_element(),
                        Ep=Ep, dTemp=dTemp, cc=cc, meshHeight=MeshHeight, T_val=T0)

    mu = interpolate(muExp, Smu)

    rhosolid = Function(Srho)
    deltarho = Function(Srho)

    v0 = Function(Svel)
    vmelt = Function(Svel)

    v_theta = (1. - theta)*v0 + theta*v

    T_theta = (1. - theta)*T + theta*T0

    r_v = (inner(sym(grad(v_t)), 2.*mu*sym(grad(v))) \
        - div(v_t)*p \
        - T*v_t[1] )*dx

    r_p = p_t*div(v)*dx

    r_T = (T_t*((T - T0) \
        + dt*inner(v_theta, grad(T_theta))) \
        + (dt/Ra)*inner(grad(T_t), grad(T_theta)) )*dx
#           + k_s*(Tf-T_theta)*dt

    Tf = T0.interpolate(FluidTemp())
    # Tf = T0.interpolate(Expression('value[0] >= 1295.0 ? value[0] : 1295.0'))

    # Tf.interpolate(Expression('value[0] >= 1295 ? value[0] : 1295'))
    # project(Expression('value[0] >= 1295 ? value[0] : 1295'), Tf)
# Alex, a question for you:
# can you see if there is a way to set Tf = T in regions where T >=1295 celsius
#
# 1295 celsius is my arbitrary choice for the LAB isotherm.  In regions
# where T < 1295 C, set Tf to be some constant for now, such as 1295 C.
# Once we do this, then we can add in a term like that last line above where
# it will only be non-zero when the solid temperature, T, is cooler than 1295
# can you do this? After this is done, we will then worry about a calculation
# where we solve for Tf as a function of time in the regions cooler than 1295 C
# Makes sense?  If not, we can skype soon -- email me with questions
# 3/19/16
    r = r_v + r_p + r_T

    bcv0 = DirichletBC(S0.sub(0), noslip, top)
    bcv1 = DirichletBC(S0.sub(0), vslip, bottom)
    bcp0 = DirichletBC(S0.sub(1), Constant(0.0), bottom)
    bct0 = DirichletBC(S0.sub(2), Constant(temp_values[0]), top)
    bct1 = DirichletBC(S0.sub(2), Constant(temp_values[3]), bottom)

    bcs = [bcv0, bcv1, bcp0, bct0, bct1]

    t = 0
    count = 0
    while (t < tEnd):
        solve(r == 0, u, bcs)
        t += dt
        nV, nP, nT = u.split()
        gp = grad(nP)
        rhosolid = rho_0 * (1 - alpha * (nT * dTemp - 1573))
        deltarho = rhosolid - rhomelt
        yvec = Constant((0.0, 1.0))
        vmelt = nV * w0 - darcy * (gp * p0 / h - deltarho * yvec * g)
        if (count % 100 == 0):
            pfile << nP
            ufile << nV
            tfile << nT
            mufile << mu
            gradpfile << project(grad(nP), Sgradp)
            mufile << project(mu * mu_a, Smu)
            rhofile << project(rhosolid, Srho)
            vmeltfile << project(vmelt, Svel)
        count += 1
        assign(T0, nT)
        assign(v0, nV)
        mu.interpolate(muExp)

    print('Case mu=%g, Tb=%g complete.' % (mu_a, Tb), ' Run time =', clock() - runtimeInit, 's')
Ejemplo n.º 16
0
def _test_linear_solver_sparse(callback_type):
    from dolfin import Function
    from rbnics.backends.dolfin import LinearSolver

    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2 * pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2 * pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2 * pi - 10 * DOLFIN_EPS

    # Define exact solution
    exact_solution_expression = Expression("x[0] + sin(2 * x[0])", element=V.ufl_element())
    exact_solution = project(exact_solution_expression, V)

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    g = Expression("4 * sin(2 * x[0])", element=V.ufl_element())
    a = inner(grad(u), grad(v)) * dx
    f = g * v * dx
    x = inner(u, v) * dx

    # Assemble inner product matrix
    X = assemble(x)

    # Define boundary condition
    bc = [DirichletBC(V, exact_solution_expression, boundary)]

    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":
        def callback(arg):
            return assemble(arg)

    # Define problem wrapper
    class ProblemWrapper(LinearProblemWrapper):
        # Vector function
        def vector_eval(self):
            return callback(f)

        # Matrix function
        def matrix_eval(self):
            return callback(a)

        # Define boundary condition
        def bc_eval(self):
            return bc

        # Define custom monitor to plot the solution
        def monitor(self, solution):
            if matplotlib.get_backend() != "agg":
                plot(solution, title="u")
                plt.show(block=False)
                plt.pause(1)
            else:
                print("||u|| = " + str(solution.vector().norm("l2")))

    # Solve the linear problem
    problem_wrapper = ProblemWrapper()
    solution = Function(V)
    solver = LinearSolver(problem_wrapper, solution)
    solver.solve()

    # Compute the error
    error = Function(V)
    error.vector().add_local(+ solution.vector().get_local())
    error.vector().add_local(- exact_solution.vector().get_local())
    error.vector().apply("")
    error_norm = error.vector().inner(X * error.vector())
    print("Sparse error (" + callback_type + "):", error_norm)
    assert isclose(error_norm, 0., atol=1.e-5)
    return (error_norm, V, a, f, X, exact_solution)
Ejemplo n.º 17
0
def _test_nonlinear_solver_sparse(callback_type):
    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2*pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2*pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2*pi - 10*DOLFIN_EPS
        
    # Define exact solution
    exact_solution_expression = Expression("x[0] + sin(2*x[0])", element=V.ufl_element())
    exact_solution = project(exact_solution_expression, V)

    # Define variational problem
    du = TrialFunction(V)
    v = TestFunction(V)
    u = Function(V)
    g = Expression("4*sin(2*x[0])*(pow(x[0]+sin(2*x[0]), 2)+1)-2*(x[0]+sin(2*x[0]))*pow(2*cos(2*x[0])+1, 2)", element=V.ufl_element())
    r = inner((1+u**2)*grad(u), grad(v))*dx - g*v*dx
    j = derivative(r, u, du)
    x = inner(du, v)*dx

    # Assemble inner product matrix
    X = assemble(x)
    
    # Define initial guess
    def sparse_initial_guess():
        initial_guess_expression = Expression("0.1 + 0.9*x[0]", element=V.ufl_element())
        return project(initial_guess_expression, V)

    # Define boundary condition
    bc = [DirichletBC(V, exact_solution_expression, boundary)]
    
    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":
        def callback(arg):
            return assemble(arg)
    
    # Define problem wrapper
    class SparseFormProblemWrapper(NonlinearProblemWrapper):
        # Residual function
        def residual_eval(self, solution):
            return callback(r)
            
        # Jacobian function
        def jacobian_eval(self, solution):
            return callback(j)
            
        # Define boundary condition
        def bc_eval(self):
            return bc
        
    # Solve the nonlinear problem
    sparse_problem_wrapper = SparseFormProblemWrapper()
    sparse_solution = u
    assign(sparse_solution, sparse_initial_guess())
    sparse_solver = SparseNonlinearSolver(sparse_problem_wrapper, sparse_solution)
    sparse_solver.set_parameters({
        "linear_solver": "mumps",
        "maximum_iterations": 20,
        "report": True
    })
    sparse_solver.solve()

    # Compute the error
    sparse_error = Function(V)
    sparse_error.vector().add_local(+ sparse_solution.vector().get_local())
    sparse_error.vector().add_local(- exact_solution.vector().get_local())
    sparse_error.vector().apply("")
    sparse_error_norm = sparse_error.vector().inner(X*sparse_error.vector())
    print("SparseNonlinearSolver error (" + callback_type + "):", sparse_error_norm)
    assert isclose(sparse_error_norm, 0., atol=1.e-5)
    return (sparse_error_norm, V, u, r, j, X, sparse_initial_guess, exact_solution)