示例#1
0
def test_assign():
    c0 = Constant(1.)
    assert c0.values() == (1,)
    c0.assign(Constant(3))
    assert c0.values() == (3,)

    c1 = Constant([1, 2])
    assert (c1.values() == (1, 2)).all()
    c1.assign(Constant([3, 4]))
    assert (c1.values() == (3, 4)).all()
示例#2
0
def _product(thetas: ThetaType, operators: tuple_of(Form)):
    try:
        output = _product_forms_output_cache[operators]
    except KeyError:
        # Keep the operators as Forms and delay assembly as long as possible
        output = 0
        constants = list()
        for (theta, operator) in zip(thetas, operators):
            theta = float(theta)
            constant = Constant(theta)
            output += constant * operator
            constants.append(constant)
        output = ProductOutput(output)
        _product_forms_output_cache[operators] = output
        _product_forms_constants_cache[operators] = constants
        return output
    else:
        constants = _product_forms_constants_cache[operators]
        for (theta, constant) in zip(thetas, constants):
            theta = float(theta)
            constant.assign(theta)
        return output
def test_unsteady_stokes():
    nx, ny = 15, 15
    k = 1
    nu = Constant(1.0e-0)
    dt = Constant(2.5e-2)
    num_steps = 20
    theta0 = 1.0  # Initial theta value
    theta1 = 0.5  # Theta after 1 step
    theta = Constant(theta0)

    mesh = UnitSquareMesh(nx, ny)

    # The 'unsteady version' of the benchmark in the 2012 paper by Labeur&Wells
    u_exact = Expression(
        (
            "sin(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                           -6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
            "-sin(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                           - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])",
        ),
        t=0,
        degree=7,
        domain=mesh,
    )
    p_exact = Expression("sin(t) * x[0]*(1.0 - x[0])",
                         t=0,
                         degree=7,
                         domain=mesh)
    du_exact = Expression(
        (
            "cos(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                            - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
            "-cos(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                            -6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])",
        ),
        t=0,
        degree=7,
        domain=mesh,
    )

    ux_exact = Expression(
        (
            "x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                            - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
            "-x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                            - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])",
        ),
        degree=7,
        domain=mesh,
    )

    px_exact = Expression("x[0]*(1.0 - x[0])", degree=7, domain=mesh)

    sin_ext = Expression("sin(t)", t=0, degree=7, domain=mesh)

    f = du_exact + sin_ext * div(px_exact * Identity(2) -
                                 2 * sym(grad(ux_exact)))

    Vhigh = VectorFunctionSpace(mesh, "DG", 7)
    Phigh = FunctionSpace(mesh, "DG", 7)

    # New syntax:
    V = VectorElement("DG", mesh.ufl_cell(), k)
    Q = FiniteElement("DG", mesh.ufl_cell(), k - 1)
    Vbar = VectorElement("DGT", mesh.ufl_cell(), k)
    Qbar = FiniteElement("DGT", mesh.ufl_cell(), k)

    mixedL = FunctionSpace(mesh, MixedElement([V, Q]))
    mixedG = FunctionSpace(mesh, MixedElement([Vbar, Qbar]))
    V2 = FunctionSpace(mesh, V)

    Uh = Function(mixedL)
    Uhbar = Function(mixedG)
    U0 = Function(mixedL)
    Uhbar0 = Function(mixedG)
    u0, p0 = split(U0)
    ubar0, pbar0 = split(Uhbar0)
    ustar = Function(V2)

    # Then the boundary conditions
    bc0 = DirichletBC(mixedG.sub(0), Constant((0, 0)), Gamma)
    bc1 = DirichletBC(mixedG.sub(1), Constant(0), Corner, "pointwise")
    bcs = [bc0, bc1]

    alpha = Constant(6 * k * k)
    forms_stokes = FormsStokes(mesh, mixedL, mixedG,
                               alpha).forms_unsteady(ustar, dt, nu, f)
    ssc = StokesStaticCondensation(
        mesh,
        forms_stokes["A_S"],
        forms_stokes["G_S"],
        forms_stokes["G_ST"],
        forms_stokes["B_S"],
        forms_stokes["Q_S"],
        forms_stokes["S_S"],
    )

    t = 0.0
    step = 0
    for step in range(num_steps):
        step += 1
        t += float(dt)
        if comm.Get_rank() == 0:
            print("Step " + str(step) + " Time " + str(t))

        # Set time level in exact solution
        u_exact.t = t
        p_exact.t = t

        du_exact.t = t - (1 - float(theta)) * float(dt)
        sin_ext.t = t - (1 - float(theta)) * float(dt)

        ssc.assemble_global_lhs()
        ssc.assemble_global_rhs()
        for bc in bcs:
            ssc.apply_boundary(bc)

        ssc.solve_problem(Uhbar, Uh, "none", "default")
        assign(U0, Uh)
        assign(ustar, U0.sub(0))
        assign(Uhbar0, Uhbar)
        if step == 1:
            theta.assign(theta1)

        udiv_e = sqrt(assemble(div(Uh.sub(0)) * div(Uh.sub(0)) * dx))

    u_ex_h = interpolate(u_exact, Vhigh)
    p_ex_h = interpolate(p_exact, Phigh)

    u_error = sqrt(assemble(dot(Uh.sub(0) - u_ex_h, Uh.sub(0) - u_ex_h) * dx))
    p_error = sqrt(assemble(dot(Uh.sub(1) - p_ex_h, Uh.sub(1) - p_ex_h) * dx))

    assert udiv_e < 1e-12
    assert u_error < 1.5e-4
    assert p_error < 1e-2
示例#4
0
class VariableDensityModel(MultiPhaseModel):
    description = 'A variable density DG transport equation model'

    def __init__(self, simulation):
        """
        A variable density scheme solving D/Dt(rho)=0 with a
        constant kinematic vosicsity nu and a variable dynamic
        visocisty mu (depending on rho)
        """
        self.simulation = simulation
        simulation.log.info('Creating variable density multiphase model')

        # Define function space and solution function
        V = simulation.data['Vrho']
        self.rho = simulation.data['rho'] = Function(V)
        self.rho_p = simulation.data['rho_p'] = Function(V)
        self.rho_pp = simulation.data['rho_pp'] = Function(V)

        # Get the physical properties
        inp = simulation.input
        self.rho_min = inp.get_value('physical_properties/rho_min',
                                     required_type='float')
        self.rho_max = inp.get_value('physical_properties/rho_max',
                                     required_type='float')
        self.nu = inp.get_value('physical_properties/nu',
                                required_type='float')

        # Create the equations when the simulation starts
        simulation.hooks.add_pre_simulation_hook(
            self.on_simulation_start, 'VariableDensityModel setup equations')

        # Update the rho and nu fields before each time step
        simulation.hooks.add_pre_timestep_hook(
            self.update, 'VariableDensityModel - update density field')
        simulation.hooks.register_custom_hook_point('MultiPhaseModelUpdated')

        self.use_analytical_solution = inp.get_value(
            'multiphase_solver/analytical_solution', False, 'bool')
        self.use_rk_method = inp.get_value(
            'multiphase_solver/explicit_rk_method', False, 'bool')
        self.is_first_timestep = True

    @classmethod
    def create_function_space(cls, simulation):
        mesh = simulation.data['mesh']
        cd = simulation.data['constrained_domain']
        Vr_name = simulation.input.get_value(
            'multiphase_solver/function_space_rho', 'Discontinuous Lagrange',
            'string')
        Pr = simulation.input.get_value(
            'multiphase_solver/polynomial_degree_rho', 1, 'int')
        Vrho = dolfin.FunctionSpace(mesh, Vr_name, Pr, constrained_domain=cd)
        simulation.data['Vrho'] = Vrho
        simulation.ndofs += Vrho.dim()

    def on_simulation_start(self):
        """
        This runs when the simulation starts. It does not run in __init__
        since the N-S solver needs the density and viscosity we define, and
        we need the velocity that is defined by the solver
        """
        if self.use_analytical_solution:
            return

        sim = self.simulation
        dirichlet_bcs = sim.data['dirichlet_bcs'].get('rho', [])

        if self.use_rk_method:
            V = self.simulation.data['Vrho']
            if not V.ufl_element().family() == 'Discontinuous Lagrange':
                ocellaris_error(
                    'VariableDensity timestepping error',
                    'Can only use explicit SSP Runge-Kutta method with DG space for rho',
                )

            Vu = sim.data['Vu']
            u_conv, self.funcs_to_extrapolate = [], []
            for d in range(sim.ndim):
                ux = Function(Vu)
                up = sim.data['up_conv%d' % d]
                upp = sim.data['upp_conv%d' % d]
                self.funcs_to_extrapolate.append((ux, up, upp))
                u_conv.append(ux)
            u_conv = dolfin.as_vector(u_conv)

            from dolfin import dot, div, jump, dS

            mesh = self.simulation.data['mesh']

            re = self.rho_explicit = dolfin.Function(V)
            c, d = dolfin.TrialFunction(V), dolfin.TestFunction(V)
            n = dolfin.FacetNormal(mesh)
            w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2
            dx = dolfin.dx(domain=mesh)

            eq = c * d * dx

            # Convection integrated by parts two times to bring back the original
            # div form (this means we must subtract and add all fluxes)
            eq += div(re * u_conv) * d * dx

            # Replace downwind flux with upwind flux on downwind internal facets
            eq -= jump(w_nD * d) * jump(re) * dS

            # Replace downwind flux with upwind BC flux on downwind external facets
            for dbc in dirichlet_bcs:
                # Subtract the "normal" downwind flux
                eq -= w_nD * re * d * dbc.ds()
                # Add the boundary value upwind flux
                eq += w_nD * dbc.func() * d * dbc.ds()

            a, L = dolfin.system(eq)
            self.rk = RungeKuttaDGTimestepping(
                self.simulation,
                a,
                L,
                self.rho,
                self.rho_explicit,
                'rho',
                order=None,
                explicit_funcs=self.funcs_to_extrapolate,
                bcs=dirichlet_bcs,
            )

        else:
            # Use backward Euler (BDF1) for timestep 1
            self.time_coeffs = Constant([1, -1, 0])

            if dolfin.norm(self.rho_pp.vector()) > 0:
                # Use BDF2 from the start
                self.time_coeffs.assign(Constant([3 / 2, -2, 1 / 2]))
                self.simulation.log.info(
                    'Using second order timestepping from the start in VariableDensity'
                )

            # Define equation for advection of the density
            #    ∂ρ/∂t +  ∇⋅(ρ u) = 0
            beta = None
            u_conv = sim.data['u_conv']
            forcing_zones = sim.data['forcing_zones'].get('rho', [])
            self.eq = AdvectionEquation(
                sim,
                sim.data['Vrho'],
                self.rho_p,
                self.rho_pp,
                u_conv,
                beta,
                self.time_coeffs,
                dirichlet_bcs,
                forcing_zones,
            )

            self.solver = linear_solver_from_input(sim, 'solver/rho', SOLVER,
                                                   PRECONDITIONER, None,
                                                   KRYLOV_PARAMETERS)
            self.slope_limiter = SlopeLimiter(sim, 'rho', self.rho)
            self.slope_limiter.set_phi_old(self.rho_p)

        # Make sure the initial value is included in XDMF results from timestep 0
        self.rho.assign(self.rho_p)

    def get_density(self, k):
        """
        Return the function as defined on timestep t^{n+k}
        """
        if k == 0:
            return self.rho
        elif k == -1:
            return self.rho_p
        elif k == -2:
            return self.rho_pp

    def get_laminar_kinematic_viscosity(self, k):
        """
        It is assumed that the kinematic viscosity is constant
        """
        return Constant(self.nu)

    def get_laminar_dynamic_viscosity(self, k):
        """
        Calculate the blended dynamic viscosity function as a function
        of the (constant) nu and (variable) rho

        Return the function as defined on timestep t^{n+k}
        """
        nu = self.get_laminar_kinematic_viscosity(k)
        rho = self.get_density(k)
        return nu * rho

    def get_density_range(self):
        """
        Return the maximum and minimum densities, rho
        """
        return self.rho_min, self.rho_max

    def get_laminar_kinematic_viscosity_range(self):
        """
        Return the maximum and minimum kinematic viscosities, nu
        """
        return self.nu, self.nu

    def get_laminar_dynamic_viscosity_range(self):
        """
        The minimum and maximum laminar dynamic viscosities, mu.
        """
        return self.nu * self.rho_min, self.nu * self.rho_max

    def update(self, timestep_number, t, dt):
        """
        Update the density field by advecting it for a time dt
        using the given divergence free velocity field
        """
        timer = dolfin.Timer('Ocellaris update rho')
        sim = self.simulation

        if timestep_number != 1:
            # Update the previous values
            self.rho_pp.assign(self.rho_p)
            self.rho_p.assign(self.rho)

        # Check for steady solution every timestep, this can change over time
        force_static = sim.input.get_value('multiphase_solver/force_static',
                                           FORCE_STATIC, 'bool')

        if force_static:
            # Keep the existing solution
            self.rho.assign(self.rho_p)

        elif self.use_analytical_solution:
            # Use an analytical density field for testing other parts of Ocellaris
            cpp_code = sim.input.get_value('initial_conditions/rho_p/cpp_code',
                                           required_type='string')
            description = 'initial condition for rho_p'
            V = sim.data['Vrho']
            ocellaris_interpolate(sim, cpp_code, description, V, self.rho)

        elif self.use_rk_method:
            # Strong-Stability-Preserving Runge-Kutta DG time integration
            self.rho.assign(self.rho_p)
            self.rho_explicit.assign(self.rho_p)
            self.rk.step(dt)

        else:
            # Compute global bounds
            if self.is_first_timestep:
                lo, hi = self.slope_limiter.set_global_bounds(self.rho)
                if self.slope_limiter.has_global_bounds:
                    sim.log.info(
                        'Setting global bounds [%r, %r] in VariableDensity' %
                        (lo, hi))

            # Solve the implicit advection equation
            A = self.eq.assemble_lhs()
            b = self.eq.assemble_rhs()
            self.solver.solve(A, self.rho.vector(), b)
            self.slope_limiter.run()
            self.time_coeffs.assign(Constant([3 / 2, -2, 1 / 2]))

        sim.reporting.report_timestep_value('min(rho)',
                                            self.rho.vector().min())
        sim.reporting.report_timestep_value('max(rho)',
                                            self.rho.vector().max())

        timer.stop()  # Stop timer before hook
        self.simulation.hooks.run_custom_hook('MultiPhaseModelUpdated')
        self.is_first_timestep = False
    assign(rho0, rho)

    # Needed for constrained map
    if projection_type == 'PDE':
        assign(ubar0_a, Uhbar.sub(0))
        assign(u0, ustar)
        assign(duh00, duh0)
        assign(duh0, project(Uh.sub(0) - ustar, W_2))
    del (t1)

    t1 = Timer("[P] Update particle field")
    p.increment(Udiv, ustar, np.array([2, 3], dtype=np.uintp), theta_p, step)
    del (t1)

    if step == 2:
        theta_L.assign(1.0)

    if step % store_step == 0:
        t1 = Timer("[P] Storing xdmf fields, just output!")
        # Set output, also throw out particle output
        xdmf_rho.write_checkpoint(rho, "rho", t, append=True)
        xdmf_u.write(Uh.sub(0), t)
        xdmf_p.write(Uh.sub(1), t)

        # Save particle data
        p.dump2file(mesh, fname_list, property_list, 'ab', False)
        comm.barrier()
        del (t1)

timer.stop()
示例#6
0
time = Timer("ZZZ Stokes solve")
for bc in bcs:
    ssc.apply_boundary(bc)
ssc.solve_problem(Uhbar.cpp_object(), Uh.cpp_object(), "mumps", "default")
del time

# Transfer the computed velocity function and compute functionals
velocity_assigner.assign(u_vec, Uh.sub(0))
output_data_step(append=False)

time_snap_shot_interval = 5.0
next_snap_shot_time = time_snap_shot_interval

for j in range(50000):
    max_u_vec = u_vec.vector().norm("linf")
    dt.assign(C_CFL * hmin / max_u_vec)

    t.assign(float(t) + float(dt))
    if float(t) > 2000.0:
        break

    info("Timestep %d, dt = %.3e, t = %.3e" % (j, float(dt), float(t)))

    time = Timer("ZZZ Do_step")
    ap.do_step(float(dt))
    del time

    time = Timer("ZZZ PDE project assemble")
    pde_projection.assemble(True, True)
    del time
示例#7
0
        print(_dmdm_predicted)
        print()

    if TEST_SENSITIVITY_REACTION_MEASUREMENTS:
        logger.info('Test reaction measurement sensitivity')

        # Uniform perturbation of reaction (traction) measurements
        perturb_T_msr = np.array([0.1 * Tx_max, 0.0, 0.0])

        m0 = np.array(inverse_solver.view_model_parameter_values())

        dm = sum(
            inverse_solver.observe_dmdT_msr(t)[i_msr_f]
            for t in inverse_solver.observation_times).dot(perturb_T_msr)

        dT_msr_noise.assign(dolfin.Constant(perturb_T_msr))

        n, b = inverse_solver.solve_inverse_problem()  # Default times
        if not b: logger.error('Inverse solver did not converge')

        m1 = np.array(inverse_solver.view_model_parameter_values())

        passed_test_sensitivity_reaction_force = \
            np.allclose(m1 - m0, dm, atol=1e-2*np.abs(dm).max())

        if passed_test_sensitivity_reaction_force:
            logger.info('Reaction measurement sensitivity test [PASSED]')
        else:
            logger.error('Reaction measurement sensitivity test [FAILED]')

        print('Reference model parameter values:')
示例#8
0
class M3H3(object):

    def __init__(self, geometry, parameters, *args, **kwargs):
        self.parameters = parameters
        self.physics = [Physics(p) for p in parameters.keys()
                                                    if Physics.has_value(p)]
        self.interactions = kwargs.get('interactions', [])
        if len(self.interactions) > 0:
            self._check_physics_interactions()

        if 'time' in kwargs.keys():
            self.time = kwargs['time']
            kwargs.pop('time', None)
        else:
            self.time = Constant(self.parameters['start_time'])

        self._setup_geometries(geometry, self.physics)
        self._setup_problems(**kwargs)
        self._setup_solvers(**kwargs)


    def step(self):
        # Setup time stepping if running step function for the first time.
        if self.time.values()[0] == self.parameters['start_time']:
            self.num_steps, self.max_dt = self._get_num_steps()

        time = float(self.time)
        solution_fields = self.get_solution_fields()

        if Physics.ELECTRO in self.physics:
            for _ in range(self.num_steps[Physics.ELECTRO]):
                electro_fields = solution_fields[str(Physics.ELECTRO)]
                self.electro_solver.step(electro_fields[1])

        if Physics.SOLID in self.physics:
            for _ in range(self.num_steps[Physics.SOLID]):
                self.solid_solver.step()

        if Physics.FLUID in self.physics:
            for _ in range(self.num_steps[Physics.FLUID]):
                self.fluid_solver.step()

        if Physics.POROUS in self.physics:
            for _ in range(self.num_steps[Physics.POROUS]):
                self.porous_solver.step()
                
        self.time.assign(time + self.max_dt)
        return time, solution_fields


    def get_solution_fields(self):
        solution_fields = {}
        if Physics.ELECTRO in self.physics:
            solution_fields[str(Physics.ELECTRO)] =\
                                    self.electro_problem._get_solution_fields()
        if Physics.SOLID in self.physics:
            pass
        if Physics.FLUID in self.physics:
            pass
        if Physics.POROUS in self.physics:
            pass
        return solution_fields


    def add_stimulus(self, stimulus):
        assert hasattr(self, 'electro_problem'), \
            "Cannot add stimulus if electrophysiology has not been set up."
        self.electro_problem.add_stimulus(stimulus)


    def _get_num_steps(self):
        dt_physics = self._get_physics_dt()
        min_dt = min(dt_physics.values())
        max_dt = max(dt_physics.values())
        num_steps = {}
        if Physics.ELECTRO in self.physics:
            dt = dt_physics[Physics.ELECTRO]
            if self._check_dt_is_multiple(dt, min_dt):
                num_steps[Physics.ELECTRO] = int(max_dt/dt)
        if Physics.SOLID in self.physics:
            dt = dt_physics[Physics.SOLID]
            if self._check_dt_is_multiple(dt, min_dt):
                num_steps[Physics.SOLID] = int(max_dt/dt)
        if Physics.FLUID in self.physics:
            dt = dt_physics[Physics.FLUID]
            if self._check_dt_is_multiple(dt, min_dt):
                num_steps[Physics.FLUID] = int(max_dt/dt)
        if Physics.POROUS in self.physics:
            dt = dt_physics[Physics.POROUS]
            if self._check_dt_is_multiple(dt, min_dt):
                num_steps[Physics.POROUS] = int(max_dt/dt)
        return num_steps, max_dt


    def _check_dt_is_multiple(self, dt, min_dt):
        if not (dt/min_dt).is_integer():
            msg = "Time step sizes have to be multiples of each other."\
                    "{} is not a multiple of {}".format(dt, min_dt)
            raise ValueError(msg)
        else:
            return True


    def _get_physics_dt(self):
        dt = {}
        if Physics.ELECTRO in self.physics:
            dt[Physics.ELECTRO] = self.parameters[str(Physics.ELECTRO)]['dt']
        if Physics.SOLID in self.physics:
            dt[Physics.SOLID] = self.parameters[str(Physics.SOLID)]['dt']
        if Physics.FLUID in self.physics:
            dt[Physics.FLUID] = self.parameters[str(Physics.FLUID)]['dt']
        if Physics.POROUS in self.physics:
            dt[Physics.POROUS] = self.parameters[str(Physics.POROUS)]['dt']
        return dt


    def _setup_problems(self, **kwargs):
        if Physics.ELECTRO in self.physics:
            self.electro_problem = ElectroProblem(
                                        self.geometries[Physics.ELECTRO],
                                        self.time,
                                        self.parameters[str(Physics.ELECTRO)],
                                        **kwargs)
            
        if Physics.SOLID in self.physics:
            self.solid_problem = SolidProblem(
                                        self.geometries[Physics.SOLID], 
                                        self.time,
                                        self.parameters[str(Physics.SOLID)],
                                        **kwargs)

        if Physics.FLUID in self.physics:
            self.fluid_problem = FluidProblem(
                                        self.geometries[Physics.FLUID],
                                        self.time,
                                        self.parameters[str(Physics.FLUID)],
                                        **kwargs)

        if Physics.POROUS in self.physics:
            self.porous_problem = PorousProblem(
                                        self.geometries[Physics.POROUS],
                                        self.time,
                                        self.parameters[str(Physics.POROUS)],
                                        **kwargs)


    def _setup_solvers(self, **kwargs):
        interval = (self.parameters['start_time'], self.parameters['end_time'])
        solution_fields = self.get_solution_fields()

        if Physics.ELECTRO in self.physics:
            elabel = str(Physics.ELECTRO)
            electro_fields = solution_fields[elabel]
            parameters = self.parameters[elabel]['linear_variational_solver']
            self.electro_solver = BasicBidomainSolver(self.time,
                                    self.electro_problem._form, electro_fields,
                                    parameters, **kwargs)

        if Physics.SOLID in self.physics:
            parameters = self.parameters[str(Physics.SOLID)]
            self.solid_solver = SolidSolver(
                                    self.solid_problem._form, self.time,
                                    interval, parameters['dt'], parameters,
                                    **kwargs)

        if Physics.FLUID in self.physics:
            parameters = self.parameters[str(Physics.FLUID)]
            self.fluid_solver = FluidSolver(
                                    self.fluid_problem._form, self.time,
                                    interval, parameters['dt'], parameters,
                                    **kwargs)

        if Physics.POROUS in self.physics:
            parameters = self.parameters[str(Physics.POROUS)]
            self.porous_solver = PorousSolver(
                                    self.porous_problem._form, self.time,
                                    interval, parameters['dt'], parameters,
                                    **kwargs)


    def _setup_geometries(self, geometry, physics):
        self.geometries = {}

        if isinstance(geometry, MultiGeometry):
            for phys in physics:
                try:
                    self.geometries[phys] = geometry.geometries[phys.value]
                except KeyError:
                    msg = "Could not find a geometry for {} physics in "\
                            "MultiGeometry. Ensure that geometry labels "\
                            "correspond to values in Physics "\
                            "enum.".format(phys.value)
                    raise KeyError(msg)

                assert isinstance(self.geometries[phys], HeartGeometry)
        elif len(physics) == 1:
            self.geometries[physics[0]] = geometry
        else:
            for phys in physics:
                self.geometries[phys] = geometry.copy(deepcopy=True)


    def _check_physics_interactions(self):
        # If multiple physics are defined, check that all are involved in an
        # interaction and that physics involved in an interaction are set up
        if len(self.physics) == 0 and len(self.interactions) > 0:
            msg = "At least one interaction has been set up, but no physics\n"\
                    "Interactions: {}".format(self.interactions)
            raise KeyError(msg)
        if len(self.physics) > 1:
            int_physics = set(np.array([ia.to_list()
                                            for ia in self.interactions]).flat)
            for p in int_physics:
                if p not in self.physics:
                    msg = "Physics {} appears in interaction, but is not set "\
                            "up.".format(p)
                    raise KeyError(msg)
            for p in self.physics:
                if p not in int_physics:
                    msg = "Physcis {} is set up, but does not appear in any "\
                            "interaction.".format(p)
                    raise KeyError(msg)


    def _setup_electro_problem(self, parameters):
        self.electro_problem = ElectroProblem(self.geometries[Physics.ELECTRO],
                                                self.time, parameters)


    def _setup_solid_problem(self, parameters):
        self.solid_problem = SolidProblem(self.geometries[Physics.SOLID],
                                                self.time, parameters)


    def _setup_fluid_problem(self, parameters):
        self.fluid_problem = FluidProblem(self.geometries[Physics.FLUID],
                                                self.time, parameters)


    def _setup_porous_problem(self, parameters):
        self.porous_problem = PorousProblem(self.geometries[Physics.POROUS],
                                                self.time, parameters)


    def update_parameters(self, physics, parameters):
        if physics == Physics.ELECTRO:
            self.parameters.set_electro_parameters(parameters)
        elif physics == Physics.SOLID:
            self.parameters.set_solid_parameters(parameters)
        elif physics == Physics.FLUID:
            self.parameters.set_fluid_parameters(parameters)
        elif physics == Physics.POROUS:
            self.parameters.set_porous_parameters(parameters)
示例#9
0
def solve_compliance_maximization_problem(
    W, P, p, p_locals, equilibrium_solve,
    phasefield_penalty_weight,
    phasefield_collision_distance,
    phasefield_iteration_stepsize,
    phasefield_meanvalue_stepsize,
    minimum_phasefield_meanvalue=None,
    maximum_phasefield_meanvalue=None,
    minimum_residual_energy=None,
    callback_at_each_phasefield_iteration=None,
    callback_at_each_phasefield_meanvalue=None,
    ):
    '''
    Parameters
    ----------
    W : dolfin.Form
        Energy (`W(u(p), p)`) to be minimized.
    P : dolfin.Form
        Phasefield penalty (`P(p)`) to be minimized.
    p : dolfin.Function
        Phasefield function (scalar-valued).

    '''

    if not isinstance(p, Function):
        raise TypeError('Parameter `p` must be a `dolfin.Function`')

    if not isinstance(p_locals, (list, tuple)):
        p_locals = (p_locals,)

    if not all(isinstance(p_i, Function) for p_i in p_locals):
        raise TypeError('Parameter `p_locals` must be a sequence of `dolfin.Function`s')

    if callback_at_each_phasefield_meanvalue is None:
        callback_at_each_phasefield_meanvalue = lambda : None
    elif not callable(callback_at_each_phasefield_meanvalue):
        raise TypeError('Parameter `callback_at_each_phasefield_meanvalue` '
                        'must be callable without any arguments')

    if minimum_phasefield_meanvalue is None:
        minimum_phasefield_meanvalue = 0

    if minimum_residual_energy is None:
        minimum_residual_energy = -np.inf

    phasefield_meanvalues = []
    phasefield_iterations = []

    energy_vs_phasefield = []
    energy_vs_iterations = []

    # Phasefield  mean-value target
    p_mean_target = Constant(0.0)

    # Phasefield mean-value constraint
    C = (p - p_mean_target) * dx

    optimizer = optim.TopologyOptimizer(
        W, P, C, p, p_locals, equilibrium_solve,
        callback_at_each_phasefield_iteration)

    p.vector()[:] = sum(p_i.vector() for p_i in p_locals)

    phasefield_meanvalue_i = max(minimum_phasefield_meanvalue,
        assemble(p*dx) / assemble(1*dx(p.function_space().mesh())))

    if maximum_phasefield_meanvalue is None:
        maximum_phasefield_meanvalue = phasefield_meanvalue_i

    elif maximum_phasefield_meanvalue < phasefield_meanvalue_i:
        phasefield_meanvalue_i = maximum_phasefield_meanvalue

    maximum_phasefield_meanvalue += EPS

    phasefield_iterations_i = 0
    iterations_failed = False

    try:

        while phasefield_meanvalue_i < maximum_phasefield_meanvalue:

            logger.info('Solve for phasefield domain fraction '
                        f'{phasefield_meanvalue_i:.3f}')

            p_mean_target.assign(phasefield_meanvalue_i)

            try:

                iterations_count_i, energy_vs_iterations_i = optimizer.optimize(
                    phasefield_iteration_stepsize, phasefield_penalty_weight,
                    phasefield_collision_distance)

            except RuntimeError as exc:

                logger.error(str(exc))
                logger.error('Solver failed for domain fraction '
                             f'{phasefield_meanvalue_i:.3f}')

                iterations_failed = True

                break

            phasefield_iterations_i += iterations_count_i

            phasefield_iterations.append(phasefield_iterations_i)
            phasefield_meanvalues.append(phasefield_meanvalue_i)

            energy_vs_iterations.extend(energy_vs_iterations_i)
            energy_vs_phasefield.append(energy_vs_iterations_i[-1])

            callback_at_each_phasefield_meanvalue()

            if energy_vs_phasefield[-1] < minimum_residual_energy:
                logger.info('Energy converged within threshold')
                break

            phasefield_meanvalue_i += phasefield_meanvalue_stepsize

        else:
            logger.info('Reached phasefield domain fraction limit')

    except KeyboardInterrupt:
        logger.info('Caught a keyboard interrupt')

    return iterations_failed, energy_vs_iterations, energy_vs_phasefield, \
        phasefield_meanvalues, phasefield_iterations, optimizer, p_mean_target
示例#10
0
class BlendedAlgebraicVofModel(VOFMixin, MultiPhaseModel):
    description = 'A blended algebraic VOF scheme implementing HRIC/CICSAM type schemes'

    def __init__(self, simulation):
        """
        A blended algebraic VOF scheme works by using a specific
        convection scheme in the advection of the colour function
        that ensures a sharp interface.

        * The convection scheme should be the name of a convection
          scheme that is tailored for advection of the colour
          function, i.e "HRIC", "MHRIC", "RHRIC" etc,
        * The velocity field should be divergence free

        The colour function is unity when rho=rho0 and nu=nu0 and
        zero when rho=rho1 and nu=nu1
        """
        self.simulation = simulation
        simulation.log.info('Creating blended VOF multiphase model')

        # Define function space and solution function
        V = simulation.data['Vc']
        self.degree = V.ufl_element().degree()
        simulation.data['c'] = Function(V)
        simulation.data['cp'] = Function(V)
        simulation.data['cpp'] = Function(V)

        # The projected density and viscosity functions for the new time step can be made continuous
        self.continuous_fields = simulation.input.get_value(
            'multiphase_solver/continuous_fields', CONTINUOUS_FIELDS, 'bool')
        if self.continuous_fields:
            simulation.log.info('    Using continuous rho and nu fields')
            mesh = simulation.data['mesh']
            V_cont = dolfin.FunctionSpace(mesh, 'CG', self.degree + 1)
            self.continuous_c = dolfin.Function(V_cont)
            self.continuous_c_old = dolfin.Function(V_cont)
            self.continuous_c_oldold = dolfin.Function(V_cont)

        self.force_bounded = simulation.input.get_value(
            'multiphase_solver/force_bounded', FORCE_BOUNDED, 'bool')
        self.force_sharp = simulation.input.get_value(
            'multiphase_solver/force_sharp', FORCE_SHARP, 'bool')

        # Calculate mu from rho and nu (i.e mu is quadratic in c) or directly from c (linear in c)
        self.calculate_mu_directly_from_colour_function = simulation.input.get_value(
            'multiphase_solver/calculate_mu_directly_from_colour_function',
            CALCULATE_MU_DIRECTLY_FROM_COLOUR_FUNCTION,
            'bool',
        )

        # Get the physical properties
        self.set_physical_properties(read_input=True)

        # The convection blending function that counteracts numerical diffusion
        scheme = simulation.input.get_value('convection/c/convection_scheme',
                                            CONVECTION_SCHEME, 'string')
        simulation.log.info(
            '    Using convection scheme %s for the colour function' % scheme)
        scheme_class = get_convection_scheme(scheme)
        self.convection_scheme = scheme_class(simulation, 'c')
        self.need_gradient = scheme_class.need_alpha_gradient

        # Create the equations when the simulation starts
        simulation.hooks.add_pre_simulation_hook(
            self.on_simulation_start,
            'BlendedAlgebraicVofModel setup equations')

        # Update the rho and nu fields before each time step
        simulation.hooks.add_pre_timestep_hook(
            self.update, 'BlendedAlgebraicVofModel - update colour field')
        simulation.hooks.register_custom_hook_point('MultiPhaseModelUpdated')

        # Linear solver
        # This causes the MPI unit tests to fail in "random" places for some reason
        # Quick fix: lazy loading of the solver
        LAZY_LOAD_SOLVER = True
        if LAZY_LOAD_SOLVER:
            self.solver = None
        else:
            self.solver = linear_solver_from_input(
                self.simulation, 'solver/c', default_parameters=SOLVER_OPTIONS)

        # Subcycle the VOF calculation multiple times per Navier-Stokes time step
        self.num_subcycles = scheme = simulation.input.get_value(
            'multiphase_solver/num_subcycles', NUM_SUBCYCLES, 'int')
        if self.num_subcycles < 1:
            self.num_subcycles = 1

        # Time stepping based on the subcycled values
        if self.num_subcycles == 1:
            self.cp = simulation.data['cp']
            self.cpp = simulation.data['cpp']
        else:
            self.cp = dolfin.Function(V)
            self.cpp = dolfin.Function(V)

        # Plot density and viscosity fields for visualization
        self.plot_fields = simulation.input.get_value(
            'multiphase_solver/plot_fields', PLOT_FIELDS, 'bool')
        if self.plot_fields:
            V_plot = V if not self.continuous_fields else V_cont
            self.rho_for_plot = Function(V_plot)
            self.nu_for_plot = Function(V_plot)
            self.rho_for_plot.rename('rho', 'Density')
            self.nu_for_plot.rename('nu', 'Kinematic viscosity')
            simulation.io.add_extra_output_function(self.rho_for_plot)
            simulation.io.add_extra_output_function(self.nu_for_plot)

        # Slope limiter in case we are using DG1, not DG0
        self.slope_limiter = SlopeLimiter(simulation, 'c',
                                          simulation.data['c'])
        simulation.log.info('    Using slope limiter: %s' %
                            self.slope_limiter.limiter_method)
        self.is_first_timestep = True

    def on_simulation_start(self):
        """
        This runs when the simulation starts. It does not run in __init__
        since the solver needs the density and viscosity we define, and
        we need the velocity that is defined by the solver
        """
        sim = self.simulation
        beta = self.convection_scheme.blending_function

        # The time step (real value to be supplied later)
        self.dt = Constant(sim.dt / self.num_subcycles)

        # Setup the equation to solve
        c = sim.data['c']
        cp = self.cp
        cpp = self.cpp
        dirichlet_bcs = sim.data['dirichlet_bcs'].get('c', [])

        # Use backward Euler (BDF1) for timestep 1
        self.time_coeffs = Constant([1, -1, 0])

        if dolfin.norm(cpp.vector()) > 0 and self.num_subcycles == 1:
            # Use BDF2 from the start
            self.time_coeffs.assign(Constant([3 / 2, -2, 1 / 2]))
            sim.log.info(
                'Using second order timestepping from the start in BlendedAlgebraicVOF'
            )

        # Make sure the convection scheme has something useful in the first iteration
        c.assign(sim.data['cp'])

        if self.num_subcycles > 1:
            cp.assign(sim.data['cp'])

        # Plot density and viscosity
        self.update_plot_fields()

        # Define equation for advection of the colour function
        #    ∂c/∂t +  ∇⋅(c u) = 0
        Vc = sim.data['Vc']
        project_dgt0 = sim.input.get_value(
            'multiphase_solver/project_uconv_dgt0', True, 'bool')
        if self.degree == 0 and project_dgt0:
            self.vel_dgt0_projector = VelocityDGT0Projector(
                sim, sim.data['u_conv'])
            self.u_conv = self.vel_dgt0_projector.velocity
        else:
            self.u_conv = sim.data['u_conv']
        forcing_zones = sim.data['forcing_zones'].get('c', [])
        self.eq = AdvectionEquation(
            sim,
            Vc,
            cp,
            cpp,
            self.u_conv,
            beta,
            time_coeffs=self.time_coeffs,
            dirichlet_bcs=dirichlet_bcs,
            forcing_zones=forcing_zones,
            dt=self.dt,
        )

        if self.need_gradient:
            # Reconstruct the gradient from the colour function DG0 field
            self.convection_scheme.initialize_gradient()

        # Notify listeners that the initial values are available
        sim.hooks.run_custom_hook('MultiPhaseModelUpdated')

    def get_colour_function(self, k):
        """
        Return the colour function on timestep t^{n+k}
        """
        if k == 0:
            if self.continuous_fields:
                c = self.continuous_c
            else:
                c = self.simulation.data['c']
        elif k == -1:
            if self.continuous_fields:
                c = self.continuous_c_old
            else:
                c = self.simulation.data['cp']
        elif k == -2:
            if self.continuous_fields:
                c = self.continuous_c_oldold
            else:
                c = self.simulation.data['cpp']

        if self.force_bounded:
            c = dolfin.max_value(dolfin.min_value(c, Constant(1.0)),
                                 Constant(0.0))

        if self.force_sharp:
            c = dolfin.conditional(dolfin.ge(c, 0.5), Constant(1.0),
                                   Constant(0.0))

        return c

    def update_plot_fields(self):
        """
        These fields are only needed to visualise the rho and nu fields
        in xdmf format for Paraview or similar
        """
        if not self.plot_fields:
            return
        V = self.rho_for_plot.function_space()
        dolfin.project(self.get_density(0), V, function=self.rho_for_plot)
        dolfin.project(self.get_laminar_kinematic_viscosity(0),
                       V,
                       function=self.nu_for_plot)

    def update(self, timestep_number, t, dt):
        """
        Update the VOF field by advecting it for a time dt
        using the given divergence free velocity field
        """
        timer = dolfin.Timer('Ocellaris update VOF')
        sim = self.simulation

        # Get the functions
        c = sim.data['c']
        cp = sim.data['cp']
        cpp = sim.data['cpp']

        # Stop early if the free surface is forced to stay still
        force_static = sim.input.get_value('multiphase_solver/force_static',
                                           FORCE_STATIC, 'bool')
        if force_static:
            c.assign(cp)
            cpp.assign(cp)
            timer.stop()  # Stop timer before hook
            sim.hooks.run_custom_hook('MultiPhaseModelUpdated')
            self.is_first_timestep = False
            return

        if timestep_number != 1:
            # Update the previous values
            cpp.assign(cp)
            cp.assign(c)

            if self.degree == 0:
                self.vel_dgt0_projector.update()

        # Reconstruct the gradients
        if self.need_gradient:
            self.convection_scheme.gradient_reconstructor.reconstruct()

        # Update the convection blending factors
        is_static = isinstance(self.convection_scheme, StaticScheme)
        if not is_static:
            self.convection_scheme.update(dt / self.num_subcycles, self.u_conv)

        # Update global bounds in slope limiter
        if self.is_first_timestep:
            lo, hi = self.slope_limiter.set_global_bounds(lo=0.0, hi=1.0)
            if self.slope_limiter.has_global_bounds:
                sim.log.info(
                    'Setting global bounds [%r, %r] in BlendedAlgebraicVofModel'
                    % (lo, hi))

        # Solve the advection equations for the colour field
        if timestep_number == 1 or is_static:
            c.assign(cp)
        else:
            if self.solver is None:
                sim.log.info('Creating colour function solver', flush=True)
                self.solver = linear_solver_from_input(
                    self.simulation,
                    'solver/c',
                    default_parameters=SOLVER_OPTIONS)

            # Solve the advection equation
            A = self.eq.assemble_lhs()
            for _ in range(self.num_subcycles):
                b = self.eq.assemble_rhs()
                self.solver.inner_solve(A, c.vector(), b, 1, 0)
                self.slope_limiter.run()
                if self.num_subcycles > 1:
                    self.cpp.assign(self.cp)
                    self.cp.assign(c)

        # Optionally use a continuous predicted colour field
        if self.continuous_fields:
            Vcg = self.continuous_c.function_space()
            dolfin.project(c, Vcg, function=self.continuous_c)
            dolfin.project(cp, Vcg, function=self.continuous_c_old)
            dolfin.project(cpp, Vcg, function=self.continuous_c_oldold)

        # Report properties of the colour field
        sim.reporting.report_timestep_value('min(c)', c.vector().min())
        sim.reporting.report_timestep_value('max(c)', c.vector().max())

        # The next update should use the dt from this time step of the
        # main Navier-Stoke solver. The update just computed above uses
        # data from the previous Navier-Stokes solve with the previous dt
        self.dt.assign(dt / self.num_subcycles)

        if dt != sim.dt_prev:
            # Temporary switch to first order timestepping for the next
            # time step. This code is run before the Navier-Stokes solver
            # in each time step
            sim.log.info(
                'VOF solver is first order this time step due to change in dt')
            self.time_coeffs.assign(Constant([1.0, -1.0, 0.0]))
        else:
            # Use second order backward time difference next time step
            self.time_coeffs.assign(Constant([3 / 2, -2.0, 1 / 2]))

        self.update_plot_fields()
        timer.stop()  # Stop timer before hook
        sim.hooks.run_custom_hook('MultiPhaseModelUpdated')
        self.is_first_timestep = False
示例#11
0
        # Set final time
        # Initialize value at T[1]
        t = trange[1]
        vold = u_T_numpy(X, Y)

        if storeV:
            Vsol = np.ndarray([nt + 1, len(ydofs), len(xdofs)])
            Vsol[0, :, :] = vold

        L_ = gamma * f * test * dx(mx)

        for i, t in enumerate(trange[1:]):
            print('Solve problem, time step t = {}'.format(np.round(t, 4)))

            # Assign current time to variable t_
            t_.assign(t)

            # Compute Ytilde, i.e. y-position of process starting in x_i,y_j
            # after application of convection in y-direction
            Ytilde = Y + by(t, X, Y) * dt[i]
            Vtilde = Yinterp1(vold, Ytilde, ydofs, ydiff)

            # Set up problem
            Sfull = M - dt[i] * S

            # Apply boundary conditions
            bc_Vx.apply(Sfull)

            # Loop over all layers in y-direction
            for j in range(ny + 1):
示例#12
0
class CavityProblemSetup():
    def __init__(self, parameters, mesh_name, facet_name):
        """
        Create the required function spaces, functions and boundary conditions
        for a channel flow problem
        """
        self.mesh = Mesh()
        with XDMFFile(mesh_name) as infile:
            infile.read(self.mesh)

        mvc = MeshValueCollection("size_t", self.mesh,
                                  self.mesh.topology().dim() - 1)
        with XDMFFile(facet_name) as infile:
            infile.read(mvc, "name_to_read")
        mf = self.mf = cpp.mesh.MeshFunctionSizet(self.mesh, mvc)
        self.bc_dict = {"bottom": 1, "right": 2, "top": 3, "left": 4}

        T_init = Constant(parameters["initial temperature [°C]"])
        self.t_amb = Constant(parameters["ambient temperature [°C]"])
        self.t_feeder = Constant(parameters["temperature feeder [°C]"])
        self.k_top = Constant(parameters["thermal conductivity top [W/(m K)]"])
        self.k_lft = Constant(
            parameters["thermal conductivity left [W/(m K)]"])
        self.k_btm = Constant(
            parameters["thermal conductivity bottom [W/(m K)]"])
        self.k_rgt = Constant(
            parameters["thermal conductivity right [W/(m K)]"])
        self.U_m = Constant(parameters["mean velocity lid [m/s]"])
        g = parameters["gravity [m/s²]"]
        self.g = Constant((0.0, -g))
        self.dt = Constant(parameters["dt [s]"])
        self.D = Constant(parameters["Diffusivity [-]"])

        self.V = V = VectorFunctionSpace(self.mesh, 'P', 2)
        self.Q = Q = FunctionSpace(self.mesh, 'P', 1)
        self.T = T = FunctionSpace(self.mesh, 'P', 1)

        self.ds_ = Measure("ds", domain=self.mesh, subdomain_data=mf)
        self.vu, self.vp, self.vt = (TestFunction(V), TestFunction(Q),
                                     TestFunction(T))
        self.u_, self.p_, self.t_ = Function(V), Function(Q), Function(T)
        self.mu, self.rho = Function(T), Function(T)
        self.u_1, self.p_1, self.t_1, self.rho_1 = (Function(V), Function(Q),
                                                    Function(T), Function(T))
        self.u, self.p, self.t = (TrialFunction(V), TrialFunction(Q),
                                  TrialFunction(T))

        # boundary conditions
        self.no_slip = Constant((0., 0))
        self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"),
                                  m=self.U_m,
                                  degree=2)
        bc0 = DirichletBC(V, self.topflow, mf, self.bc_dict["top"])
        bc1 = DirichletBC(V, self.no_slip, mf, self.bc_dict["left"])
        bc2 = DirichletBC(V, self.no_slip, mf, self.bc_dict["bottom"])
        bc3 = DirichletBC(V, self.no_slip, mf, self.bc_dict["right"])
        # bc4 = df.DirichletBC(Q, df.Constant(0), top)
        # bc3 = df.DirichletBC(T, df.Constant(800), top)
        self.bcu = [bc0, bc1, bc2, bc3]
        self.bcp = [DirichletBC(Q, Constant(0), mf, self.bc_dict["top"])]
        self.bcp = []
        self.bct = []
        # self.bct = [DirichletBC(T, Constant(self.t_feeder), mf,
        #                         self.bc_dict["top"])]

        self.robin_boundary_terms = (
            self.k_btm * (self.t - self.t_amb) * self.vt * self.ds_(1) +
            self.k_rgt * (self.t - self.t_amb) * self.vt * self.ds_(2)
            # + self.k_top*(self.t - self.t_feeder)*self.vt*self.ds_(3)
            + self.k_lft * (self.t - self.t_amb) * self.vt * self.ds_(4))
        print("k, T", self.k_btm.values(), self.t_feeder.values())
        print("k, T", self.k_rgt.values(), self.t_amb.values())
        # print("k, T", self.k_top.values(), self.t_amb.values())
        print("k, T", self.k_lft.values(), self.t_amb.values())

        # set initial values
        # TODO: find a better solution
        x, y = T.tabulate_dof_coordinates().T
        self.u_1.vector().vec().array[:] = 1e-6
        # self.u_k.vector().vec().array[:] = 1e-6
        self.p_.vector().vec(
        ).array[:] = -self.rho.vector().vec().array * g * y
        self.p_1.vector().vec(
        ).array[:] = -self.rho.vector().vec().array * g * y
        self.t_1.vector().vec().array = T_init
        self.t_.assign(self.t_1)
        return

    def stokes(self):
        P2 = VectorElement("CG", self.mesh.ufl_cell(), 2)
        P1 = FiniteElement("CG", self.mesh.ufl_cell(), 1)
        TH = P2 * P1
        VQ = FunctionSpace(self.mesh, TH)
        mf = self.mf
        self.no_slip = Constant((0., 0))
        self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"),
                                  m=self.U_m,
                                  degree=2)
        bc0 = DirichletBC(VQ.sub(0), self.topflow, mf, self.bc_dict["top"])
        bc1 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["left"])
        bc2 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["bottom"])
        bc3 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["right"])
        # bc4 = DirichletBC(VQ.sub(1), Constant(0), mf, self.bc_dict["top"])
        bcs = [bc0, bc1, bc2, bc3]

        vup = TestFunction(VQ)
        up = TrialFunction(VQ)
        # the solution will be in here:
        up_ = Function(VQ)

        u, p = split(up)  # Trial
        vu, vp = split(vup)  # Test
        u_, p_ = split(up_)  # Function holding the solution
        F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \
            - inner(vp, div(u))*dx + dot(self.g*self.rho, vu)*dx
        solve(lhs(F) == rhs(F), up_, bcs=bcs)
        self.u_.assign(project(u_, self.V))
        self.p_.assign(project(p_, self.Q))
        return

    def initial_condition_from_file(self, path_u, path_p):
        f_in = XDMFFile(path_u)
        f_in.read_checkpoint(self.u_, "f", 0)
        f_in = XDMFFile(path_p)
        f_in.read_checkpoint(self.p_, "f", 0)
        return

    def get_rho(self):
        return self.rho.vector().vec().array

    def set_rho(self, rho):
        self.rho.vector().vec().array[:] = rho

    def get_mu(self):
        return self.mu.vector().vec().array

    def set_mu(self, mu):
        self.mu.vector().vec().array[:] = mu

    def get_t(self):
        return self.t_.vector().vec().array

    def set_t(self, t):
        self.t_.vector().vec().array[:] = t

    def get_dt(self):
        return self.dt.values()

    def set_dt(self, dt):
        self.dt.assign(dt)

    def get_D(self):
        return self.D.values()

    def set_D(self, D):
        self.D.assign(D)

    def get_t_amb(self):
        return self.t_amb.values()

    def set_t_amb(self, t_amb):
        self.t_amb.assign(t_amb)

    def plot(self):
        cmap = mpl.cm.inferno
        cmap_r = mpl.cm.inferno_r
        u, p, t, m, r = self.u_, self.p_, self.t_, self.mu, self.rho
        mesh = self.mesh
        w0 = u.compute_vertex_values(mesh)
        w0.shape = (2, -1)
        magnitude = np.linalg.norm(w0, axis=0)
        x, y = np.split(mesh.coordinates(), 2, 1)
        u, v = np.split(w0, 2, 0)
        x, y, u, v = x.ravel(), y.ravel(), u.ravel(), v.ravel()
        tri = mesh.cells()
        pressure = p.compute_vertex_values(mesh)
        temperature = t.compute_vertex_values(mesh)
        viscosity = m.compute_vertex_values(mesh)
        density = r.compute_vertex_values(mesh)

        fig = plt.figure(figsize=(12, 8))
        ax1 = plt.subplot(121)
        ax2 = plt.subplot(243, sharex=ax1, sharey=ax1)
        ax3 = plt.subplot(244, sharex=ax1, sharey=ax1)
        ax4 = plt.subplot(247, sharex=ax1, sharey=ax1)
        ax5 = plt.subplot(248, sharex=ax1, sharey=ax1)
        ax1.plot(x, y, "k.", ms=.5)
        not0 = magnitude > 1e-6
        if np.sum(not0) > 0:
            ax1.quiver(x[not0], y[not0], u[not0], v[not0], magnitude[not0])
        c2 = ax2.tricontourf(x, y, tri, pressure, levels=40, cmap=cmap)
        c3 = ax3.tricontourf(x, y, tri, temperature, levels=40, cmap=cmap)
        c4 = ax4.tricontourf(
            x,
            y,
            tri,
            viscosity,
            levels=40,
            # vmin=self.mu(800, .1), vmax=self.mu(600, .1),
            cmap=cmap_r)
        c5 = ax5.tricontourf(
            x,
            y,
            tri,
            density,
            levels=40,
            # vmin=self.rho(800.), vmax=self.rho(600.),
            cmap=cmap_r)
        plt.colorbar(c2, ax=ax2)
        plt.colorbar(c3, ax=ax3, ticks=[temperature.min(), temperature.max()])
        plt.colorbar(c4, ax=ax4, ticks=[viscosity.min(), viscosity.max()])
        plt.colorbar(c5, ax=ax5, ticks=[density.min(), density.max()])
        ax1.set_aspect("equal")
        ax2.set_aspect("equal")
        ax3.set_aspect("equal")
        ax4.set_aspect("equal")
        ax5.set_aspect("equal")
        ax1.set_title("velocity\n{:.4f} ... {:.5f} m/s".format(
            magnitude.min(), magnitude.max()))
        ax2.set_title("pressure")
        ax3.set_title("temperature")
        ax4.set_title("viscosity")
        ax5.set_title("density")
        ax1.set_xlim([-.1, 1.1])
        ax1.set_ylim([-.1, 1.1])
        # plt.tight_layout()
        return fig, (ax1, ax2)
示例#13
0
    t1 = Timer("[P] Assign and output")
    # Needed for particle advection
    assign(Udiv, Uh.sub(0))

    # Needed for constrained map
    assign(ubar0_a, Uhbar.sub(0))
    assign(u0_a, ustar)
    assign(duh00, duh0)
    assign(duh0, project(Uh.sub(0) - ustar, W_2))

    p.increment(Udiv.cpp_object(), ustar.cpp_object(),
                np.array([1, 2], dtype=np.uintp), theta_p, step)

    if step == 2:
        theta_L.assign(theta_next)

    # Probably can be combined into one file?
    xdmf_u.write(Uh.sub(0), t)
    xdmf_p.write(Uh.sub(1), t)
    del t1

timer.stop()

# Compute errors
u_exact.t = t
p_exact.t = t

u_error = sqrt(assemble(dot(Uh.sub(0) - u_exact, Uh.sub(0) - u_exact) * dx))
p_error = sqrt(assemble(dot(Uh.sub(1) - p_exact, Uh.sub(1) - p_exact) * dx))
udiv = sqrt(assemble(div(Uh.sub(0)) * div(Uh.sub(0)) * dx))
示例#14
0
    Uvector = 3 * as_backend_type(u_n.vector()).get_local()
    _3u_n.vector().set_local(Uvector)
    _3u_A, _3u_B, _3u_C, _3u_T = _3u_n.split()
    _u_D = _3u_C

    if Data_postprocessing:
        fA_out.write_checkpoint(_u_A, "A", t, XDMFFile.Encoding.HDF5, True)
        fB_out.write_checkpoint(_u_B, "B", t, XDMFFile.Encoding.HDF5, True)
        fC_out.write_checkpoint(_u_C, "C", t, XDMFFile.Encoding.HDF5, True)
        fD_out.write_checkpoint(_u_D, "D", t, XDMFFile.Encoding.HDF5, True)
        fT_out.write_checkpoint(_u_T, "T", t, XDMFFile.Encoding.HDF5, True)

    Twall_n = Twall
    ufl_integral = assemble(_u_T * ds_wall)
    Numer = (roW * Vw *
             Cpw) / dt * Twall_n + fw * Cpw * Tcool_in + hw * A * ufl_integral
    Twall_new = Numer / Denom
    print('Wall temperature {} K'.format(np.around(float(Twall_new), 4)))

    Twall.assign(Twall_new)
    u_n.assign(u)

fA_out.close()
fB_out.close()
fC_out.close()
fD_out.close()
fT_out.close()
End_St = dtm.datetime.now()  # The end time of execution----------------------
Execution_time(Start_St, End_St, 'Reports', 'PhtAnh_PBR', True)
# _______________END_______________ #