예제 #1
0
    def __init__(self, model, particle, variation, kernel, options, comm):
        self.model = model
        self.particle = particle  # number of particles
        self.variation = variation
        self.kernel = kernel
        self.options = options
        self.comm = comm
        self.rank = comm.Get_rank()
        self.nproc = comm.Get_size()

        self.save_kernel = options["save_kernel"]
        self.type_Hessian = options["type_Hessian"]
        self.ncalls = 0
        self.gls = GlobalLocalSwitch(self.model, self.particle, self.options,
                                     self.comm)

        if not self.options["is_projection"]:
            if self.particle.number_particles_all == 1:
                z_trial = dl.TrialFunction(self.gls.Vh_Local)
                z_test = dl.TestFunction(self.gls.Vh_Local)
                self.Hessian = dl.assemble(z_trial * z_test * dl.dx)
            else:
                z_vec = [None] * particle.number_particles_all
                c_vec = [None] * particle.number_particles_all
                for n in range(particle.number_particles_all):
                    z_trial = dl.TrialFunction(self.gls.Vh_Global.sub(0))
                    z_test = dl.TestFunction(self.gls.Vh_Global.sub(0))
                    z_vec[n] = z_trial
                    c_vec[n] = z_test
                z_vec = dl.as_vector(z_vec)
                c_vec = dl.as_vector(c_vec)
                self.Hessian = dl.assemble(dl.dot(c_vec, z_vec) * dl.dx)
예제 #2
0
def bulk_electrostriction(E, e_r, p, direction, q_b):
    """ calculate the bulk electrostriction force """
    pp = as_matrix(p)  # photoelestic tensor is stored as as numpy array
    if direction == 'backward':
        EE_6vec_r = as_vector([
            E[0] * E[0], E[1] * E[1], -E[2] * E[2], 0.0, 0.0, 2.0 * E[0] * E[1]
        ])
        EE_6vec_i = as_vector(
            [0.0, 0.0, 0.0, 2.0 * E[1] * E[2], 2.0 * E[0] * E[2], 0.0])
        sigma_r = -0.5 * epsilon_0 * e_r**2 * pp * EE_6vec_r
        sigma_i = -0.5 * epsilon_0 * e_r**2 * pp * EE_6vec_i
        f_r = f_elst_r(sigma_r, sigma_i, q_b)
        f_i = f_elst_i(sigma_r, sigma_i, q_b)

    elif direction == 'forward':
        EE_6vec_r = as_vector([
            E[0] * E[0], E[1] * E[1], E[2] * E[2], 0.0, 0.0, 2.0 * E[0] * E[1]
        ])
        # EE_6vec_i, sigma_i, q_b is zero
        sigma_r = -0.5 * epsilon_0 * e_r**2 * pp * EE_6vec_r
        # no need to multiply zeros ...
        f_r = as_vector([
            -Dx(sigma_r[0], 0) - Dx(sigma_r[5], 1),
            -Dx(sigma_r[5], 0) - Dx(sigma_r[1], 1),
            -Dx(sigma_r[4], 0) - Dx(sigma_r[3], 1)
        ])
        f_i = Constant((0.0, 0.0, 0.0), cell=triangle)
        #f_i = as_vector([ - q_b*sigma_r[4],- q_b*sigma_r[3],- q_b*sigma_r[2]])

    else:
        raise ValueError('Specify scattering direction as forward or backward')

    return (f_r, f_i)
예제 #3
0
def test_bdm_identity_transform(gdim):
    N = 5
    k = 2

    # Create mesh and define a divergence free field
    if gdim == 2:
        mesh = dolfin.UnitSquareMesh(N, N)
        field = ['-sin(pi*x[1])*cos(pi*x[0])', 'sin(pi*x[0])*cos(pi*x[1])']
    elif gdim == 3:
        mesh = dolfin.UnitCubeMesh(N, N, N)
        field = [
            '-sin(pi*x[0])*cos(pi*x[1])*sin(pi*x[2])',
            'sin(pi*x[0])*cos(pi*x[1])*sin(pi*x[2])',
            '-cos(pi*x[2])*cos(pi*(x[0]-x[1]))',
        ]

    V = dolfin.FunctionSpace(mesh, 'DG', k)
    u = dolfin.as_vector([dolfin.Function(V) for _ in range(gdim)])
    a = dolfin.as_vector([dolfin.Function(V) for _ in range(gdim)])

    # Make a divergence free field
    for i, cpp in enumerate(field):
        ei = dolfin.Expression(cpp, degree=k)
        u[i].interpolate(ei)
        a[i].assign(u[i])

    # Run the projection into BDM and then assign this to u
    bdm = VelocityBDMProjection(simulation=Simulation(), w=u, use_bcs=False)
    bdm.run()

    # Check the changes made
    for ui, ai in zip(u, a):
        error = dolfin.errornorm(ai, ui, degree_rise=0)
        assert error < 1e-15
    def permeability_tensor(self, K):
        FS = self.geometry.f0.function_space()
        TS = TensorFunctionSpace(self.geometry.mesh, 'P', 1)
        d = self.geometry.dim()
        fibers = Function(FS)
        fibers.vector()[:] = self.geometry.f0.vector().get_local()
        fibers.vector()[:] /= df.norm(self.geometry.f0)
        if self.geometry.s0 is not None:
            # normalize vectors
            sheet = Function(FS)
            sheet.vector()[:] = self.geometry.s0.vector().get_local()
            sheet.vector()[:] /= df.norm(self.geometry.s0)
            if d == 3:
                csheet = Function(FS)
                csheet.vector()[:] = self.geometry.n0.vector().get_local()
                csheet.vector()[:] /= df.norm(self.geometry.n0)
        else:
            return Constant(1)

        from ufl import diag
        factor = 10
        if d == 3:
            ftensor = df.as_matrix(((fibers[0], sheet[0], csheet[0]),
                                    (fibers[1], sheet[1], csheet[1]),
                                    (fibers[2], sheet[2], csheet[2])))
            ktensor = diag(df.as_vector([K, K / factor, K / factor]))
        else:
            ftensor = df.as_matrix(
                ((fibers[0], sheet[0]), (fibers[1], sheet[1])))
            ktensor = diag(df.as_vector([K, K / factor]))

        permeability = df.project(
            df.dot(df.dot(ftensor, ktensor), df.inv(ftensor)), TS)
        return permeability
예제 #5
0
파일: homog2d.py 프로젝트: bd1747/HO_homog
    def Displacement2Epsilon0(self, U):
        """Converti le localisateur en deplacement en champ de predeformation
        a appliquer au probleme auxiliaire suivant"""
        Epsilon0 = []

        for i in range(len(U)):
            Epsilon0 = Epsilon0 + [
                fe.as_vector((
                    U[i][0],
                    fe.interpolate(fe.Constant(0.0), self.X),
                    U[i][1] / fe.sqrt(2),
                ))
            ]
        # zero_ = fe.interpolate(fe.Constant(0.0), self.X)
        # # Possibilité de mettre directement fe.Constant(0.0) ?
        # prestrain_ = (U[i][0], zero_, U[i][1] / fe.sqrt(2))
        # prestrain_ = fe.as_vector(prestrain_)
        # Epsilon0.append(prestrain_)

        for i in range(len(U)):
            Epsilon0 = Epsilon0 + [
                fe.as_vector((
                    fe.interpolate(fe.Constant(0.0), self.X),
                    U[i][1],
                    U[i][0] / fe.sqrt(2),
                ))
            ]
        # zero_ = fe.interpolate(fe.Constant(0.0), self.X)
        # # Possibilité de mettre directement fe.Constant(0.0) ?
        # prestrain_ = (zero_, U[i][1], U[i][0] / fe.sqrt(2))
        # prestrain_ = fe.as_vector(prestrain_)
        # Epsilon0.append(prestrain_)
        return Epsilon0
예제 #6
0
def test_is_zero_simple_vector_expressions():
    mesh = UnitSquareMesh(4, 4)
    V = FunctionSpace(mesh, 'CG', 1)
    v = TestFunction(V)
    u = TrialFunction(V)

    check_is_zero(dot(as_vector([Zero(), u]), as_vector([Zero(), v])), 1)
    check_is_zero(dot(as_vector([Zero(), u]), as_vector([v, Zero()])), 0)
def test_I5y(F_dict, F_str):
    F = F_dict[F_str]

    if "2D" in F_str:
        y = df.as_vector([0, 1])
    else:
        y = df.as_vector([0, 1, 0])

    assert abs(df.assemble(kinematics.I5(F, y) * df.dx) - B**4) < 1e-12
def test_I5x(F_dict, F_str):
    F = F_dict[F_str]

    if "2D" in F_str:
        x = df.as_vector([1, 0])
    else:
        x = df.as_vector([1, 0, 0])

    assert abs(df.assemble(kinematics.I5(F, x) * df.dx) - A**4) < 1e-12
예제 #9
0
    def create_functions(self):
        """
        Create functions to hold solutions
        """
        sim = self.simulation

        # Function spaces
        Vu = sim.data['Vu']
        Vp = sim.data['Vp']
        cd = sim.data['constrained_domain']

        # Create coupled mixed function space and mixed function to hold results
        func_spaces = [Vu] * sim.ndim + [Vp]
        self.subspace_names = ['u%d' % d for d in range(sim.ndim)] + ['p']

        # Create stress tensor space
        P = Vu.ufl_element().degree()
        Vs = dolfin.FunctionSpace(sim.data['mesh'],
                                  'DG',
                                  P,
                                  constrained_domain=cd)
        for i in range(sim.ndim**2):
            stress_name = 'stress_%d' % i
            sim.data[stress_name] = dolfin.Function(Vs)
            func_spaces.append(Vs)
            self.subspace_names.append(stress_name)

        # Create mixed space
        e_mixed = dolfin.MixedElement([fs.ufl_element() for fs in func_spaces])
        Vcoupled = dolfin.FunctionSpace(sim.data['mesh'], e_mixed)
        sim.data['Vcoupled'] = Vcoupled

        # Create function assigner
        Nspace = len(func_spaces)
        self.subspaces = [Vcoupled.sub(i) for i in range(Nspace)]
        sim.data['coupled'] = self.coupled_func = dolfin.Function(Vcoupled)
        self.assigner = dolfin.FunctionAssigner(func_spaces, Vcoupled)

        # Create segregated functions on component and vector form
        u_list, up_list, upp_list, u_conv = [], [], [], []
        for d in range(sim.ndim):
            sim.data['u%d' % d] = u = dolfin.Function(Vu)
            sim.data['up%d' % d] = up = dolfin.Function(Vu)
            sim.data['upp%d' % d] = upp = dolfin.Function(Vu)
            sim.data['u_conv%d' % d] = uc = dolfin.Function(Vu)
            u_list.append(u)
            up_list.append(up)
            upp_list.append(upp)
            u_conv.append(uc)
        sim.data['u'] = dolfin.as_vector(u_list)
        sim.data['up'] = dolfin.as_vector(up_list)
        sim.data['upp'] = dolfin.as_vector(upp_list)
        sim.data['u_conv'] = dolfin.as_vector(u_conv)
        sim.data['p'] = dolfin.Function(Vp)
예제 #10
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)
예제 #11
0
 def fit_primitives(vec, deepcopy=False, indexed=True):
     assert not (deepcopy and indexed)
     N = self.parameters["N"]  # 'self' is visible from here
     if indexed:
         ws = split(vec[0])
         pv = [as_vector(ws[:N - 1]), as_vector(ws[N - 1:])]
         pv += list(split(vec[1]))
     else:
         ws = vec[0].split(deepcopy)
         pv = [as_vector(ws[:N - 1]), as_vector(ws[N - 1:])]
         pv += list(vec[1].split(deepcopy))
     return tuple(pv)
예제 #12
0
def total_flux(Mo, rho_mat, chi):
    """
    :returns: total flux
    :rtype: :py:class:`ufl.core.expr.Expr`
    """
    N = len(rho_mat)
    rho_mat = list(map(Constant, rho_mat))
    rho_diff = as_vector(rho_mat[:-1]) - as_vector((N - 1) * [
        rho_mat[-1],
    ])
    J = -Mo * dot(grad(chi).T, rho_diff)
    return J
def test_I8xy(F_dict, F_str):
    F = F_dict[F_str]

    if "2D" in F_str:
        x = df.as_vector([1, 0])
        y = df.as_vector([0, 1])
    else:
        x = df.as_vector([1, 0, 0])
        y = df.as_vector([0, 1, 0])

    assert (
        abs(df.assemble(kinematics.I8(F, x, y) * df.dx) -
            (A**2 * 0 + 0 * B)) < 1e-12)
예제 #14
0
    def define_coupled_equation(self):
        """
        Setup the coupled Navier-Stokes equation

        This implementation assembles the full LHS and RHS each time they are needed
        """
        Vcoupled = self.simulation.data['Vcoupled']

        # Unpack the coupled trial and test functions
        uc = dolfin.TrialFunction(Vcoupled)
        vc = dolfin.TestFunction(Vcoupled)
        ulist = []
        vlist = []
        ndim = self.simulation.ndim
        for d in range(ndim):
            ulist.append(uc[d])
            vlist.append(vc[d])

        u = dolfin.as_vector(ulist)
        v = dolfin.as_vector(vlist)
        p = uc[ndim]
        q = vc[ndim]

        lm_trial = lm_test = None
        if self.use_lagrange_multiplicator:
            lm_trial = uc[ndim + 1]
            lm_test = vc[ndim + 1]

        assert self.flux_type == UPWIND
        eq = define_dg_equations(
            u,
            v,
            p,
            q,
            lm_trial,
            lm_test,
            self.simulation,
            include_hydrostatic_pressure=self.include_hydrostatic_pressure,
            incompressibility_flux_type=self.incompressibility_flux_type,
            use_grad_q_form=self.use_grad_q_form,
            use_grad_p_form=self.use_grad_p_form,
            use_stress_divergence_form=self.use_stress_divergence_form,
            velocity_continuity_factor_D12=self.velocity_continuity_factor_D12,
            pressure_continuity_factor=self.pressure_continuity_factor,
        )

        a, L = dolfin.system(eq)
        self.form_lhs = a
        self.form_rhs = L
        self.tensor_lhs = None
        self.tensor_rhs = None
    def eps(self, u):
        e = df.sym(df.grad(u))
        dim = self.mesh.geometric_dimension()
        if dim == 1:
            return df.as_vector([e[0, 0]])

        if dim == 2:
            return df.as_vector([e[0, 0], e[1, 1], 2 * e[0, 1]])

        if dim == 3:
            return df.as_vector([
                e[0, 0], e[1, 1], e[2, 2], 2 * e[1, 2], 2 * e[0, 2],
                2 * e[0, 1]
            ])
예제 #16
0
 def fit_primitives(vec, deepcopy=False, indexed=True):
     assert not (deepcopy and indexed)
     N = self.parameters["N"]  # 'self' is visible from here
     if indexed:
         ws = split(vec[0])
         # FIXME: Remove the following hack
         #ws_ch = split(ws[0]) # Not working with older versions of DOLFIN
         ws_ch = tuple([ws[0][i] for i in range(len(ws[0]))])
     else:
         ws = vec[0].split(deepcopy)
         ws_ch = ws[0].split(deepcopy)
     pv = [as_vector(ws_ch[:N - 1]), as_vector(ws_ch[N - 1:])]
     pv += ws[1:]
     return tuple(pv)
예제 #17
0
 def set_function_space(self):
     """set_function_space."""
     self.V = df.VectorFunctionSpace(self.mesh,'P',1,dim=self.number_of_moment)
     #Set test function(s)
     v_list = df.TestFunctions(self.V) 
     #Convert to ufl form
     self.v = df.as_vector(v_list) 
     #set trial function(s)
     if self.problem_type == 'nonlinear':
         u_list = df.Function(self.V) 
     elif self.problem_type == 'linear':
         u_list = df.TrialFunctions(self.V)
     #Convert to ufl form
     self.u = df.as_vector(u_list) 
예제 #18
0
    def updateCoefficients(self):

        # Init coefficient matrix
        x = SpatialCoordinate(self.mesh)[0]

        self.a = as_matrix([[.5 * (x * self.gamma[0] * self.sigmax)**2]])
        self.b = as_vector([x * (self.gamma[0] * (self.mu - self.r) + self.r)])
        self.c = Constant(0.0)

        # Init right-hand side
        self.f = Constant(0.0)
        self.u_ = exp(
            ((self.mu - self.r)**2 / (2 * self.sigmax**2) * self.alpha /
             (1 - self.alpha) + self.r * self.alpha) *
            (self.T[1] - self.t)) * (x**self.alpha) / self.alpha
        self.u_T = (x**self.alpha) / self.alpha

        # Set boundary conditions
        # self.g_t = lambda t : [(Constant(0.0), "near(x[0],0)")]
        self.g = Constant(0.0)
        # self.g_t = lambda t : self.u_t(t)

        self.gamma_star = [
            Constant((self.mu - self.r) / (self.sigmax**2 * (1 - self.alpha)))
        ]

        self.loc = conditional(x > 0.5, conditional(x < 1.5, 1, 0), 0)
예제 #19
0
    def setup(self):
        """
        Create mesh velocity and deformation functions
        """
        sim = self.simulation
        assert self.active is False, 'Trying to setup mesh morphing twice in the same simulation'

        # Store previous cell volumes
        mesh = sim.data['mesh']
        Vcvol = dolfin.FunctionSpace(mesh, 'DG', 0)
        sim.data['cvolp'] = dolfin.Function(Vcvol)

        # The function spaces for mesh velocities and displacements
        Vmesh = dolfin.FunctionSpace(mesh, 'CG', 1)
        Vmesh_vec = dolfin.VectorFunctionSpace(mesh, 'CG', 1)
        sim.data['Vmesh'] = Vmesh

        # Create mesh velocity functions
        u_mesh = []
        for d in range(sim.ndim):
            umi = dolfin.Function(Vmesh)
            sim.data['u_mesh%d' % d] = umi
            u_mesh.append(umi)
        u_mesh = dolfin.as_vector(u_mesh)
        sim.data['u_mesh'] = u_mesh

        # Create mesh displacement vector function
        self.displacement = dolfin.Function(Vmesh_vec)
        self.assigners = [
            dolfin.FunctionAssigner(Vmesh_vec.sub(d), Vmesh)
            for d in range(sim.ndim)
        ]
        self.active = True
예제 #20
0
	def sigma(self, uu):
		eps = self.RR*self.epsilon(uu)*self.RR.T
		ss = self.DD*dolfin.as_vector([eps[0, 0], eps[1, 1], eps[2, 2]])
		ss_01 = 2*self.G_01*eps[0, 1]
		ss_02 = 2*self.G_02*eps[0, 2]
		ss_12 = 2*self.G_12*eps[1, 2]
		return self.RR.T*dolfin.as_matrix([[ss[0], ss_01, ss_02], [ss_01, ss[1], ss_12], [ss_02, ss_12, ss[2]]])*self.RR
예제 #21
0
def main():
    args = get_settings()

    interp = itp.Interpolation(args.mesh_file_in,
                               args.u_file_in,
                               p_filename_in=args.p_file_in)
    interp.update(args.step)

    u_1 = interp.u
    p_1 = interp.p

    mesh_2 = import_mesh(args.other_mesh_in)
    S_2 = df.FunctionSpace(mesh_2, "CG", 1)

    u_ = dict()
    for key, val in u_1.iteritems():
        u_[key] = ft.interpolate_nonmatching_mesh(val, S_2)
    u__ = df.as_vector([u_[key] for key in u_.keys()])
    u = AssignedVectorFunction(u__)
    u()
    p = ft.interpolate_nonmatching_mesh(p_1, S_2)

    xdmff_u = df.XDMFFile(mesh_2.mpi_comm(), args.initfile_out + "_u.xdmf")
    xdmff_u.parameters["rewrite_function_mesh"] = False
    xdmff_u.parameters["flush_output"] = True
    xdmff_u.write(u, 0.)
    xdmff_p = df.XDMFFile(mesh_2.mpi_comm(), args.initfile_out + "_p.xdmf")
    xdmff_p.parameters["rewrite_function_mesh"] = False
    xdmff_p.parameters["flush_output"] = True
    xdmff_p.write(p, 0.)
예제 #22
0
def steadystate(geo, phys, F, u0):
    F = dolfin.as_vector([F])
    bc = dict(upperb=dolfin.Constant(c0), lowerb=dolfin.Constant(c0))
    pde = ConvectionDiffusionSteady(geo, phys, F=F, u0=u0, bc=bc)
    pde.add_functionals([partial(current, F=F), selectivity])
    pde.single_solve()
    return pde
예제 #23
0
def get_collected_velocity_bcs(simulation, name):
    """
    When mixed Dirichlet/Neumann BCs on the same facet (for different velocity
    components) is not supported it can be convenient to get all BCs collected
    by boundary region. This function returns a dictionary for Dirichlet or
    Neumann BCs where the "ds" meassure is the key and a vector of boundary
    values for each velocity component is the value

    The "name" parameter must be 'dirichlet_bcs' or 'neumann_bcs'
    """
    # Collect BCs
    bc_dict = {}
    for d in range(simulation.ndim):
        for bc in simulation.data[name].get('u%d' % d, []):
            if d == 0:
                bc_dict[bc.ds()] = [bc.func()]
            else:
                bc_dict[bc.ds()].append(bc.func())

    # Verify that all components are present and convert to vector
    for ds, u_bc in bc_dict.items():
        assert len(u_bc) == simulation.ndim
        bc_dict[ds] = dolfin.as_vector(u_bc)

    simulation.log.debug('    Found %d %s boundary regions' %
                         (len(bc_dict), name))
    return bc_dict
예제 #24
0
def force_diff(**params):
    # for random walk (with pointsize force field, no current)
    setup = Setup(create_geo=False, **params)
    # DEBUG
    #print "active params", setup.active_params
    #print "inactive params", setup.inactive_params
    F = force_pointsize(**params)
    if setup.phys.posDTarget:
        D = diffusivity_simple(**params)
        name = "diffusivity_div_simple"
        if not fields.exists(name, **params):
            V = D.function_space()
            divD = dolfin.project(
                dolfin.as_vector([dolfin.grad(D[0])[0],
                                  dolfin.grad(D[1])[1]]), V)
            fields.save_functions(name, setup.active_params, divD=divD)
            fields.update()
        divD, = fields.get_functions(name, "divD", **params)
    else:
        D0 = setup.phys.DTargetBulk
        D0a = np.array([D0, D0, D0])
        divDa = np.array([0., 0., 0.])
        D = lambda x: D0a
        divD = lambda x: divDa
    return F, D, divD
예제 #25
0
def df_wrap(val, description, degree, sim):
    """
    Wrap numbers as dolfin.Constant and strings as
    dolfin.Expression C++ code. Lists must be ndim
    long and contain either numbers or strings
    """
    if isinstance(val, (int, float)):
        # A real number
        return dolfin.Constant(val)
    elif isinstance(val, str):
        # A C++ code string
        return OcellarisCppExpression(sim, val, description, degree)
    elif isinstance(val, (list, tuple)):
        D = sim.ndim
        L = len(val)
        if L != D:
            raise OcellarisError(
                'Invalid length of list',
                'BC list in "%r" must be length %d, is %d.' %
                (description, D, L),
            )

        if all(isinstance(v, str) for v in val):
            # A list of C++ code strings
            return OcellarisCppExpression(sim, val, description, degree)
        else:
            # A mix of constants and (possibly) C++ strings
            val = [
                df_wrap(v, description + ' item %d' % i, degree, sim)
                for i, v in enumerate(val)
            ]
            return dolfin.as_vector(val)
예제 #26
0
def Wactive_orthotropic(Ta, C, f0, s0, n0):
    """Return active strain energy for an orthotropic
    active stress

    
    Arguments
    ---------
    Ta : dolfin.Function or dolfin.Constant
        A vector function representng the mangnitude of the
        active stress in the reference configuration (firt Pioala).
        Ta = (Ta_f0, Ta_s0, Ta_n0)
    C : ufl.Form
        The right Cauchy-Green deformation tensor
    f0 : dolfin.Function
        A vector function representng the direction of the
        first component
    s0 : dolfin.Function
        A vector function representng the direction of the
        second component
    n0 : dolfin.Function
        A vector function representng the direction of the
        third component
    """
    I4f = dolfin.inner(C * f0, f0)
    I4s = dolfin.inner(C * s0, s0)
    I4n = dolfin.inner(C * n0, n0)

    I4 = dolfin.as_vector([I4f - 1, I4s - 1, I4n - 1])
    return dolfin.Constant(0.5) * dolfin.inner(Ta, I4)
예제 #27
0
 def source_term(self):
     if self.moment_order == 3:
         F_rhs = [0.0] * self.number_of_moments
         F_rhs[0] = df.Expression(
             "2.0 - 1.0 * pow(sqrt(pow(x[0],2)+pow(x[1],2)),2)", degree=2)
     elif self.moment_order == 'nono6':
         F_rhs = [0.0] * NoV
     elif self.moment_order == 'nono13':
         F_rhs = [0.0] * NoV
         R = Expression("sqrt(pow(x[0],2)+pow(x[1],2))", degree=2)
         F_rhs[0] = Expression(
             "1.0 * (1.0 - (5.0*pow(R,2))/(18.0*pow(kn,2))) * cos(phi)",
             R=R,
             kn=Kn,
             phi=phi,
             degree=2)
         F_rhs[3] = Expression(
             "1.0 * (1.0 - (5.0*pow(R,2))/(18.0*pow(kn,2))) * cos(phi)",
             R=R,
             kn=Kn,
             phi=phi,
             degree=2)
         F_rhs[0] = Expression(
             "2.0 - 1.0 * pow(sqrt(pow(x[0],2)+pow(x[1],2)),2)", degree=2)
         F_rhs[3] = Expression(
             "2.0 - 1.0 * pow(sqrt(pow(x[0],2)+pow(x[1],2)),2)", degree=2)
     if self.moment_order == 3:
         F_rhs = df.as_vector(F_rhs)  # converting to ufl vector
         local_source_term = df.inner(self.v, F_rhs) * df.dx
     return local_source_term
예제 #28
0
    def updateCoefficients(self):

        # Init coefficient matrix
        P, Inv = SpatialCoordinate(self.mesh)

        self.a = as_matrix([[+.5 * (P * self.sigma)**2, 0], [0, 0]])

        # def K(t): return self.K0 + beta_SA * sin(4*pi*(t - t_SA))
        def K(t):
            return self.K0

        self.b = as_vector([
            +self.alpha * (K(self.t) - P),
            -(self.gamma[0] + self.cost(self.gamma[0]))
        ])

        self.c = Constant(-self.r)

        # Init right-hand side
        self.f = -(self.gamma[0] - self.cost(self.gamma[0])) * P

        self.u_T = -2 * P * ufl.Max(1000 - Inv, 0)
        # self.u_T = Constant(0.0)

        # Set boundary conditions
        # self.g_t = lambda t : [(Constant(0.0), "near(x[0],0)")]
        self.g = self.u_T
예제 #29
0
    def get_variable(self, name):
        zero = dolfin.Constant(0.0)
        if name == 'u':
            # Assume that the waves are traveling in x-direction
            if self.simulation.ndim == 2:
                return dolfin.as_vector([self.get_variable('uhoriz'), zero])
            else:
                return dolfin.as_vector(
                    [self.get_variable('uhoriz'), zero, zero])
        elif name == 'uvert':
            return zero

        if name not in self._functions:
            expr = self._get_expression(name)
            self._functions[name] = dolfin.interpolate(expr, self.V)
        return self._functions[name]
예제 #30
0
    def __init__(self, simulation, u_conv):
        """
        Given a velocity in DG, e.g DG2, produce a velocity in DGT0,
        i.e. a constant on each facet
        """
        V = u_conv[0].function_space()
        V_dgt0 = dolfin.FunctionSpace(V.mesh(), 'DGT', 0)
        u = dolfin.TrialFunction(V_dgt0)
        v = dolfin.TestFunction(V_dgt0)

        ndim = simulation.ndim
        w = u_conv
        w_new = dolfin.as_vector(
            [dolfin.Function(V_dgt0) for _ in range(ndim)])

        dot, avg, dS, ds = dolfin.dot, dolfin.avg, dolfin.dS, dolfin.ds
        a = dot(avg(u), avg(v)) * dS + dot(u, v) * ds

        L = []
        for d in range(ndim):
            L.append(avg(w[d]) * avg(v) * dS + w[d] * v * ds)

        self.lhs = [dolfin.Form(Li) for Li in L]
        self.A = dolfin.assemble(a)
        self.solver = dolfin.PETScKrylovSolver('cg')
        self.velocity = simulation.data['u_conv_dgt0'] = w_new
예제 #31
0
    def __init__(
            self, WPQ,
            kappa, rho, rho_const, mu, cp,
            g, extra_force,
            heat_source,
            u_bcs, p_bcs,
            theta_dirichlet_bcs=None,
            theta_neumann_bcs=None,
            theta_robin_bcs=None,
            my_dx=dx,
            my_ds=ds
            ):
        super(StokesHeat, self).__init__()

        theta_dirichlet_bcs = theta_dirichlet_bcs or {}
        theta_neumann_bcs = theta_neumann_bcs or {}
        theta_robin_bcs = theta_robin_bcs or {}

        # Translate the Dirichlet boundary conditions into the product space.
        self.dirichlet_bcs = helpers.dbcs_to_productspace(
            WPQ,
            [u_bcs, p_bcs, theta_dirichlet_bcs]
            )

        self.uptheta = Function(WPQ)
        u, p, theta = split(self.uptheta)
        v, q, zeta = TestFunctions(WPQ)

        mesh = WPQ.mesh()
        r = SpatialCoordinate(mesh)[0]

        # Right-hand side for momentum equation.
        f = rho(theta) * g  # coupling
        if extra_force is not None:
            f += as_vector((extra_force[0], extra_force[1], 0.0))
        self.stokes_F = stokes.F(
            u, p, v, q, f, r, mu, my_dx
            )

        self.heat_F = heat.F(
                theta, zeta,
                kappa=kappa, rho=rho_const, cp=cp,
                convection=u,  # coupling
                source=heat_source,
                r=r,
                neumann_bcs=theta_neumann_bcs,
                robin_bcs=theta_robin_bcs,
                my_dx=my_dx,
                my_ds=my_ds
                )

        self.F0 = self.stokes_F + self.heat_F
        self.jacobian = derivative(self.F0, self.uptheta)
        return
from src.model import Model
from pylab     import zeros, linspace, sqrt
from dolfin    import project, Function, File, as_vector

nx = 40
ny = 40
nz = 7

model = Model()
model.generate_uniform_mesh(nx,ny,nz,0,1,0,1,deform=False,generate_pbcs=True)

Q = model.Q
U_obs = project(dolfin.as_vector([Function(Q),Function(Q)]))
b_obs = Function(Q)
U_opt = project(as_vector([Function(Q),Function(Q),Function(Q)]))
b_opt = Function(Q)

rcParams['text.usetex']=True
rcParams['font.size'] = 12
rcParams['font.family'] = 'serif'

for L in [10000]:
    
    File('./results/U_obs.xml') >> U_obs
    File('./results/U_opt.xml') >> U_opt
    File('./results/beta2_obs.xml') >> b_obs
    File('./results/beta2_opt.xml') >> b_opt

    U_b = zeros(100)
    U_p = zeros(100)
예제 #33
0
 def grad(f):
   g = dolfin.grad(f)
   if len(g.shape()) == 0:
     return dolfin.as_vector([g])
   else:
     return g
예제 #34
0
def solve_fixed_point(
        mesh,
        W_element, P_element, Q_element,
        u0, p0, theta0,
        kappa, rho, mu, cp,
        g, extra_force,
        heat_source,
        u_bcs, p_bcs,
        theta_dirichlet_bcs,
        theta_neumann_bcs,
        my_dx, my_ds,
        max_iter,
        tol
        ):
    # Solve the coupled heat-Stokes equation approximately. Do this
    # iteratively by solving the heat equation, then solving Stokes with the
    # updated heat, the heat equation with the updated velocity and so forth
    # until the change is 'small'.
    WP = FunctionSpace(mesh, MixedElement([W_element, P_element]))
    Q = FunctionSpace(mesh, Q_element)
    # Initialize functions.
    up0 = Function(WP)
    u0, p0 = up0.split()

    theta1 = Function(Q)
    for _ in range(max_iter):
        heat_problem = heat.Heat(
            Q,
            kappa=kappa,
            rho=rho(theta0),
            cp=cp,
            convection=u0,
            source=heat_source,
            dirichlet_bcs=theta_dirichlet_bcs,
            neumann_bcs=theta_neumann_bcs,
            my_dx=my_dx,
            my_ds=my_ds
            )

        theta1.assign(heat_problem.solve_stationary())

        # Solve problem for velocity, pressure.
        f = rho(theta0) * g  # coupling
        if extra_force:
            f += as_vector((extra_force[0], extra_force[1], 0.0))
        # up1 = up0.copy()
        stokes.stokes_solve(
            up0,
            mu,
            u_bcs, p_bcs,
            f,
            my_dx=my_dx,
            tol=1.0e-10,
            verbose=False,
            maxiter=1000
            )

        # from dolfin import plot
        # plot(u0)
        # plot(theta0)

        theta_diff = errornorm(theta0, theta1)
        info('||theta - theta0|| = {:e}'.format(theta_diff))
        # info('||u - u0||         = {:e}'.format(u_diff))
        # info('||p - p0||         = {:e}'.format(p_diff))
        # diff = theta_diff + u_diff + p_diff
        diff = theta_diff
        info('sum = {:e}'.format(diff))

        # # Show the iterates.
        # plot(theta0, title='theta0')
        # plot(u0, title='u0')
        # interactive()
        # #exit()
        if diff < tol:
            break

        theta0.assign(theta1)

    # Create a *deep* copy of u0, p0, to be able to deal with them as
    # actually separate entities.
    u0, p0 = up0.split(deepcopy=True)
    return u0, p0, theta0
예제 #35
0
파일: test_24.py 프로젝트: MiroK/fenics-qa
space_S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3)

# Create two scalar functions and a vector function
# from the previously defined spaces
f1 = df.interpolate(df.Expression("1"), space_S1)
f2 = df.Function(space_S1)
f3 = df.Function(space_S3)

# If we want a scalar function with twice
# the values of f1 (THIS WORKS)
vec = df.assemble(df.dot(2 * f1, df.TestFunction(space_S1)) * df.dP)
f2.vector().axpy(1, vec)

# Now we want to modify the vector function space
# to get the vector (2, 1, 1) in every vertex
vec = df.assemble(df.dot(df.as_vector((2 * f1, f1, f1)), df.TestFunction(space_S3)) * df.dP)
f3.vector().axpy(1, vec)

# Scalar space assign
g2 = df.Function(space_S1)
g2.assign(df.FunctionAXPY(f1, 2.))

g2.vector().axpy(-1, f2.vector())
assert df.near(g2.vector().norm('l2'), 0)

# Assigner for components of the vector space
S3_assigners = [df.FunctionAssigner(space_S3.sub(i), space_S1) for i in range(space_S3.num_sub_spaces())]

g3 = df.Function(space_S3)
# Assign to components
comps = [f2, f1, f1]
import src.model

import pylab 
import dolfin
import pickle
from pylab import *

nx = 20
ny = 20
nz = 6

model = src.model.Model()
model.generate_uniform_mesh(nx,ny,nz,0,1,0,1,deform=False,generate_pbcs=True)

Q = model.Q
U_opt = dolfin.project(dolfin.as_vector([dolfin.Function(Q),dolfin.Function(Q),dolfin.Function(Q)]))
b_opt = dolfin.Function(Q)
n = len(b_opt.compute_vertex_values())

rcParams['text.usetex']=True
rcParams['font.size'] = 12
rcParams['font.family'] = 'serif'

Us = zeros((50,n))
betas = zeros((50,n))

fig,axs = subplots(2,1,sharex=True)
fig.set_size_inches(8,4)

bed_indices = model.mesh.coordinates()[:,2]==0
surface_indices = model.mesh.coordinates()[:,2]==1
예제 #37
0
def compute_pressure(
    P,
    p0,
    mu,
    ui,
    u,
    my_dx,
    p_bcs=None,
    rotational_form=False,
    tol=1.0e-10,
    verbose=True,
):
    """Solve the pressure Poisson equation

    .. math::

        \\begin{align}
          -\\frac{1}{r} \\div(r \\nabla (p_1-p_0)) =
              -\\frac{1}{r} \\div(r u),\\\\
          \\text{(with boundary conditions)},
        \\end{align}

    for :math:`\\nabla p = u`.

    The pressure correction is based on the update formula

    .. math::
        \\frac{\\rho}{dt} (u_{n+1}-u^*)
            + \\begin{pmatrix}
                \\text{d}\\phi/\\text{d}r\\\\
                \\text{d}\\phi/\\text{d}z\\\\
                \\frac{1}{r} \\text{d}\\phi/\\text{d}\\theta
              \\end{pmatrix}
                = 0

    with :math:`\\phi = p_{n+1} - p^*` and

    .. math::

         \\frac{1}{r} \\frac{\\text{d}}{\\text{d}r} (r u_r^{(n+1)})
       + \\frac{\\text{d}}{\\text{d}z}  (u_z^{(n+1)})
       + \\frac{1}{r} \\frac{\\text{d}}{\\text{d}\\theta} (u_{\\theta}^{(n+1)})
           = 0

    With the assumption that u does not change in the direction
    :math:`\\theta`, one derives

    .. math::

       - \\frac{1}{r}   \\div(r \\nabla \\phi) =
           \\frac{1}{r} \\frac{\\rho}{dt}   \\div(r (u_{n+1} - u^*))\\\\
       - \\frac{1}{r} \\langle n, r \\nabla \\phi\\rangle =
           \\frac{1}{r} \\frac{\\rho}{dt} \\langle n, r (u_{n+1} - u^*)\\rangle

    In its weak form, this is

    .. math::

      \\int r \\langle\\nabla\\phi, \\nabla q\\rangle \\,2 \\pi =
           - \\frac{\\rho}{dt} \\int \\div(r u^*) q \\, 2 \\pi
           - \\frac{\\rho}{dt} \\int_{\\Gamma}
                 \\langle n,  r (u_{n+1}-u^*)\\rangle q \\, 2\\pi.

    (The terms :math:`1/r` cancel with the volume elements :math:`2\\pi r`.)
    If the Dirichlet boundary conditions are applied to both :math:`u^*` and
    :math:`u_n` (the latter in the velocity correction step), the boundary
    integral vanishes.

    If no Dirichlet conditions are given (which is the default case), the
    system has no unique solution; one eigenvalue is 0. This however, does not
    hurt CG convergence if the system is consistent, cf. :cite:`vdV03`. And
    indeed it is consistent if and only if

    .. math::
        \\int_\\Gamma r \\langle n, u\\rangle = 0.

    This condition makes clear that for incompressible Navier-Stokes, one
    either needs to make sure that inflow and outflow always add up to 0, or
    one has to specify pressure boundary conditions.

    Note that, when using a multigrid preconditioner as is done here, the
    coarse solver must be chosen such that it preserves the nullspace of the
    problem.
    """
    W = ui.function_space()
    r = SpatialCoordinate(W.mesh())[0]

    p = TrialFunction(P)
    q = TestFunction(P)
    a2 = dot(r * grad(p), grad(q)) * 2 * pi * my_dx
    # The boundary conditions
    #     n.(p1-p0) = 0
    # are implicitly included.
    #
    # L2 = -div(r*u) * q * 2*pi*my_dx
    div_u = 1 / r * (r * u[0]).dx(0) + u[1].dx(1)
    L2 = -div_u * q * 2 * pi * r * my_dx
    if p0:
        L2 += r * dot(grad(p0), grad(q)) * 2 * pi * my_dx

    # In the Cartesian variant of the rotational form, one makes use of the
    # fact that
    #
    #     curl(curl(u)) = grad(div(u)) - div(grad(u)).
    #
    # The same equation holds true in cylindrical form. Hence, to get the
    # rotational form of the splitting scheme, we need to
    #
    # rotational form
    if rotational_form:
        # If there is no dependence of the angular coordinate, what is
        # div(grad(div(u))) in Cartesian coordinates becomes
        #
        #     1/r div(r * grad(1/r div(r*u)))
        #
        # in cylindrical coordinates (div and grad are in cylindrical
        # coordinates). Unfortunately, we cannot write it down that
        # compactly since u_phi is in the game.
        # When using P2 elements, this value will be 0 anyways.
        div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1)
        grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1)))
        L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2 * pi * my_dx
        # div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \
        #     + (grad_div_ui[1]).dx(1)
        # L2 += mu * div_grad_div_ui * q * 2*pi*r*dx
        # n = FacetNormal(Q.mesh())
        # L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \
        #     * q * 2*pi*r*ds

    p1 = Function(P)
    if p_bcs:
        solve(
            a2 == L2,
            p1,
            bcs=p_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,
                },
            },
        )
    else:
        # If we're dealing with a pure Neumann problem here (which is the
        # default case), this doesn't hurt CG if the system is consistent,
        # cf. :cite:`vdV03`. And indeed it is consistent if and only if
        #
        #   \int_\Gamma r n.u = 0.
        #
        # This makes clear that for incompressible Navier-Stokes, one
        # either needs to make sure that inflow and outflow always add up
        # to 0, or one has to specify pressure boundary conditions.
        #
        # If the right-hand side is very small, round-off errors may impair
        # the consistency of the system. Make sure the system we are
        # solving remains consistent.
        A = assemble(a2)
        b = assemble(L2)
        # Assert that the system is indeed consistent.
        e = Function(P)
        e.interpolate(Constant(1.0))
        evec = e.vector()
        evec /= norm(evec)
        alpha = b.inner(evec)
        normB = norm(b)
        # Assume that in every component of the vector, a round-off error
        # of the magnitude DOLFIN_EPS is present. This leads to the
        # criterion
        #    |<b,e>| / (||b||*||e||) < DOLFIN_EPS
        # as a check whether to consider the system consistent up to
        # round-off error.
        #
        # TODO think about condition here
        # if abs(alpha) > normB * DOLFIN_EPS:
        if abs(alpha) > normB * 1.0e-12:
            # divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1)
            adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * my_dx)
            info("\\int 1/r * div(r*u) * 2*pi*r  =  {:e}".format(adivu))
            n = FacetNormal(P.mesh())
            boundary_integral = assemble((n[0] * u[0] + n[1] * u[1]) * 2 * pi * r * ds)
            info("\\int_Gamma n.u * 2*pi*r = {:e}".format(boundary_integral))
            message = (
                "System not consistent! "
                "<b,e> = {:g}, ||b|| = {:g}, <b,e>/||b|| = {:e}.".format(
                    alpha, normB, alpha / normB
                )
            )
            info(message)
            # # Plot the stuff, and project it to a finer mesh with linear
            # # elements for the purpose.
            # plot(divu, title='div(u_tentative)')
            # # Vp = FunctionSpace(Q.mesh(), 'CG', 2)
            # # Wp = MixedFunctionSpace([Vp, Vp])
            # # up = project(u, Wp)
            # fine_mesh = Q.mesh()
            # for k in range(1):
            #     fine_mesh = refine(fine_mesh)
            # V = FunctionSpace(fine_mesh, 'CG', 1)
            # W = V * V
            # # uplot = Function(W)
            # # uplot.interpolate(u)
            # uplot = project(u, W)
            # plot(uplot[0], title='u_tentative[0]')
            # plot(uplot[1], title='u_tentative[1]')
            # # plot(u, title='u_tentative')
            # interactive()
            # exit()
            raise RuntimeError(message)
        # Project out the roundoff error.
        b -= alpha * evec

        #
        # In principle, the ILU preconditioner isn't advised here since it
        # might destroy the semidefiniteness needed for CG.
        #
        # The system is consistent, but the matrix has an eigenvalue 0.
        # This does not harm the convergence of CG, but when
        # preconditioning one has to make sure that the preconditioner
        # preserves the kernel. ILU might destroy this (and the
        # semidefiniteness). With AMG, the coarse grid solves cannot be LU
        # then, so try Jacobi here.
        # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html>
        #
        prec = PETScPreconditioner("hypre_amg")
        from dolfin import PETScOptions

        PETScOptions.set("pc_hypre_boomeramg_relax_type_coarse", "jacobi")
        solver = PETScKrylovSolver("cg", prec)
        solver.parameters["absolute_tolerance"] = 0.0
        solver.parameters["relative_tolerance"] = tol
        solver.parameters["maximum_iterations"] = 100
        solver.parameters["monitor_convergence"] = verbose
        # Create solver and solve system
        A_petsc = as_backend_type(A)
        b_petsc = as_backend_type(b)
        p1_petsc = as_backend_type(p1.vector())
        solver.set_operator(A_petsc)
        solver.solve(p1_petsc, b_petsc)
    return p1
예제 #38
0
 def FacetNormal(mesh):
   nm = dolfin.FacetNormal(mesh)
   if len(nm.shape()) == 0:
     return dolfin.as_vector([nm])
   else:
     return nm
예제 #39
0
  def initialize_eqs(self):
    """
    """


    # initial height
    h = self.initial_h(120+0.0003*self.L, self.c, 0.4*self.L, self.L)

    self.h_old = d.project(h, self.V)
    # initial guess of velocity
    u = d.project(d.Expression('x[0]/L', L=1000*self.L), self.V)     
    self.h_u_dhdx = d.project(d.as_vector((h,u,h.dx(0))), self.V3)
    self.h,self.u,self.dhdx = d.split(self.h_u_dhdx)

    # initialize floating conditional
    class FloatBoolean(Expression):
      """
      creates boolean function over length of ice, true when ice is floating.
      """
      def eval(s,value,x):
        if self.h_u_dhdx(x[0])[0] <= -h_b(x[0])*(self.rho_w/self.rho-1):
          value[0] = 1
        else:
          value[0] = 0

    # floating conditional
    fc = self.smooth_step_conditional(FloatBoolean())

    # A useful expression for the effective pressure term
    reduction = fc*(self.rho_w/self.rho)*self.h_b
    
    # H (ice thickness) conditional on floating
    if self.floating:
      # archimedes principle, H (ice thickness)
      self.H = fc * (h/(1-self.rho/self.rho_w)) + (1-fc) * (self.h-self.h_b) 
    else:
      # ice thickness = surface elevation - bed elevation
      self.H = self.h - self.h_b  

    H = self.H
    h = self.h
    W = self.W
    u = self.u
    n = self.n

    # basal drag
    self.basal_drag = self.mu*self.A_s*(self.H+reduction)**self.p*u**(1/n)

    if self.floating:
      self.basal_drag = (1-fc) * self.basal_drag

    # define variational problem
    testFunction  = TestFunction(self.V3)
    trialFunction = TrialFunction(self.V3)
    phi1, phi2, phi3 = split(testFunction)

    self.driving_stress = self.rho*self.g*H*self.dhdx
    self.lateral_drag = (self.B_s*H/W)*((n+2)*u/(2*W))**(1/n)
    
    force_balance = (self.driving_stress+self.basal_drag+self.lateral_drag)*phi2 
    
    ####????####################################################################
    mass_conservation = ((h-self.h_old)/self.dt + (H*u*W).dx(0)/W - M)*phi1
    ####????####################################################################
    
    F = (mass_conservation + force_balance)*d.dx
    
    ###????#####################################################################
    invariant_squared = ((n+2.)/(n+1.)*u/W)**2+u.dx(0)**2
    self.longitudinal_stress = \
            2*self.B_s*H*invariant_squared**((1-n)/(2*n))*u.dx(0)
    
    F += self.longitudinal_stress * phi2.dx(0) * d.dx
    F -= self.longitudinal_stress * phi2 * self.ds(self.TERMINUS)
    F += (self.h.dx(0)-self.dhdx)*phi3*d.dx
    ###????#####################################################################


    J = derivative(F, self.h_u_dhdx, trialFunction)
    problem =\
    NonlinearVariationalProblem(F, self.h_u_dhdx, self.boundary_conditions, J)
    self.solver  = NonlinearVariationalSolver(problem)
nz = 10

m = UnitCubeMesh(nx,ny,nz)
Q = FunctionSpace(m,"CG",1)
u = Function(Q)
v = Function(Q)
w = Function(Q)
S = Function(Q)

for L in [5000,10000,20000,40000,80000,160000]:

    File('./results_stokes/'+str(L)+'/u.xml') >> u
    File('./results_stokes/'+str(L)+'/v.xml') >> v
    File('./results_stokes/'+str(L)+'/w.xml') >> w

    U = zeros(100)
    profile = linspace(0,1,100)

    for ii,x in enumerate(profile):
        uu = u(x,0.25,0.99999)
        vv = v(x,0.25,0.99999)
        ww = w(x,0.25,0.99999)
        U[ii] = sqrt(uu**2 + vv**2)

    #plot(profile,U)
    #data = zip(profile,U)
    #dump(data,open("djb1a{0:03d}.p".format(L/1000),'w'))
    U = project(as_vector([u,v,w]))
    File('./results_stokes/'+str(L)+'/U.pvd') << U

예제 #41
0
def _compute_boussinesq(
    problem, u0, p0, theta0, lorentz, joule, target_time=0.1, show=False
):
    # Define a facet measure on the boundaries. See discussion on
    # <https://bitbucket.org/fenics-project/dolfin/issue/249/facet-specification-doesnt-work-on-ds>.
    ds_workpiece = Measure("ds", subdomain_data=problem.wp_boundaries)

    submesh_workpiece = problem.W.mesh()

    # Start time, time step.
    t = 0.0
    dt = 1.0e-3
    dt_max = 1.0e-1

    # Standard gravity, <https://en.wikipedia.org/wiki/Standard_gravity>.
    grav = 9.80665
    assert problem.W.num_sub_spaces() == 3
    g = Constant((0.0, -grav, 0.0))

    # Compute a few mesh characteristics.
    wpi_area = assemble(1.0 * dx(submesh_workpiece))
    # mesh.hmax() is a local function; get the global hmax.
    hmax_workpiece = MPI.max(submesh_workpiece.mpi_comm(), submesh_workpiece.hmax())

    # Take the maximum length in x-direction as characteristic length of the
    # domain.
    coords = submesh_workpiece.coordinates()
    char_length = max(coords[:, 0]) - min(coords[:, 0])

    # Prepare some parameters for the Navier-Stokes simulation in the workpiece
    m = problem.subdomain_materials[problem.wpi]
    k_wpi = m.thermal_conductivity
    cp_wpi = m.specific_heat_capacity
    rho_wpi = m.density
    mu_wpi = m.dynamic_viscosity

    theta_average = average(theta0)

    # show_total_force = True
    # if show_total_force:
    #     f = rho_wpi(theta0) * g
    #     if lorentz:
    #         f += as_vector((lorentz[0], lorentz[1], 0.0))
    #     tri = plot(f, mesh=submesh_workpiece, title='Total external force')
    #     plt.colorbar(tri)
    #     plt.show()

    with XDMFFile(submesh_workpiece.mpi_comm(), "all.xdmf") as outfile:
        outfile.parameters["flush_output"] = True
        outfile.parameters["rewrite_function_mesh"] = False

        _store(outfile, u0, p0, theta0, t)
        if show:
            _plot(p0, theta0)
            plt.show()

        successful_steps = 0
        failed_steps = 0
        while t < target_time + DOLFIN_EPS:
            info(
                "Successful steps: {}    (failed: {}, total: {})".format(
                    successful_steps, failed_steps, successful_steps + failed_steps
                )
            )
            with Message("Time step {:e} -> {:e}...".format(t, t + dt)):
                # Do one heat time step.
                with Message("Computing heat..."):
                    # Redefine the heat problem with the new u0.
                    heat_problem = cyl_heat.Heat(
                        problem.Q,
                        kappa=k_wpi,
                        rho=rho_wpi(theta_average),
                        cp=cp_wpi,
                        convection=u0,
                        source=joule,
                        dirichlet_bcs=problem.theta_bcs_d,
                        neumann_bcs=problem.theta_bcs_n,
                        my_dx=dx(submesh_workpiece),
                        my_ds=ds_workpiece,
                    )

                    # For time-stepping in buoyancy-driven flows, see
                    #
                    # Numerical solution of buoyancy-driven flows;
                    # Einar Rossebø Christensen;
                    # Master's thesis;
                    # <http://www.diva-portal.org/smash/get/diva2:348831/FULLTEXT01.pdf>.
                    #
                    # Similar to the present approach, one first solves for
                    # velocity and pressure, then for temperature.
                    #
                    heat_stepper = parabolic.ImplicitEuler(heat_problem)

                    ns_stepper = cyl_ns.IPCS(time_step_method="backward euler")
                    theta1 = heat_stepper.step(theta0, t, dt)

                theta0_average = average(theta0)
                try:
                    # Do one Navier-Stokes time step.
                    with Message("Computing flux and pressure..."):
                        # Include proper temperature-dependence here to account
                        # for the Boussinesq effect.
                        f0 = rho_wpi(theta0) * g
                        f1 = rho_wpi(theta1) * g
                        if lorentz is not None:
                            f = as_vector((lorentz[0], lorentz[1], 0.0))
                            f0 += f
                            f1 += f
                        u1, p1 = ns_stepper.step(
                            Constant(dt),
                            {0: u0},
                            p0,
                            problem.W,
                            problem.P,
                            problem.u_bcs,
                            problem.p_bcs,
                            # Make constant TODO
                            Constant(rho_wpi(theta0_average)),
                            Constant(mu_wpi(theta0_average)),
                            f={0: f0, 1: f1},
                            tol=1.0e-10,
                            my_dx=dx(submesh_workpiece),
                        )
                except RuntimeError as e:
                    info(e.args[0])
                    info(
                        "Navier--Stokes solver failed to converge. "
                        "Decrease time step from {:e} to {:e} and try again.".format(
                            dt, 0.5 * dt
                        )
                    )
                    dt *= 0.5
                    failed_steps += 1
                    continue
                successful_steps += 1

                # Assignments and plotting.
                theta0.assign(theta1)
                u0.assign(u1)
                p0.assign(p1)

                _store(outfile, u0, p0, theta0, t + dt)
                if show:
                    _plot(p0, theta0)
                    plt.show()

                t += dt
                with Message("Diagnostics..."):
                    # Print some general info on the flow in the crucible.
                    umax = get_umax(u0)
                    _print_diagnostics(
                        theta0,
                        umax,
                        submesh_workpiece,
                        wpi_area,
                        problem.subdomain_materials,
                        problem.wpi,
                        rho_wpi,
                        mu_wpi,
                        char_length,
                        grav,
                    )
                    info("")
                with Message("Step size adaptation..."):
                    # Some smooth step-size adaption.
                    target_dt = 0.2 * hmax_workpiece / umax
                    info("previous dt: {:e}".format(dt))
                    info("target dt: {:e}".format(target_dt))
                    # agg is the aggressiveness factor. The distance between
                    # the current step size and the target step size is reduced
                    # by |1-agg|. Hence, if agg==1 then dt_next==target_dt.
                    # Otherwise target_dt is approached more slowly.
                    agg = 0.5
                    dt = min(
                        dt_max,
                        # At most double the step size from step to step.
                        dt * min(2.0, 1.0 + agg * (target_dt - dt) / dt),
                    )
                    info("new dt:    {:e}".format(dt))
                    info("")
                info("")
    return u0, p0, theta0
예제 #42
0
def les_setup(u_, mesh, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace):
    """
    Set up for solving the Germano Dynamic LES model applying
    Lagrangian Averaging.
    """

    # Create function spaces
    CG1 = FunctionSpace(mesh, "CG", 1)
    p, q = TrialFunction(CG1), TestFunction(CG1)
    dim = mesh.geometry().dim()

    # Define delta and project delta**2 to CG1
    delta = pow(CellVolume(mesh), 1. / dim)
    delta_CG1_sq = project(delta, CG1)
    delta_CG1_sq.vector().set_local(delta_CG1_sq.vector().array()**2)
    delta_CG1_sq.vector().apply("insert")

    # Define nut_
    Sij = sym(grad(u_))
    magS = sqrt(2 * inner(Sij, Sij))
    Cs = Function(CG1)
    nut_form = Cs**2 * delta**2 * magS
    # Create nut_ BCs
    ff = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
    bcs_nut = []
    for i, bc in enumerate(bcs['u0']):
        bc.apply(u_[0].vector())  # Need to initialize bc
        m = bc.markers()  # Get facet indices of boundary
        ff.array()[m] = i + 1
        bcs_nut.append(DirichletBC(CG1, Constant(0), ff, i + 1))
    nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver,
                       bcs=bcs_nut, bounded=True, name="nut")

    # Create functions for holding the different velocities
    u_CG1 = as_vector([Function(CG1) for i in range(dim)])
    u_filtered = as_vector([Function(CG1) for i in range(dim)])
    dummy = Function(CG1)
    ll = LagrangeInterpolator()

    # Assemble required filter matrices and functions
    G_under = Function(CG1, assemble(TestFunction(CG1) * dx))
    G_under.vector().set_local(1. / G_under.vector().array())
    G_under.vector().apply("insert")
    G_matr = assemble(inner(p, q) * dx)

    # Set up functions for Lij and Mij
    Lij = [Function(CG1) for i in range(dim * dim)]
    Mij = [Function(CG1) for i in range(dim * dim)]
    # Check if case is 2D or 3D and set up uiuj product pairs and
    # Sij forms, assemble required matrices
    Sijcomps = [Function(CG1) for i in range(dim * dim)]
    Sijfcomps = [Function(CG1) for i in range(dim * dim)]
    # Assemble some required matrices for solving for rate of strain terms
    Sijmats = [assemble_matrix(p.dx(i) * q * dx) for i in range(dim)]
    if dim == 3:
        tensdim = 6
        uiuj_pairs = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
    else:
        tensdim = 3
        uiuj_pairs = ((0, 0), (0, 1), (1, 1))

    # Set up Lagrange functions
    JLM = Function(CG1)
    JLM.vector()[:] += 1E-32
    JMM = Function(CG1)
    JMM.vector()[:] += 1

    return dict(Sij=Sij, nut_form=nut_form, nut_=nut_, delta=delta, bcs_nut=bcs_nut,
                delta_CG1_sq=delta_CG1_sq, CG1=CG1, Cs=Cs, u_CG1=u_CG1,
                u_filtered=u_filtered, ll=ll, Lij=Lij, Mij=Mij, Sijcomps=Sijcomps,
                Sijfcomps=Sijfcomps, Sijmats=Sijmats, JLM=JLM, JMM=JMM, dim=dim,
                tensdim=tensdim, G_matr=G_matr, G_under=G_under, dummy=dummy,
                uiuj_pairs=uiuj_pairs)
예제 #43
0
nz = 10

m = dolfin.UnitCubeMesh(nx,ny,nz)
Q = dolfin.FunctionSpace(m,"CG",1)
u = dolfin.Function(Q)
v = dolfin.Function(Q)
w = dolfin.Function(Q)
S = dolfin.Function(Q)

for L in [5000,10000,20000,40000,80000,160000]:

    dolfin.File('./results_stokes/'+str(L)+'/u.xml') >> u
    dolfin.File('./results_stokes/'+str(L)+'/v.xml') >> v
    dolfin.File('./results_stokes/'+str(L)+'/w.xml') >> w

    U = pylab.zeros(100)
    profile = pylab.linspace(0,1,100)

    for ii,x in enumerate(profile):
        uu = u(x,0.25,0.99999)
        vv = v(x,0.25,0.99999)
        ww = w(x,0.25,0.99999)
        U[ii] = pylab.sqrt(uu**2 + vv**2)

    #pylab.plot(profile,U)
    #data = zip(profile,U)
    #pickle.dump(data,open("djb1a{0:03d}.p".format(L/1000),'w'))
    U = dolfin.project(dolfin.as_vector([u,v,w]))
    dolfin.File('./results_stokes/'+str(L)+'/U.pvd') << U

    def _pressure_poisson(self, p1, p0,
                          mu, ui,
                          u,
                          p_bcs=None,
                          rotational_form=False,
                          tol=1.0e-10,
                          verbose=True
                          ):
        '''Solve the pressure Poisson equation
            -1/r \div(r \nabla (p1-p0)) = -1/r div(r*u),
            boundary conditions,
        for
            \nabla p = u.
        '''
        r = Expression('x[0]', degree=1, domain=self.W.mesh())

        Q = p1.function_space()

        p = TrialFunction(Q)
        q = TestFunction(Q)
        a2 = dot(r * grad(p), grad(q)) * 2 * pi * dx
        # The boundary conditions
        #     n.(p1-p0) = 0
        # are implicitly included.
        #
        # L2 = -div(r*u) * q * 2*pi*dx
        div_u = 1/r * (r * u[0]).dx(0) + u[1].dx(1)
        L2 = -div_u * q * 2*pi*r*dx
        if p0:
            L2 += r * dot(grad(p0), grad(q)) * 2*pi*dx

        # In the Cartesian variant of the rotational form, one makes use of the
        # fact that
        #
        #     curl(curl(u)) = grad(div(u)) - div(grad(u)).
        #
        # The same equation holds true in cylindrical form. Hence, to get the
        # rotational form of the splitting scheme, we need to
        #
        # rotational form
        if rotational_form:
            # If there is no dependence of the angular coordinate, what is
            # div(grad(div(u))) in Cartesian coordinates becomes
            #
            #     1/r div(r * grad(1/r div(r*u)))
            #
            # in cylindrical coordinates (div and grad are in cylindrical
            # coordinates). Unfortunately, we cannot write it down that
            # compactly since u_phi is in the game.
            # When using P2 elements, this value will be 0 anyways.
            div_ui = 1/r * (r * ui[0]).dx(0) + ui[1].dx(1)
            grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1)))
            L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2*pi*dx
            #div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \
            #    + (grad_div_ui[1]).dx(1)
            #L2 += mu * div_grad_div_ui * q * 2*pi*r*dx
            #n = FacetNormal(Q.mesh())
            #L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \
            #    * q * 2*pi*r*ds

        if p_bcs:
            solve(
                a2 == L2, p1,
                bcs=p_bcs,
                solver_parameters={
                    'linear_solver': 'iterative',
                    'symmetric': True,
                    'preconditioner': 'amg',
                    'krylov_solver': {'relative_tolerance': tol,
                                      'absolute_tolerance': 0.0,
                                      'maximum_iterations': 100,
                                      'monitor_convergence': verbose}
                    }
                )
        else:
            # If we're dealing with a pure Neumann problem here (which is the
            # default case), this doesn't hurt CG if the system is consistent,
            # cf. :cite:`vdV03`. And indeed it is consistent if and only if
            #
            #   \int_\Gamma r n.u = 0.
            #
            # This makes clear that for incompressible Navier-Stokes, one
            # either needs to make sure that inflow and outflow always add up
            # to 0, or one has to specify pressure boundary conditions.
            #
            # If the right-hand side is very small, round-off errors may impair
            # the consistency of the system. Make sure the system we are
            # solving remains consistent.
            A = assemble(a2)
            b = assemble(L2)
            # Assert that the system is indeed consistent.
            e = Function(Q)
            e.interpolate(Constant(1.0))
            evec = e.vector()
            evec /= norm(evec)
            alpha = b.inner(evec)
            normB = norm(b)
            # Assume that in every component of the vector, a round-off error
            # of the magnitude DOLFIN_EPS is present. This leads to the
            # criterion
            #    |<b,e>| / (||b||*||e||) < DOLFIN_EPS
            # as a check whether to consider the system consistent up to
            # round-off error.
            #
            # TODO think about condition here
            #if abs(alpha) > normB * DOLFIN_EPS:
            if abs(alpha) > normB * 1.0e-12:
                divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1)
                adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * dx)
                info('\int 1/r * div(r*u) * 2*pi*r  =  %e' % adivu)
                n = FacetNormal(Q.mesh())
                boundary_integral = assemble((n[0] * u[0] + n[1] * u[1])
                                             * 2 * pi * r * ds)
                info('\int_Gamma n.u * 2*pi*r = %e' % boundary_integral)
                message = ('System not consistent! '
                           '<b,e> = %g, ||b|| = %g, <b,e>/||b|| = %e.') \
                           % (alpha, normB, alpha / normB)
                info(message)
                # Plot the stuff, and project it to a finer mesh with linear
                # elements for the purpose.
                plot(divu, title='div(u_tentative)')
                #Vp = FunctionSpace(Q.mesh(), 'CG', 2)
                #Wp = MixedFunctionSpace([Vp, Vp])
                #up = project(u, Wp)
                fine_mesh = Q.mesh()
                for k in range(1):
                    fine_mesh = refine(fine_mesh)
                V = FunctionSpace(fine_mesh, 'CG', 1)
                W = V * V
                #uplot = Function(W)
                #uplot.interpolate(u)
                uplot = project(u, W)
                plot(uplot[0], title='u_tentative[0]')
                plot(uplot[1], title='u_tentative[1]')
                #plot(u, title='u_tentative')
                interactive()
                exit()
                raise RuntimeError(message)
            # Project out the roundoff error.
            b -= alpha * evec

            #
            # In principle, the ILU preconditioner isn't advised here since it
            # might destroy the semidefiniteness needed for CG.
            #
            # The system is consistent, but the matrix has an eigenvalue 0.
            # This does not harm the convergence of CG, but when
            # preconditioning one has to make sure that the preconditioner
            # preserves the kernel.  ILU might destroy this (and the
            # semidefiniteness). With AMG, the coarse grid solves cannot be LU
            # then, so try Jacobi here.
            # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html>
            #
            prec = PETScPreconditioner('hypre_amg')
            from dolfin import PETScOptions
            PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi')
            solver = PETScKrylovSolver('cg', prec)
            solver.parameters['absolute_tolerance'] = 0.0
            solver.parameters['relative_tolerance'] = tol
            solver.parameters['maximum_iterations'] = 100
            solver.parameters['monitor_convergence'] = verbose
            # Create solver and solve system
            A_petsc = as_backend_type(A)
            b_petsc = as_backend_type(b)
            p1_petsc = as_backend_type(p1.vector())
            solver.set_operator(A_petsc)
            solver.solve(p1_petsc, b_petsc)
            # This would be the stump for Epetra:
            #solve(A, p.vector(), b, 'cg', 'ml_amg')
        return
예제 #45
0
def test(show=False):
    problem = problems.Crucible()
    # The voltage is defined as
    #
    #     v(t) = Im(exp(i omega t) v)
    #          = Im(exp(i (omega t + arg(v)))) |v|
    #          = sin(omega t + arg(v)) |v|.
    #
    # Hence, for a lagging voltage, arg(v) needs to be negative.
    voltages = [
        38.0 * numpy.exp(-1j * 2 * pi * 2 * 70.0 / 360.0),
        38.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0),
        38.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0),
        25.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0),
        25.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0),
    ]

    lorentz, joule, Phi = get_lorentz_joule(problem, voltages, show=show)

    # Some assertions
    ref = 1.4627674791126285e-05
    assert abs(norm(Phi[0], "L2") - ref) < 1.0e-3 * ref
    ref = 3.161363929287592e-05
    assert abs(norm(Phi[1], "L2") - ref) < 1.0e-3 * ref
    #
    ref = 12.115309575057681
    assert abs(norm(lorentz, "L2") - ref) < 1.0e-3 * ref
    #
    ref = 1406.336109054347
    V = FunctionSpace(problem.submesh_workpiece, "CG", 1)
    jp = project(joule, V)
    jp.rename("s", "Joule heat source")
    assert abs(norm(jp, "L2") - ref) < 1.0e-3 * ref

    # check_currents = False
    # if check_currents:
    #     r = SpatialCoordinate(problem.mesh)[0]
    #     begin('Currents computed after the fact:')
    #     k = 0
    #     with XDMFFile('currents.xdmf') as xdmf_file:
    #         for coil in coils:
    #             for ii in coil['rings']:
    #                 J_r = sigma[ii] * (
    #                     voltages[k].real/(2*pi*r) + problem.omega * Phi[1]
    #                     )
    #                 J_i = sigma[ii] * (
    #                     voltages[k].imag/(2*pi*r) - problem.omega * Phi[0]
    #                     )
    #                 alpha = assemble(J_r * dx(ii))
    #                 beta = assemble(J_i * dx(ii))
    #                 info('J = {:e} + i {:e}'.format(alpha, beta))
    #                 info(
    #                     '|J|/sqrt(2) = {:e}'.format(
    #                         numpy.sqrt(0.5 * (alpha**2 + beta**2))
    #                     ))
    #                 submesh = SubMesh(problem.mesh, problem.subdomains, ii)
    #                 V1 = FunctionSpace(submesh, 'CG', 1)
    #                 # Those projections may take *very* long.
    #                 # TODO find out why
    #                 j_v1 = [
    #                     project(J_r, V1),
    #                     project(J_i, V1)
    #                     ]
    #                 # show=Trueplot(j_v1[0], title='j_r')
    #                 # plot(j_v1[1], title='j_i')
    #                 current = project(as_vector(j_v1), V1*V1)
    #                 current.rename('j{}'.format(ii), 'current {}'.format(ii))
    #                 xdmf_file.write(current)
    #                 k += 1
    #     end()

    filename = "./maxwell.xdmf"
    with XDMFFile(filename) as xdmf_file:
        xdmf_file.parameters["flush_output"] = True
        xdmf_file.parameters["rewrite_function_mesh"] = False

        # Store phi
        info("Writing out Phi to {}...".format(filename))
        V = FunctionSpace(problem.mesh, "CG", 1)
        phi = Function(V, name="phi")
        Phi0 = project(Phi[0], V)
        Phi1 = project(Phi[1], V)
        omega = problem.omega
        for t in numpy.linspace(0.0, 2 * pi / omega, num=100, endpoint=False):
            # Im(Phi * exp(i*omega*t))
            phi.vector().zero()
            phi.vector().axpy(sin(problem.omega * t), Phi0.vector())
            phi.vector().axpy(cos(problem.omega * t), Phi1.vector())
            xdmf_file.write(phi, t)

        # Show the resulting magnetic field
        #
        #   B_r = -dphi/dz,
        #   B_z = 1/r d(rphi)/dr.
        #
        r = SpatialCoordinate(problem.mesh)[0]
        g = 1.0 / r * grad(r * Phi[0])
        V_element = FiniteElement("CG", V.mesh().ufl_cell(), 1)
        VV = FunctionSpace(V.mesh(), V_element * V_element)

        B_r = project(as_vector((-g[1], g[0])), VV)
        g = 1 / r * grad(r * Phi[1])
        B_i = project(as_vector((-g[1], g[0])), VV)
        info("Writing out B to {}...".format(filename))
        B = Function(VV)
        B.rename("B", "magnetic field")
        if abs(problem.omega) < DOLFIN_EPS:
            B.assign(B_r)
            xdmf_file.write(B)
            # plot(B_r, title='Re(B)')
            # plot(B_i, title='Im(B)')
        else:
            # Write those out to a file.
            lspace = numpy.linspace(
                0.0, 2 * pi / problem.omega, num=100, endpoint=False
            )
            for t in lspace:
                # Im(B * exp(i*omega*t))
                B.vector().zero()
                B.vector().axpy(sin(problem.omega * t), B_r.vector())
                B.vector().axpy(cos(problem.omega * t), B_i.vector())
                xdmf_file.write(B, t)

    filename = "./lorentz-joule.xdmf"
    info("Writing out Lorentz force and Joule heat source to {}...".format(filename))
    with XDMFFile(filename) as xdmf_file:
        xdmf_file.write(lorentz, 0.0)
        # xdmf_file.write(jp, 0.0)

    return
예제 #46
0
파일: heat.py 프로젝트: nschloe/maelstrom
def F(
    u,
    v,
    kappa,
    rho,
    cp,
    convection,
    source,
    r,
    neumann_bcs,
    robin_bcs,
    my_dx,
    my_ds,
    stabilization,
):
    """
    Compute

    .. math::

        F(u) =
            \\int_\\Omega \\kappa r
                \\langle\\nabla u, \\nabla \\frac{v}{\\rho c_p}\\rangle
                \\, 2\\pi \\, \\text{d}x
            + \\int_\\Omega \\langle c, \\nabla u\\rangle v
                \\, 2\\pi r\\,\\text{d}x
            - \\int_\\Omega \\frac{1}{\\rho c_p} f v
                \\, 2\\pi r \\,\\text{d}x\\\\
            - \\int_\\Gamma r \\kappa \\langle n, \\nabla T\\rangle v
                \\frac{1}{\\rho c_p} 2\\pi \\,\\text{d}s
            - \\int_\\Gamma  r \\kappa  \\alpha (u - u_0) v
                \\frac{1}{\\rho c_p} \\, 2\\pi \\,\\text{d}s,

    used for time-stepping

    .. math::

        u' = F(u).
    """
    rho_cp = rho * cp

    F0 = kappa * r * dot(grad(u), grad(v / rho_cp)) * 2 * pi * my_dx

    # F -= dot(b, grad(u)) * v * 2*pi*r * dx_workpiece(0)
    if convection is not None:
        c = as_vector([convection[0], convection[1]])
        F0 += dot(c, grad(u)) * v * 2 * pi * r * my_dx

    # Joule heat
    F0 -= source * v / rho_cp * 2 * pi * r * my_dx

    # Neumann boundary conditions
    for k, n_grad_T in neumann_bcs.items():
        F0 -= r * kappa * n_grad_T * v / rho_cp * 2 * pi * my_ds(k)

    # Robin boundary conditions
    for k, value in robin_bcs.items():
        alpha, u0 = value
        F0 -= r * kappa * alpha * (u - u0) * v / rho_cp * 2 * pi * my_ds(k)

    if stabilization == "supg":
        # Add SUPG stabilization.
        assert convection is not None
        # TODO u_t?
        R = (
            -div(kappa * r * grad(u)) / rho_cp * 2 * pi
            + dot(c, grad(u)) * 2 * pi * r
            - source / rho_cp * 2 * pi * r
        )
        mesh = v.function_space().mesh()
        element_degree = v.ufl_element().degree()
        tau = stab.supg(mesh, convection, kappa, element_degree)
        F0 += R * tau * dot(convection, grad(v)) * my_dx
    else:
        assert stabilization is None

    return F0
예제 #47
0
 def eps(u):
     """ Returns a vector of strains of size (3,1) in the Voigt notation
     layout {eps_xx, eps_yy, gamma_xy} where gamma_xy = 2*eps_xy"""
     return df.as_vector([u[i].dx(i) for i in range(2)] +
                         [u[i].dx(j) + u[j].dx(i) for (i,j) in [(0,1)]])