Exemplo n.º 1
0
 def generateMesh(self, maxh):
     mesh = self.collection.GenerateMesh(maxh=maxh)
     mesh.GenerateVolumeMesh()
     tmp_name = datetime.now().isoformat()
     mesh.Export(f'{tmp_name}.msh', 'Gmsh2 Format')
     meshconvert.convert2xml(f'{tmp_name}.msh', f'{tmp_name}.xml')
     os.remove(f'{tmp_name}.msh')
     os.remove(f'{tmp_name}_facet_region.xml')
     self.mesh = dolfin.Mesh(f'{tmp_name}.xml')
     os.remove(f'{tmp_name}.xml')
     self.domains = dolfin.MeshFunction('size_t', self.mesh,
                                        f'{tmp_name}_physical_region.xml')
     os.remove(f'{tmp_name}_physical_region.xml')
     self.domains.array()[:] -= self.domains.array().min()
     self.boundaries = dolfin.MeshFunction('size_t', self.mesh, 2, 0)
     for ii, subdomain in enumerate(self.csg_boundaries):
         subdomain.mark(self.boundaries, ii + 1)
Exemplo n.º 2
0
 def get(self):
     """ Unzip and convert to xml if possible."""
     mesh = output = None
     import tempfile
     import os
     if not os.path.isfile(self.params):
         return None
     params = self.params
     try:
         split = os.path.splitext(params)
         if split[-1] == '.gz':
             # unzip the mesh
             import gzip
             f = gzip.open(params, 'rb')
             content = f.read()
             f.close()
             input = tempfile.NamedTemporaryFile(
                 suffix=os.path.splitext(split[0])[-1],
                 delete=False)
             input.write(content)
             input.close()
             params = input.name
             split = os.path.splitext(params)
         if split[-1] != '.xml':
             # convert using dolfin's meshconvert
             from dolfin_utils.meshconvert import meshconvert
             output = tempfile.NamedTemporaryFile(
                 suffix='.xml',
                 delete=False)
             output.close()
             meshconvert.convert2xml(params, output.name)
             params = output.name
         # use Mesh constructor with filename
         mesh = Mesh(params)
         try:
             os.unlink(output.name)
         except OSError:
             pass
         os.unlink(input.name)
     # many things could go wrong here
     # just return None as mesh if mesh importing failed
     finally:
         return mesh
Exemplo n.º 3
0
 def get(self):
     """ Unzip and convert to xml if possible."""
     mesh = output = None
     import tempfile
     import os
     if not os.path.isfile(self.params):
         return None
     params = self.params
     try:
         split = os.path.splitext(params)
         if split[-1] == '.gz':
             # unzip the mesh
             import gzip
             f = gzip.open(params, 'rb')
             content = f.read()
             f.close()
             input = tempfile.NamedTemporaryFile(suffix=os.path.splitext(
                 split[0])[-1],
                                                 delete=False)
             input.write(content)
             input.close()
             params = input.name
             split = os.path.splitext(params)
         if split[-1] != '.xml':
             # convert using dolfin's meshconvert
             from dolfin_utils.meshconvert import meshconvert
             output = tempfile.NamedTemporaryFile(suffix='.xml',
                                                  delete=False)
             output.close()
             meshconvert.convert2xml(params, output.name)
             params = output.name
         # use Mesh constructor with filename
         mesh = Mesh(params)
         try:
             os.unlink(output.name)
         except OSError:
             pass
         os.unlink(input.name)
     # many things could go wrong here
     # just return None as mesh if mesh importing failed
     finally:
         return mesh
Exemplo n.º 4
0
def main(argv):
    "Main function"

    # Get command-line arguments
    try:
        opts, args = getopt.getopt(argv, "hi:o:",
                                   ["help", "input=", "output="])
    except getopt.GetoptError:
        usage()
        sys.exit(2)

    # Get options
    iformat = None
    oformat = None
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit()
        elif opt in ("-i", "--input"):
            iformat = arg
        elif opt in ("-o", "--output"):
            oformat = arg

    # Check that we got two filenames
    if not len(args) == 2:
        usage()
        sys.exit(2)

    # Get filenames
    ifilename = args[0]
    ofilename = args[1]

    # Can only convert to XML
    if oformat and oformat != "xml":
        error("Unable to convert to format %s." % (oformat, ))

    # Convert to XML
    meshconvert.convert2xml(ifilename, ofilename, iformat=iformat)
Exemplo n.º 5
0
                "gmsh", "-2", "-o", subdir + meshname + ".msh",
                subdir + meshname + ".geo"
            ])
        except OSError:
            print(
                "-----------------------------------------------------------------------------"
            )
            print(" Error: unable to generate the mesh using gmsh")
            print(
                " Make sure that you have gmsh installed and have added it to your system PATH"
            )
            print(
                "-----------------------------------------------------------------------------"
            )

        meshconvert.convert2xml(subdir + meshname + ".msh",
                                subdir + meshname + ".xml", "gmsh")

    # Convert to XDMF
    MPI.barrier(mpi_comm_world())
    mesh = Mesh(subdir + meshname + ".xml")
    XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
    XDMF.write(mesh)
    XDMF.read(_mesh)

    if os.path.isfile(subdir + meshname +
                      "_physical_region.xml") and os.path.isfile(
                          subdir + meshname + "_facet_region.xml"):
        if MPI.rank(mpi_comm_world()) == 0:
            mesh = Mesh(subdir + meshname + ".xml")
            subdomains = MeshFunction(
                "size_t", mesh, subdir + meshname + "_physical_region.xml")
Exemplo n.º 6
0
def Fracking(hsize, pressure_max, ell, E, nu, Model, law):
    #=======================================================================================
    # Input date
    #=======================================================================================
    # Geometry
    L = 4.0  # length
    H = 4.0  # height
    #hsize= 0.01 # target cell size
    meshname = "fracking_hsize%g" % (hsize)

    # Material constants
    #ell = Constant(4 * hsize) # internal length scale
    #E = 10. # Young modulus
    #nu = 0.3 # Poisson ratio

    biot = 0.  #Biot coefficient

    PlaneStress = False

    gc = 1.  # fracture toughness
    k_ell = Constant(1.0e-12)  # residual stiffness
    #law = "AT1"

    # effective toughness
    if law == "AT2":
        Gc = gc / (1 + hsize / (2 * ell))  #AT2
    elif law == "AT1":
        Gc = gc / (1 + 3 * hsize / (8 * ell))  #AT1
    else:
        Gc = gc

    Gc = 1.

    ModelB = False
    if not ModelB:  # Model A (isotropic model)
        Model = 'Isotropic'
    else:  # Model B (Amor's model)
        Model = 'Amor'

    # Stopping criteria for the alternate minimization
    max_iterations = 50
    tolerance = 1.0e-5

    # Loading
    ut = 0.0  # reference value for the loading (imposed displacement)
    body_force = Constant((0., 0.))  # bulk load
    pressure_min = 0.  # load multiplier min value
    #pressure_max = 1. # load multiplier max value
    pressure_steps = 10  # number of time steps

    WheelerApproach = False

    #=======================================================================================
    # Geometry and mesh generation
    #=======================================================================================
    # Generate a XDMF/HDF5 based mesh from a Gmsh string
    geofile = \
      """
			lc = DefineNumber[ %g, Name "Parameters/lc" ];
			H = 4;
			L = 4;
		        Point(1) = {0, 0, 0, 10*lc};
		        Point(2) = {L, 0, 0, 10*lc};
		        Point(3) = {L, H, 0, 10*lc};
		        Point(4) = {0, H, 0, 10*lc};
		        Point(5) = {1.8, H/2, 0, 1*lc};
		        Point(6) = {2.2, H/2, 0, 1*lc};
		        Line(1) = {1, 2};
		        Line(2) = {2, 3};
		        Line(3) = {3, 4};
		        Line(4) = {4, 1};
		        Line Loop(5) = {1, 2, 3, 4};
			Plane Surface(30) = {5};

			Line(6) = {5, 6};
		        Line{6} In Surface{30};


			Physical Surface(1) = {30};

			Physical Line(101) = {6};

	"""%(hsize)

    subdir = "meshes/"
    _mesh = Mesh()  #creat empty mesh object
    if not os.path.isfile(subdir + meshname + ".xdmf"):
        if MPI.rank(mpi_comm_world()) == 0:
            # Create temporary .geo file defining the mesh
            if os.path.isdir(subdir) == False:
                os.mkdir(subdir)
            fgeo = open(subdir + meshname + ".geo", "w")
            fgeo.writelines(geofile)
            fgeo.close()
            # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
            try:
                subprocess.call([
                    "gmsh", "-2", "-o", subdir + meshname + ".msh",
                    subdir + meshname + ".geo"
                ])
            except OSError:
                print(
                    "-----------------------------------------------------------------------------"
                )
                print(" Error: unable to generate the mesh using gmsh")
                print(
                    " Make sure that you have gmsh installed and have added it to your system PATH"
                )
                print(
                    "-----------------------------------------------------------------------------"
                )

            meshconvert.convert2xml(subdir + meshname + ".msh",
                                    subdir + meshname + ".xml", "gmsh")

        # Convert to XDMF
        MPI.barrier(mpi_comm_world())
        mesh = Mesh(subdir + meshname + ".xml")
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.write(mesh)
        XDMF.read(_mesh)

        if os.path.isfile(subdir + meshname +
                          "_physical_region.xml") and os.path.isfile(
                              subdir + meshname + "_facet_region.xml"):
            if MPI.rank(mpi_comm_world()) == 0:
                mesh = Mesh(subdir + meshname + ".xml")
                subdomains = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_physical_region.xml")
                boundaries = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_facet_region.xml")
                HDF5 = HDF5File(mesh.mpi_comm(),
                                subdir + meshname + "_physical_facet.h5", "w")
                HDF5.write(mesh, "/mesh")
                HDF5.write(subdomains, "/subdomains")
                HDF5.write(boundaries, "/boundaries")
                print("Finish writting physical_facet to HDF5")

        if MPI.rank(mpi_comm_world()) == 0:
            # Keep only the .xdmf mesh
            #os.remove(subdir + meshname + ".geo")
            #os.remove(subdir + meshname + ".msh")
            #os.remove(subdir + meshname + ".xml")

            # Info
            print("Mesh completed")

    # Read the mesh if existing
    else:
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.read(_mesh)

    mesh = Mesh('meshes/fracking_hsize' + str(float(hsize)) + '.xml')
    mesh_fun = MeshFunction(
        "size_t", mesh,
        "meshes/fracking_hsize" + str(float(hsize)) + "_facet_region.xml")
    #plt.figure(1)
    #plot(mesh, "2D mesh")
    #plt.interactive(True)

    ndim = mesh.geometry().dim()  # get number of space dimensions

    #=======================================================================================
    # Constitutive functions of the damage model
    #=======================================================================================
    def a(alpha_):
        """
		Modulation of the elastic stiffness
		"""
        if law == "AT1":
            return (1 - alpha_)**2
        elif law == "AT2":
            return (1 - alpha_)**2
        elif law == "ATk":
            return (1 - w(alpha_)) / (1 + (k - 1) * w(alpha_))

    def w(alpha_):
        """
		Local energy dissipation
		"""
        if law == "AT1":
            return alpha_
        elif law == "AT2":
            return alpha_**2
        elif law == "ATk":
            return 1 - (1 - alpha_)**2

    #=======================================================================================
    # strain, stress and strain energy for Isotropic and Amor's model
    #=======================================================================================
    def angle_bracket_plus(a):
        return (a + abs(a)) / 2

    def angle_bracket_minus(a):
        return (a - abs(a)) / 2

    #----------------------------------------------------------------------------------------
    def g(alpha_):
        """
		degradation function
		"""
        return ((1 - alpha_)**2 + k_ell)

    #----------------------------------------------------------------------------------------
    def eps(u_):
        """
		Geometrical strain
		"""
        return sym(grad(u_))

    def dev_eps(u_):
        """

		"""
        return eps(u_) - 1 / 3 * tr(eps(u_)) * Identity(ndim)

    #----------------------------------------------------------------------------------------
    def sigma0(u_):
        """
		Application of the sound elasticy tensor on the strain tensor
		"""
        Id = Identity(len(u_))
        return 2.0 * mu * eps(u_) + lmbda * tr(eps(u_)) * Id

    def sigma_A(u_, alpha_):
        """
		Stress Model A
		"""
        return g(alpha_) * sigma0(u_)

    def sigma_B(u_, alpha_):
        """
		Stress Model B
		"""
        return g(alpha_) * (
            (lmbda + 2 / 3 * mu) *
            (angle_bracket_plus(tr(eps(u_))) * Identity(ndim)) +
            2 * mu * dev_eps(u_)) + (lmbda + 2 / 3 * mu) * (
                angle_bracket_minus(tr(dev_eps(u_))) * Identity(ndim))

    #----------------------------------------------------------------------------------------
    def psi_0(u_):
        """
		The strain energy density for a linear isotropic ma-
		terial
		"""
        return 0.5 * lmbda * tr(eps(u_))**2 + mu * eps(u_)**2

    def psi_A(u_, alpha_):
        """
		The strain energy density for model A
		"""
        return g(alpha_) * psi_0(u_)

    def psi_B(u_, alpha_):
        """
		The strain energy density for model B
		"""
        return g(alpha_) * (0.5 * K *
                            (angle_bracket_plus(tr(dev_eps(u_))))**2 +
                            mu * dev_eps(u_)**2) + 0.5 * K * (
                                angle_bracket_minus(tr(dev_eps(u_))))**2

    #----------------------------------------------------------------------------------------

    if not ModelB:  # Model A (isotropic model)
        psi = psi_A
        sigma = sigma_A
    else:  # Model B (Amor's model)
        psi = psi_B
        sigma = sigma_B

    #=======================================================================================
    # others definitions
    #=======================================================================================
    prefix = "%s-%s-L%s-H%.2f-S%.4f-l%.4f" % (law, Model, L, H, hsize, ell)
    save_dir = "Fracking_result/" + prefix + "/"

    if os.path.isdir(save_dir):
        shutil.rmtree(save_dir)

    # zero and unit vectors
    zero_v = Constant((0., ) * ndim)
    e1 = [Constant([1., 0.]), Constant((1., 0., 0.))][ndim - 2]

    # Normalization constant for the dissipated energy
    # to get Griffith surface energy for ell going to zero
    z = sympy.Symbol("z", positive=True)
    c_w = float(4 * sympy.integrate(sympy.sqrt(w(z)), (z, 0, 1)))

    # plane strain or plane stress
    if not PlaneStress:  # plane strain
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))
    else:  # plane stress
        lmbda = E * nu / (1.0 - nu**2)

    # shear modulus
    mu = E / (2.0 * (1.0 + nu))

    #=======================================================================================
    # Define boundary sets for boundary conditions
    #=======================================================================================
    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0] - L) * 0.01, 0)

    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0]) * 0.01, 0.)

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1] - H) * 0.01, 0)

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1]) * 0.01, 0)

    # Initialize sub-domain instances
    right = Right()
    left = Left()
    top = Top()
    bottom = Bottom()

    # define meshfunction to identify boundaries by numbers
    boundaries = FacetFunction("size_t", mesh)
    boundaries.set_all(9999)
    right.mark(boundaries, 1)  # mark top as 1
    left.mark(boundaries, 2)  # mark top as 2
    top.mark(boundaries, 3)  # mark top as 3
    bottom.mark(boundaries, 4)  # mark bottom as 4

    # Define new measure including boundary naming
    ds = Measure("ds")[boundaries]  # left: ds(1), right: ds(2)
    #=======================================================================================
    # Variational formulation
    #=======================================================================================
    # Create function space for 2D elasticity + Damage
    V_u = VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = FunctionSpace(mesh, "CG", 1)

    # Define the function, test and trial fields
    u_, u, u_t = Function(V_u), TrialFunction(V_u), TestFunction(V_u)
    alpha_, alpha, alpha_t = Function(V_alpha), TrialFunction(
        V_alpha), TestFunction(V_alpha)

    alpha_0 = interpolate(
        Constant(0.0), V_alpha)  # initial (known) alpha, undamaged everywhere.
    #=======================================================================================
    # Dirichlet boundary condition for a traction test boundary
    #=======================================================================================
    # Define a time dependent pressure
    p_b = Expression("t", t=0.0, degree=1)
    Pressure = interpolate(p_b, V_alpha)

    # bc - u (imposed displacement)
    u_R = zero_v
    u_L = zero_v
    u_T = Expression((
        "0.",
        "t",
    ), t=0.0, degree=1)
    u_B = Expression((
        "0.",
        "-t",
    ), t=0.0, degree=1)

    Gamma_u_0 = DirichletBC(V_u, u_R, boundaries, 1)
    Gamma_u_1 = DirichletBC(V_u, u_L, boundaries, 2)
    Gamma_u_2 = DirichletBC(V_u, u_T, boundaries, 3)
    Gamma_u_3 = DirichletBC(V_u, u_B, boundaries, 4)
    bc_u = [Gamma_u_0, Gamma_u_1, Gamma_u_2, Gamma_u_3]

    # bc - alpha (zero damage)
    Gamma_alpha_0 = DirichletBC(V_alpha, 0.0, boundaries, 1)
    Gamma_alpha_1 = DirichletBC(V_alpha, 0.0, boundaries, 2)
    Gamma_alpha_2 = DirichletBC(V_alpha, 0.0, boundaries, 3)
    Gamma_alpha_3 = DirichletBC(V_alpha, 0.0, boundaries, 4)
    Gamma_alpha_4 = DirichletBC(V_alpha, 1.0, mesh_fun, 101)
    bc_alpha = [
        Gamma_alpha_0, Gamma_alpha_1, Gamma_alpha_2, Gamma_alpha_3,
        Gamma_alpha_4
    ]
    #====================================================================================
    # Define  problem and solvers
    #====================================================================================
    elastic_energy = psi(u_, alpha_) * dx
    external_work = dot(body_force, u_) * dx

    if not WheelerApproach:  # Bourdin approach, 2012 , SPE 159154, equation (5)
        pressurized_energy = Pressure * inner(u_, grad(alpha_)) * dx
    else:  # M.F. Wheeler et al., CAMAME, 2014, eqution (4)
        pressurized_energy = -(biot - 1.) * (
            (1. - alpha_)**2 * Pressure * div(u_)) * dx + dot(
                (1 - alpha_)**2 * grad(Pressure), u_) * dx

    dissipated_energy = Gc / float(c_w) * (
        w(alpha_) / ell + ell * inner(grad(alpha_), grad(alpha_))) * dx

    total_energy = elastic_energy + dissipated_energy + pressurized_energy - external_work

    # Residual and Jacobian of elasticity problem
    Du_total_energy = derivative(total_energy, u_, u_t)
    J_u = derivative(Du_total_energy, u_, u)

    # Residual and Jacobian of damage problem
    Dalpha_total_energy = derivative(total_energy, alpha_, alpha_t)
    J_alpha = derivative(Dalpha_total_energy, alpha_, alpha)

    # Variational problem for the displacement
    problem_u = NonlinearVariationalProblem(Du_total_energy, u_, bc_u, J_u)

    # Variational problem for the damage (non-linear to use variational inequality solvers of petsc)
    # Define the minimisation problem by using OptimisationProblem class
    class DamageProblem(OptimisationProblem):
        def __init__(self):
            OptimisationProblem.__init__(self)

        # Objective function
        def f(self, x):
            alpha_.vector()[:] = x
            return assemble(total_energy)

        # Gradient of the objective function
        def F(self, b, x):
            alpha_.vector()[:] = x
            assemble(Dalpha_total_energy, tensor=b)

        # Hessian of the objective function
        def J(self, A, x):
            alpha_.vector()[:] = x
            assemble(J_alpha, tensor=A)

    # Create the PETScTAOSolver
    problem_alpha = DamageProblem()

    # Parse (PETSc) parameters
    parameters.parse()

    # Set up the solvers
    solver_u = NonlinearVariationalSolver(problem_u)
    prm = solver_u.parameters
    prm["newton_solver"]["absolute_tolerance"] = 1E-8
    prm["newton_solver"]["relative_tolerance"] = 1E-7
    prm["newton_solver"]["maximum_iterations"] = 25
    prm["newton_solver"]["relaxation_parameter"] = 1.0
    prm["newton_solver"]["preconditioner"] = "default"
    prm["newton_solver"]["linear_solver"] = "mumps"

    #set_log_level(PROGRESS)

    solver_alpha = PETScTAOSolver()

    alpha_lb = interpolate(Expression("0.", degree=1),
                           V_alpha)  # lower bound, set to 0
    alpha_ub = interpolate(Expression("1.", degree=1),
                           V_alpha)  # upper bound, set to 1

    for bc in bc_alpha:
        bc.apply(alpha_lb.vector())

    for bc in bc_alpha:
        bc.apply(alpha_ub.vector())
    #=======================================================================================
    # To store results
    #=======================================================================================
    results = []
    file_alpha = File(save_dir +
                      "/alpha.pvd")  # use .pvd if .xdmf is not working
    file_u = File(save_dir + "/u.pvd")  # use .pvd if .xdmf is not working

    #=======================================================================================
    # Solving at each timestep
    #=======================================================================================
    load_multipliers = np.linspace(pressure_min, pressure_max, pressure_steps)
    energies = np.zeros((len(load_multipliers), 5))
    iterations = np.zeros((len(load_multipliers), 2))
    forces = np.zeros((len(load_multipliers), 2))

    for (i_t, t) in enumerate(load_multipliers):

        print "\033[1;32m--- Time step %d: t = %g ---\033[1;m" % (i_t, t)
        #u_T.t = t*ut
        #u_B.t = t*ut
        p_b.t = t
        Pressure.assign(interpolate(p_b, V_alpha))
        # Alternate mininimization
        # Initialization
        iter = 1
        err_alpha = 1
        # Iterations
        while err_alpha > tolerance and iter < max_iterations:
            # solve elastic problem
            solver_u.solve()
            # solve damage problem
            solver_alpha.solve(problem_alpha, alpha_.vector(),
                               alpha_lb.vector(), alpha_ub.vector())

            # test error
            err_alpha = (alpha_.vector() - alpha_0.vector()).norm('linf')
            # monitor the results
            if mpi_comm_world().rank == 0:
                print "Iteration:  %2d, Error: %2.8g, alpha_max: %.8g" % (
                    iter, err_alpha, alpha_.vector().max())

            # update iteration
            alpha_0.vector()[:] = alpha_.vector()
            iter += 1

        # Update the lower bound to account for the irreversibility
        alpha_lb.vector()[:] = alpha_.vector()

        ## plot the damage fied
        #plt.figure(2)
        #plot(alpha_, range_min = 0., range_max = 1., key = "alpha", title = "Damage at loading %.4f"%(ut*t))
        #plt.show()
        #plt.interactive(True)
        #=======================================================================================
        # Some post-processing
        #=======================================================================================
        # Save number of iterations for the time step
        iterations[i_t] = np.array([t, iter])
        # Calculate the energies
        elastic_energy_value = assemble(elastic_energy)
        dissipated_energy_value = assemble(dissipated_energy)
        pressurized_energy_value = assemble(pressurized_energy)
        if mpi_comm_world().rank == 0:
            print("\nEnd of timestep %d with load multiplier %g" % (i_t, t))
            print("AM: Iteration number: %i - Elastic_energy: %.3e" %
                  (i_t, elastic_energy_value))
            print("AM: Iteration number: %i - Dissipated_energy: %.3e" %
                  (i_t, dissipated_energy_value))
            print("AM: Iteration number: %i - pressurized_energy: %.3e" %
                  (i_t, pressurized_energy_value))
            print "\033[1;32m--------------------------------------------------------------\033[1;m"

        energies[i_t] = np.array([
            t, elastic_energy_value, dissipated_energy_value,
            pressurized_energy_value, elastic_energy_value +
            dissipated_energy_value + pressurized_energy_value
        ])
        # Calculate the axial force resultant
        forces[i_t] = np.array(
            [t, assemble(inner(sigma(u_, alpha_) * e1, e1) * ds(1))])
        # Dump solution to file
        file_alpha << (alpha_, t)
        file_u << (u_, t)
        # Save some global quantities as a function of the time
        np.savetxt(save_dir + '/energies.txt', energies)
        np.savetxt(save_dir + '/forces.txt', forces)
        np.savetxt(save_dir + '/iterations.txt', iterations)

    #=======================================================================================
    # Save alpha and displacement data
    #=======================================================================================
    output_file_u = HDF5File(mpi_comm_world(), save_dir + "u_4_opening.h5",
                             "w")  # self.save_dir + "uO.h5"
    output_file_u.write(u_, "solution")
    output_file_u.close()

    output_file_alpha = HDF5File(mpi_comm_world(),
                                 save_dir + "alpha_4_opening.h5", "w")
    output_file_alpha.write(alpha_, "solution")
    output_file_alpha.close()
Exemplo n.º 7
0
def Fracking(hsize, mu_dynamic, pressure_steps,j):
	#=======================================================================================
	# Input date
	#=======================================================================================
	# Geometry
	L = 200.0 # length
	H = 200.0 # height
	#hsize= 0.5 # target cell size
	meshname="fracking_hsize%g" % (hsize)



	# Stopping criteria for the alternate minimization
	max_iterations = 200
	tolerance = 1.0e-5

	# Loading
	pressure_min = 0. # load multiplier min value
	pressure_max = 5. # load multiplier max value
	#pressure_steps = 20 # number of time steps


	#====================================================================================
	# To define  pressure field
	#====================================================================================
	f = Constant(0)


	kappa = 1.e-12
	M_biot = 1.
	#mu_dynamic = 1.


	nu =0.34
	E=6.e3
	G =E/(2.*(1.+nu))
	c = (2.*G*(1.-nu)/(1.-2.*nu))*kappa/mu_dynamic
	print c
	print G


	#t_stop = hsize**2 *mu_dynamic/(kappa*M_biot)  # non dimensional time (s) 
	#DeltaT=1.e-4#COE*hsize**2 *mu_dynamic/(kappa*M_biot)  
	DeltaT=1e-3#hsize**2/c
	print DeltaT

	#Q=5.e-4
	#=======================================================================================
	# Geometry and mesh generation
	#=======================================================================================
	# Generate a XDMF/HDF5 based mesh from a Gmsh string
	geofile = \
			"""
			lc = DefineNumber[ %g, Name "Parameters/lc" ];
			H = 200.;
			L = 200.;

			r=10.;
			a=10.;

		        Point(1) = {0, 0, 0, 5*lc};
		        Point(2) = {L, 0, 0, 5*lc};
		        Point(3) = {L, H, 0, 5*lc};
		        Point(4) = {0, H, 0, 5*lc};

		        Point(5) = {L/2, H/2+r+a, 0, 0.1*lc};
		        Point(6) = {L/2, H/2+r, 0, 0.1*lc};

		        Point(7) = {L/2, H/2-r, 0, 0.1*lc};
		        Point(8) = {L/2, H/2-r-a, 0, 0.1*lc};

		        Point(9) = {L/2, H/2, 0, 0.1*lc};



		        Line(1) = {1, 2};
		        Line(2) = {2, 3};
		        Line(3) = {3, 4};
		        Line(4) = {4, 1};
		        Line Loop(5) = {1, 2, 3, 4};


			Circle(8) = {6, 9, 7};
			Circle(9) = {7, 9, 6};
			Line Loop(11) = {8, 9};
			
			Plane Surface(30) = {5,11};


			Line(6) = {5, 6};
		        Line{6} In Surface{30};

			Line(7) = {7, 8};
		        Line{7} In Surface{30};



			Physical Surface(1) = {30};

			Physical Line(101) = {6};
			Physical Line(102) = {7};




	"""%(hsize)


	subdir = "meshes/"
	_mesh  = Mesh() #creat empty mesh object
	if not os.path.isfile(subdir + meshname + ".xdmf"):
		if MPI.rank(mpi_comm_world()) == 0:
		    # Create temporary .geo file defining the mesh
		    if os.path.isdir(subdir) == False:
		        os.mkdir(subdir)
		    fgeo = open(subdir + meshname + ".geo", "w")
		    fgeo.writelines(geofile)
		    fgeo.close()
		    # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
		    try:
		        subprocess.call(["gmsh", "-2", "-o", subdir + meshname + ".msh", subdir + meshname + ".geo"])
		    except OSError:
		        print("-----------------------------------------------------------------------------")
		        print(" Error: unable to generate the mesh using gmsh")
		        print(" Make sure that you have gmsh installed and have added it to your system PATH")
		        print("-----------------------------------------------------------------------------")


		    meshconvert.convert2xml(subdir + meshname + ".msh", subdir + meshname + ".xml", "gmsh")

		# Convert to XDMF
		MPI.barrier(mpi_comm_world())
		mesh = Mesh(subdir + meshname + ".xml")
		XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
		XDMF.write(mesh)
		XDMF.read(_mesh)

		if os.path.isfile(subdir + meshname + "_physical_region.xml") and os.path.isfile(subdir + meshname + "_facet_region.xml"):
		    if MPI.rank(mpi_comm_world()) == 0:
		        mesh = Mesh(subdir + meshname + ".xml")
		        subdomains = MeshFunction("size_t", mesh, subdir + meshname + "_physical_region.xml")
		        boundaries = MeshFunction("size_t", mesh, subdir + meshname + "_facet_region.xml")
		        HDF5 = HDF5File(mesh.mpi_comm(), subdir + meshname + "_physical_facet.h5", "w")
		        HDF5.write(mesh, "/mesh")
		        HDF5.write(subdomains, "/subdomains")
		        HDF5.write(boundaries, "/boundaries")
		        print("Finish writting physical_facet to HDF5")

		if MPI.rank(mpi_comm_world()) == 0:
		    # Keep only the .xdmf mesh
		    #os.remove(subdir + meshname + ".geo")
		    #os.remove(subdir + meshname + ".msh")
		    #os.remove(subdir + meshname + ".xml")

		    # Info
		    print("Mesh completed")

	    # Read the mesh if existing
	else:
		XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
		XDMF.read(_mesh)


	mesh = Mesh('meshes/fracking_hsize'+str(float(hsize))+'.xml')
	#mesh_fun = MeshFunction("size_t", mesh,"meshes/fracking_hsize"+str(float(hsize))+"_facet_region.xml")
	#plt.figure(1)
	#plot(mesh, "2D mesh")
	#plt.interactive(False)

	ndim = mesh.geometry().dim() # get number of space dimensions
	#=======================================================================================
	# Constitutive functions of the damage model
	#=======================================================================================
	def a(alpha_):
		"""
		Modulation of the elastic stiffness
		"""
		if law == "AT1":
		    return (1-alpha_)**2
		elif law == "AT2":
		    return (1-alpha_)**2
		elif law == "ATk":
		    return (1-w(alpha_))/(1+(k-1)*w(alpha_))

	def w(alpha_):
		"""
		Local energy dissipation
		"""
		if law == "AT1":
		    return alpha_
		elif law == "AT2":
		    return alpha_**2
		elif law == "ATk":
		    return 1-(1-alpha_)**2

	#=======================================================================================
	# strain, stress and strain energy for Isotropic and Amor's model
	#=======================================================================================
	#=======================================================================================
	# others definitions
	#=======================================================================================
	prefix = "L%s-H%.2f-S%.4f-mu%s"%(L,H,hsize, j)
	save_dir = "Fracking_result/" + prefix + "/"

	if os.path.isdir(save_dir):
	    shutil.rmtree(save_dir)

	# zero and unit vectors
	zero_v = Constant((0.,)*ndim)
	e1 = [Constant([1.,0.]),Constant((1.,0.,0.))][ndim-2]
	#=======================================================================================
	# Define boundary sets for boundary conditions
	#=======================================================================================
	class Right(SubDomain):
	    def inside(self, x, on_boundary):
		return near((x[0] - L) * 0.01, 0)
		
	class Left(SubDomain):
	    def inside(self, x, on_boundary):
		return near((x[0]) * 0.01, 0.)

	class Top(SubDomain):
	    def inside(self, x, on_boundary):
		return near((x[1] - H) * 0.01, 0)
	  
	class Bottom(SubDomain):
	    def inside(self, x, on_boundary):
		return near((x[1]) * 0.01, 0)

	class Void(SubDomain):
	    def inside(self, x, on_boundary):
		#return   x[0] <= 2.5 and x[0] >= 1.5  and  x[1] <= 2.5 and x[1] >= 1.5 and on_boundary
		H = 200.
		L = 200.
		radius = 10.
		return   x[0] <= L/2+1.5*radius and x[0] >= L/2-1.5*radius  and  x[1] <= H/2+1.5*radius and x[1] >= H/2-1.5*radius and on_boundary


	# Initialize sub-domain instances
	right=Right()
	left=Left()
	top=Top()
	bottom=Bottom()
	void=Void()



	# define meshfunction to identify boundaries by numbers
	boundaries = FacetFunction("size_t", mesh)
	boundaries.set_all(9999)
	right.mark(boundaries, 1) # mark top as 1
	left.mark(boundaries, 2) # mark top as 2
	top.mark(boundaries, 3) # mark top as 3
	bottom.mark(boundaries, 4) # mark bottom as 4
	void.mark(boundaries, 5) # mark void as 5


	# Define new measure including boundary naming 
	#ds = Measure("ds")[boundaries] # left: ds(1), right: ds(2)
	ds=Measure('ds', domain=mesh, subdomain_data=boundaries)
	#=======================================================================================
	# Variational formulation
	#=======================================================================================
	# Create function space for 2D elasticity + Damage
	V_p = FunctionSpace(mesh, "CG", 1)

	# Define the function, test and trial fields
	P_, P, P_t= Function(V_p), TrialFunction(V_p), TestFunction(V_p),

	P_0 = interpolate(Expression("0.0", degree=1), V_p)
	#=======================================================================================
	# Dirichlet boundary condition for a traction test boundary
	#=======================================================================================
	## bc - P (imposed pressure)
	P_C = Expression("p", p=0.0, degree=1)
	Gamma_P_0 = DirichletBC(V_p, 0.0, boundaries, 1)
	Gamma_P_1 = DirichletBC(V_p, 0.0, boundaries, 2)
	Gamma_P_2 = DirichletBC(V_p, 0.0, boundaries, 3)
	Gamma_P_3 = DirichletBC(V_p, 0.0, boundaries, 4)
	Gamma_P_4 = DirichletBC(V_p, 1.0, boundaries, 5)

	bc_P = [ Gamma_P_0, Gamma_P_1, Gamma_P_2, Gamma_P_3, Gamma_P_4]
	#====================================================================================
	# Define  problem and solvers
	#====================================================================================
	Pressure = P_*P*dx +DeltaT*c*inner(nabla_grad(P), nabla_grad(P_))*dx-(P_0 +DeltaT*f)*P*dx#-DeltaT*Q*P*ds(1) # Wang et. al 2017 eq(8)

	#Jacobian of pressure problem
	J_p  = derivative(Pressure, P_, P_t) 

	problem_pressure = NonlinearVariationalProblem(Pressure, P_, bc_P, J=J_p)
	solver_pressure = NonlinearVariationalSolver(problem_pressure)     

	#=======================================================================================
	# To store results
	#=======================================================================================
	results = []
	file_p = File(save_dir+"/p.pvd") 
	#=======================================================================================
	# Solving at each timestep
	#=======================================================================================
	load_multipliers = np.linspace(pressure_min,pressure_max,pressure_steps)



	iteration = 0; err_P = 1; 
	# Iterations

	while  err_P>tolerance and iteration<max_iterations:
	     	# solve pressure problem
		solver_pressure.solve()
	       	err_P = (P_.vector() - P_0.vector()).norm('linf')
	       	if mpi_comm_world().rank == 0:
	       		print "Iteration:  %2d, pressure_Error: %2.8g, P_max: %.8g" %(iteration, err_P, P_.vector().max())

	       	iteration += 1
	    	P_0.vector()[:] = P_.vector()
		file_p << P_
Exemplo n.º 8
0
def Fracking(E, nu, hsize, ell, law, ModelB, ka, kb, k, mu_dynamic):

    #=======================================================================================
    # Input date
    #=======================================================================================
    # Geometry
    L = 200.  # length
    H = 200.  # height
    #hsize= 0.8 # target cell size
    radius = Constant(10.)
    meshname = "fracking_hsize%g" % (hsize)

    # Material constants
    #E = 6.e3 # Young modulus
    #nu = 0.34 # Poisson ratio

    PlaneStress = False

    # Stopping criteria for the alternate minimization
    max_iterations = 200
    tolerance = 1.0e-8

    # Loading
    body_force = Constant((0., 0.))  # bulk load
    pressure_min = 0.  # load multiplier min value
    pressure_max = 1.  # load multiplier max value
    pressure_steps = 100  # number of time steps

    #====================================================================================
    # To define  pressure field
    #====================================================================================
    biot = 1.0
    kappa = 1.e-12  #is the permeability of the rock #m^2
    #mu_dynamic= 0.79e-9  #is the dynamic viscosity of the fluid #MPa

    f = Constant(0)

    G = E / (2. * (1. + nu))
    c = (2. * G * (1. - nu) / (1. - 2. * nu)) * kappa / mu_dynamic

    DeltaT = 1e-3  #hsize**2 *mu_dynamic/(kappa*M_biot)  # non dimensional time (s)

    #=======================================================================================
    # Geometry and mesh generation
    #=======================================================================================
    # Generate a XDMF/HDF5 based mesh from a Gmsh string
    geofile = \
      """
			lc = DefineNumber[ %g, Name "Parameters/lc" ];
			H = 200.;
			L = 200.;

			r=10.;
			a=10.;

		        Point(1) = {0, 0, 0, 5*lc};
		        Point(2) = {L, 0, 0, 5*lc};
		        Point(3) = {L, H, 0, 5*lc};
		        Point(4) = {0, H, 0, 5*lc};

		        Point(5) = {L/2, H/2+r+a, 0, 0.1*lc};
		        Point(6) = {L/2, H/2+r, 0, 0.1*lc};

		        Point(7) = {L/2, H/2-r, 0, 0.1*lc};
		        Point(8) = {L/2, H/2-r-a, 0, 0.1*lc};

		        Point(9) = {L/2, H/2, 0, 0.1*lc};



		        Line(1) = {1, 2};
		        Line(2) = {2, 3};
		        Line(3) = {3, 4};
		        Line(4) = {4, 1};
		        Line Loop(5) = {1, 2, 3, 4};


			Circle(8) = {6, 9, 7};
			Circle(9) = {7, 9, 6};
			Line Loop(11) = {8, 9};
			
			Plane Surface(30) = {5,11};


			Line(6) = {5, 6};
		        Line{6} In Surface{30};

			Line(7) = {7, 8};
		        Line{7} In Surface{30};



			Physical Surface(1) = {30};

			Physical Line(101) = {6};
			Physical Line(102) = {7};


	"""%(hsize)

    subdir = "meshes/"
    _mesh = Mesh()  #creat empty mesh object
    if not os.path.isfile(subdir + meshname + ".xdmf"):
        if MPI.rank(mpi_comm_world()) == 0:
            # Create temporary .geo file defining the mesh
            if os.path.isdir(subdir) == False:
                os.mkdir(subdir)
            fgeo = open(subdir + meshname + ".geo", "w")
            fgeo.writelines(geofile)
            fgeo.close()
            # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
            try:
                subprocess.call([
                    "gmsh", "-2", "-o", subdir + meshname + ".msh",
                    subdir + meshname + ".geo"
                ])
            except OSError:
                print(
                    "-----------------------------------------------------------------------------"
                )
                print(" Error: unable to generate the mesh using gmsh")
                print(
                    " Make sure that you have gmsh installed and have added it to your system PATH"
                )
                print(
                    "-----------------------------------------------------------------------------"
                )

            meshconvert.convert2xml(subdir + meshname + ".msh",
                                    subdir + meshname + ".xml", "gmsh")

        # Convert to XDMF
        MPI.barrier(mpi_comm_world())
        mesh = Mesh(subdir + meshname + ".xml")
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.write(mesh)
        XDMF.read(_mesh)

        if os.path.isfile(subdir + meshname +
                          "_physical_region.xml") and os.path.isfile(
                              subdir + meshname + "_facet_region.xml"):
            if MPI.rank(mpi_comm_world()) == 0:
                mesh = Mesh(subdir + meshname + ".xml")
                subdomains = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_physical_region.xml")
                boundaries = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_facet_region.xml")
                HDF5 = HDF5File(mesh.mpi_comm(),
                                subdir + meshname + "_physical_facet.h5", "w")
                HDF5.write(mesh, "/mesh")
                HDF5.write(subdomains, "/subdomains")
                HDF5.write(boundaries, "/boundaries")
                print("Finish writting physical_facet to HDF5")

        if MPI.rank(mpi_comm_world()) == 0:
            # Keep only the .xdmf mesh
            #os.remove(subdir + meshname + ".geo")
            #os.remove(subdir + meshname + ".msh")
            #os.remove(subdir + meshname + ".xml")

            # Info
            print("Mesh completed")

    # Read the mesh if existing
    else:
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.read(_mesh)

    mesh = Mesh('meshes/fracking_hsize' + str(float(hsize)) + '.xml')
    mesh_fun = MeshFunction(
        "size_t", mesh,
        "meshes/fracking_hsize" + str(float(hsize)) + "_facet_region.xml")
    ndim = mesh.geometry().dim()  # get number of space dimensions

    #=======================================================================================
    # strain, stress and strain energy for Isotropic and Amor's model
    #=======================================================================================
    def eps(u_):
        """
		Geometrical strain
		"""
        return sym(grad(u_))

    #----------------------------------------------------------------------------------------
    def sigma0(u_):
        """
		Application of the sound elasticy tensor on the strain tensor
		"""
        Id = Identity(len(u_))
        return 2.0 * mu * eps(u_) + lmbda * tr(eps(u_)) * Id

    #----------------------------------------------------------------------------------------
    def psi_0(u_):
        """
		The strain energy density for a linear isotropic ma-
		terial
		"""
        return 0.5 * lmbda * tr(eps(u_))**2 + mu * eps(u_)**2

    #=======================================================================================
    # others definitions
    #=======================================================================================
    prefix = "%s-L%s-H%.2f-S%.4f-l%.4f-ka%s-kb%s-steps%s,mu%s" % (
        law, L, H, hsize, ell, ka, kb, pressure_steps, k)
    save_dir = "Fracking_result/" + prefix + "/"

    if os.path.isdir(save_dir):
        shutil.rmtree(save_dir)

    # zero and unit vectors
    zero_v = Constant((0., ) * ndim)
    e1 = [Constant([1., 0.]), Constant((1., 0., 0.))][ndim - 2]
    e2 = [Constant([0., 1.]), Constant((0., 1., 0.))][ndim - 2]

    # plane strain or plane stress
    if not PlaneStress:  # plane strain
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))
    else:  # plane stress
        lmbda = E * nu / (1.0 - nu**2)

    # shear modulus
    mu = E / (2.0 * (1.0 + nu))

    #=======================================================================================
    # Define boundary sets for boundary conditions
    #=======================================================================================
    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0] - L) * 0.01, 0)

    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0]) * 0.01, 0.)

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1] - H) * 0.01, 0)

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1]) * 0.01, 0)

    class Void(SubDomain):
        def inside(self, x, on_boundary):
            #return   x[0] <= 2.5 and x[0] >= 1.5  and  x[1] <= 2.5 and x[1] >= 1.5 and on_boundary
            H = 200.
            L = 200.
            radius = 10.
            return x[0] <= L / 2 + 1.5 * radius and x[
                0] >= L / 2 - 1.5 * radius and x[
                    1] <= H / 2 + 1.5 * radius and x[
                        1] >= H / 2 - 1.5 * radius and on_boundary

    # Initialize sub-domain instances
    right = Right()
    left = Left()
    top = Top()
    bottom = Bottom()
    void = Void()

    # define meshfunction to identify boundaries by numbers
    boundaries = FacetFunction("size_t", mesh)
    boundaries.set_all(9999)
    right.mark(boundaries, 1)  # mark top as 1
    left.mark(boundaries, 2)  # mark top as 2
    top.mark(boundaries, 3)  # mark top as 3
    bottom.mark(boundaries, 4)  # mark bottom as 4
    void.mark(boundaries, 5)  # mark void as 5

    # Define new measure including boundary naming
    ds = Measure("ds")[boundaries]  # left: ds(1), right: ds(2)
    #=======================================================================================
    # Variational formulation
    #=======================================================================================
    # Create function space for 2D elasticity + Damage
    V_u = VectorFunctionSpace(mesh, "CG", 1)
    V_p = FunctionSpace(mesh, "CG", 1)

    # Define the function, test and trial fields
    u_, u, u_t = Function(V_u), TrialFunction(V_u), TestFunction(V_u)
    P_, P, P_t = Function(V_p), TrialFunction(V_p), TestFunction(V_p),

    P_0 = interpolate(Expression("0.0", degree=1), V_p)
    u_0 = interpolate(zero_v, V_u)
    ##############################################################################################################
    # read the displacement data from a plain strain elasticity problem imposed by in-situ stress
    prefix_stress = "L%s-H%.2f-%s-%g" % (L, H, 'DispBC', hsize)
    save_dir_stress = "Elasticity_result/" + prefix_stress + "/"

    # To read the solution for u_
    u_imported = Function(V_u)
    input_file_u = HDF5File(mesh.mpi_comm(), save_dir_stress + "u_4_bc.h5",
                            "r")
    input_file_u.read(u_imported, "solution")
    input_file_u.close()

    class MyExpr(Expression):
        def eval(self, values, x):
            point = (x[0], x[1])
            values[0] = u_imported(point)[0]
            values[1] = u_imported(point)[1]

        def value_shape(self):
            return (2, )

    my_expr = MyExpr(degree=1)

    ##############################################################################################################
    #=======================================================================================
    # Dirichlet boundary condition for a traction test boundary
    #=======================================================================================
    Gamma_u_0 = DirichletBC(V_u, my_expr, boundaries, 1)
    Gamma_u_1 = DirichletBC(V_u, my_expr, boundaries, 2)
    Gamma_u_2 = DirichletBC(V_u, my_expr, boundaries, 3)
    Gamma_u_3 = DirichletBC(V_u, my_expr, boundaries, 4)
    bc_u = [Gamma_u_0, Gamma_u_1, Gamma_u_2, Gamma_u_3]

    ## bc - P (imposed pressure)
    P_C = Expression("p", p=0.0, degree=1)

    Gamma_P_0 = DirichletBC(V_p, 0.0, boundaries, 1)
    Gamma_P_1 = DirichletBC(V_p, 0.0, boundaries, 2)
    Gamma_P_2 = DirichletBC(V_p, 0.0, boundaries, 3)
    Gamma_P_3 = DirichletBC(V_p, 0.0, boundaries, 4)
    #Gamma_P_4 = DirichletBC(V_p, P_C, mesh_fun, 101)
    Gamma_P_4 = DirichletBC(V_p, 1.0, boundaries, 5)
    bc_P = [Gamma_P_0, Gamma_P_1, Gamma_P_2, Gamma_P_3, Gamma_P_4]

    #====================================================================================
    # Define  problem and solvers
    #====================================================================================
    Pressure = P_ * P * dx + DeltaT * c * inner(nabla_grad(P), nabla_grad(
        P_)) * dx - (P_0 + DeltaT *
                     f) * P * dx  #-DeltaT*Q*P*ds(5) # Wang et. al 2017 eq(8)
    #------------------------------------------------------------------------------------
    elastic_energy = psi_0(u_) * dx - biot * P_ * div(u_) * dx
    external_work = dot(
        body_force, u_) * dx  #+ dot(sigma_R, u_)*ds(1)+ dot(sigma_T, u_)*ds(3)

    total_energy = elastic_energy + external_work

    # Residual and Jacobian of elasticity problem
    Du_total_energ = derivative(total_energy, u_, u_t)
    J_u = derivative(Du_total_energ, u_, u)

    #Jacobian of pressure problem
    J_p = derivative(Pressure, P_, P_t)

    # Variational problem for the displacement
    problem_u = NonlinearVariationalProblem(Du_total_energ, u_, bc_u, J_u)

    # Parse (PETSc) parameters
    parameters.parse()

    # Set up the solvers
    solver_u = NonlinearVariationalSolver(problem_u)
    prm = solver_u.parameters
    prm["newton_solver"]["absolute_tolerance"] = 1E-6
    prm["newton_solver"]["relative_tolerance"] = 1E-6
    prm["newton_solver"]["maximum_iterations"] = 200
    prm["newton_solver"]["relaxation_parameter"] = 1.0
    prm["newton_solver"]["preconditioner"] = "default"
    prm["newton_solver"]["linear_solver"] = "mumps"

    problem_pressure = NonlinearVariationalProblem(Pressure, P_, bc_P, J=J_p)
    solver_pressure = NonlinearVariationalSolver(problem_pressure)

    #=======================================================================================
    # To store results
    #=======================================================================================
    results = []
    file_u = File(save_dir + "/u.pvd")  # use .pvd if .xdmf is not working
    file_p = File(save_dir + "/p.pvd")
    file_stress_tt = File(save_dir + "/stress_tt.pvd")
    file_stress_rr = File(save_dir + "/stress_rr.pvd")
    file_stress_rt = File(save_dir + "/stress_rt.pvd")
    #=======================================================================================
    # Solving at each timestep
    #=======================================================================================

    iteration = 0
    iter = 0
    err_P = 1
    err_alpha = 1
    # Iterations

    while iter < pressure_steps:
        # solve pressure problem
        solver_pressure.solve()
        err_P = (P_.vector() - P_0.vector()).norm('linf')
        if mpi_comm_world().rank == 0:
            print "Iteration:  %2d, pressure_Error: %2.8g, P_max: %.8g" % (
                iter, err_P, P_.vector().max())
        P_0.vector()[:] = P_.vector()

        # solve elastic problem
        solver_u.solve()
        if mpi_comm_world().rank == 0:
            print "elastic iteration: %2d" % (iter)

        u_0.vector()[:] = u_.vector()
        iter += 1

        # Dump solution to file
        file_u << u_
        file_p << P_

        stress_tt = project(sigma0(u_)[0, 0], V_p)

        file_stress_tt << stress_tt

        stress_rr = project(sigma0(u_)[1, 1], V_p)
        file_stress_rr << stress_rr

        stress_rt = project(sigma0(u_)[0, 1], V_p)
        file_stress_rt << stress_rt
Exemplo n.º 9
0
def create_patches(box=np.array([0, 0, 0, 1, 1, 1]),
                   patch_num=3,
                   patch_nums=None,
                   alpha=1.25,
                   beta=2.0,
                   max_resolution=0.5,
                   num=6,
                   create_inclusions=False,
                   skip_patches=[],
                   prefix='test',
                   logger=None,
                   ldomain=False,
                   corner_refine=3,
                   hole=False,
                   hole_radius=None,
                   layers=1,
                   max_refines=1,
                   elem_per_layer=3):
    if logger is not None:
        info = logger.info
    else:
        info = print

    basedim = 3
    low = box[:basedim].copy()
    high = box[basedim:].copy()
    lengths = high - low
    diameter = np.sqrt(lengths @ lengths)
    myeps = sa_utils.myeps * diameter
    center = (high + low) * .5
    info('low {:s}, high {:s}, lengths {:s}, center {:s}, diameter {:.2e}'.
         format(str(low), str(high), str(lengths), str(center), diameter))

    layer_bricks = []
    layer_hz = lengths[2] / layers
    layer_low = np.array(
        [low[0] - lengths[0], low[1] - lengths[1], low[2] - lengths[2]])
    layer_high = np.array(
        [low[0] + lengths[0], low[1] + lengths[1], low[2] + 2 * lengths[2]])
    for ii in range(layers - 1):
        for jj in range(1, elem_per_layer + 1):
            layer_bricks.append(
                OrthoBrick(
                    Pnt(*layer_low),
                    Pnt(low[0] + lengths[0], low[1] + lengths[1],
                        low[2] + (ii + jj * 1. / elem_per_layer) * layer_hz)))
        info('layer [{:d}/{:d}], {:s}, {:s}'.format(
            ii, layers, str(layer_low),
            str(
                np.array([
                    low[0] + lengths[0], low[1] + lengths[1],
                    low[2] + ii * layer_hz
                ]))))
    for jj in range(1, elem_per_layer):
        layer_bricks.append(
            OrthoBrick(
                Pnt(*layer_low),
                Pnt(
                    low[0] + lengths[0], low[1] + lengths[1], low[2] +
                    (layers - 1 + jj * 1. / elem_per_layer) * layer_hz)))
    layer_bricks.append(OrthoBrick(Pnt(*layer_low), Pnt(*layer_high)))
    sublayers = len(layer_bricks)
    info('layer [{:d}/{:d}], {:s}, {:s}'.format(layers, layers, str(layer_low),
                                                str(layer_high)))

    info('{:d} layers, {:d} sublayers, {:d} bricks'.format(
        layers, sublayers, len(layer_bricks)))

    bc_dict = dict()
    left = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[0], low[0], eps=myeps))
    bc_dict[1] = left
    right = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[0], high[0], eps=myeps))
    bc_dict[2] = right
    front = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[1], low[1], eps=myeps))
    bc_dict[3] = front
    back = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[1], high[1], eps=myeps))
    bc_dict[4] = back
    bottom = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[2], low[2], eps=myeps))
    bc_dict[5] = bottom
    top = dolfin.AutoSubDomain(
        lambda xx, on: on and dolfin.near(xx[2], high[2], eps=myeps))
    bc_dict[6] = top
    border = dolfin.AutoSubDomain(lambda xx, on: on)
    if ldomain:
        corner_lr = dolfin.AutoSubDomain(
            lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near(
                xx[0], center[0], eps=myeps))
        bc_dict[7] = corner_lr
        corner_fb = dolfin.AutoSubDomain(
            lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near(
                xx[1], center[1], eps=myeps))
        bc_dict[8] = corner_fb
        corner_bt = dolfin.AutoSubDomain(
            lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near(
                xx[2], center[2], eps=myeps))
        bc_dict[9] = corner_bt
        corner_subdomains = []
        corner_close = 0.1 * diameter + myeps
        for ii in range(corner_refine):
            corner_subdomains.append(
                dolfin.AutoSubDomain(
                    (lambda what: lambda xx, on: np.sqrt(xx @ xx) < what
                     )(corner_close)))
            corner_close *= 0.5
    if create_inclusions and num:
        info('random inclusions')
        if num:
            number = num * num * num
            info('n = ' + str(number))
            inc_radius = 0.5 / num
            info('r = ' + str(inc_radius))
            nodes = []
            radii = []
            rnd_low = low - 0.5 * inc_radius
            rnd_high = high + 0.5 * inc_radius
            width = rnd_high - rnd_low
            while (len(nodes) < number):
                notok = True
                while (notok):
                    new = rnd.rand(3) * width + rnd_low
                    radius = (0.5 + rnd.rand()) * inc_radius
                    notok = False
                    for old, rr in zip(nodes, radii):
                        diff = new - old
                        if np.sqrt(diff.dot(diff)) < 1.3 * (radius + rr):
                            notok = True
                            break
                nodes.append(new.copy())
                radii.append(radius)
            nodes = np.array(nodes)
            radii = np.array(radii)
            info('found locations for ' + str(len(nodes)) + ' inclusions')
            np.savetxt(prefix + '/' + prefix + '_inclusions.csv',
                       np.hstack((nodes, radii.reshape(len(nodes), 1))),
                       fmt='%.15e',
                       delimiter=', ')
            del nodes, radii, number, inc_radius

    nohole_whole = OrthoBrick(Pnt(*low), Pnt(*high))
    if ldomain is True:
        nohole_whole = nohole_whole - OrthoBrick(
            Pnt(*center), Pnt(*(center + 2 * (high - center))))
    if num:
        data = np.loadtxt(prefix + '/' + prefix + '_inclusions.csv',
                          delimiter=', ')
        number = len(data)
    else:
        number = 0
    if number:
        nodes = data[:, :3]
        radii = data[:, 3]

        inclusions = Sphere(Pnt(*nodes[0]), radii[0])
        for kk in range(1, len(nodes)):
            inclusions += Sphere(Pnt(*nodes[kk]), radii[kk])
        nohole_matrix = nohole_whole - inclusions
        nohole_incs = nohole_whole * inclusions
    if hole_radius is not None:
        hole = True
    if hole:
        if hole_radius is None:
            hole_radius = lengths[1] / 9.
        near_hole = dolfin.AutoSubDomain(lambda xx, on: on and np.sqrt(
            (xx[0] - center[0]) * (xx[0] - center[0]) + (xx[1] - center[1]) *
            (xx[1] - center[1])) < hole_radius + 1e4 * myeps)
        bc_dict[10] = near_hole

    if patch_nums is None:
        hh = lengths[0] / float(patch_num)
        patch_nums = np.array(np.ceil(lengths / hh), dtype=int)
    hs = lengths / patch_nums
    hs_alpha = hs * alpha * 0.5
    hs_beta = hs_alpha * beta

    patches = []
    patches_ext = []
    for kk in range(patch_nums[2]):
        pt_z = low[0] + (0.5 + kk) * hs[2]
        for jj in range(patch_nums[1]):
            pt_y = low[1] + (0.5 + jj) * hs[1]
            for ii in range(patch_nums[0]):
                pt_x = low[2] + (0.5 + ii) * hs[0]
                pt_center = np.array([pt_x, pt_y, pt_z])
                pt_low = pt_center - hs_alpha
                if ldomain and (p_low >= center - myeps).all():
                    print('[{:d}, {:d}, {:d}] skipped'.format(ii, jj, kk))
                    continue

                patches.append(
                    OrthoBrick(Pnt(*(pt_center - hs_alpha)),
                               Pnt(*(pt_center + hs_alpha))))
                patches_ext.append(
                    OrthoBrick(Pnt(*(pt_center -
                                     hs_beta)), Pnt(*(pt_center + hs_beta))) -
                    patches[-1])
    patch_num = len(patches)
    print('[{:d}] patches total'.format(patch_num))
    patch_fill = int(np.log(patch_num) / np.log(10.)) + 1

    pt_low = dict()
    pt_high = dict()
    pt_inside = dict()

    info('Patch size computations')
    sa_utils.makedirs_norace(prefix + '/' + prefix + '_patch_descriptors')
    ff = open(prefix + '/' + prefix + '_patch_descriptors/0.csv', 'w')
    ff.write('idx, left, right, front, back, bottom, top\n')
    for kk in range(patch_num):
        info(str(kk + 1) + '/' + str(patch_num))
        geo = CSGeometry()
        geo.Add(nohole_whole * patches[kk])
        mesh = geo.GenerateMesh(maxh=max_resolution)
        del geo
        mesh.Export('tmp.msh', 'Gmsh2 Format')
        del mesh
        meshconvert.convert2xml('tmp.msh', 'tmp.xml')
        os.remove('tmp.msh')
        os.remove('tmp_facet_region.xml')
        os.remove('tmp_physical_region.xml')

        mesh = dolfin.Mesh('tmp.xml')
        os.remove('tmp.xml')
        nodes = mesh.coordinates()
        del mesh
        pt_low[kk] = np.min(nodes, axis=0)
        pt_high[kk] = np.max(nodes, axis=0)
        ff.write('%d, %.15e, %.15e, %.15e, %.15e, %.15e, %.15e\n' %
                 (kk, pt_low[kk][0], pt_high[kk][0], pt_low[kk][1],
                  pt_high[kk][1], pt_low[kk][2], pt_high[kk][2]))
        del nodes
        pt_inside[kk] = dolfin.AutoSubDomain(lambda xx, on: (pt_low[
            kk] - myeps <= xx).all() and (xx <= pt_high[kk] + myeps).all())
    ff.close()
    info('Patch size computations finished')

    hole_ratio = hole_radius / lengths[1]
    for ref in range(max_refines):
        info('Start meshing resolution {:d}/{:d}'.format(ref + 1, max_refines))
        res = max_resolution * 0.5**ref

        if hole:
            hole_maxh = res * hole_ratio
            #           hole_maxh = np.min([res*hole_ratio, lengths[2]/layers])
            if number:
                matrix = nohole_matrix - Cylinder(
                    Pnt(center[0], center[1], center[2] - diameter),
                    Pnt(center[0], center[1], center[2] + diameter),
                    hole_radius).maxh(hole_maxh)
                incs = nohole_matrix - Cylinder(
                    Pnt(center[0], center[1], center[2] - diameter),
                    Pnt(center[0], center[1], center[2] + diameter),
                    hole_radius).maxh(hole_maxh)
            else:
                whole = nohole_whole - Cylinder(
                    Pnt(center[0], center[1], center[2] - diameter),
                    Pnt(center[0], center[1], center[2] + diameter),
                    hole_radius).maxh(hole_maxh)

        dirname = '{:s}/{:s}_{:d}_patches/0/'.format(prefix, prefix, ref)
        sa_utils.makedirs_norace(dirname)

        basename = '{:s}/{:s}_{:d}'.format(prefix, prefix, ref)
        info('Global CSG')
        geo = CSGeometry()

        if number:
            geo.Add(matrix * layer_bricks[0])
            for ii in range(1, sublayers):
                geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1]))
            geo.Add(incs * layer_bricks[0])
            for ii in range(1, sublayers):
                geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]))
        else:
            geo.Add(whole * layer_bricks[0])
            for ii in range(1, sublayers):
                geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]))
        info('Global CSG constructed')
        mesh = geo.GenerateMesh(maxh=res)
        info('Global surface meshed')
        del geo

        gc.collect()

        mesh.GenerateVolumeMesh()
        mesh.Export(basename + '.msh', 'Gmsh2 Format')
        meshconvert.convert2xml(basename + '.msh', basename + '.xml')
        del mesh
        os.remove(basename + '.msh')
        os.remove(basename + '_facet_region.xml')
        info('Global volume meshed')

        gc.collect()

        global_mesh = dolfin.Mesh(basename + '.xml')
        tmp_nodes = global_mesh.coordinates()
        tmp_low = np.min(tmp_nodes, axis=0)
        tmp_high = np.max(tmp_nodes, axis=0)
        info('global mesh: {:s}, {:s}, {:s}'.format(
            str(tmp_low), str(tmp_high), str(top.inside(tmp_high, True))))

        os.remove(basename + '.xml')
        info('Correcting cell markers')
        global_domains_tmp = dolfin.MeshFunction(
            'size_t', global_mesh, basename + '_physical_region.xml')
        os.remove(basename + '_physical_region.xml')
        global_domains_tmp.array()[:] -= np.min(global_domains_tmp.array())
        global_domains_tmp.array()[:] //= elem_per_layer
        global_domains = dolfin.MeshFunction('size_t', global_mesh, basedim, 0)
        if number:
            where = np.where(global_domains_tmp.array() < layers)
            global_domains.array(
            )[where] = 4 * global_domains_tmp.array()[where]
            where = np.where(layers <= global_domains_tmp.array())
            global_domains.array(
            )[where] = 4 * (global_domains_tmp.array()[where] - layers) + 1
            del where
        else:
            global_domains.array()[:] = 4 * global_domains_tmp.array()
        del global_domains_tmp
        if ldomain:
            for ii in range(corner_refine):
                mf = dolfin.CellFunction('bool', global_mesh, False)
                corner_subdomains[ii].mark(mf, True)
                global_mesh = dolfin.refine(global_mesh, mf)
                global_domains = dolfin.adapt(global_domains, global_mesh)
                del mf
        inside_fun = dolfin.MeshFunction('bool', global_mesh, basedim, True)
        global_mesh = dolfin.refine(global_mesh, inside_fun)
        global_domains = dolfin.adapt(global_domains, global_mesh)
        info('Correcting facet markers')
        global_facets = dolfin.MeshFunction('size_t', global_mesh, basedim - 1,
                                            0)
        for key in bc_dict:
            bc_dict[key].mark(global_facets, key)
        sa_hdf5.write_dolfin_mesh(global_mesh,
                                  basename,
                                  cell_function=global_domains,
                                  facet_function=global_facets)
        del global_facets, global_mesh, global_domains, basename

        gc.collect()

        for kk in range(patch_num):
            if kk in skip_patches:
                continue
            info(str(kk) + '/' + str(patch_num))
            basename = 'patch_' + str(kk).zfill(patch_fill)
            extname = basename + '_' + str(beta)

            info('    csg')
            geo = CSGeometry()
            if number:
                geo.Add(matrix * layer_bricks[0] * patches[kk])
                for ii in range(1, sublayers):
                    geo.Add(matrix *
                            (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches[kk])
                geo.Add(incs * layer_bricks[0] * patches[kk])
                for ii in range(1, sublayers):
                    geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches[kk])
                geo.Add(matrix * layer_bricks[0] * patches_ext[kk])
                for ii in range(1, sublayers):
                    geo.Add(matrix *
                            (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches_ext[kk])
                geo.Add(incs * layer_bricks[0] * patches_ext[kk])
                for ii in range(1, sublayers):
                    geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches_ext[kk])
            else:
                geo.Add(whole * layer_bricks[0] * patches[kk])
                for ii in range(1, sublayers):
                    geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches[kk])
                geo.Add(whole * layer_bricks[0] * patches_ext[kk])
                for ii in range(1, sublayers):
                    geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) *
                            patches_ext[kk])
            info('    csg done')
            mesh = geo.GenerateMesh(maxh=res)
            info('    surface meshed')
            del geo

            gc.collect()

            mesh.GenerateVolumeMesh()
            info('    volume meshed')
            mesh.Export(dirname + '/' + basename + '.msh', 'Gmsh2 Format')
            meshconvert.convert2xml(dirname + '/' + basename + '.msh',
                                    dirname + '/' + basename + '.xml')
            del mesh
            os.remove(dirname + '/' + basename + '.msh')
            os.remove(dirname + '/' + basename + '_facet_region.xml')

            gc.collect()

            ext_mesh = dolfin.Mesh(dirname + '/' + basename + '.xml')
            os.remove(dirname + '/' + basename + '.xml')
            info('    cell function')
            ext_domains_tmp = dolfin.MeshFunction(
                'size_t', ext_mesh,
                dirname + '/' + basename + '_physical_region.xml')
            os.remove(dirname + '/' + basename + '_physical_region.xml')
            ext_domains_tmp.array()[:] -= np.min(ext_domains_tmp.array())
            ext_domains_tmp.array()[:] //= elem_per_layer
            ext_domains = dolfin.MeshFunction('size_t', ext_mesh, basedim, 0)
            if number:
                where = np.where(ext_domains_tmp.array() < layers)
                ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where]
                where = np.where(
                    layers <= ext_domains_tmp.array() < 2 * layers)
                ext_domains.array(
                )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 1
                where = np.where(
                    2 * layers <= ext_domains_tmp.array() < 3 * layers)
                ext_domains.array()[where] = 4 * (
                    ext_domains_tmp.array()[where] - 2 * layers) + 2
                where = np.where(3 * layers <= ext_domains_tmp.array())
                ext_domains.array()[where] = 4 * (
                    ext_domains_tmp.array()[where] - 3 * layers) + 3
                del where
            else:
                where = np.where(ext_domains_tmp.array() < layers)
                ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where]
                where = np.where(layers <= ext_domains_tmp.array())
                ext_domains.array(
                )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 2
            del ext_domains_tmp
            if ldomain:
                for ii in range(corner_refine):
                    mf = dolfin.CellFunction('bool', ext_mesh, False)
                    corner_subdomains[ii].mark(mf, True)
                    ext_mesh = dolfin.refine(ext_mesh, mf)
                    ext_domains = dolfin.adapt(ext_domains, ext_mesh)
                    del mf
            inside_fun = dolfin.MeshFunction('bool', ext_mesh, basedim, False)
            pt_inside[kk].mark(inside_fun, True)
            ext_mesh = dolfin.refine(ext_mesh, inside_fun)
            del inside_fun
            ext_domains = dolfin.adapt(ext_domains, ext_mesh)
            info('    cell function done')

            pt_mesh = dolfin.SubMesh(ext_mesh, pt_inside[kk])

            pt_domains = dolfin.MeshFunction('size_t', pt_mesh, basedim, 0)
            tree = ext_mesh.bounding_box_tree()
            for cell in dolfin.cells(pt_mesh):
                global_index = tree.compute_first_entity_collision(
                    cell.midpoint())
                pt_domains[cell] = ext_domains[dolfin.Cell(
                    ext_mesh, global_index)]
            del tree

            pt_facets = dolfin.MeshFunction('size_t', pt_mesh, basedim - 1, 0)
            border.mark(pt_facets, 100)
            for key in bc_dict:
                bc_dict[key].mark(pt_facets, key)
            sa_hdf5.write_dolfin_mesh(pt_mesh,
                                      '{:s}/{:s}'.format(dirname, basename),
                                      cell_function=pt_domains,
                                      facet_function=pt_facets)

            tmp_nodes = ext_mesh.coordinates()
            tmp_low = np.min(tmp_nodes, axis=0)
            tmp_high = np.max(tmp_nodes, axis=0)
            is_part = (tmp_low > low + myeps).any() or (tmp_high <
                                                        high - myeps).any()
            del tmp_low, tmp_high, tmp_nodes
            info('patch [{:d}/{:d}], beta [{:.2e}] is real subdomain [{:}]'.
                 format(kk + 1, patch_num, beta, is_part))

            if is_part:
                vals = np.arange(1, 11)
            else:
                vals = np.unique(pt_facets.array())
                vals = vals[np.where(vals > 0)]
            patch_dict = dict()
            for key in bc_dict:
                if key in vals:
                    patch_dict[key] = bc_dict[key]
                else:
                    patch_dict[key] = dolfin.AutoSubDomain(
                        (lambda what: (lambda xx, on: bc_dict[what].inside(
                            xx, on) and pt_inside[kk].inside(xx, on)))(key))
            ext_facets = dolfin.MeshFunction('size_t', ext_mesh, basedim - 1,
                                             0)
            border.mark(ext_facets, 100)
            for key in patch_dict:
                patch_dict[key].mark(ext_facets, key)
            del patch_dict, vals
            sa_hdf5.write_dolfin_mesh(ext_mesh,
                                      dirname + '/' + basename + '_' +
                                      str(beta),
                                      cell_function=ext_domains,
                                      facet_function=ext_facets)
            del ext_mesh, ext_domains, ext_facets, pt_mesh, pt_domains, pt_facets

            gc.collect()

    del pt_low, pt_high, pt_inside
Exemplo n.º 10
0
import dolfin
from netgen.csg import *
from dolfin_utils.meshconvert import meshconvert

box = OrthoBrick(Pnt(-1, -1, -1), Pnt(1, 1, 1))
cone = Cone(Pnt(0, 0, -1), Pnt(0, 0, 2), 0, 2) * Plane(Pnt(
    0, 0, -1), Vec(0, 0, -1)) * Plane(Pnt(0, 0, 2), Vec(1, 0, 0))
geo = CSGeometry()
geo.Add(box * cone)
mesh = geo.GenerateMesh(maxh=0.2)
mesh.GenerateVolumeMesh()
mesh.Export('tmp.msh', 'Gmsh2 Format')
meshconvert.convert2xml('tmp.msh', 'tmp.xml')
bla = dolfin.Mesh('tmp.xml')
dolfin.File('tmp.pvd') << bla
Exemplo n.º 11
0
def Fracking(E, nu, hsize, ell, law, ModelB, ka, kb, q, pressure_steps):

    #=======================================================================================
    # Input date
    #=======================================================================================
    # Geometry
    L = 170.  # length
    H = 170.  # height
    #hsize= 0.8 # target cell size
    radius = Constant(5.)
    meshname = "fracking_hsize%g" % (hsize)

    # Material constants
    #ell = Constant(2 * hsize) # internal length scale
    #E = 6.e3 # Young modulus
    #nu = 0.34 # Poisson ratio

    biot = 0.  #Biot coefficient

    PlaneStress = False

    gc = 1.  # fracture toughness
    k_ell = Constant(1.0e-10)  # residual stiffness
    #law = "AT1"

    # effective toughness
    if law == "AT2":
        Gc = gc / (1 + hsize / (2 * ell))  #AT2
    elif law == "AT1":
        Gc = gc / (1 + 3 * hsize / (8 * ell))  #AT1
    else:
        Gc = gc

    #ModelB= False

    # Stopping criteria for the alternate minimization
    max_iterations = 200
    tolerance = 1.0e-5

    # Loading
    ut = 1.e-5  # reference value for the loading (imposed displacement)
    st = 1  # reference value for the loading (imposed stress)
    body_force = Constant((0., 0.))  # bulk load
    pressure_min = 0.  # load multiplier min value
    pressure_max = 1.  # load multiplier max value
    #pressure_steps = 1 # number of time steps

    WheelerApproach = True
    #====================================================================================
    # To define  pressure field
    #====================================================================================
    biot = 0.85
    phi = 0.01  #porosity
    K_f = 0.625e3  #is the pore fluid bulk modulus #MPa
    K_s = 10e3  #is the porous medium solid grain bulk modulus #MPa

    M_biot = 1 / (phi / K_f +
                  (biot - phi) / K_s)  #1./M_biot=phi/K_f+(alpha-phi)/K_s #MPa
    print "M_biot", M_biot
    kappa = 1.e-12  #is the permeability of the rock #m^2
    mu_dynamic = 0.79e-9  #is the dynamic viscosity of the fluid #MPa

    f = Constant(0)

    t_stop = H**2 * mu_dynamic / (kappa * M_biot)  # non dimensional time (s)
    DeltaT = t_stop / (pressure_steps - 1)

    #q=3.e-8
    #=======================================================================================
    # Geometry and mesh generation
    #=======================================================================================
    # Generate a XDMF/HDF5 based mesh from a Gmsh string
    geofile = \
      """
			lc = DefineNumber[ %g, Name "Parameters/lc" ];
			H = 170.;
			L = 170.;

			r=5.;
			a=1.;

		        Point(1) = {0, 0, 0, 1*lc};
		        Point(2) = {L, 0, 0, 1*lc};
		        Point(3) = {L, H, 0, 1*lc};
		        Point(4) = {0, H, 0, 1*lc};

		        Point(5) = {L/2, H/2+r+a, 0, 1*lc};
		        Point(6) = {L/2, H/2+r, 0, 1*lc};

		        Point(7) = {L/2, H/2-r, 0, 1*lc};
		        Point(8) = {L/2, H/2-r-a, 0, 1*lc};

		        Point(9) = {L/2, H/2, 0, 1*lc};

		        Line(1) = {1, 2};
		        Line(2) = {2, 3};
		        Line(3) = {3, 4};
		        Line(4) = {4, 1};
		        Line Loop(5) = {1, 2, 3, 4};


			Circle(8) = {6, 9, 7};
			Circle(9) = {7, 9, 6};
			Line Loop(11) = {8, 9};
			
			Plane Surface(30) = {5,11};


			Line(6) = {5, 6};
		        Line{6} In Surface{30};

			Line(7) = {7, 8};
		        Line{7} In Surface{30};

			Physical Surface(1) = {30};

			Physical Line(101) = {6};
			Physical Line(102) = {7};
			Physical Line(103) = {8};
			Physical Line(104) = {9};

	"""%(hsize)

    subdir = "meshes/"
    _mesh = Mesh()  #creat empty mesh object
    if not os.path.isfile(subdir + meshname + ".xdmf"):
        if MPI.rank(mpi_comm_world()) == 0:
            # Create temporary .geo file defining the mesh
            if os.path.isdir(subdir) == False:
                os.mkdir(subdir)
            fgeo = open(subdir + meshname + ".geo", "w")
            fgeo.writelines(geofile)
            fgeo.close()
            # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
            try:
                subprocess.call([
                    "gmsh", "-2", "-o", subdir + meshname + ".msh",
                    subdir + meshname + ".geo"
                ])
            except OSError:
                print(
                    "-----------------------------------------------------------------------------"
                )
                print(" Error: unable to generate the mesh using gmsh")
                print(
                    " Make sure that you have gmsh installed and have added it to your system PATH"
                )
                print(
                    "-----------------------------------------------------------------------------"
                )

            meshconvert.convert2xml(subdir + meshname + ".msh",
                                    subdir + meshname + ".xml", "gmsh")

        # Convert to XDMF
        MPI.barrier(mpi_comm_world())
        mesh = Mesh(subdir + meshname + ".xml")
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.write(mesh)
        XDMF.read(_mesh)

        if os.path.isfile(subdir + meshname +
                          "_physical_region.xml") and os.path.isfile(
                              subdir + meshname + "_facet_region.xml"):
            if MPI.rank(mpi_comm_world()) == 0:
                mesh = Mesh(subdir + meshname + ".xml")
                subdomains = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_physical_region.xml")
                boundaries = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_facet_region.xml")
                HDF5 = HDF5File(mesh.mpi_comm(),
                                subdir + meshname + "_physical_facet.h5", "w")
                HDF5.write(mesh, "/mesh")
                HDF5.write(subdomains, "/subdomains")
                HDF5.write(boundaries, "/boundaries")
                print("Finish writting physical_facet to HDF5")

        if MPI.rank(mpi_comm_world()) == 0:
            # Keep only the .xdmf mesh
            #os.remove(subdir + meshname + ".geo")
            #os.remove(subdir + meshname + ".msh")
            #os.remove(subdir + meshname + ".xml")

            # Info
            print("Mesh completed")

    # Read the mesh if existing
    else:
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.read(_mesh)

    mesh = Mesh('meshes/fracking_hsize' + str(float(hsize)) + '.xml')
    mesh_fun = MeshFunction(
        "size_t", mesh,
        "meshes/fracking_hsize" + str(float(hsize)) + "_facet_region.xml")
    #plt.figure(1)
    #plot(mesh, "2D mesh")
    #plt.interactive(False)

    ndim = mesh.geometry().dim()  # get number of space dimensions

    #=======================================================================================
    # Constitutive functions of the damage model
    #=======================================================================================
    def a(alpha_):
        """
		Modulation of the elastic stiffness
		"""
        if law == "AT1":
            return (1 - alpha_)**2
        elif law == "AT2":
            return (1 - alpha_)**2
        elif law == "ATk":
            return (1 - w(alpha_)) / (1 + (k - 1) * w(alpha_))

    def w(alpha_):
        """
		Local energy dissipation
		"""
        if law == "AT1":
            return alpha_
        elif law == "AT2":
            return alpha_**2
        elif law == "ATk":
            return 1 - (1 - alpha_)**2

    #=======================================================================================
    # strain, stress and strain energy for Isotropic and Amor's model
    #=======================================================================================
    def angle_bracket_plus(a):
        return (a + abs(a)) / 2

    def angle_bracket_minus(a):
        return (a - abs(a)) / 2

    #----------------------------------------------------------------------------------------
    def g(alpha_):
        """
		degradation function
		"""
        return ((1 - alpha_)**2 + k_ell)

    #----------------------------------------------------------------------------------------
    def eps(u_):
        """
		Geometrical strain
		"""
        return sym(grad(u_))

    def dev_eps(u_):
        """

		"""
        return eps(u_) - 1 / 3 * tr(eps(u_)) * Identity(ndim)

    #----------------------------------------------------------------------------------------
    def sigma0(u_):
        """
		Application of the sound elasticy tensor on the strain tensor
		"""
        Id = Identity(len(u_))
        return 2.0 * mu * eps(u_) + lmbda * tr(eps(u_)) * Id

    def sigma_A(u_, alpha_):
        """
		Stress Model A
		"""
        return g(alpha_) * sigma0(u_)

    def sigma_B(u_, alpha_):
        """
		Stress Model B
		"""
        return g(alpha_) * (
            (lmbda + 2 / 3 * mu) *
            (angle_bracket_plus(tr(eps(u_))) * Identity(ndim)) +
            2 * mu * dev_eps(u_)) + (lmbda + 2 / 3 * mu) * (
                angle_bracket_minus(tr(dev_eps(u_))) * Identity(ndim))

    #----------------------------------------------------------------------------------------
    def psi_0(u_):
        """
		The strain energy density for a linear isotropic ma-
		terial
		"""
        return 0.5 * lmbda * tr(eps(u_))**2 + mu * eps(u_)**2

    def psi_A(u_, alpha_):
        """
		The strain energy density for model A
		"""
        return g(alpha_) * psi_0(u_)

    def psi_B(u_, alpha_):
        """
		The strain energy density for model B
		"""
        return g(alpha_) * (0.5 * (lmbda + 2 / 3 * mu) *
                            (angle_bracket_plus(tr(dev_eps(u_))))**2 + mu *
                            dev_eps(u_)**2) + 0.5 * (lmbda + 2 / 3 * mu) * (
                                angle_bracket_minus(tr(dev_eps(u_))))**2

    #----------------------------------------------------------------------------------------

    if not ModelB:  # Model A (isotropic model)
        psi = psi_A
        sigma = sigma_A
    else:  # Model B (Amor's model)
        psi = psi_B
        sigma = sigma_B

    #=======================================================================================
    # others definitions
    #=======================================================================================
    prefix = "%s-L%s-H%.2f-S%.4f-l%.4f-ka%s-kb%s-steps%s" % (
        law, L, H, hsize, ell, ka, kb, pressure_steps)
    save_dir = "Fracking_result/" + prefix + "/"

    if os.path.isdir(save_dir):
        shutil.rmtree(save_dir)

    # zero and unit vectors
    zero_v = Constant((0., ) * ndim)
    e1 = [Constant([1., 0.]), Constant((1., 0., 0.))][ndim - 2]

    # Normalization constant for the dissipated energy
    # to get Griffith surface energy for ell going to zero
    z = sympy.Symbol("z", positive=True)
    c_w = float(4 * sympy.integrate(sympy.sqrt(w(z)), (z, 0, 1)))

    # plane strain or plane stress
    if not PlaneStress:  # plane strain
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))
    else:  # plane stress
        lmbda = E * nu / (1.0 - nu**2)

    # shear modulus
    mu = E / (2.0 * (1.0 + nu))

    #=======================================================================================
    # Define boundary sets for boundary conditions
    #=======================================================================================
    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0] - L) * 0.01, 0)

    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0]) * 0.01, 0.)

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1] - H) * 0.01, 0)

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1]) * 0.01, 0)

    class Void(SubDomain):
        def inside(self, x, on_boundary):
            #return   x[0] <= 2.5 and x[0] >= 1.5  and  x[1] <= 2.5 and x[1] >= 1.5 and on_boundary
            H = 170
            L = 170
            radius = 5.
            return x[0] <= L / 2 + 2 * radius and x[
                0] >= L / 2 - 2 * radius and x[1] <= H / 2 + 2 * radius and x[
                    1] >= H / 2 - 2 * radius and on_boundary

    # Initialize sub-domain instances
    right = Right()
    left = Left()
    top = Top()
    bottom = Bottom()
    void = Void()

    # define meshfunction to identify boundaries by numbers
    boundaries = FacetFunction("size_t", mesh)
    boundaries.set_all(9999)
    right.mark(boundaries, 1)  # mark top as 1
    left.mark(boundaries, 2)  # mark top as 2
    top.mark(boundaries, 3)  # mark top as 3
    bottom.mark(boundaries, 4)  # mark bottom as 4
    void.mark(boundaries, 5)  # mark void as 5

    # Define new measure including boundary naming
    ds = Measure("ds")[boundaries]  # left: ds(1), right: ds(2)
    #=======================================================================================
    # Variational formulation
    #=======================================================================================
    # Create function space for 2D elasticity + Damage
    V_u = VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = FunctionSpace(mesh, "CG", 1)
    V_p = FunctionSpace(mesh, "CG", 1)

    # Define the function, test and trial fields
    u_, u, u_t = Function(V_u), TrialFunction(V_u), TestFunction(V_u)
    alpha_, alpha, alpha_t = Function(V_alpha), TrialFunction(
        V_alpha), TestFunction(V_alpha)
    P_, P, P_t = Function(V_p), TrialFunction(V_p), TestFunction(V_p),

    alpha_0 = Function(V_alpha)
    #define_alpha_0=Expression("x[1] == 2. & x[0] <= 2.2 & x[0] >=1.8 ? 1.0 : 0.0", degree=1)
    #define_alpha_0=Expression("(x[0] == 2. & x[1] <= 1.75 & x[1] >=1.55)  ? 1.0 : 0.0", degree=1)
    #alpha_0.interpolate(define_alpha_0) #added by Mostafa
    alpha_0 = interpolate(
        Constant(0.0), V_alpha)  # initial (known) alpha, undamaged everywhere.

    P_0 = interpolate(Expression("0.1", degree=1), V_p)
    #=======================================================================================
    # Dirichlet boundary condition for a traction test boundary
    #=======================================================================================
    # bc - u (imposed displacement)
    u_R = zero_v  #Expression(("-2*p", "0.",), p=0.0, degree=1)
    u_L = zero_v  #Expression(("-2*p", "0.",), p=0.0, degree=1)
    u_T = zero_v  #Expression(("0.", "-p",), p=0.0, degree=1)
    u_B = zero_v  #Expression(("0.", "-p",), p=0.0, degree=1)

    Gamma_u_0 = DirichletBC(V_u, u_R, boundaries, 1)
    Gamma_u_1 = DirichletBC(V_u, u_L, boundaries, 2)
    Gamma_u_2 = DirichletBC(V_u, u_T, boundaries, 3)
    Gamma_u_3 = DirichletBC(V_u, u_B, boundaries, 4)
    bc_u = [Gamma_u_1, Gamma_u_3, Gamma_u_0, Gamma_u_2]

    # bc - alpha (zero damage)
    Gamma_alpha_0 = DirichletBC(V_alpha, 0.0, boundaries, 1)
    Gamma_alpha_1 = DirichletBC(V_alpha, 0.0, boundaries, 2)
    Gamma_alpha_2 = DirichletBC(V_alpha, 0.0, boundaries, 3)
    Gamma_alpha_3 = DirichletBC(V_alpha, 0.0, boundaries, 4)
    Gamma_alpha_4 = DirichletBC(V_alpha, 1.0, mesh_fun, 101)
    Gamma_alpha_5 = DirichletBC(V_alpha, 1.0, mesh_fun, 102)

    bc_alpha = [
        Gamma_alpha_0, Gamma_alpha_1, Gamma_alpha_2, Gamma_alpha_3,
        Gamma_alpha_4, Gamma_alpha_5
    ]

    ## bc - P (imposed pressure)
    P_C = Expression("p", p=0.0, degree=1)

    Gamma_P_0 = DirichletBC(V_p, 0.1, boundaries, 1)
    Gamma_P_1 = DirichletBC(V_p, 0.1, boundaries, 2)
    Gamma_P_2 = DirichletBC(V_p, 0.1, boundaries, 3)
    Gamma_P_3 = DirichletBC(V_p, 0.1, boundaries, 4)
    #Gamma_P_4 = DirichletBC(V_p, P_C, mesh_fun, 101)
    #Gamma_P_4 = DirichletBC(V_p, P_C, boundaries, 5)
    bc_P = [Gamma_P_0, Gamma_P_1, Gamma_P_2, Gamma_P_3]  #, Gamma_P_4]

    ## bc - Q (imposed Flowrate)
    Q = Expression("p*q", p=0.0, q=q, degree=1)

    # bc - sigma (imposed traction)
    sigma_R = Expression((
        "-p",
        "0.",
    ), p=0.0, degree=1)  #traction on TOP boundary
    sigma_T = Expression((
        "0.",
        "-p",
    ), p=0.0, degree=1)  #traction on TOP boundary

    #====================================================================================
    # Define  problem and solvers
    #====================================================================================
    Pressure = 1. / M_biot * P_ * P * dx + DeltaT * kappa * exp(
        pow(ka * alpha_, kb)) / mu_dynamic * inner(
            nabla_grad(P), nabla_grad(P_)) * dx - (
                1 / M_biot * P_0 + DeltaT * f) * P * dx - DeltaT * Q * P * ds(
                    5)  # Wang et. al 2017 eq(8)
    #------------------------------------------------------------------------------------
    elastic_energy = psi(u_, alpha_) * dx
    external_work = dot(
        body_force, u_) * dx  #+ dot(sigma_R, u_)*ds(1)+ dot(sigma_T, u_)*ds(3)

    if not WheelerApproach:  # Bourdin approach, 2012 , SPE 159154, equation (5)
        pressurized_energy = P_ * inner(u_, grad(alpha_)) * dx
    else:  # M.F. Wheeler et al., CAMAME, 2014, eqution (4)
        pressurized_energy = -(biot - 1.) * (
            (1. - alpha_)**2 * P_ * div(u_)) * dx + dot(
                (1 - alpha_)**2 * grad(P_), u_) * dx

    dissipated_energy = Gc / float(c_w) * (
        w(alpha_) / ell + ell * inner(grad(alpha_), grad(alpha_))) * dx

    total_energy = elastic_energy + dissipated_energy + pressurized_energy - external_work

    # Residual and Jacobian of elasticity problem
    Du_total_energ = derivative(total_energy, u_, u_t)
    J_u = derivative(Du_total_energ, u_, u)

    # Residual and Jacobian of damage problem
    Dalpha_total_energy = derivative(total_energy, alpha_, alpha_t)
    J_alpha = derivative(Dalpha_total_energy, alpha_, alpha)

    #Jacobian of pressure problem
    J_p = derivative(Pressure, P_, P_t)

    # Variational problem for the displacement
    problem_u = NonlinearVariationalProblem(Du_total_energ, u_, bc_u, J_u)

    # Variational problem for the damage (non-linear to use variational inequality solvers of petsc)
    # Define the minimisation problem by using OptimisationProblem class
    class DamageProblem(OptimisationProblem):
        def __init__(self):
            OptimisationProblem.__init__(self)

        # Objective function
        def f(self, x):
            alpha_.vector()[:] = x
            return assemble(total_energy)

        # Gradient of the objective function
        def F(self, b, x):
            alpha_.vector()[:] = x
            assemble(Dalpha_total_energy, tensor=b)

        # Hessian of the objective function
        def J(self, A, x):
            alpha_.vector()[:] = x
            assemble(J_alpha, tensor=A)

    # Create the PETScTAOSolver
    problem_alpha = DamageProblem()

    # Parse (PETSc) parameters
    parameters.parse()

    # Set up the solvers
    solver_u = NonlinearVariationalSolver(problem_u)
    prm = solver_u.parameters
    prm["newton_solver"]["absolute_tolerance"] = 1E-6
    prm["newton_solver"]["relative_tolerance"] = 1E-6
    prm["newton_solver"]["maximum_iterations"] = 200
    prm["newton_solver"]["relaxation_parameter"] = 1.0
    prm["newton_solver"]["preconditioner"] = "default"
    prm["newton_solver"]["linear_solver"] = "mumps"

    solver_alpha = PETScTAOSolver()

    alpha_lb = interpolate(Expression("0.", degree=1),
                           V_alpha)  # lower bound, set to 0
    alpha_ub = interpolate(Expression("1.", degree=1),
                           V_alpha)  # upper bound, set to 1

    for bc in bc_alpha:
        bc.apply(alpha_lb.vector())

    for bc in bc_alpha:
        bc.apply(alpha_ub.vector())

    problem_pressure = NonlinearVariationalProblem(Pressure, P_, bc_P, J=J_p)
    solver_pressure = NonlinearVariationalSolver(problem_pressure)

    #=======================================================================================
    # To store results
    #=======================================================================================
    results = []
    file_alpha = File(save_dir +
                      "/alpha.pvd")  # use .pvd if .xdmf is not working
    file_u = File(save_dir + "/u.pvd")  # use .pvd if .xdmf is not working
    file_p = File(save_dir + "/p.pvd")
    #=======================================================================================
    # Solving at each timestep
    #=======================================================================================
    load_multipliers = np.linspace(pressure_min, pressure_max, pressure_steps)
    energies = np.zeros((len(load_multipliers), 5))
    iterations = np.zeros((len(load_multipliers), 2))
    forces = np.zeros((len(load_multipliers), 2))
    Borehole_Pressure = np.zeros((len(load_multipliers), 5))

    for (i_p, p) in enumerate(load_multipliers):

        print "\033[1;32m--- Time step %d: time = %g, Flowrate= %g ---\033[1;m" % (
            i_p, i_p * DeltaT, p * q)
        #u_R.p = p*ut
        #u_L.p = p#*ut
        #u_B.p = p#*ut
        #u_T.p = p*ut
        #P_C.p = p
        Q.p = p * q
        #sigma_T.p = p*st
        #sigma_R.p = p*st

        iteration = 0
        iter = 0
        err_P = 1
        err_alpha = 1
        # Iterations

        while err_P > tolerance and err_alpha > tolerance and iteration < max_iterations:
            # solve pressure problem
            solver_pressure.solve()
            err_P = (P_.vector() - P_0.vector()).norm('linf')
            if mpi_comm_world().rank == 0:
                print "Iteration:  %2d, pressure_Error: %2.8g, P_max: %.8g" % (
                    iter, err_P, P_.vector().max())
            P_0.vector()[:] = P_.vector()

            # solve elastic problem
            solver_u.solve()
            if mpi_comm_world().rank == 0:
                print "elastic iteration: %2d" % (iter)

            # solve damage problem
            solver_alpha.solve(problem_alpha, alpha_.vector(),
                               alpha_lb.vector(), alpha_ub.vector())
            # test error
            err_alpha = (alpha_.vector() - alpha_0.vector()).norm('linf')
            # monitor the results
            if mpi_comm_world().rank == 0:
                print "alpha iteration: %2d, Error: %2.8g" % (iter, err_alpha)
            # update iteration
            alpha_0.vector()[:] = alpha_.vector()
            iter += 1

        # Update the lower bound to account for the irreversibility
        alpha_lb.vector()[:] = alpha_.vector()

        #plt.figure(2)
        #plot(P_, key = "P", title = "Pressure %.4f"%(p*pressure_max))
        #plt.show()
        #plt.interactive(True)

        # plot the damage fied
        #plt.figure(3)
        #plot(alpha_, range_min = 0., range_max = 1., key = "alpha", title = "Damage at loading %.4f"%(p*pressure_max))
        #plt.show()
        #plt.interactive(True)
        #=======================================================================================
        # Some post-processing
        #=======================================================================================
        # Save number of iterations for the time step
        iterations[i_p] = np.array([p, iter])
        # Calculate the energies
        elastic_energy_value = assemble(elastic_energy)
        dissipated_energy_value = assemble(dissipated_energy)
        pressurized_energy_value = assemble(pressurized_energy)
        if mpi_comm_world().rank == 0:
            print("\nEnd of timestep %d with load multiplier %g" % (i_p, p))
            print("AM: Iteration number: %i - Elastic_energy: %.3e" %
                  (i_p, elastic_energy_value))
            print("AM: Iteration number: %i - Dissipated_energy: %.3e" %
                  (i_p, dissipated_energy_value))
            print("AM: Iteration number: %i - pressurized_energy: %.3e" %
                  (i_p, pressurized_energy_value))
            print "\033[1;32m--------------------------------------------------------------\033[1;m"

        energies[i_p] = np.array([
            p, elastic_energy_value, dissipated_energy_value,
            pressurized_energy_value, elastic_energy_value +
            dissipated_energy_value + pressurized_energy_value
        ])
        # Calculate the axial force resultant
        forces[i_p] = np.array(
            [p, assemble(inner(sigma(u_, alpha_) * e1, e1) * ds(1))])
        # max pressure

        point_a = (L / 2, H / 2 + radius)
        point_b = (L / 2 + radius, H / 2)
        point_c = (L / 2, H / 2 - radius)
        point_d = (L / 2 - radius, H / 2)
        P_point_a = P_(point_a)
        P_point_b = P_(point_b)
        P_point_c = P_(point_c)
        P_point_d = P_(point_d)

        Borehole_Pressure[i_p] = np.array(
            [p, P_point_a, P_point_b, P_point_c, P_point_d])

        # Dump solution to file
        file_alpha << (alpha_, p)
        file_u << (u_, p)
        file_p << (P_, p)
        # Save some global quantities as a function of the time
        np.savetxt(save_dir + '/energies.txt', energies)
        np.savetxt(save_dir + '/forces.txt', forces)
        np.savetxt(save_dir + '/iterations.txt', iterations)
        np.savetxt(save_dir + '/pressureboreholes.txt', Borehole_Pressure)
    #=======================================================================================
    # Plot energy and stresses
    #=======================================================================================
    #def critical_stress():
    #    xs = sympy.Symbol('x')
    #    wx = w(xs); sx = 1/(E*H*a(xs));
    #    res = sympy.sqrt(2*(Gc*H/c_w)*wx.diff(xs)/(sx.diff(xs)*ell))
    #    return res.evalf(subs={xs:0})

    #def plot_stress():
    #    plt.plot(forces[:,0], forces[:,1], 'b-o', linewidth = 2)
    #    plt.xlabel('Displacement')
    #    plt.ylabel('Force')
    #    force_cr = critical_stress()
    #    plt.axvline(x = force_cr/(E*H)*L, color = 'grey', linestyle = '--', linewidth = 2)
    #    plt.axhline(y = force_cr, color = 'grey', linestyle = '--', linewidth = 2)

    #def plot_energy():
    #    p1, = plt.plot(energies[:,0], energies[:,1],'b-o',linewidth=2)
    #    p2, = plt.plot(energies[:,0], energies[:,2],'r-o',linewidth=2)
    #    p3, = plt.plot(energies[:,0], energies[:,3],'k--',linewidth=2)
    #    plt.legend([p1, p2, p3], ["Elastic","Dissipated","Total"])
    #    plt.xlabel('Displacement')
    #    plt.ylabel('Energies')
    #    force_cr = critical_stress()
    #    plt.axvline(x = force_cr/(E*H)*L, color = 'grey',linestyle = '--', linewidth = 2)
    #    plt.axhline(y = H,color = 'grey', linestyle = '--', linewidth = 2)

    #def plot_energy_stress():
    #    plt.subplot(211)
    #    plot_stress()
    #    plt.subplot(212)
    #    plot_energy()
    #    plt.savefig(save_dir+'/energies_force.png')
    #    plt.show()

    def plot_PressureEvolution():
        plt.xlabel('Time steps')
        plt.ylabel('Pressure (MPa)')
        p1, = plt.plot(Borehole_Pressure[:, 0],
                       Borehole_Pressure[:, 1],
                       'b-o',
                       linewidth=2)
        p2, = plt.plot(Borehole_Pressure[:, 0],
                       Borehole_Pressure[:, 2],
                       'r-o',
                       linewidth=2)
        p3, = plt.plot(Borehole_Pressure[:, 0],
                       Borehole_Pressure[:, 3],
                       'k-o',
                       linewidth=2)
        p4, = plt.plot(Borehole_Pressure[:, 0],
                       Borehole_Pressure[:, 4],
                       'g-o',
                       linewidth=2)
        plt.legend([p1, p2, p3, p4],
                   ["Point A", "Point B", "Point C", "Point D"])

    def plot_PressurePoint():
        plot_PressureEvolution()
        plt.savefig(save_dir + '/PressurePoint.png')
        plt.show()

    # Project and write stress field to post-processing file
    s = sigma_A(u_, alpha_) - (1. / 3) * tr(sigma_A(u_, alpha_)) * Identity(
        ndim)  # deviatoric stress
    von_Mises = sqrt(3. / 2 * inner(s, s))
    V = FunctionSpace(mesh, 'P', 1)
    von_Mises = project(von_Mises, V)
    File(save_dir + "von_Mises.pvd") << von_Mises

    stress_tr = project(tr(sigma_A(u_, alpha_)), V)
    File(save_dir + "stress_tr.pvd") << stress_tr

    VV = VectorFunctionSpace(mesh, "CG", 1)
    Velocity_darcy = -kappa * exp(
        (ka * alpha_)**kb) * Identity(ndim) / mu_dynamic * nabla_grad(P_)
    Velocity_D = project(Velocity_darcy, VV)
    File(save_dir + "Velocity_D.pvd") << Velocity_D

    #plot_energy_stress()
    #plt.interactive(True)
    plot_PressurePoint()
Exemplo n.º 12
0
def Fracking(E, nu, hsize, ell, law, ModelB, load_steps):

    #=======================================================================================
    # Input date
    #=======================================================================================
    # Geometry
    L = 1.0  # length
    H = 1.0  # height
    #hsize= 1.0e-2 # target cell size
    meshname = "fracture_hsize%g" % (hsize)

    # Material constants
    #ell = Constant(4* hsize) # internal length scale
    #E = 6e3 # Young modulus MPa
    #nu = 0.3 # Poisson ratio

    PlaneStress = False

    gc = 2.7  #2.7e-3 #1.0 # fracture toughness MPa.mm
    k_ell = Constant(1.0e-12)  # residual stiffness
    #law = "AT2"

    # effective toughness
    if law == "AT2":
        Gc = gc / (1 + hsize / (2 * ell))  #AT2
    elif law == "AT1":
        Gc = gc / (1 + 3 * hsize / (8 * ell))  #AT1
    else:
        Gc = gc  #??

    #ModelB= False
    if not ModelB:  # Model A (isotropic model)
        Model = 'Isotropic'
    else:  # Model B (Amor's model)
        Model = 'Amor'

    # Stopping criteria for the alternate minimization
    max_iterations = 1000
    tolerance = 1.0e-6

    # Loading
    ut = 6.e-3  # reference value for the loading (imposed displacement)
    body_force = Constant((0., 0.))  # bulk load
    load_min = 0.  # load multiplier min value
    load_max = 1.  # load multiplier max value
    #load_steps = 20 # number of time steps

    #=======================================================================================
    # Geometry and mesh generation
    #=======================================================================================
    # Generate a XDMF/HDF5 based mesh from a Gmsh string
    geofile = \
      """
			lc = DefineNumber[ %g, Name "Parameters/lc" ];
                             // Geometry Boundary
		        Point(1) = {0,0,0,lc};
		        Point(2) = {1,0,0,lc};
		        Point(3) = {1,.5,0,lc};
		        Point(4) = {1,1,0,lc};
		        Point(5) = {0,1,0,lc};
		        Point(6) = {0,.5,0,lc};

		        Line(1) ={1,2};
		        Line(2) ={2,3};
		        Line(3) ={3,4};
		        Line(4) ={4,5};
		        Line(5) ={5,6};


		        // Crack Geometry
		        Point(7) = {.5,.5,0,lc};
		        Point(8) = {0,.5,0,lc};

		        Line(7) = {6,7}; // <-- dummy divider
		        Line(8) = {7,3}; // <-- crack

		        // added by Vahid
		        Line(9) = {7,8}; // <-- crack

		        Line(6) ={8,1};

		        //Make line loops and surfaces
		        Line Loop(1) = {1,2,-8,9,6}; // Bottom half
		        Line Loop(2) = {3,4,5,7,8}; // Top half
		        Plane Surface(1) = {1};
		        Plane Surface(2) = {2};

		        //Assign physical IDs (numbers picked just so they will be obvious in .msh file)
		        Physical Surface(100) = {1}; // bottom will have ID 100
		        Physical Surface(200) = {2}; // top will have ID 101
		        Physical Line(101) = {7}; // crack will have ID 10
		        Physical Line(201) = {9}; // crack will have ID 10

		        // more physical ids on top and bottom for boundary conditions in a solver
		        // Physical Line(1) = {1};
		        // Physical Line(2) = {4};

	"""%(hsize)

    subdir = "meshes/"
    _mesh = Mesh()  #creat empty mesh object
    if not os.path.isfile(subdir + meshname + ".xdmf"):
        if MPI.rank(mpi_comm_world()) == 0:
            # Create temporary .geo file defining the mesh
            if os.path.isdir(subdir) == False:
                os.mkdir(subdir)
            fgeo = open(subdir + meshname + ".geo", "w")
            fgeo.writelines(geofile)
            fgeo.close()
            # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
            try:
                subprocess.call([
                    "gmsh", "-2", "-o", subdir + meshname + ".msh",
                    subdir + meshname + ".geo"
                ])
            except OSError:
                print(
                    "-----------------------------------------------------------------------------"
                )
                print(" Error: unable to generate the mesh using gmsh")
                print(
                    " Make sure that you have gmsh installed and have added it to your system PATH"
                )
                print(
                    "-----------------------------------------------------------------------------"
                )

            meshconvert.convert2xml(subdir + meshname + ".msh",
                                    subdir + meshname + ".xml", "gmsh")

        # Convert to XDMF
        MPI.barrier(mpi_comm_world())
        mesh = Mesh(subdir + meshname + ".xml")
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.write(mesh)
        XDMF.read(_mesh)

        if os.path.isfile(subdir + meshname +
                          "_physical_region.xml") and os.path.isfile(
                              subdir + meshname + "_facet_region.xml"):
            if MPI.rank(mpi_comm_world()) == 0:
                mesh = Mesh(subdir + meshname + ".xml")
                subdomains = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_physical_region.xml")
                boundaries = MeshFunction(
                    "size_t", mesh, subdir + meshname + "_facet_region.xml")
                HDF5 = HDF5File(mesh.mpi_comm(),
                                subdir + meshname + "_physical_facet.h5", "w")
                HDF5.write(mesh, "/mesh")
                HDF5.write(subdomains, "/subdomains")
                HDF5.write(boundaries, "/boundaries")
                print("Finish writting physical_facet to HDF5")

        if MPI.rank(mpi_comm_world()) == 0:
            # Keep only the .xdmf mesh
            #os.remove(subdir + meshname + ".geo")
            #os.remove(subdir + meshname + ".msh")
            #os.remove(subdir + meshname + ".xml")

            # Info
            print("Mesh completed")

    # Read the mesh if existing
    else:
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.read(_mesh)

    mesh = Mesh('meshes/fracture_hsize' + str(float(hsize)) + '.xml')
    mesh_fun = MeshFunction(
        "size_t", mesh,
        "meshes/fracture_hsize" + str(float(hsize)) + "_facet_region.xml")
    #plt.figure(1)
    #plot(mesh, "2D mesh")
    #plt.interactive(True)

    ndim = mesh.geometry().dim()  # get number of space dimensions

    #=======================================================================================
    # Constitutive functions of the damage model
    #=======================================================================================
    def a(alpha_):
        """
		Modulation of the elastic stiffness
		"""
        if law == "AT1":
            return (1 - alpha_)**2
        elif law == "AT2":
            return (1 - alpha_)**2
        elif law == "ATk":
            return (1 - w(alpha_)) / (1 + (k - 1) * w(alpha_))

    def w(alpha_):
        """
		Local energy dissipation
		"""
        if law == "AT1":
            return alpha_
        elif law == "AT2":
            return alpha_**2
        elif law == "ATk":
            return 1 - (1 - alpha_)**2

    #=======================================================================================
    # strain, stress and strain energy for Isotropic and Amor's model
    #=======================================================================================
    def angle_bracket_plus(a):
        return (a + abs(a)) / 2

    def angle_bracket_minus(a):
        return (a - abs(a)) / 2

    #----------------------------------------------------------------------------------------
    def g(alpha_):
        """
		degradation function
		"""
        return ((1 - alpha_)**2 + k_ell)

    #----------------------------------------------------------------------------------------
    def eps(u_):
        """
		Geometrical strain
		"""
        return sym(grad(u_))

    def dev_eps(u_):
        """

		"""
        return eps(u_) - 1 / 3 * tr(eps(u_)) * Identity(ndim)

    #----------------------------------------------------------------------------------------
    def sigma0(u_):
        """
		Application of the sound elasticy tensor on the strain tensor
		"""
        Id = Identity(len(u_))
        return 2.0 * mu * eps(u_) + lmbda * tr(eps(u_)) * Id

    def sigma_A(u_, alpha_):
        """
		Stress Model A
		"""
        return g(alpha_) * sigma0(u_)

    def sigma_B(u_, alpha_):
        """
		Stress Model B
		"""
        K = lmbda + 2 / 3 * mu
        return  g(alpha_) * ( K * ( angle_bracket_plus( tr(eps(u_))) * Identity(ndim) )+ 2*mu*dev_eps(u_) ) \
         + K*( angle_bracket_minus(tr(dev_eps(u_))) * Identity(ndim))

    #----------------------------------------------------------------------------------------
    def psi_0(u_):
        """
		The strain energy density for a linear isotropic ma-
		terial
		"""
        return 0.5 * lmbda * tr(eps(u_))**2 + mu * eps(u_)**2

    def psi_A(u_, alpha_):
        """
		The strain energy density for model A
		"""
        return g(alpha_) * psi_0(u_)

    def psi_B(u_, alpha_):
        """
		The strain energy density for model B
		"""
        K = lmbda + 2 / 3 * mu
        return g(alpha_) * (0.5 * K *
                            (angle_bracket_plus(tr(dev_eps(u_))))**2 +
                            mu * dev_eps(u_)**2) + 0.5 * K * (
                                angle_bracket_minus(tr(dev_eps(u_))))**2

    #----------------------------------------------------------------------------------------

    if not ModelB:  # Model A (isotropic model)
        psi = psi_A
        sigma = sigma_A
    else:  # Model B (Amor's model)
        psi = psi_B
        sigma = sigma_B

    #=======================================================================================
    # others definitions
    #=======================================================================================
    prefix = "%s-%s-L%s-H%.2f-S%.4f-l%.4f-load_steps%s " % (
        law, Model, L, H, hsize, ell, load_steps)
    save_dir = "Fracture_QS_result/" + prefix + "/"

    if os.path.isdir(save_dir):
        shutil.rmtree(save_dir)

    # zero and unit vectors
    zero_v = Constant((0., ) * ndim)
    e1 = [Constant([1., 0.]), Constant((1., 0., 0.))][ndim - 2]
    e2 = [Constant([0., 1.]), Constant((0., 1., 0.))][ndim - 2]
    # Normalization constant for the dissipated energy
    # to get Griffith surface energy for ell going to zero
    z = sympy.Symbol("z", positive=True)
    c_w = float(4 * sympy.integrate(sympy.sqrt(w(z)), (z, 0, 1)))

    # plane strain or plane stress
    if not PlaneStress:  # plane strain
        lmbda = 121.15e3  # E*nu/((1.0+nu)*(1.0-2.0*nu))
    else:  # plane stress
        lmbda = 121.15e3  # E*nu/(1.0-nu**2)

    # shear modulus
    mu = 80.77e3  # E / (2.0 * (1.0 + nu))

    #=======================================================================================
    # Define boundary sets for boundary conditions
    #=======================================================================================
    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0] - L) * 0.01, 0)

    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[0]) * 0.01, 0.)

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1] - H) * 0.01, 0)

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near((x[1]) * 0.01, 0)

    # Initialize sub-domain instances
    right = Right()
    left = Left()
    top = Top()
    bottom = Bottom()

    # define meshfunction to identify boundaries by numbers
    boundaries = FacetFunction("size_t", mesh)
    boundaries.set_all(9999)
    right.mark(boundaries, 1)  # mark top as 1
    left.mark(boundaries, 2)  # mark top as 2
    top.mark(boundaries, 3)  # mark top as 3
    bottom.mark(boundaries, 4)  # mark bottom as 4

    # Define new measure including boundary naming
    ds = Measure("ds")[boundaries]  # left: ds(1), right: ds(2)
    #=======================================================================================
    # Variational formulation
    #=======================================================================================
    # Create function space for 2D elasticity + Damage
    V_u = VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = FunctionSpace(mesh, "CG", 1)

    # Define the function, test and trial fields
    u_, u, u_t = Function(V_u), TrialFunction(V_u), TestFunction(V_u)
    alpha_, alpha, alpha_t = Function(V_alpha), TrialFunction(
        V_alpha), TestFunction(V_alpha)

    alpha_0 = Function(V_alpha)
    define_alpha_0 = Expression(
        "x[1] == 0.5 & x[0] <= 0.5 & x[0] >=0 ? 1.0 : 0.0", degree=1)
    alpha_0.interpolate(define_alpha_0)  #added by Mostafa
    #alpha_0 = interpolate(Constant(0.0), V_alpha) # initial (known) alpha, undamaged everywhere.
    #=======================================================================================
    # Dirichlet boundary condition for a traction test boundary
    #=======================================================================================
    # bc - u (imposed displacement)
    u_R = zero_v  #Expression(("t", "0.",), t=0.0, degree=1)
    u_L = zero_v
    u_T = Expression((
        "0.",
        "t",
    ), t=0.0, degree=1)
    u_B = Expression((
        "0.",
        "-t",
    ), t=0.0, degree=1)

    Gamma_u_0 = DirichletBC(V_u, u_R, boundaries, 1)
    Gamma_u_1 = DirichletBC(V_u, u_L, boundaries, 2)
    Gamma_u_2 = DirichletBC(V_u, u_T, boundaries, 3)
    Gamma_u_3 = DirichletBC(V_u, zero_v, boundaries, 4)
    bc_u = [Gamma_u_2, Gamma_u_3]

    # bc - alpha (zero damage)
    Gamma_alpha_0 = DirichletBC(V_alpha, Constant(0.0), boundaries, 1)
    Gamma_alpha_1 = DirichletBC(V_alpha, Constant(0.0), boundaries, 2)
    Gamma_alpha_2 = DirichletBC(V_alpha, Constant(0.0), boundaries, 3)
    Gamma_alpha_3 = DirichletBC(V_alpha, Constant(0.0), boundaries, 4)
    Gamma_alpha_4 = DirichletBC(V_alpha, Constant(1.0), mesh_fun, 101)
    bc_alpha = [
    ]  #Gamma_alpha_0, Gamma_alpha_1, Gamma_alpha_2, Gamma_alpha_3]#, Gamma_alpha_4]

    # bc - sigma (imposed traction)
    sigma_T = Expression((
        "0.",
        "t",
    ), t=0.0, degree=1)  #traction on TOP boundary
    sigma_B = Expression((
        "0.",
        "-t",
    ), t=0.0, degree=1)  #traction on TOP boundary

    #====================================================================================
    # Define  problem and solvers
    #====================================================================================
    elastic_energy = psi(u_, alpha_) * dx
    external_work = dot(
        body_force, u_) * dx  #+ dot(sigma_T, u_)*ds(3)+ dot(sigma_B, u_)*ds(4)
    dissipated_energy = Gc / float(c_w) * (
        w(alpha_) / ell + ell * inner(grad(alpha_), grad(alpha_))) * dx

    print c_w
    total_energy = elastic_energy + dissipated_energy - external_work

    # First derivatives of energies (Residual)
    Du_total_energy = derivative(total_energy, u_, u_t)
    Dalpha_total_energy = derivative(total_energy, alpha_, alpha_t)

    # Second derivatives of energies (Jacobian)
    J_u = derivative(Du_total_energy, u_, u)
    J_alpha = derivative(Dalpha_total_energy, alpha_, alpha)

    # Variational problem for the displacement
    problem_u = NonlinearVariationalProblem(Du_total_energy, u_, bc_u, J_u)

    # Variational problem for the damage (non-linear to use variational inequality solvers of petsc)
    # Define the minimisation problem by using OptimisationProblem class
    class DamageProblem(OptimisationProblem):
        def __init__(self):
            OptimisationProblem.__init__(self)

        # Objective function
        def f(self, x):
            alpha_.vector()[:] = x
            return assemble(total_energy)

        # Gradient of the objective function
        def F(self, b, x):
            alpha_.vector()[:] = x
            assemble(Dalpha_total_energy, tensor=b)

        # Hessian of the objective function
        def J(self, A, x):
            alpha_.vector()[:] = x
            assemble(J_alpha, tensor=A)

    # Create the PETScTAOSolver
    problem_alpha = DamageProblem()

    # Parse (PETSc) parameters
    parameters.parse()

    #-------------------
    # Solver setup
    #-------------------
    # Set up the solvers
    solver_u = NonlinearVariationalSolver(problem_u)
    prm = solver_u.parameters
    prm["newton_solver"]["absolute_tolerance"] = 1E-6
    prm["newton_solver"]["relative_tolerance"] = 1E-6
    prm["newton_solver"]["maximum_iterations"] = 100
    prm["newton_solver"]["relaxation_parameter"] = 1.0
    prm["newton_solver"]["preconditioner"] = "default"
    prm["newton_solver"]["linear_solver"] = "mumps"
    #set_log_level(PROGRESS)

    solver_alpha = PETScTAOSolver()

    alpha_lb = interpolate(Expression("0.", degree=1),
                           V_alpha)  # lower bound, set to 0
    alpha_ub = interpolate(Expression("1.", degree=1),
                           V_alpha)  # upper bound, set to 1
    #info(solver_alpha.parameters,True) # uncomment to see available parameters
    for bc in bc_alpha:
        bc.apply(alpha_lb.vector())

    for bc in bc_alpha:
        bc.apply(alpha_ub.vector())
    #=======================================================================================
    # To store results
    #=======================================================================================
    results = []
    file_alpha = File(save_dir +
                      "/alpha.pvd")  # use .pvd if .xdmf is not working
    file_u = File(save_dir + "/u.pvd")  # use .pvd if .xdmf is not working

    #=======================================================================================
    # Solving at each timestep
    #=======================================================================================
    load_multipliers = np.linspace(load_min, load_max, load_steps)
    energies = np.zeros((len(load_multipliers), 4))
    iterations = np.zeros((len(load_multipliers), 2))
    forces_x = np.zeros((len(load_multipliers), 2))
    forces_y = np.zeros((len(load_multipliers), 2))

    for (i_t, t) in enumerate(load_multipliers):

        print "\033[1;32m--- Time step %d: t = %g ---\033[1;m" % (i_t, t)
        u_T.t = t * ut
        #u_B.t = t*ut
        #sigma_T.t = t
        #sigma_B.t = t

        # Alternate mininimization
        # Initialization
        iter = 1
        err_alpha = 1
        # Iterations
        while err_alpha > tolerance and iter < max_iterations:
            # solve elastic problem
            solver_u.solve()

            #plt.figure(2)
            #plot(u_, title = "Displacement %.4f"%(ut*t))
            #plt.show()

            # solve damage problem
            solver_alpha.solve(problem_alpha, alpha_.vector(),
                               alpha_lb.vector(), alpha_ub.vector())

            # plot the damage fied
            #plt.figure(3)
            #plot(alpha_, range_min = 0., range_max = 1., key = "alpha", title = "Damage at loading %.4f"%(ut*t))
            #plt.show()

            # test error
            err_alpha = (alpha_.vector() - alpha_0.vector()).norm('linf')
            # monitor the results
            if mpi_comm_world().rank == 0:
                print "Iteration:  %2d, Error: %2.8g, alpha_max: %.8g" % (
                    iter, err_alpha, alpha_.vector().max())

            # update iteration
            alpha_0.vector()[:] = alpha_.vector()
            iter += 1

        # Update the lower bound to account for the irreversibility
        alpha_lb.vector()[:] = alpha_.vector()

        #plt.interactive(True)
        #=======================================================================================
        # Some post-processing
        #=======================================================================================
        # Save number of iterations for the time step
        iterations[i_t] = np.array([t, iter])
        # Calculate the energies
        elastic_energy_value = assemble(elastic_energy)
        surface_energy_value = assemble(dissipated_energy)
        if mpi_comm_world().rank == 0:
            print("\nEnd of timestep %d with load multiplier %g" % (i_t, t))
            print("AM: Iteration number: %i - Elastic_energy: %.3e" %
                  (i_t, elastic_energy_value))
            print("AM: Iteration number: %i - Dissipated_energy: %.3e" %
                  (i_t, surface_energy_value))
            print "\033[1;32m--------------------------------------------------------------\033[1;m"

        energies[i_t] = np.array([
            t, elastic_energy_value, surface_energy_value,
            elastic_energy_value + surface_energy_value
        ])
        # Calculate the axial force resultant
        forces_x[i_t] = np.array(
            [ut * t,
             assemble(inner(sigma(u_, alpha_) * e1, e1) * ds(3))])
        forces_y[i_t] = np.array(
            [ut * t,
             assemble(inner(sigma(u_, alpha_) * e2, e2) * ds(3))])
        # Dump solution to file
        file_alpha << (alpha_, t)
        file_u << (u_, t)
        # Save some global quantities as a function of the time
        np.savetxt(save_dir + '/energies.txt', energies)
        np.savetxt(save_dir + '/forces_x.txt', forces_x)
        np.savetxt(save_dir + '/forces_y.txt', forces_y)
        np.savetxt(save_dir + '/iterations.txt', iterations)

    #=======================================================================================
    # Plot energy and stresses
    #=======================================================================================
    #def critical_stress():
    #    xs = sympy.Symbol('x')
    #    wx = w(xs); sx = 1/(E*H*a(xs));
    #    res = sympy.sqrt(2*(Gc*H/c_w)*wx.diff(xs)/(sx.diff(xs)*ell))
    #    return res.evalf(subs={xs:0})

    def plot_stress():
        plt.plot(forces[:, 0], forces[:, 1], 'b-o', linewidth=2)
        plt.xlabel('Displacement')
        plt.ylabel('Force')
        #force_cr = critical_stress()
        #plt.axvline(x = force_cr/(E*H)*L, color = 'grey', linestyle = '--', linewidth = 2)
        #plt.axhline(y = force_cr, color = 'grey', linestyle = '--', linewidth = 2)

    def plot_energy():
        p1, = plt.plot(energies[:, 0], energies[:, 1], 'b-o', linewidth=2)
        p2, = plt.plot(energies[:, 0], energies[:, 2], 'r-o', linewidth=2)
        p3, = plt.plot(energies[:, 0], energies[:, 3], 'k--', linewidth=2)
        plt.legend([p1, p2, p3], ["Elastic", "Dissipated", "Total"])
        plt.xlabel('Displacement')
        plt.ylabel('Energies')
        #force_cr = critical_stress()
        #plt.axvline(x = force_cr/(E*H)*L, color = 'grey',linestyle = '--', linewidth = 2)
        #plt.axhline(y = H,color = 'grey', linestyle = '--', linewidth = 2)

    #def plot_energy_stress():
    #    plt.subplot(211)
    #    plot_stress()
    #    plt.subplot(212)
    #    plot_energy()
    #    plt.savefig(save_dir+'/energies_force.png')
    #plt.show()

    #plot_energy_stress()
    #plt.interactive(True)
    #=======================================================================================
    # Save alpha and displacement data
    #=======================================================================================
    output_file_u = HDF5File(mpi_comm_world(), save_dir + "u_4_opening.h5",
                             "w")  # self.save_dir + "uO.h5"
    output_file_u.write(u_, "solution")
    output_file_u.close()

    output_file_alpha = HDF5File(mpi_comm_world(),
                                 save_dir + "alpha_4_opening.h5", "w")
    output_file_alpha.write(alpha_, "solution")
    output_file_alpha.close()
Exemplo n.º 13
0
    def createMesh(self):
        print("Defining mesh geometry...")
        self.initMesher()
        #subdomains is a dictionary keyed by 'left', 'top', etc. with the
        #face subdomains as values.
        #electrodes is a list of the electrode subdomains.
        self.subdomains, self.electrodes = self.mesher.createGeometry()

        # attempt to use meshio to import the mesh first, fallback to
        # dolfin-convert failing that

        try:
            print("Converting mesh from .msh to .xdmf using meshio...")
            f_gmsh = os.path.join(self.exporter.abs_in_dir, "domain.msh")
            f_mesh_xdmf = os.path.join(self.exporter.abs_in_dir, "mesh.xdmf")
            f_mf_xdmf = os.path.join(self.exporter.abs_in_dir, "mf.xdmf")
            f_cf_xdmf = os.path.join(self.exporter.abs_in_dir, "cf.xdmf")
            gm_dict_type = 'gmsh:physical'  # 'gmsh:geometrical'
            msh = meshio.read(f_gmsh)

            for cell in msh.cells:
                if cell.type == "triangle":
                    triangle_cells = cell.data
                elif cell.type == "tetra":
                    tetra_cells = cell.data

            for key in msh.cell_data_dict[gm_dict_type].keys():
                if key == "triangle":
                    triangle_data = msh.cell_data_dict[gm_dict_type][key]
                elif key == "tetra":
                    tetra_data = msh.cell_data_dict[gm_dict_type][key]

            tetra_mesh = meshio.Mesh(points=msh.points,
                                     cells={"tetra": tetra_cells})
            triangle_mesh = meshio.Mesh(
                points=msh.points,
                cells=[("triangle", triangle_cells)],
                cell_data={"name_to_read": [triangle_data]})
            cell_function = meshio.Mesh(
                points=msh.points,
                cells=[("tetra", tetra_cells)],
                cell_data={"name_to_read": [tetra_data]})

            meshio.write(f_mesh_xdmf, tetra_mesh)
            meshio.write(f_mf_xdmf, triangle_mesh)
            meshio.write(f_cf_xdmf, cell_function)

            print("Importing mesh from .xdmf...")
            self.mesh = dolfin.Mesh()
            with dolfin.XDMFFile(f_mesh_xdmf) as infile:
                infile.read(self.mesh)
            mvc = dolfin.MeshValueCollection("size_t", self.mesh, 2)
            with dolfin.XDMFFile(f_mf_xdmf) as infile:
                infile.read(mvc, "name_to_read")
            mf = dolfin.cpp.mesh.MeshFunctionSizet(self.mesh, mvc)

            mvc = dolfin.MeshValueCollection("size_t", self.mesh, 3)
            with dolfin.XDMFFile(f_cf_xdmf) as infile:
                infile.read(mvc, "name_to_read")
            cf = dolfin.cpp.mesh.MeshFunctionSizet(self.mesh, mvc)

        except:
            print(
                "meshio failed, reverting to legacy dolfin-convert conversion")

            #convert mesh to xml suitable for dolfin
            print("Converting mesh from .msh to .xml...")
            meshconvert.convert2xml(
                os.path.join(self.exporter.abs_in_dir, "domain.msh"),
                os.path.join(self.exporter.abs_in_dir, "domain.xml"))

            # legacy
            print("Importing mesh from .xml...")
            #set as mesh in model
            self.mesh = dolfin.Mesh(
                os.path.join(self.exporter.abs_in_dir, 'domain.xml'))
Exemplo n.º 14
0
def mesher(geofile, meshname):

    subdir = "meshes/"
    _mesh  = Mesh() #creat empty mesh object
    if not os.path.isfile(subdir + meshname + ".xdmf"):

        if MPI.rank(mpi_comm_world()) == 0:

            # Create temporary .geo file defining the mesh
            if os.path.isdir(subdir) == False:
                os.mkdir(subdir)
            fgeo = open(subdir + meshname + ".geo", "w")
            fgeo.writelines(geofile)
            fgeo.close()

            # Calling gmsh and dolfin-convert to generate the .xml mesh (as well as a MeshFunction file)
            try:
                subprocess.call(["gmsh", "-2", "-o", subdir + meshname + ".msh", subdir + meshname + ".geo"])
            except OSError:
                print("-----------------------------------------------------------------------------")
                print(" Error: unable to generate the mesh using gmsh")
                print(" Make sure that you have gmsh installed and have added it to your system PATH")
                print("-----------------------------------------------------------------------------")
                return
            meshconvert.convert2xml(subdir + meshname + ".msh", subdir + meshname + ".xml", "gmsh")

        # Convert to XDMF
        MPI.barrier(mpi_comm_world())
        mesh = Mesh(subdir + meshname + ".xml")
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.write(mesh)
        XDMF.read(_mesh)

        if os.path.isfile(subdir + meshname + "_physical_region.xml") and os.path.isfile(subdir + meshname + "_facet_region.xml"):

            if MPI.rank(mpi_comm_world()) == 0:

                mesh = Mesh(subdir + meshname + ".xml")
                subdomains = MeshFunction("size_t", mesh, subdir + meshname + "_physical_region.xml")
                boundaries = MeshFunction("size_t", mesh, subdir + meshname + "_facet_region.xml")
                HDF5 = HDF5File(mesh.mpi_comm(), subdir + meshname + "_physical_facet.h5", "w")
                HDF5.write(mesh, "/mesh")
                HDF5.write(subdomains, "/subdomains")
                HDF5.write(boundaries, "/boundaries")

                print("Finish writting physical_facet to HDF5")

        if MPI.rank(mpi_comm_world()) == 0:

            # Keep only the .xdmf mesh
            os.remove(subdir + meshname + ".geo")
            os.remove(subdir + meshname + ".msh")
            #os.remove(subdir + meshname + ".xml")

            # Info
            print("Mesh completed")

    # Read the mesh if existing
    else:
        XDMF = XDMFFile(mpi_comm_world(), subdir + meshname + ".xdmf")
        XDMF.read(_mesh)

    return _mesh