Пример #1
0
def test_save_1d_tensor(tempfile, file_options):
    mesh = UnitIntervalMesh(MPI.COMM_WORLD, 32)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    u.vector.set(1)
    VTKFile(tempfile + "u.pvd").write(u)
    for file_option in file_options:
        VTKFile(tempfile + "u.pvd", file_option).write(u)
Пример #2
0
def test_save_3d_tensor(tempdir, encoding, cell_type):
    filename = os.path.join(tempdir, "u3t.xdmf")
    mesh = UnitCubeMesh(MPI.comm_world, 4, 4, 4, cell_type)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    u.vector.set(1.0 + (1j if has_petsc_complex else 0))
    with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file:
        file.write(u)
Пример #3
0
def test_save_2d_tensor(tempdir, encoding, cell_type):
    filename = os.path.join(tempdir, "tensor.xdmf")
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 16, 16, cell_type)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    u.vector.set(1.0 + (1j if has_petsc_complex else 0))
    with XDMFFile(mesh.mpi_comm(), filename, "w", encoding=encoding) as file:
        file.write_mesh(mesh)
        file.write_function(u)
Пример #4
0
def test_save_3d_tensor(tempdir):
    mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    with u.vector.localForm() as loc:
        loc.set(1.0)

    filename = os.path.join(tempdir, "u.pvd")
    with VTKFile(mesh.mpi_comm(), filename, "w") as vtk:
        vtk.write_function(u, 0.)
Пример #5
0
def test_save_3d_tensor(tempfile, file_options):
    mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    u.vector.set(1)
    VTKFile(tempfile + "u.pvd").write(u)
    f = VTKFile(tempfile + "u.pvd")
    f.write(u, 0.)
    f.write(u, 1.)
    for file_option in file_options:
        VTKFile(tempfile + "u.pvd", file_option).write(u)
Пример #6
0
def test_save_2d_tensor(tempfile, file_options):
    mesh = UnitSquareMesh(MPI.comm_world, 16, 16)
    u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2)))
    u.vector.set(1)
    VTKFile(tempfile + "u.pvd").write(u)
    f = VTKFile(tempfile + "u.pvd")
    f.write(u, 0.)
    f.write(u, 1.)
    for file_option in file_options:
        VTKFile(tempfile + "u.pvd", file_option).write(u)
Пример #7
0
def Q(mesh):
    return TensorFunctionSpace(mesh, ('CG', 1))
Пример #8
0
    def __init__(self, io_params, time_params, fem_params, constitutive_models, bc_dict, time_curves, io, comm=None):
        problem_base.__init__(self, io_params, time_params, comm)

        self.problem_physics = 'solid'

        self.simname = io_params['simname']

        self.io = io
        
        # number of distinct domains (each one has to be assigned a own material model)
        self.num_domains = len(constitutive_models)

        self.order_disp = fem_params['order_disp']
        try: self.order_pres = fem_params['order_pres']
        except: self.order_pres = 1
        self.quad_degree = fem_params['quad_degree']
        self.incompressible_2field = fem_params['incompressible_2field']
        
        self.fem_params = fem_params
        self.constitutive_models = constitutive_models

        # collect domain data
        self.dx_, self.rho0, self.rayleigh, self.eta_m, self.eta_k = [], [], [False]*self.num_domains, [], []
        for n in range(self.num_domains):
            # integration domains
            self.dx_.append(dx(subdomain_data=self.io.mt_d, subdomain_id=n+1, metadata={'quadrature_degree': self.quad_degree}))
            # data for inertial and viscous forces: density and damping
            if self.timint != 'static':
                self.rho0.append(constitutive_models['MAT'+str(n+1)+'']['inertia']['rho0'])
                if 'rayleigh_damping' in constitutive_models['MAT'+str(n+1)+''].keys():
                    self.rayleigh[n] = True
                    self.eta_m.append(constitutive_models['MAT'+str(n+1)+'']['rayleigh_damping']['eta_m'])
                    self.eta_k.append(constitutive_models['MAT'+str(n+1)+'']['rayleigh_damping']['eta_k'])

        try: self.prestress_initial = fem_params['prestress_initial']
        except: self.prestress_initial = False

        # type of discontinuous function spaces
        if str(self.io.mesh.ufl_cell()) == 'tetrahedron' or str(self.io.mesh.ufl_cell()) == 'triangle3D':
            dg_type = "DG"
            if (self.order_disp > 1 or self.order_pres > 1) and self.quad_degree < 3:
                raise ValueError("Use at least a quadrature degree of 3 or more for higher-order meshes!")
        elif str(self.io.mesh.ufl_cell()) == 'hexahedron' or str(self.io.mesh.ufl_cell()) == 'quadrilateral3D':
            dg_type = "DQ"
            if (self.order_disp > 1 or self.order_pres > 1) and self.quad_degree < 5:
                raise ValueError("Use at least a quadrature degree of 5 or more for higher-order meshes!")
        else:
            raise NameError("Unknown cell/element type!")
        
        # create finite element objects for u and p
        P_u = VectorElement("CG", self.io.mesh.ufl_cell(), self.order_disp)
        P_p = FiniteElement("CG", self.io.mesh.ufl_cell(), self.order_pres)
        # function spaces for u and p
        self.V_u = FunctionSpace(self.io.mesh, P_u)
        self.V_p = FunctionSpace(self.io.mesh, P_p)

        # Quadrature tensor, vector, and scalar elements
        Q_tensor = TensorElement("Quadrature", self.io.mesh.ufl_cell(), degree=1, quad_scheme="default")
        Q_vector = VectorElement("Quadrature", self.io.mesh.ufl_cell(), degree=1, quad_scheme="default")
        Q_scalar = FiniteElement("Quadrature", self.io.mesh.ufl_cell(), degree=1, quad_scheme="default")

        # not yet working - we cannot interpolate into Quadrature elements with the current dolfinx version currently!
        #self.Vd_tensor = FunctionSpace(self.io.mesh, Q_tensor)
        #self.Vd_vector = FunctionSpace(self.io.mesh, Q_vector)
        #self.Vd_scalar = FunctionSpace(self.io.mesh, Q_scalar)

        # Quadrature function spaces (currently not properly functioning for higher-order meshes!!!)
        self.Vd_tensor = TensorFunctionSpace(self.io.mesh, (dg_type, self.order_disp-1))
        self.Vd_vector = VectorFunctionSpace(self.io.mesh, (dg_type, self.order_disp-1))
        self.Vd_scalar = FunctionSpace(self.io.mesh, (dg_type, self.order_disp-1))

        # functions
        self.du    = TrialFunction(self.V_u)            # Incremental displacement
        self.var_u = TestFunction(self.V_u)             # Test function
        self.dp    = TrialFunction(self.V_p)            # Incremental pressure
        self.var_p = TestFunction(self.V_p)             # Test function
        self.u     = Function(self.V_u, name="Displacement")
        self.p     = Function(self.V_p, name="Pressure")
        # values of previous time step
        self.u_old = Function(self.V_u)
        self.v_old = Function(self.V_u)
        self.a_old = Function(self.V_u)
        self.p_old = Function(self.V_p)
        # a setpoint displacement for multiscale analysis
        self.u_set = Function(self.V_u)
        self.p_set = Function(self.V_p)
        self.tau_a_set = Function(self.Vd_scalar)
        # initial (zero) functions for initial stiffness evaluation (e.g. for Rayleigh damping)
        self.u_ini, self.p_ini, self.theta_ini, self.tau_a_ini = Function(self.V_u), Function(self.V_p), Function(self.Vd_scalar), Function(self.Vd_scalar)
        self.theta_ini.vector.set(1.0)
        self.theta_ini.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
        # growth stretch
        self.theta = Function(self.Vd_scalar, name="theta")
        self.theta_old = Function(self.Vd_scalar)
        self.growth_thres = Function(self.Vd_scalar)
        # initialize to one (theta = 1 means no growth)
        self.theta.vector.set(1.0), self.theta_old.vector.set(1.0)
        self.theta.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD), self.theta_old.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
        # active stress
        self.tau_a = Function(self.Vd_scalar, name="tau_a")
        self.tau_a_old = Function(self.Vd_scalar)
        self.amp_old, self.amp_old_set = Function(self.Vd_scalar), Function(self.Vd_scalar)
        self.amp_old.vector.set(1.0), self.amp_old_set.vector.set(1.0)
        self.amp_old.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD), self.amp_old_set.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
        # prestressing history defgrad and spring prestress
        if self.prestress_initial:
            self.F_hist = Function(self.Vd_tensor, name="Defgrad_hist")
            self.u_pre = Function(self.V_u)
        else:
            self.F_hist = None
            self.u_pre = None
        
        self.internalvars     = {"theta" : self.theta, "tau_a" : self.tau_a}
        self.internalvars_old = {"theta" : self.theta_old, "tau_a" : self.tau_a_old}
        
        
        # reference coordinates
        self.x_ref = Function(self.V_u)
        self.x_ref.interpolate(self.x_ref_expr)
        
        if self.incompressible_2field:
            self.ndof = self.u.vector.getSize() + self.p.vector.getSize()
        else:
            self.ndof = self.u.vector.getSize()

        # initialize solid time-integration class
        self.ti = timeintegration.timeintegration_solid(time_params, fem_params, time_curves, self.t_init, self.comm)

        # check for materials that need extra treatment (anisotropic, active stress, growth, ...)
        have_fiber1, have_fiber2 = False, False
        self.have_active_stress, self.active_stress_trig, self.have_frank_starling, self.have_growth = False, 'ode', False, False
        self.mat_active_stress, self.mat_growth, self.mat_remodel, self.mat_growth_dir, self.mat_growth_trig, self.mat_growth_thres = [False]*self.num_domains, [False]*self.num_domains, [False]*self.num_domains, [None]*self.num_domains, [None]*self.num_domains, []*self.num_domains

        self.localsolve, growth_dir = False, None
        self.actstress = []
        for n in range(self.num_domains):
            
            if 'holzapfelogden_dev' in self.constitutive_models['MAT'+str(n+1)+''].keys() or 'guccione_dev' in self.constitutive_models['MAT'+str(n+1)+''].keys():
                have_fiber1, have_fiber2 = True, True
            
            if 'active_fiber' in self.constitutive_models['MAT'+str(n+1)+''].keys():
                have_fiber1 = True
                self.mat_active_stress[n], self.have_active_stress = True, True
                # if one mat has a prescribed active stress, all have to be!
                if 'prescribed_curve' in self.constitutive_models['MAT'+str(n+1)+'']['active_fiber']:
                    self.active_stress_trig = 'prescribed'
                if 'prescribed_multiscale' in self.constitutive_models['MAT'+str(n+1)+'']['active_fiber']:
                    self.active_stress_trig = 'prescribed_multiscale'
                if self.active_stress_trig == 'ode':
                    act_curve = self.ti.timecurves(self.constitutive_models['MAT'+str(n+1)+'']['active_fiber']['activation_curve'])
                    self.actstress.append(activestress_activation(self.constitutive_models['MAT'+str(n+1)+'']['active_fiber'], act_curve))
                    if self.actstress[-1].frankstarling: self.have_frank_starling = True
                if self.active_stress_trig == 'prescribed':
                    self.ti.funcs_to_update.append({self.tau_a : self.ti.timecurves(self.constitutive_models['MAT'+str(n+1)+'']['active_fiber']['prescribed_curve'])})

            if 'active_iso' in self.constitutive_models['MAT'+str(n+1)+''].keys():
                self.mat_active_stress[n], self.have_active_stress = True, True
                # if one mat has a prescribed active stress, all have to be!
                if 'prescribed_curve' in self.constitutive_models['MAT'+str(n+1)+'']['active_iso']:
                    self.active_stress_trig = 'prescribed'
                if 'prescribed_multiscale' in self.constitutive_models['MAT'+str(n+1)+'']['active_iso']:
                    self.active_stress_trig = 'prescribed_multiscale'
                if self.active_stress_trig == 'ode':
                    act_curve = self.ti.timecurves(self.constitutive_models['MAT'+str(n+1)+'']['active_iso']['activation_curve'])
                    self.actstress.append(activestress_activation(self.constitutive_models['MAT'+str(n+1)+'']['active_iso'], act_curve))
                if self.active_stress_trig == 'prescribed':
                    self.ti.funcs_to_update.append({self.tau_a : self.ti.timecurves(self.constitutive_models['MAT'+str(n+1)+'']['active_iso']['prescribed_curve'])})

            if 'growth' in self.constitutive_models['MAT'+str(n+1)+''].keys():
                self.mat_growth[n], self.have_growth = True, True
                self.mat_growth_dir[n] = self.constitutive_models['MAT'+str(n+1)+'']['growth']['growth_dir']
                self.mat_growth_trig[n] = self.constitutive_models['MAT'+str(n+1)+'']['growth']['growth_trig']
                # need to have fiber fields for the following growth options
                if self.mat_growth_dir[n] == 'fiber' or self.mat_growth_trig[n] == 'fibstretch':
                    have_fiber1 = True
                if self.mat_growth_dir[n] == 'radial':
                    have_fiber1, have_fiber2 = True, True
                # in this case, we have a theta that is (nonlinearly) dependent on the deformation, theta = theta(C(u)),
                # therefore we need a local Newton iteration to solve for equilibrium theta (return mapping) prior to entering
                # the global Newton scheme - so flag localsolve to true
                if self.mat_growth_trig[n] != 'prescribed' and self.mat_growth_trig[n] != 'prescribed_multiscale':
                    self.localsolve = True
                    self.mat_growth_thres.append(self.constitutive_models['MAT'+str(n+1)+'']['growth']['growth_thres'])
                else:
                    self.mat_growth_thres.append(as_ufl(0))
                # for the case that we have a prescribed growth stretch over time, append curve to functions that need time updates
                # if one mat has a prescribed growth model, all have to be!
                if self.mat_growth_trig[n] == 'prescribed':
                    self.ti.funcs_to_update.append({self.theta : self.ti.timecurves(self.constitutive_models['MAT'+str(n+1)+'']['growth']['prescribed_curve'])})
                if 'remodeling_mat' in self.constitutive_models['MAT'+str(n+1)+'']['growth'].keys():
                    self.mat_remodel[n] = True
            else:
                self.mat_growth_thres.append(as_ufl(0))
                
        # full linearization of our remodeling law can lead to excessive compiler times for ffcx... :-/
        # let's try if we might can go without one of the critial terms (derivative of remodeling fraction w.r.t. C)
        try: self.lin_remod_full = fem_params['lin_remodeling_full']
        except: self.lin_remod_full = True

        # growth threshold (as function, since in multiscale approach, it can vary element-wise)
        if self.have_growth and self.localsolve:
            growth_thres_proj = project(self.mat_growth_thres, self.Vd_scalar, self.dx_)
            self.growth_thres.vector.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
            self.growth_thres.interpolate(growth_thres_proj)
        
        # read in fiber data
        if have_fiber1:

            fibarray = ['fiber']
            if have_fiber2: fibarray.append('sheet')

            # fiber function space - vector defined on quadrature points
            V_fib = self.Vd_vector
            self.fib_func = self.io.readin_fibers(fibarray, V_fib, self.dx_)

        else:
            self.fib_func = None

        
        # for multiscale G&R analysis
        self.tol_stop_large = 0

        # initialize kinematics class
        self.ki = solid_kinematics_constitutive.kinematics(fib_funcs=self.fib_func, F_hist=self.F_hist)

        # initialize material/constitutive class
        self.ma = []
        for n in range(self.num_domains):
            self.ma.append(solid_kinematics_constitutive.constitutive(self.ki, self.constitutive_models['MAT'+str(n+1)+''], self.incompressible_2field, mat_growth=self.mat_growth[n], mat_remodel=self.mat_remodel[n]))

        # initialize solid variational form class
        self.vf = solid_variationalform.variationalform(self.var_u, self.du, self.var_p, self.dp, self.io.n0, self.x_ref)
        
        # initialize boundary condition class
        self.bc = boundaryconditions.boundary_cond_solid(bc_dict, self.fem_params, self.io, self.ki, self.vf, self.ti)

        if self.prestress_initial:
            # initialize prestressing history deformation gradient
            Id_proj = project(Identity(len(self.u)), self.Vd_tensor, self.dx_)
            self.F_hist.interpolate(Id_proj)
  
        self.bc_dict = bc_dict
        
        # Dirichlet boundary conditions
        if 'dirichlet' in self.bc_dict.keys():
            self.bc.dirichlet_bcs(self.V_u)

        self.set_variational_forms_and_jacobians()
Пример #9
0
def Q(mesh):
    return TensorFunctionSpace(mesh, ('Lagrange', 1))
Пример #10
0
    def __init__(self,
                 io_params,
                 time_params,
                 fem_params,
                 constitutive_models,
                 bc_dict,
                 time_curves,
                 io,
                 comm=None):
        problem_base.__init__(self, io_params, time_params, comm)

        self.problem_physics = 'fluid'

        self.simname = io_params['simname']

        self.io = io

        # number of distinct domains (each one has to be assigned a own material model)
        self.num_domains = len(constitutive_models)

        self.order_vel = fem_params['order_vel']
        self.order_pres = fem_params['order_pres']
        self.quad_degree = fem_params['quad_degree']

        # collect domain data
        self.dx_, self.rho = [], []
        for n in range(self.num_domains):
            # integration domains
            self.dx_.append(
                dx(subdomain_data=self.io.mt_d,
                   subdomain_id=n + 1,
                   metadata={'quadrature_degree': self.quad_degree}))
            # data for inertial forces: density
            self.rho.append(constitutive_models['MAT' + str(n + 1) +
                                                '']['inertia']['rho'])

        self.incompressible_2field = True  # always true!
        self.localsolve = False  # no idea what might have to be solved locally...
        self.prestress_initial = False  # guess prestressing in fluid is somehow senseless...
        self.p11 = as_ufl(
            0
        )  # can't think of a fluid case with non-zero 11-block in system matrix...

        # type of discontinuous function spaces
        if str(self.io.mesh.ufl_cell()) == 'tetrahedron' or str(
                self.io.mesh.ufl_cell()) == 'triangle3D':
            dg_type = "DG"
            if (self.order_vel > 1
                    or self.order_pres > 1) and self.quad_degree < 3:
                raise ValueError(
                    "Use at least a quadrature degree of 3 or more for higher-order meshes!"
                )
        elif str(self.io.mesh.ufl_cell()) == 'hexahedron' or str(
                self.io.mesh.ufl_cell()) == 'quadrilateral3D':
            dg_type = "DQ"
            if (self.order_vel > 1
                    or self.order_pres > 1) and self.quad_degree < 5:
                raise ValueError(
                    "Use at least a quadrature degree of 5 or more for higher-order meshes!"
                )
        else:
            raise NameError("Unknown cell/element type!")

        # create finite element objects for v and p
        self.P_v = VectorElement("CG", self.io.mesh.ufl_cell(), self.order_vel)
        self.P_p = FiniteElement("CG", self.io.mesh.ufl_cell(),
                                 self.order_pres)
        # function spaces for v and p
        self.V_v = FunctionSpace(self.io.mesh, self.P_v)
        self.V_p = FunctionSpace(self.io.mesh, self.P_p)

        # a discontinuous tensor, vector, and scalar function space
        self.Vd_tensor = TensorFunctionSpace(self.io.mesh,
                                             (dg_type, self.order_vel - 1))
        self.Vd_vector = VectorFunctionSpace(self.io.mesh,
                                             (dg_type, self.order_vel - 1))
        self.Vd_scalar = FunctionSpace(self.io.mesh,
                                       (dg_type, self.order_vel - 1))

        # functions
        self.dv = TrialFunction(self.V_v)  # Incremental velocity
        self.var_v = TestFunction(self.V_v)  # Test function
        self.dp = TrialFunction(self.V_p)  # Incremental pressure
        self.var_p = TestFunction(self.V_p)  # Test function
        self.v = Function(self.V_v, name="Velocity")
        self.p = Function(self.V_p, name="Pressure")
        # values of previous time step
        self.v_old = Function(self.V_v)
        self.a_old = Function(self.V_v)
        self.p_old = Function(self.V_p)

        self.ndof = self.v.vector.getSize() + self.p.vector.getSize()

        # initialize fluid time-integration class
        self.ti = timeintegration.timeintegration_fluid(
            time_params, fem_params, time_curves, self.t_init, self.comm)

        # initialize kinematics_constitutive class
        self.ki = fluid_kinematics_constitutive.kinematics()

        # initialize material/constitutive class
        self.ma = []
        for n in range(self.num_domains):
            self.ma.append(
                fluid_kinematics_constitutive.constitutive(
                    self.ki, constitutive_models['MAT' + str(n + 1) + '']))

        # initialize fluid variational form class
        self.vf = fluid_variationalform.variationalform(
            self.var_v, self.dv, self.var_p, self.dp, self.io.n0)

        # initialize boundary condition class
        self.bc = boundaryconditions.boundary_cond_fluid(
            bc_dict, fem_params, self.io, self.ki, self.vf, self.ti)

        self.bc_dict = bc_dict

        # Dirichlet boundary conditions
        if 'dirichlet' in self.bc_dict.keys():
            self.bc.dirichlet_bcs(self.V_v)

        self.set_variational_forms_and_jacobians()