示例#1
0
def initial_conditions_wave_system(my_mesh):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    if (dim != 1):
        raise ValueError(
            "initial_conditions_wave_system: Mesh dimension should be 1")

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, dim)
    U = cdmath.Field("Conservative vector", cdmath.CELLS, my_mesh, dim + 1)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()

        pressure_field[i] = p0
        if (x > 0.5):
            velocity_field[i, 0] = 1
        else:
            velocity_field[i, 0] = -1

        U[i, 0] = p0
        U[i, 1] = rho0 * velocity_field[i, 0]

    return U, pressure_field, velocity_field
示例#2
0
def initial_conditions_wave_system(my_mesh):
    test_desc["Initial_data"]="Constant pressure, divergence free velocity"
    
    dim     = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()
        y = my_mesh.getCell(i).y()

        pressure_field[i] = p0
        if(dim==1):
            velocity_field[i,0] = 1
            velocity_field[i,1] = 0
            velocity_field[i,2] = 0
        elif(dim==2):
            velocity_field[i,0] =  sin(pi*x)*cos(pi*y)
            velocity_field[i,1] = -sin(pi*y)*cos(pi*x)
            velocity_field[i,2] = 0
        elif(dim==3):
            z = my_mesh.getCell(i).z()
            velocity_field[i,0] =    sin(pi*x)*cos(pi*y)*cos(pi*z)
            velocity_field[i,1] =    sin(pi*y)*cos(pi*x)*cos(pi*z)
            velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y)
        
    return pressure_field, velocity_field
示例#3
0
def initial_conditions_square_vortex(my_mesh):
    print "Initial data : Square vortex (Constant pressure, divergence free velocity)"
    dim     = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()
        y = my_mesh.getCell(i).y()
        z = my_mesh.getCell(i).z()

        pressure_field[i] = p0
        if(dim==1):
            velocity_field[i,0] = 1
            velocity_field[i,1] = 0
            velocity_field[i,2] = 0
        elif(dim==2):
            velocity_field[i,0] =  sin(pi*x)*cos(pi*y)
            velocity_field[i,1] = -sin(pi*y)*cos(pi*x)
            velocity_field[i,2] = 0
        elif(dim==3):
            velocity_field[i,0] =    sin(pi*x)*cos(pi*y)*cos(pi*z)
            velocity_field[i,1] =    sin(pi*y)*cos(pi*x)*cos(pi*z)
            velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y)
        
    return pressure_field, velocity_field
示例#4
0
def initial_conditions_RiemannProblem(my_mesh):
    print "Initial data : Riemann problem"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    xcentre = 0

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()

        velocity_field[i, 0] = 0
        velocity_field[i, 1] = 0
        velocity_field[i, 2] = 0

        if x < xcentre:
            pressure_field[i] = p0
            pass
        else:
            pressure_field[i] = p0 / 2
            pass
        pass

    return pressure_field, velocity_field
示例#5
0
def source_term_and_stat_solution_wave_system(my_mesh):
    test_desc["Source_term"] = "True"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells * (dim + 1))

    stat_pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    stat_momentum_field = cdmath.Field("Momentum", cdmath.CELLS, my_mesh, 3)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if (dim == 1):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * sign(x - 1. / 2)
            source_vector[k * (dim + 1) + 1] = 0

            stat_pressure_field[k] = abs(x - 1. / 2) * (x - 1. / 2)
            stat_momentum_field[k, 0] = -2 * abs(x - 1. / 2)
            stat_momentum_field[k, 1] = 0
            stat_momentum_field[k, 2] = 0
        elif (dim == 2):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * (
                sign(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) * sign(y - 1. / 2))
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0

            stat_pressure_field[k] = (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[
                k, 0] = -2 * abs(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[
                k, 1] = -2 * (x - 1. / 2) * abs(x - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[k, 2] = 0
        elif (dim == 3):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * (
                sign(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2) *
                (z - 1. / 2) * abs(z - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) * sign(y - 1. / 2) *
                (z - 1. / 2) * abs(z - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) *
                (y - 1. / 2) * abs(y - 1. / 2) * sign(z - 1. / 2))
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0
            source_vector[k * (dim + 1) + 3] = 0

            stat_pressure_field[k] = (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 0] = -2 * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 1] = -2 * (x - 1. / 2) * abs(
                x - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 2] = -2 * (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * abs(z - 1. / 2)

    return source_vector, stat_pressure_field, stat_momentum_field
def source_term_and_stat_solution_wave_system(my_mesh):
    test_desc["Source_term"] = "True"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells * (dim + 1))

    stat_pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    stat_velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if (dim == 1):
            source_vector[k * (dim + 1) +
                          0] = c0 * c0 * 4 * pi * pi * sin(2 * pi * x)
            source_vector[k * (dim + 1) + 1] = 0

            stat_pressure_field[k] = sin(2 * pi * x)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) / rho0
            stat_velocity_field[k, 1] = 0
            stat_velocity_field[k, 2] = 0
        elif (dim == 2):
            source_vector[k * (dim + 1) + 0] = 2 * c0 * c0 * 4 * pi * pi * sin(
                2 * pi * x) * sin(2 * pi * y)
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0

            stat_pressure_field[k] = sin(2 * pi * x) * sin(2 * pi * y)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) * sin(
                2 * pi * y) / rho0
            stat_velocity_field[k, 1] = -2 * pi * sin(2 * pi * x) * cos(
                2 * pi * y) / rho0
            stat_velocity_field[k, 2] = 0
        elif (dim == 3):
            source_vector[k * (dim + 1) + 0] = 3 * c0 * c0 * 4 * pi * pi * sin(
                2 * pi * x) * sin(2 * pi * y) * sin(2 * pi * z)
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0
            source_vector[k * (dim + 1) + 3] = 0

            stat_pressure_field[k] = sin(2 * pi * x) * sin(2 * pi * y) * sin(
                2 * pi * z)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) * sin(
                2 * pi * y) * sin(2 * pi * z) / rho0
            stat_velocity_field[k, 1] = -2 * pi * sin(2 * pi * x) * cos(
                2 * pi * y) * sin(2 * pi * z) / rho0
            stat_velocity_field[k, 2] = -2 * pi * sin(2 * pi * x) * sin(
                2 * pi * y) * cos(2 * pi * z) / rho0

    return source_vector, stat_pressure_field, stat_velocity_field
示例#7
0
def initial_conditions_wave_system_staggered(my_mesh):
    test_desc["Initial_data"] = "Constant pressure, divergence free velocity"

    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    if (not my_mesh.isStructured()):
        raise ValueError("WaveSystemStaggered: the mesh should be structured")

    NxNyNz = my_mesh.getCellGridStructure()
    DxDyDz = my_mesh.getDXYZ()
    dx = DxDyDz[0]
    if (dim >= 2):
        dy = DxDyDz[1]
        if (dim == 3):
            dz = DxDyDz[2]

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        x = Ci.x()

        pressure_field[i] = p0

        #We take only the normal component of the velocity on a cartesian grid
        #We save the x component from the back face, the y component from the left face and the z component from the bottom face
        #Warning : boundary values should be the same for left and right as well as top and down (front and back in 3D) boundaries
        if (dim == 2):
            y = Ci.y()
            velocity_field[i, 0] = sin(pi * (x - 0.5 * dx)) * cos(
                pi * y)  # value on the left face
            velocity_field[i, 1] = -sin(pi * (y - 0.5 * dy)) * cos(
                pi * x)  # value on the bottom face
            velocity_field[i, 2] = 0
        elif (dim == 3):
            y = Ci.y()
            z = Ci.z()
            velocity_field[i,
                           0] = sin(pi * (x - 0.5 * dx)) * cos(pi * y) * cos(
                               pi * z)  # value on the back face
            velocity_field[i,
                           1] = sin(pi * (y - 0.5 * dy)) * cos(pi * x) * cos(
                               pi * z)  # value on the left face
            velocity_field[i, 2] = -2 * sin(pi * (z - 0.5 * dz)) * cos(
                pi * x) * cos(pi * y)  # value on the bottom face
        else:
            raise ValueError(
                "initial_conditions_wave_system_staggered: the 1D mesh not yet implemented"
            )

    return pressure_field, velocity_field
示例#8
0
def initial_conditions_shock(my_mesh, isCircle):
    print "Initial data : Spherical wave"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    rayon = 0.15
    if (not isCircle):
        xcentre = 0.5
        ycentre = 0.5
        zcentre = 0.5
    else:
        xcentre = 0.
        ycentre = 0.
        zcentre = 0.

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        velocity_field[i, 0] = 0
        velocity_field[i, 1] = 0
        velocity_field[i, 2] = 0

        x = my_mesh.getCell(i).x()
        valX = (x - xcentre) * (x - xcentre)

        if (dim == 1):
            val = sqrt(valX)
        if (dim == 2):
            y = my_mesh.getCell(i).y()
            valY = (y - ycentre) * (y - ycentre)
            val = sqrt(valX + valY)
        if (dim == 3):
            y = my_mesh.getCell(i).y()
            z = my_mesh.getCell(i).z()
            valY = (y - ycentre) * (y - ycentre)
            valZ = (z - zcentre) * (z - zcentre)
            val = sqrt(valX + valY + valZ)

        if val < rayon:
            pressure_field[i] = p0
            pass
        else:
            pressure_field[i] = p0 / 2
            pass
        pass

    return pressure_field, velocity_field
def source_term_and_stat_solution_transport_equation(my_mesh,velocity):
    test_desc["Source_term"]="True"
    dim     = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells)

    stat_field = cdmath.Field("Stationary field", cdmath.CELLS, my_mesh, 1)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if(dim==1):
            source_vector[k] = 2*pi*velocity[0]*cos(2*pi*x)
            stat_field[k]    =                  sin(2*pi*x)
        elif(dim==2):
            source_vector[k*(dim+1)+0] = 2*pi*(velocity[0]*cos(2*pi*x)*sin(2*pi*y)+velocity[1]*sin(2*pi*x)*cos(2*pi*y))
            stat_field[k]   =                              sin(2*pi*x)*sin(2*pi*y)
        elif(dim==3):
            source_vector[k*(dim+1)+0] = 2*pi*(velocity[0]*cos(2*pi*x)*sin(2*pi*y)*sin(2*pi*z)+velocity[1]*sin(2*pi*x)*cos(2*pi*y)*sin(2*pi*z)+velocity[2]*sin(2*pi*x)*sin(2*pi*y)*cos(2*pi*z))
            stat_field[k]   =                              sin(2*pi*x)*sin(2*pi*y)*sin(2*pi*z)

    return source_vector, stat_field
示例#10
0
def initial_conditions_wave_system(my_mesh):
    print "Spherical wave initial data"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    rayon = 0.15
    xcentre = 0.5
    ycentre = 0.5
    zcentre = 0.5

    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)
    U = cdmath.Field("Conservative vector", cdmath.CELLS, my_mesh, dim + 1)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()
        y = my_mesh.getCell(i).y()

        velocity_field[i, 0] = 0
        velocity_field[i, 1] = 0
        velocity_field[i, 2] = 0

        valX = (x - xcentre) * (x - xcentre)
        valY = (y - ycentre) * (y - ycentre)

        if (dim == 2):
            val = sqrt(valX + valY)
        if (dim == 3):
            z = my_mesh.getCell(i).z()
            valZ = (z - zcentre) * (z - zcentre)
            val = sqrt(valX + valY + valZ)

        if val < rayon:
            pressure_field[i] = p0
            pass
        else:
            pressure_field[i] = p0 / 2
            pass
        pass

        U[i, 0] = pressure_field[i]
        U[i, 1] = rho0 * velocity_field[i, 0]
        U[i, 2] = rho0 * velocity_field[i, 1]

    return U, pressure_field, velocity_field
示例#11
0
def main():
    a = -5.0
    b = 5.0
    nx = 1000
    ntmax = 1000
    dx = (b - a) / nx
    pi = 3.1415927
    # Transport velocity
    cfl = 0.5
    u = 3.
    dt = cfl * dx / u

    my_mesh = cdmath.Mesh(a, b, nx)
    conc = cdmath.Field("Concentration", cdmath.CELLS, my_mesh, 1)

    # Initial conditions
    sigma = math.sqrt(0.2)
    for i in xrange(my_mesh.getNumberOfCells()):
        x = my_mesh.getCell(i).x()
        conc[i] = 0.5 / (sigma * math.sqrt(2 * pi)) * math.exp(-0.5 * math.pow(
            (x / sigma), 2))
        pass

    time = 0.
    tmax = 3.0
    it = 0

    print("MED post-treatment of the solution at T=" + str(time) + "…")
    output_filename = "EqTr1D"
    conc.setTime(time, it)
    conc.writeMED(output_filename)
    conc.writeVTK(output_filename)
    conc.writeCSV(output_filename)
    output_freq = 10

    # Time loop
    while (it < ntmax and time <= tmax):
        print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " +
              str(dt))
        conc[0] = conc[0] - u * dt / dx * (
            conc[0] - conc[my_mesh.getNumberOfCells() - 1])
        for j in xrange(1, my_mesh.getNumberOfCells()):
            conc[j] = conc[j] - u * dt / dx * (conc[j] - conc[j - 1])
            pass
        time += dt
        it += 1
        if (it % output_freq == 0):
            conc.setTime(time, it)
            conc.writeMED(output_filename, False)
            conc.writeVTK(output_filename, False)
            conc.writeCSV(output_filename)
            pass
        pass
    print("CDMATH calculation done.")
    return
示例#12
0
def initial_conditions_disk_vortex(my_mesh):
    print "Disk vortex initial data"
    dim     = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    if(dim!=2):
        raise ValueError("Wave system on disk : mesh dimension should be 2")
        
    pressure_field = cdmath.Field("Pressure",            cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity",            cdmath.CELLS, my_mesh, 3)

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()
        y = my_mesh.getCell(i).y()

        pressure_field[i] = p0

        velocity_field[i,0] = -y
        velocity_field[i,1] =  x
        velocity_field[i,2] = 0

    return pressure_field, velocity_field
示例#13
0
文件: main.py 项目: tajchman/CDMATH
def initial_conditions(my_mesh):
    rayon = 0.15
    xcentre = 0.25
    ycentre = 0.25
    y_field = cdmath.Field("Y field", cdmath.CELLS, my_mesh, 1)
    nbCells = my_mesh.getNumberOfCells()
    for j in range(nbCells):
        x = my_mesh.getCell(j).x()
        y = my_mesh.getCell(j).y()
        valX = (x - xcentre) * (x - xcentre)
        valY = (y - ycentre) * (y - ycentre)
        val = math.sqrt(valX + valY)
        if val < rayon:
            y_field[j] = 1.0
            pass
        else:
            y_field[j] = 0.0
            pass
        pass
    return y_field
示例#14
0
def initial_conditions_transport_equation(my_mesh):
    print "Initial_data", "Shock"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    initial_field = cdmath.Field("unknown", cdmath.CELLS, my_mesh, 1)

    rayon = 0.15
    xcentre = 0.5
    ycentre = 0.5
    zcentre = 0.5

    for i in range(nbCells):
        x = my_mesh.getCell(i).x()

        valX = (x - xcentre) * (x - xcentre)

        if (dim == 1):
            val = sqrt(valX)
        if (dim == 2):
            y = my_mesh.getCell(i).y()
            valY = (y - ycentre) * (y - ycentre)
            val = sqrt(valX + valY)
        if (dim == 3):
            y = my_mesh.getCell(i).y()
            z = my_mesh.getCell(i).z()
            valY = (y - ycentre) * (y - ycentre)
            valZ = (z - zcentre) * (z - zcentre)
            val = sqrt(valX + valY + valZ)

        if val < rayon:
            initial_field[i] = 1
            pass
        else:
            initial_field[i] = 0
            pass
        pass

    return initial_field
示例#15
0
my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder") #Bord DROIT
my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder") #Bord BAS
my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder") #Bord HAUT
#my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder") #Bord AVANT si calcul 3D
#my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder") #Bord ARRIERE si calcul 3D

nbNodes = my_mesh.getNumberOfNodes()
nbCells = my_mesh.getNumberOfCells()

print("Fin chargement du maillage")
print("nb of nodes = ", nbNodes)
print("nb of cells = ", nbCells)

# Discrétisation du second membre et détermination des noeuds intérieurs
#=======================================================================
my_RHS_field = cdmath.Field("RHS field", cdmath.NODES, my_mesh, 1)
nbInteriorNodes = 0
nbBoundaryNodes = 0
maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
interiorNodes = []
boundaryNodes = []

# Parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
for i in range(nbNodes):
    Ni = my_mesh.getNode(i)
    x = Ni.x()
    y = Ni.y()
    #z=Ni.z() si calcul 3D
    my_RHS_field[i] = 2*pi*pi*sin(pi*x)*sin(pi*y)#mettre la fonction definie au second membre de l'edp
    if my_mesh.isBorderNode(i): # Détection des noeuds frontière
        boundaryNodes.append(i)
def solve(filename,resolution,meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"]=meshType
    test_desc["Test_color"]=testColor
    
    #Chargement du maillage triangulaire de la sphère
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename+".med")
    if(not my_mesh.isTriangular()) :
        raise ValueError("Wrong cell types : mesh is not made of triangles")
    if(my_mesh.getMeshDimension()!=2) :
        raise ValueError("Wrong mesh dimension : expected a surface of dimension 2")
    if(my_mesh.getSpaceDimension()!=3) :
        raise ValueError("Wrong space dimension : expected a space of dimension 3")
    
    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()
    
    test_desc["Space_dimension"]=my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"]=my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"]=my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"]=my_mesh.getElementTypes()

    print("Mesh building/loading done")
    print("nb of nodes=", nbNodes)
    print("nb of cells=", nbCells)
    
    #Discrétisation du second membre et détermination des noeuds intérieurs
    #======================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1)
    maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    
    #parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni=my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()
        z = Ni.z()
    
        my_RHSfield[i]=12*y*(3*x*x-y*y)/pow(x*x+y*y+z*z,3/2)#vecteur propre du laplacien sur la sphère
        if my_mesh.isBorderNode(i): # Détection des noeuds frontière
            raise ValueError("Mesh should not contain borders")
        else:
            maxNbNeighbours = max(1+Ni.getNumberOfCells(),maxNbNeighbours)
    
    test_desc["Mesh_max_number_of_neighbours"]=maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)
    print("Integral of the RHS", my_RHSfield.integral(0))
    
    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite=cdmath.SparseMatrixPetsc(nbNodes,nbNodes,maxNbNeighbours)# warning : third argument is number of non zero coefficients per line
    RHS=cdmath.Vector(nbNodes)
    
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle
    GradShapeFunc0=cdmath.Vector(3)
    GradShapeFunc1=cdmath.Vector(3)
    GradShapeFunc2=cdmath.Vector(3)
    
    normalFace0=cdmath.Vector(3)
    normalFace1=cdmath.Vector(3)
    
    #On parcourt les triangles du domaine
    for i in range(nbCells):
    
        Ci=my_mesh.getCell(i)
    
        #Contribution à la matrice de rigidité
        nodeId0=Ci.getNodeId(0)
        nodeId1=Ci.getNodeId(1)
        nodeId2=Ci.getNodeId(2)
        N0=my_mesh.getNode(nodeId0)
        N1=my_mesh.getNode(nodeId1)
        N2=my_mesh.getNode(nodeId2)
    
        #Build normal to cell Ci
        normalFace0[0]=Ci.getNormalVector(0,0)
        normalFace0[1]=Ci.getNormalVector(0,1)
        normalFace0[2]=Ci.getNormalVector(0,2)
        normalFace1[0]=Ci.getNormalVector(1,0)
        normalFace1[1]=Ci.getNormalVector(1,1)
        normalFace1[2]=Ci.getNormalVector(1,2)
    
        normalCell = normalFace0.crossProduct(normalFace1)
        test = normalFace0.tensProduct(normalFace1)
        normalCell = normalCell/normalCell.norm()
    
        cellMat=cdmath.Matrix(4)
        cellMat[0,0]=N0.x()
        cellMat[0,1]=N0.y()
        cellMat[0,2]=N0.z()
        cellMat[1,0]=N1.x()
        cellMat[1,1]=N1.y()
        cellMat[1,2]=N1.z()
        cellMat[2,0]=N2.x()
        cellMat[2,1]=N2.y()
        cellMat[2,2]=N2.z()
        cellMat[3,0]=normalCell[0]
        cellMat[3,1]=normalCell[1]
        cellMat[3,2]=normalCell[2]
        cellMat[0,3]=1
        cellMat[1,3]=1
        cellMat[2,3]=1
        cellMat[3,3]=0
    
        #Formule des gradients voir EF P1 -> calcul déterminants
        GradShapeFunc0[0]= cellMat.partMatrix(0,0).determinant()/2
        GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()/2
        GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()/2
        GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()/2
        GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()/2
        GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()/2
        GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()/2
        GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()/2
        GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()/2
    
        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme
        GradShapeFuncs={nodeId0 : GradShapeFunc0}
        GradShapeFuncs[nodeId1]=GradShapeFunc1
        GradShapeFuncs[nodeId2]=GradShapeFunc2
    
        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0,nodeId1,nodeId2] : 
            #Ajout de la contribution de la cellule triangulaire i au second membre du noeud j 
            RHS[j]=Ci.getMeasure()/3*my_RHSfield[j]+RHS[j] # intégrale dans le triangle du produit f x fonction de base
            #Contribution de la cellule triangulaire i à la ligne j du système linéaire
            for k in [nodeId0,nodeId1,nodeId2] : 
                Rigidite.addValue(j,k,GradShapeFuncs[j]*GradShapeFuncs[k]/Ci.getMeasure())
    
    print("Linear system matrix building done")
    
    # Résolution du système linéaire
    #=================================
    LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-2,"CG","ILU")#Remplacer CG par CHOLESKY pour solveur direct
    LS.isSingular()#En raison de l'absence de bord
    LS.setComputeConditionNumber()
    SolSyst=LS.solve()

    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print "Final residual : ", LS.getResidu()
    print("Linear system solved")
    
    test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
    test_desc["Linear_solver_precision"]=LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
    test_desc["Linear_system_max_actual_iterations_number"]=LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"]=LS.getResidu()
    test_desc["Linear_system_max_actual_condition number"]=LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbNodes):
        my_ResultField[j]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    
    end = time.time()

    print("Integral of the numerical solution", my_ResultField.integral(0))
    print("Numerical solution of poisson equation on a sphere using finite elements done")
    
    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 12
    max_abs_sol_exacte=0
    erreur_abs=0
    max_sol_num=0
    min_sol_num=0
    for i in range(nbNodes) :
        if max_abs_sol_exacte < abs(my_RHSfield[i]) :
            max_abs_sol_exacte = abs(my_RHSfield[i])
        if erreur_abs < abs(my_RHSfield[i]/12 - my_ResultField[i]) :
            erreur_abs = abs(my_RHSfield[i]/12 - my_ResultField[i])
        if max_sol_num < my_ResultField[i] :
            max_sol_num = my_ResultField[i]
        if min_sol_num > my_ResultField[i] :
            min_sol_num = my_ResultField[i]
    max_abs_sol_exacte = max_abs_sol_exacte/12
    
    print("Absolute error = max(| exact solution - numerical solution |) = ",erreur_abs )
    print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_abs/max_abs_sol_exacte)
    print ("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num)

    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Absolute_error"]=erreur_abs
    test_desc["Relative_error"]=erreur_abs/max_abs_sol_exacte

    #Postprocessing : 
    #================
    # save 3D picture
    PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    # save 3D clip
    VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',[0.25,0.25,0.25], [-0.5,-0.5,-0.5],resolution )
    PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    # save plot around circumference
    finiteElementsOnSphere_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu'])
    slice1 = pvs.Slice(Input=finiteElementsOnSphere_0vtu)
    slice1.SliceType.Normal = [0.5, 0.5, 0.5]
    renderView1 = pvs.GetActiveViewOrCreate('RenderView')
    finiteElementsOnSphere_0vtuDisplay = pvs.Show(finiteElementsOnSphere_0vtu, renderView1)
    pvs.ColorBy(finiteElementsOnSphere_0vtuDisplay, ('POINTS', 'ResultField'))
    slice1Display = pvs.Show(slice1, renderView1)
    pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_Slice_"+meshType+str(nbNodes)+'.png', magnification=1, quality=100, view=renderView1)
    plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1)
    pvs.SaveData('./FiniteElementsOnSpherePoisson_PlotOnSortedLines'+meshType+str(nbNodes)+'.csv', proxy=plotOnSortedLines1)
    lineChartView2 = pvs.CreateView('XYChartView')
    plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2)
    plotOnSortedLines1Display.UseIndexForXAxis = 0
    plotOnSortedLines1Display.XArrayName = 'arc_length'
    plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)']
    pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_PlotOnSortedLine_"+meshType+str(nbNodes)+'.png', magnification=1, quality=100, view=lineChartView2)
    pvs.Delete(lineChartView2)

    with open('test_Poisson'+str(my_mesh.getMeshDimension())+'D_EF_'+meshType+str(nbCells)+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)

    return erreur_abs/max_abs_sol_exacte, nbNodes, min_sol_num, max_sol_num, end - start
示例#17
0
文件: main.py 项目: tajchman/CDMATH
def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
    # Fluxes calculation #
    SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
    my_mesh = y_field.getMesh()
    nbCells = my_mesh.getNumberOfCells()
    normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
    for j in range(nbCells):
        Cj = my_mesh.getCell(j)
        nbFace = Cj.getNumberOfFaces()
        SumF = 0.0
        minlengthFk = 1.E30
        for k in range(nbFace):
            indexFace = Cj.getFacesId()[k]
            Fk = my_mesh.getFace(indexFace)
            NormalX = Cj.getNormalVector(k, 0)
            NormalY = Cj.getNormalVector(k, 1)
            LengthFk = Fk.getMeasure()
            UN = VitesseX * NormalX + VitesseY * NormalY
            minlengthFk = min(minlengthFk, LengthFk / abs(UN))
            minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
            minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
            conc = 0.0
            cellCourante = j
            cellAutre = -1
            if (not Fk.isBorder()):
                indexC1 = Fk.getCellsId()[0]
                indexC2 = Fk.getCellsId()[1]
                # hypothese: La cellule d'index indexC1 est la cellule courante index j #
                if (indexC1 == j):
                    # hypothese verifie #
                    cellCourante = indexC1
                    cellAutre = indexC2
                    pass
                elif (indexC2 == j):
                    # hypothese non verifie #
                    cellCourante = indexC2
                    cellAutre = indexC1
                    pass
                # definir la cellule gauche et droite par le prduit vitesse * normale sortante
                # si u*n>0 : rien a faire sinon inverser la gauche et la droite
                if (UN > 1.E-15):
                    conc = y_field[cellCourante]
                    pass
                else:
                    conc = y_field[cellAutre]
                    pass
                pass
            else:
                # conditions aux limites neumann homogene #
                if (Fk.getGroupName() == "LeftEdge" or Fk.getGroupName() == "RightEdge"):
                    if (UN > 1.E-15):
                        conc = y_field[cellCourante]
                        pass
                    else:
                        conc = 0.0
                        pass
                    pass
                # conditions aux limites periodiques #
                if (Fk.getGroupName() == "BottomEdge" or Fk.getGroupName() == "TopEdge"):
                    indexFP = indexFacesPerio[indexFace]
                    # une autre manière de recuperer l'index de la face periodique #
                    # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
                    Fp = my_mesh.getFace(indexFP)
                    indexCp = Fp.getCellsId()[0]
                    if (UN > 1.E-15):
                        conc = y_field[cellCourante]
                        pass
                    else:
                        conc = y_field[indexCp]
                        pass
                    pass
                pass
            SumF = SumF + UN * LengthFk * conc
            pass
        dt = cfl * minlengthFk / normU
        SumFlux[j] = dt * SumF / Cj.getMeasure()
        pass
    return dt, SumFlux
示例#18
0
def WaveSystem1DVF(ntmax, tmax, cfl, my_mesh, output_freq, resolution):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim + 1)

    # Initial conditions #
    print("Construction of the initial condition …")
    U, pressure_field, velocity_field = initial_conditions_wave_system(my_mesh)

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

    print(
        "Starting computation of the linear wave system with an UPWIND explicit scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        computeFluxes(U, SumFluxes)

        SumFluxes *= dt
        maxVector = SumFluxes.normMax()
        isStationary = maxVector[0] / p0 < precision and maxVector[
            1] / rho0 < precision
        U -= SumFluxes

        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " +
                  str(dt))
            print "Variation temporelle relative : pressure ", maxVector[
                0] / p0, ", velocity x", maxVector[1] / rho0
            print

            for k in range(nbCells):
                pressure_field[k] = U[k, 0]
                velocity_field[k, 0] = U[k, 1] / rho0

            pressure_field.setTime(time, it)
            pressure_field.writeCSV("WaveSystem1DUpwind_pressure")
            velocity_field.setTime(time, it)
            velocity_field.writeCSV("WaveSystem1DUpwind_velocity")

    print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
    print "|| Un+1 - Un || : pressure ", maxVector[
        0] / p0, ", velocity x", maxVector[1] / rho0
    print

    if (it >= ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
        raise ValueError(
            "Maximum number of time steps reached : Stationary state not found !!!!!!!"
        )
    elif (isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        for k in range(nbCells):
            pressure_field[k] = U[k, 0]
            velocity_field[k, 0] = U[k, 1] / rho0

        pressure_field.setTime(time, 0)
        pressure_field.writeCSV("WaveSystem1DUpwind_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeCSV("WaveSystem1DUpwind_velocity_Stat")

    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
def solve(my_mesh, filename, resolution, meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"] = meshType
    test_desc["Test_color"] = testColor

    nbCells = my_mesh.getNumberOfCells()

    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfCells()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh groups done")
    print("Number of cells  = ", nbCells)

    #Discrétisation du second membre et extraction du nb max de voisins d'une cellule
    #================================================================================
    my_ExactSol = cdmath.Field("Exact_field", cdmath.CELLS, my_mesh, 1)
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    eps = 1e-6  #For coarse meshes

    #parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        x = Ci.x()
        y = Ci.y()

        #Robust calculation of atan(2x/(x**2+y**2-1)
        if x**2 + y**2 - 1 > eps:
            print("!!! Warning Mesh ", meshType,
                  " !!! Cell is not in the unit disk.", ", eps=", eps,
                  ", x**2+y**2 - 1=", x**2 + y**2 - 1)
            #raise ValueError("Exact solution computation !!! Domain should be the unit disk.")
        if x**2 + y**2 - 1 < -eps:
            my_ExactSol[i] = atan(2 * x / (x**2 + y**2 - 1))
        elif x > 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = -pi / 2
        elif x < 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = pi / 2
        else:  #x=0
            my_ExactSol[i] = 0

        # compute maximum number of neighbours
        maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)

    # Construction de la matrice et du vecteur second membre du système linéaire
    #===========================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbCells, nbCells, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbCells)

    #Parcours des cellules du domaine
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        for j in range(Ci.getNumberOfFaces()):  # parcours des faces voisinnes
            Fj = my_mesh.getFace(Ci.getFaceId(j))
            if not Fj.isBorder():
                k = Fj.getCellId(0)
                if k == i:
                    k = Fj.getCellId(1)
                Ck = my_mesh.getCell(k)
                distance = Ci.getBarryCenter().distance(Ck.getBarryCenter())
                coeff = Fj.getMeasure() / Ci.getMeasure() / distance
                Rigidite.setValue(i, k, -coeff)  # terme extradiagonal
            else:
                coeff = Fj.getMeasure() / Ci.getMeasure() / Ci.getBarryCenter(
                ).distance(Fj.getBarryCenter())
                #For the particular case where the mesh boundary does not coincide with the domain boundary
                x = Fj.getBarryCenter().x()
                y = Fj.getBarryCenter().y()
                if x**2 + y**2 - 1 > eps:
                    print("!!! Warning Mesh ", meshType,
                          " !!! Face is not in the unit disk.", ", eps=", eps,
                          ", x**2+y**2 - 1=", x**2 + y**2 - 1)
                    #raise ValueError("!!! Domain should be the unit disk.")
                if x**2 + y**2 - 1 < -eps:
                    RHS[i] += coeff * atan(2 * x / (x**2 + y**2 - 1))
                elif x > 0:  #x**2+y**2-1>=0
                    RHS[i] += coeff * (-pi / 2)
                elif x < 0:  #x**2+y**2-1>=0
                    RHS[i] += coeff * pi / 2
                else:  #x=0
                    RHS[i] += 0
            Rigidite.addValue(i, i, coeff)  # terme diagonal

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(Rigidite, RHS, 500, 1.E-6, "CG", "LU")
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print("Preconditioner used : ", LS.getNameOfPc())
    print("Number of iterations used : ", LS.getNumberOfIter())
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.CELLS, my_mesh, 1)
    for i in range(nbCells):
        my_ResultField[i] = SolSyst[i]
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteVolumes2DPoissonStiffBC_DISK_" + meshType +
                            str(nbCells))
    my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_DISK_" + meshType +
                         str(nbCells))

    print(
        "Numerical solution of 2D Poisson equation on a disk using finite volumes done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    l2_norm_sol_exacte = my_ExactSol.normL2()[0]
    l2_error = (my_ExactSol - my_ResultField).normL2()[0]

    print(
        "L2 relative error = norm( exact solution - numerical solution )/norm( exact solution ) = ",
        l2_error / l2_norm_sol_exacte)
    print("Maximum numerical solution = ", my_ResultField.max(),
          " Minimum numerical solution = ", my_ResultField.min())
    print("Maximum exact solution = ", my_ExactSol.max(),
          " Minimum exact solution = ", my_ExactSol.min())

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, -1, 0], [0, 1, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteVolumes2DPoissonStiffBC_DISK_" + meshType + str(nbCells) +
        '_0.vtu', "ResultField", 'CELLS',
        "FiniteVolumes2DPoissonStiffBC_DISK_" + meshType + str(nbCells))
    PV_routines.Save_PV_data_to_picture_file(
        "ExactSol2DPoissonStiffBC_DISK_" + meshType + str(nbCells) + '_0.vtu',
        "Exact_field", 'CELLS',
        "ExactSol2DPoissonStiffBC_DISK_" + meshType + str(nbCells))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = l2_error
    test_desc["Relative_error"] = l2_error / l2_norm_sol_exacte

    with open(
            'test_PoissonStiffBC' + str(my_mesh.getMeshDimension()) + 'D_VF_' +
            "DISK_" + str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return l2_error / l2_norm_sol_exacte, nbCells, diag_data, my_ResultField.min(
    ), my_ResultField.max(), end - start
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,
                 scaling, test_bc):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    iterGMRESMax = 50

    #iteration vectors
    Un = cdmath.Vector(nbCells * (dim + 1))
    dUn = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial condition …")
    if (meshName.find("square") == -1 and meshName.find("Square") == -1
            and meshName.find("cube") == -1 and meshName.find("Cube") == -1):
        print "Mesh name : ", meshName
        raise ValueError(
            "Mesh name should contain substring square or cube to use wave system with smooth source term"
        )
    pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)
    for k in range(nbCells):  # fields initialisation
        pressure_field[k] = 0
        velocity_field[k, 0] = 0
        velocity_field[k, 1] = 0
        velocity_field[k, 2] = 0
    S, stat_pressure, stat_velocity = source_term_and_stat_solution_wave_system(
        my_mesh)

    for k in range(nbCells):
        Un[k * (dim + 1) + 0] = pressure_field[k]
        Un[k * (dim + 1) + 1] = rho0 * velocity_field[k, 0]
        Un[k * (dim + 1) + 2] = rho0 * velocity_field[k, 1]
        if (dim == 3):
            Un[k * (dim + 1) + 3] = rho0 * velocity_field[k, 2]

    if (scaling == 1):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0)
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / (c0 * c0)
    elif (scaling == 2):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / c0
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / c0

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time, it)
    pressure_field.writeVTK("WaveSystem" + str(dim) + "DCentered" + meshName +
                            "_pressure")
    velocity_field.setTime(time, it)
    velocity_field.writeVTK("WaveSystem" + str(dim) + "DCentered" + meshName +
                            "_velocity")
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DCentered" + meshName + "_pressure" +
        '_0.vtu', "Pressure", 'CELLS',
        "WaveSystem" + str(dim) + "DCentered" + meshName + "_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DCentered" + meshName + "_velocity" +
        '_0.vtu', "Velocity", 'CELLS',
        "WaveSystem" + str(dim) + "DCentered" + meshName + "_velocity_initial")

    total_pressure_initial = pressure_field.integral(
    )  #For conservation test later
    total_velocity_initial = velocity_field.integral(
    )  #For conservation test later

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0
    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling,
                                     test_bc)
    #Adding the momentum friction term
    for j in range(nbCells):
        for i in range(dim):
            divMat.addValue(j * (dim + 1) + 1 + i, j * (dim + 1) + 1 + i, dt)

    #Add the identity matrix on the diagonal
    if (scaling == 0 or scaling == 2):
        divMat.diagonalShift(1)  #only after  filling all coefficients
    else:
        for j in range(nbCells):
            divMat.addValue(j * (dim + 1), j * (dim + 1),
                            1 / (c0 * c0))  #/(c0*c0)
            for i in range(dim):
                divMat.addValue(j * (dim + 1) + 1 + i,
                                j * (dim + 1) + 1 + i, 1)

    if (scaling == 0):
        LS = cdmath.LinearSolver(divMat, Un + S * dt, iterGMRESMax, precision,
                                 "GMRES", "ILU")
    else:
        LS = cdmath.LinearSolver(divMat, Vn + S * dt, iterGMRESMax, precision,
                                 "GMRES", "ILU")
    LS.setComputeConditionNumber()

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc["Numerical_parameter_space_step"] = dx_min
    test_desc["Numerical_parameter_time_step"] = dt
    test_desc["Linear_solver_with_scaling"] = scaling

    test_desc['Linear_system_max_actual_iterations_number'] = 0
    test_desc["Linear_system_max_actual_error"] = 0
    test_desc["Linear_system_max_actual_condition number"] = 0

    print(
        "Starting computation of the linear wave system with a centered scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        dUn = Un.deepCopy()
        if (scaling == 0):
            LS.setSndMember(Un + S * dt)
        else:
            LS.setSndMember(Vn + S * dt)
        if (scaling < 2):
            Un = LS.solve()
            if (scaling == 1):
                Vn = Un.deepCopy()
                for k in range(nbCells):
                    Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0)
        else:  #( scaling==2)
            Vn = LS.solve()
            Un = Vn.deepCopy()
            for k in range(nbCells):
                Un[k * (dim + 1) + 0] = c0 * Vn[k * (dim + 1) + 0]

        if (not LS.getStatus()):
            print "Linear system did not converge ", iterGMRES, " GMRES iterations"
            raise ValueError("Pas de convergence du système linéaire")
        dUn -= Un

        test_desc["Linear_system_max_actual_iterations_number"] = max(
            LS.getNumberOfIter(),
            test_desc["Linear_system_max_actual_iterations_number"])
        test_desc["Linear_system_max_actual_error"] = max(
            LS.getResidu(), test_desc["Linear_system_max_actual_error"])
        test_desc["Linear_system_max_actual_condition number"] = max(
            LS.getConditionNumber(),
            test_desc["Linear_system_max_actual_condition number"])

        maxVector = dUn.maxVector(dim + 1)

        isStationary = maxVector[0] < precision and maxVector[
            1] / rho0 < precision and maxVector[2] / rho0 < precision

        if (dim == 3):
            isStationary = isStationary and maxVector[3] / rho0 < precision
        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print "-- Iter: " + str(it) + ", Time: " + str(
                time) + ", dt: " + str(dt)
            print "Variation temporelle relative : pressure ", maxVector[
                0], ", velocity x", maxVector[
                    1] / rho0, ", velocity y", maxVector[2] / rho0
            print "Linear system converged in ", LS.getNumberOfIter(
            ), " GMRES iterations"

            delta_press = 0
            delta_v = cdmath.Vector(dim)
            for k in range(nbCells):
                pressure_field[k] = Un[k * (dim + 1) + 0]
                velocity_field[k, 0] = Un[k * (dim + 1) + 1] / rho0
                if (dim > 1):
                    velocity_field[k, 1] = Un[k * (dim + 1) + 2] / rho0
                    if (dim > 2):
                        velocity_field[k, 2] = Un[k * (dim + 1) + 3] / rho0
                if (abs(stat_pressure[k] - pressure_field[k]) > delta_press):
                    delta_press = abs(stat_pressure[k] - pressure_field[k])
                if (abs(stat_velocity[k, 0] - velocity_field[k, 0]) >
                        delta_v[0]):
                    delta_v[0] = abs(stat_velocity[k, 0] -
                                     velocity_field[k, 0])
                if (abs(stat_velocity[k, 1] - velocity_field[k, 1]) >
                        delta_v[1]):
                    delta_v[1] = abs(stat_velocity[k, 1] -
                                     velocity_field[k, 1])
                if (dim == 3):
                    if (abs(stat_velocity[k, 2] - velocity_field[k, 2]) >
                            delta_v[2]):
                        delta_v[2] = abs(stat_velocity[k, 2] -
                                         velocity_field[k, 2])

            pressure_field.setTime(time, it)
            pressure_field.writeVTK(
                "WaveSystem" + str(dim) + "DCentered" + meshName + "_pressure",
                False)
            velocity_field.setTime(time, it)
            velocity_field.writeVTK(
                "WaveSystem" + str(dim) + "DCentered" + meshName + "_velocity",
                False)

            print "Ecart au stationnaire exact : error_p= ", delta_press, " error_||u||= ", delta_v.maxVector(
            )[0]
            print
    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : pressure ", maxVector[
        0], ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[
            2] / rho0
    print

    if (it >= ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
        raise ValueError(
            "Maximum number of time steps reached : Stationary state not found !!!!!!!"
        )
    elif (isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        print "------------------------------------------------------------------------------------"

        pressure_field.setTime(time, 0)
        pressure_field.writeVTK("WaveSystem" + str(dim) + "DCentered" +
                                meshName + "_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeVTK("WaveSystem" + str(dim) + "DCentered" +
                                meshName + "_velocity_Stat")

        #Postprocessing : Extraction of the diagonal data
        if (dim == 2):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 1, 0], [1, 0, 0], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 1, 0], [1, 0, 0], resolution)
        elif (dim == 3):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 0, 0], [1, 1, 1], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 0, 0], [1, 1, 1], resolution)
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DCentered" + meshName +
            "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" +
            str(dim) + "DCentered" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DCentered" + meshName +
            "_velocity_Stat" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" +
            str(dim) + "DCentered" + meshName + "_velocity_Stat")

        return delta_press, delta_v.maxVector(
        )[0], nbCells, time, it, velocity_field.getNormEuclidean().max(
        ), diag_data_press, diag_data_vel, test_desc[
            "Linear_system_max_actual_condition number"]
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
示例#21
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution):
    dim=my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()
    meshName=my_mesh.getName()
    
    dt = 0.
    time = 0.
    it=0;
    isStationary=False;
    
    SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim+1)

    # Initial conditions #
    print("Construction of the initial condition …")
    if(filename.find("square")>-1 or filename.find("Square")>-1 or filename.find("cube")>-1 or filename.find("Cube")>-1):
        pressure_field, velocity_field = initial_conditions_square_shock(my_mesh)
    elif(filename.find("disk")>-1 or filename.find("Disk")>-1):
        pressure_field, velocity_field = initial_conditions_disk_vortex(my_mesh)
    else:
        print "Mesh name : ", filename
        raise ValueError("Mesh name should contain substring square, cube or disk")

    U              = cdmath.Field("Conservative vector", cdmath.CELLS, my_mesh, dim+1)
    for i in range(nbCells):
        U[i,0] =       pressure_field[i]
        U[i,1] =  rho0*velocity_field[i,0]
        U[i,2] =  rho0*velocity_field[i,1]

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time,it);
    pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure");
    velocity_field.setTime(time,it);
    velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity");

    dx_min=my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0
    
    print("Starting computation of the linear wave system with an explicit UPWIND scheme …")
    
    # Starting time loop
    while (it<ntmax and time <= tmax and not isStationary):
        computeFluxes(U,SumFluxes);

        SumFluxes*=dt;
        maxVector=SumFluxes.normMax()
        isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
        U-=SumFluxes;
    
        time=time+dt;
        it=it+1;
 
         #Sauvegardes
        if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
            print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
            print "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0

            for k in range(nbCells):
                pressure_field[k]=U[k,0]
                velocity_field[k,0]=U[k,1]/rho0
                if(dim>1):
                    velocity_field[k,1]=U[k,2]/rho0
                    if(dim>2):
                        velocity_field[k,2]=U[k,3]/rho0

            pressure_field.setTime(time,it);
            pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False);
            velocity_field.setTime(time,it);
            velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False);

    print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
    print "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0
    print

    if(it>=ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
    elif(isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time

        pressure_field.setTime(time,0);
        pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat");
        velocity_field.setTime(time,0);
        velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat");

        #Postprocessing : Extraction of the diagonal data
        diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)    
        diag_data_vel  =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)    
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
        
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
示例#22
0
eps=1e-6
my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE
my_mesh.setGroupAtPlan(1,0,eps,"DirichletBorder")#Bord DROIT
my_mesh.setGroupAtPlan(0,1,eps,"DirichletBorder")#Bord BAS
my_mesh.setGroupAtPlan(1,1,eps,"DirichletBorder")#Bord HAUT
my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder")#Bord AVANT 
my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder")#Bord ARRIERE 

nbCells = my_mesh.getNumberOfCells()

print("Mesh loading done")
print("Number of cells ", nbCells)

#Discrétisation du second membre et extraction du nb max de voisins d'une cellule
#================================================================================
my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1)
my_ExactSol = cdmath.Field("EXACT_SOL", cdmath.CELLS, my_mesh, 1)

maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
for i in range(nbCells): 
	Ci = my_mesh.getCell(i)
	x = Ci.x()
	y = Ci.y()
	z = Ci.z() 

	r=sqrt(x*x+y*y+z*z)
	phi=atan2(y,x)
	theta=atan2(y,z*sin(phi))

	my_RHSfield[i]=6*r*sin(theta)**2*cos(phi)+3*(r-1)*cos(phi)#mettre la fonction definie au second membre de l'edp
示例#23
0
文件: main.py 项目: tajchman/CDMATH
def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
    # Calculation of fluxes #
    SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
    my_mesh = y_field.getMesh()
    nbCells = my_mesh.getNumberOfCells()
    normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
    for j in range(nbCells):
        Cj = my_mesh.getCell(j)
        nbFace = Cj.getNumberOfFaces()
        SumF = 0.0
        minlengthFk = 1.E30
        for k in range(nbFace):
            indexFace = Cj.getFacesId()[k]
            Fk = my_mesh.getFace(indexFace)
            NormalX = Cj.getNormalVector(k, 0)
            NormalY = Cj.getNormalVector(k, 1)
            LengthFk = Fk.getMeasure()
            UN = VitesseX * NormalX + VitesseY * NormalY
            minlengthFk = min(minlengthFk, LengthFk / abs(UN))
            minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
            minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
            conc = 0.0
            cellCourante = j
            cellAutre = -1
            if (not Fk.isBorder()):
                indexC1 = Fk.getCellsId()[0]
                indexC2 = Fk.getCellsId()[1]
                # hypothesis: the cell of index indexC1 is the current cell of index j #
                if (indexC1 == j):
                    # hypothese is verified #
                    cellCourante = indexC1
                    cellAutre = indexC2
                    pass
                elif (indexC2 == j):
                    # hypothesis is not verified #
                    cellCourante = indexC2
                    cellAutre = indexC1
                    pass
                # define left and right cell with the product of velocity * outward normal vector
                # if u*n>0: nothing to do, else invert left and right
                if (UN > 1.E-15):
                    conc = y_field[cellCourante]
                    pass
                else:
                    conc = y_field[cellAutre]
                    pass
                pass
            else:
                # homogeneous Neumann boundary conditions #
                if (Fk.getGroupName() == "GAUCHE" or Fk.getGroupName() == "DROITE"):
                    if (UN > 1.E-15):
                        conc = y_field[cellCourante]
                        pass
                    else:
                        conc = 0.0
                        pass
                    pass
                # periodical boundary conditions #
                if (Fk.getGroupName() == "BAS" or Fk.getGroupName() == "HAUT"):
                    indexFP = indexFacesPerio[indexFace]
                    # another way to get the index of the periodical face #
                    # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
                    Fp = my_mesh.getFace(indexFP)
                    indexCp = Fp.getCellsId()[0]
                    if (UN > 1.E-15):
                        conc = y_field[cellCourante]
                        pass
                    else:
                        conc = y_field[indexCp]
                        pass
                    pass
                pass
            SumF = SumF + UN * LengthFk * conc
            pass
        dt = cfl * minlengthFk / normU
        SumFlux[j] = dt * SumF / Cj.getMeasure()
        pass
    return dt, SumFlux
示例#24
0
def solve(filename, resolution, meshName, testColor):
    start = time.time()
    test_desc["Mesh_name"] = meshName
    test_desc["Test_color"] = testColor

    #Chargement du maillage triangulaire du disque unité D(0,1)
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename + ".med")
    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )
    if (not my_mesh.isTriangular()):
        raise ValueError("Wrong cell types : mesh is not made of triangles")

    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh loading done")
    print("Number of nodes=", nbNodes)
    print("Number of cells=", nbCells)

    #Détermination des noeuds intérieurs
    #======================================================================
    my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1)
    nbInteriorNodes = 0
    nbBoundaryNodes = 0
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    interiorNodes = []
    boundaryNodes = []
    eps = 1e-6

    #parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni = my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()

        #Robust calculation of atan(2x/(x**2+y**2-1)
        #my_ExactSol[i]=atan2(2*x*sign(x**2+y**2-1),abs(x**2+y**2-1))#mettre la solution exacte de l'edp
        if x**2 + y**2 - 1 > eps:
            print("!!! Warning Mesh ", meshName,
                  " !!! Node is not in the unit disk.", ", eps=", eps,
                  ", x**2+y**2-1=", x**2 + y**2 - 1)
            #raise ValueError("!!! Domain should be the unit disk.")
        if x**2 + y**2 - 1 < -eps:
            my_ExactSol[i] = atan(2 * x / (x**2 + y**2 - 1))
        elif x > 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = -pi / 2
        elif x < 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = pi / 2
        else:  #x=0
            my_ExactSol[i] = 0

        if my_mesh.isBorderNode(i):  # Détection des noeuds frontière
            boundaryNodes.append(i)
            nbBoundaryNodes = nbBoundaryNodes + 1
        else:  # Détection des noeuds intérieurs
            interiorNodes.append(i)
            nbInteriorNodes = nbInteriorNodes + 1
            maxNbNeighbours = max(
                1 + Ni.getNumberOfCells(), maxNbNeighbours
            )  #true only in 2D, need a function Ni.getNumberOfNeighbourNodes()

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Number of interior nodes=", nbInteriorNodes)
    print("Number of boundary nodes=", nbBoundaryNodes)
    print("Max number of neighbours=", maxNbNeighbours)

    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbInteriorNodes, nbInteriorNodes, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbInteriorNodes)

    M = cdmath.Matrix(3, 3)
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle (hypothèse 2D)
    GradShapeFunc0 = cdmath.Vector(2)
    GradShapeFunc1 = cdmath.Vector(2)
    GradShapeFunc2 = cdmath.Vector(2)

    #On parcourt les triangles du domaine
    for i in range(nbCells):

        Ci = my_mesh.getCell(i)

        #Contribution à la matrice de rigidité
        nodeId0 = Ci.getNodeId(0)
        nodeId1 = Ci.getNodeId(1)
        nodeId2 = Ci.getNodeId(2)

        N0 = my_mesh.getNode(nodeId0)
        N1 = my_mesh.getNode(nodeId1)
        N2 = my_mesh.getNode(nodeId2)

        M[0, 0] = N0.x()
        M[0, 1] = N0.y()
        M[0, 2] = 1
        M[1, 0] = N1.x()
        M[1, 1] = N1.y()
        M[1, 2] = 1
        M[2, 0] = N2.x()
        M[2, 1] = N2.y()
        M[2, 2] = 1

        #Values of each shape function at each node
        values0 = [1, 0, 0]
        values1 = [0, 1, 0]
        values2 = [0, 0, 1]

        GradShapeFunc0 = gradientNodal(M, values0) / 2
        GradShapeFunc1 = gradientNodal(M, values1) / 2
        GradShapeFunc2 = gradientNodal(M, values2) / 2

        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme)
        GradShapeFuncs = {nodeId0: GradShapeFunc0}
        GradShapeFuncs[nodeId1] = GradShapeFunc1
        GradShapeFuncs[nodeId2] = GradShapeFunc2

        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0, nodeId1, nodeId2]:
            if boundaryNodes.count(
                    j
            ) == 0:  #seuls les noeuds intérieurs contribuent au système linéaire (matrice de rigidité et second membre)
                j_int = interiorNodes.index(
                    j)  #indice du noeud j en tant que noeud intérieur
                #Pas de contribution au second membre car pas de terme source
                boundaryContributionAdded = False  #Needed in case j is a border cell
                #Contribution de la cellule triangulaire i à la ligne j_int du système linéaire
                for k in [nodeId0, nodeId1, nodeId2]:
                    if boundaryNodes.count(
                            k
                    ) == 0:  #seuls les noeuds intérieurs contribuent à la matrice du système linéaire
                        k_int = interiorNodes.index(
                            k)  #indice du noeud k en tant que noeud intérieur
                        Rigidite.addValue(
                            j_int, k_int, GradShapeFuncs[j] *
                            GradShapeFuncs[k] / Ci.getMeasure())
                    elif boundaryContributionAdded == False:  #si condition limite non nulle au bord (ou maillage non recouvrant), ajouter la contribution du bord au second membre de la cellule j
                        if boundaryNodes.count(nodeId0) != 0:
                            u0 = my_ExactSol[nodeId0]
                        else:
                            u0 = 0
                        if boundaryNodes.count(nodeId1) != 0:
                            u1 = my_ExactSol[nodeId1]
                        else:
                            u1 = 0
                        if boundaryNodes.count(nodeId2) != 0:
                            u2 = my_ExactSol[nodeId2]
                        else:
                            u2 = 0
                        boundaryContributionAdded = True  #Contribution from the boundary to matrix line j is done in one step
                        GradGh = gradientNodal(M, [u0, u1, u2]) / 2
                        RHS[j_int] += -(GradGh *
                                        GradShapeFuncs[j]) / Ci.getMeasure()

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(
        Rigidite, RHS, 100, 1.E-6, "CG",
        "LU")  #Remplacer CG par CHOLESKY pour solveur direct
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print("Preconditioner used : ", LS.getNameOfPc())
    print("Number of iterations used : ", LS.getNumberOfIter())
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbInteriorNodes):
        my_ResultField[interiorNodes[j]] = SolSyst[j]
        #remplissage des valeurs pour les noeuds intérieurs
    for j in range(nbBoundaryNodes):
        my_ResultField[boundaryNodes[j]] = my_ExactSol[boundaryNodes[j]]
        #remplissage des valeurs pour les noeuds frontière (condition limite)
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElements2DPoissonStiffBC_DISK_" + meshName +
                            str(nbNodes))

    print(
        "Numerical solution of 2D Poisson equation on a disk using finite elements done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    l2_norm_sol_exacte = my_ExactSol.normL2()[0]
    l2_error = (my_ExactSol - my_ResultField).normL2()[0]

    print(
        "L2 relative error = norm( exact solution - numerical solution )/norm( exact solution ) = ",
        l2_error / l2_norm_sol_exacte)
    print("Maximum numerical solution = ", my_ResultField.max(),
          " Minimum numerical solution = ", my_ResultField.min())
    print("Maximum exact solution = ", my_ExactSol.max(),
          " Minimum exact solution = ", my_ExactSol.min())

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, -1, 0], [0, 1, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteElements2DPoissonStiffBC_DISK_" + meshName + str(nbNodes) +
        '_0.vtu', "ResultField", 'NODES',
        "FiniteElements2DPoissonStiffBC_DISK_" + meshName + str(nbNodes))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = l2_error
    test_desc["Relative_error"] = l2_error / l2_norm_sol_exacte

    with open(
            'test_PoissonStiffBC' + str(my_mesh.getMeshDimension()) + 'D_EF_' +
            "DISK_" + meshName + str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return l2_error / l2_norm_sol_exacte, nbNodes, diag_data, my_ResultField.min(
    ), my_ResultField.max(), end - start
    raise ValueError(
        "Wrong space or mesh dimension : space and mesh dimensions should be 2"
    )
if (not my_mesh.isTriangular()):
    raise ValueError("Wrong cell types : mesh is not made of triangles")

nbNodes = my_mesh.getNumberOfNodes()
nbCells = my_mesh.getNumberOfCells()

print("Mesh loading done")
print("Number of nodes=", nbNodes)
print("Number of cells=", nbCells)

#Discrétisation du second membre et détermination des noeuds intérieurs
#======================================================================
my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1)
my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1)
nbInteriorNodes = 0
nbBoundaryNodes = 0
maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
interiorNodes = []
boundaryNodes = []

#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
for i in range(nbNodes):
    Ni = my_mesh.getNode(i)
    x = Ni.x()
    y = Ni.y()

    r = sqrt(x * x + y * y)
    theta = atan2(y, x)
if (my_mesh.getMeshDimension() != 2):
    raise ValueError(
        "Wrong mesh dimension : expected a surface of dimension 2")
if (my_mesh.getSpaceDimension() != 3):
    raise ValueError("Wrong space dimension : expected a space of dimension 3")

nbNodes = my_mesh.getNumberOfNodes()
nbCells = my_mesh.getNumberOfCells()

print("Mesh building/loading done")
print("nb of nodes=", nbNodes)
print("nb of cells=", nbCells)

#Discrétisation du second membre et détermination des noeuds intérieurs
#======================================================================
my_RHSfield = cdmath.Field("RHS field", cdmath.NODES, my_mesh, 1)
maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix

#parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud
for i in range(nbNodes):
    Ni = my_mesh.getNode(i)
    x = Ni.x()
    y = Ni.y()
    z = Ni.z()

    my_RHSfield[i] = 12 * y * (3 * x * x - y * y) / pow(
        x * x + y * y + z * z,
        3 / 2)  #vecteur propre du laplacien sur la sphère
    if my_mesh.isBorderNode(i):  # Détection des noeuds frontière
        raise ValueError("Mesh should not contain borders")
    else:
示例#27
0
eps = 1e-6
my_mesh.setGroupAtPlan(0, 0, eps, "DirichletBorder")  #Bord GAUCHE
my_mesh.setGroupAtPlan(1, 0, eps, "DirichletBorder")  #Bord DROIT
my_mesh.setGroupAtPlan(0, 1, eps, "DirichletBorder")  #Bord BAS
my_mesh.setGroupAtPlan(1, 1, eps, "DirichletBorder")  #Bord HAUT
my_mesh.setGroupAtPlan(0, 2, eps, "DirichletBorder")  #Bord AVANT
my_mesh.setGroupAtPlan(1, 2, eps, "DirichletBorder")  #Bord ARRIERE

nbCells = my_mesh.getNumberOfCells()

print("Mesh loading done")
print("Number of cells ", nbCells)

#Discrétisation du second membre et extraction du nb max de voisins d'une cellule
#================================================================================
my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1)
maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
for i in range(nbCells):
    Ci = my_mesh.getCell(i)
    x = Ci.x()
    y = Ci.y()
    z = Ci.z()
    my_RHSfield[i] = 3 * pi * pi * sin(pi * x) * sin(pi * y) * sin(
        pi * z)  #mettre la fonction definie au second membre de l edp
    # compute maximum number of neighbours
    maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

print("Right hand side discretisation done")
print("Maximum number of neighbours=", maxNbNeighbours)
	raise ValueError("Wrong space dimension : expected a space of dimension 3")
nbNodes = my_mesh.getNumberOfNodes()

nbCells = my_mesh.getNumberOfCells()

print("Mesh building/loading done")
print("nb of nodes=", nbNodes)
print("nb of cells=", nbCells)

# Torus radii (calculation  will fail if the mesh is not correct)
R=1 #Grand rayon
r=0.6 #Petit rayon

#Discrétisation du second membre, de la solution exacte et détermination des noeuds intérieurs
#======================================================================
my_RHSfield = cdmath.Field("RHS field", cdmath.NODES, my_mesh, 1)
exactSolField = cdmath.Field("Exact solution field", cdmath.NODES, my_mesh, 1)

maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix

#parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud
for i in range(nbNodes):
	Ni=my_mesh.getNode(i)
	x = Ni.x()
	y = Ni.y()
	z = Ni.z()
      
	theta=atan2(z,sqrt(x*x+y*y)-R)
	phi=atan2(y,x)

	exactSolField[i] = sin(3*phi)*cos(3*theta+ phi) # for the exact solution we use the funtion given in the article of Olshanskii, Reusken 2009, page 19
示例#29
0
def solve(filename,resolution,meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"]=meshType
    test_desc["Test_color"]=testColor
    
    #Chargement du maillage triangulaire du domaine carré [0,1]x[0,1], définition des bords
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename+".med")
    if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) :
        raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2")
    if(not my_mesh.isTriangular()) :
        raise ValueError("Wrong cell types : mesh is not made of triangles")
    eps=1e-6
    my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE
    my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT
    my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS
    my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT
    
    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()
    
    test_desc["Space_dimension"]=my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"]=my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"]=my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"]=my_mesh.getElementTypes()

    print("Mesh loading done")
    print("Number of nodes=", nbNodes)
    print("Number of cells=", nbCells)
    
    #Discrétisation du second membre et détermination des noeuds intérieurs
    #======================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1)
    nbInteriorNodes = 0
    nbBoundaryNodes = 0
    maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    interiorNodes=[]
    boundaryNodes=[]
    
    #parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni=my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()
    
        my_RHSfield[i]=2*pi*pi*sin(pi*x)*sin(pi*y)#mettre la fonction definie au second membre de l'edp
        if my_mesh.isBorderNode(i): # Détection des noeuds frontière
            boundaryNodes.append(i)
            nbBoundaryNodes=nbBoundaryNodes+1
        else: # Détection des noeuds intérieurs
            interiorNodes.append(i)
            nbInteriorNodes=nbInteriorNodes+1
            maxNbNeighbours= max(1+Ni.getNumberOfCells(),maxNbNeighbours) #true only in 2D, need a function Ni.getNumberOfNeighbourNodes()

    test_desc["Mesh_max_number_of_neighbours"]=maxNbNeighbours
    
    print("Right hand side discretisation done")
    print("Number of interior nodes=", nbInteriorNodes)
    print("Number of boundary nodes=", nbBoundaryNodes)
    print("Max number of neighbours=", maxNbNeighbours)
    
    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite=cdmath.SparseMatrixPetsc(nbInteriorNodes,nbInteriorNodes,maxNbNeighbours) # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS=cdmath.Vector(nbInteriorNodes)
    
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle (hypothèse 2D)
    GradShapeFunc0=cdmath.Vector(2)
    GradShapeFunc1=cdmath.Vector(2)
    GradShapeFunc2=cdmath.Vector(2)
    
    #On parcourt les triangles du domaine
    for i in range(nbCells):
    
        Ci=my_mesh.getCell(i)
    
        #Contribution à la matrice de rigidité
        nodeId0=Ci.getNodeId(0)
        nodeId1=Ci.getNodeId(1)
        nodeId2=Ci.getNodeId(2)
    
        N0=my_mesh.getNode(nodeId0)
        N1=my_mesh.getNode(nodeId1)
        N2=my_mesh.getNode(nodeId2)
    
        #Formule des gradients voir EF P1 -> calcul déterminants
        GradShapeFunc0[0]= (N1.y()-N2.y())/2
        GradShapeFunc0[1]=-(N1.x()-N2.x())/2
        GradShapeFunc1[0]=-(N0.y()-N2.y())/2
        GradShapeFunc1[1]= (N0.x()-N2.x())/2
        GradShapeFunc2[0]= (N0.y()-N1.y())/2
        GradShapeFunc2[1]=-(N0.x()-N1.x())/2
    
        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme
        GradShapeFuncs={nodeId0 : GradShapeFunc0}
        GradShapeFuncs[nodeId1]=GradShapeFunc1
        GradShapeFuncs[nodeId2]=GradShapeFunc2
    
    
        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0,nodeId1,nodeId2] :
            if boundaryNodes.count(j)==0 : #seuls les noeuds intérieurs contribuent au système linéaire (matrice de rigidité et second membre)
                j_int=interiorNodes.index(j)#indice du noeud j en tant que noeud intérieur
                #Ajout de la contribution de la cellule triangulaire i au second membre du noeud j 
                RHS[j_int]=Ci.getMeasure()/3*my_RHSfield[j]+RHS[j_int] # intégrale dans le triangle du produit f x fonction de base
                #Contribution de la cellule triangulaire i à la ligne j_int du système linéaire
                for k in [nodeId0,nodeId1,nodeId2] : 
                    if boundaryNodes.count(k)==0 : #seuls les noeuds intérieurs contribuent à la matrice du système linéaire
                        k_int=interiorNodes.index(k)#indice du noeud k en tant que noeud intérieur
                        Rigidite.addValue(j_int,k_int,GradShapeFuncs[j]*GradShapeFuncs[k]/Ci.getMeasure())
                    #else: si condition limite non nulle au bord, ajouter la contribution du bord au second membre de la cellule j
    
    print("Linear system matrix building done")
    
    # Résolution du système linéaire
    #=================================
    LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"CG","ILU")#Remplacer CG par CHOLESKY pour solveur direct
    LS.setComputeConditionNumber()
    SolSyst=LS.solve()
    
    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print("Linear system solved")
    
    test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
    test_desc["Linear_solver_precision"]=LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
    test_desc["Linear_system_max_actual_iterations_number"]=LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"]=LS.getResidu()
    test_desc["Linear_system_max_actual_condition number"]=LS.getConditionNumber()


    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbInteriorNodes):
        my_ResultField[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs
    for j in range(nbBoundaryNodes):
        my_ResultField[boundaryNodes[j]]=0;#remplissage des valeurs pour les noeuds frontière (condition limite)
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes))
    
    print("Numerical solution of 2D Poisson equation on a square using finite elements done")
    
    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 2*pi*pi
    max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(2*pi*pi)
    max_sol_num=my_ResultField.max()
    min_sol_num=my_ResultField.min()
    erreur_abs=0
    for i in range(nbNodes) :
        if erreur_abs < abs(my_RHSfield[i]/(2*pi*pi) - my_ResultField[i]) :
            erreur_abs = abs(my_RHSfield[i]/(2*pi*pi) - my_ResultField[i])
    
    print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_abs/max_abs_sol_exacte)
    print ("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num)
    
    #Postprocessing : 
    #================
	# Extraction of the diagonal data
    diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes))
    
    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Absolute_error"]=erreur_abs
    test_desc["Relative_error"]=erreur_abs/max_abs_sol_exacte

    with open('test_Poisson'+str(my_mesh.getMeshDimension())+'D_EF_'+"SQUARE_"+meshType+str(nbCells)+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)

    return erreur_abs/max_abs_sol_exacte, nbNodes, diag_data, min_sol_num, max_sol_num, end - start
示例#30
0
def solve(my_mesh, filename, resolution, meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"] = meshType
    test_desc["Test_color"] = testColor

    nbCells = my_mesh.getNumberOfCells()

    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfCells()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh groups done")
    print("Number of cells  = ", nbCells)

    #Discrétisation du second membre et extraction du nb max de voisins d'une cellule
    #================================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1)
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    #parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        x = Ci.x()
        y = Ci.y()

        my_RHSfield[i] = 2 * pi * pi * sin(pi * x) * sin(
            pi * y)  #mettre la fonction definie au second membre de l edp
        # compute maximum number of neighbours
        maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)

    # Construction de la matrice et du vecteur second membre du système linéaire
    #===========================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbCells, nbCells, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbCells)
    #Parcours des cellules du domaine
    for i in range(nbCells):
        RHS[i] = my_RHSfield[
            i]  #la valeur moyenne du second membre f dans la cellule i
        Ci = my_mesh.getCell(i)
        for j in range(Ci.getNumberOfFaces()):  # parcours des faces voisinnes
            Fj = my_mesh.getFace(Ci.getFaceId(j))
            if not Fj.isBorder():
                k = Fj.getCellId(0)
                if k == i:
                    k = Fj.getCellId(1)
                Ck = my_mesh.getCell(k)
                distance = Ci.getBarryCenter().distance(Ck.getBarryCenter())
                coeff = Fj.getMeasure() / Ci.getMeasure() / distance
                Rigidite.setValue(i, k, -coeff)  # terme extradiagonal
            else:
                coeff = Fj.getMeasure() / Ci.getMeasure() / Ci.getBarryCenter(
                ).distance(Fj.getBarryCenter())
                #For the particular case where the mesh boundary does not coincide with the domain boundary
                x = Fj.getBarryCenter().x()
                y = Fj.getBarryCenter().y()
                RHS[i] += coeff * sin(pi * x) * sin(
                    pi * y
                )  #mettre ici la condition limite du problème de Dirichlet
            Rigidite.addValue(i, i, coeff)  # terme diagonal

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(Rigidite, RHS, 500, 1.E-6, "CG", "LU")
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.CELLS, my_mesh, 1)
    for i in range(nbCells):
        my_ResultField[i] = SolSyst[i]
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteVolumes2DPoisson_SQUARE_" + meshType +
                            str(nbCells))

    print(
        "Numerical solution of 2D Poisson equation on a square using finite elements done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 2*pi*pi
    max_abs_sol_exacte = max(my_RHSfield.max(),
                             -my_RHSfield.min()) / (2 * pi * pi)
    max_sol_num = my_ResultField.max()
    min_sol_num = my_ResultField.min()
    erreur_abs = 0
    for i in range(nbCells):
        if erreur_abs < abs(my_RHSfield[i] /
                            (2 * pi * pi) - my_ResultField[i]):
            erreur_abs = abs(my_RHSfield[i] / (2 * pi * pi) -
                             my_ResultField[i])

    print(
        "Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",
        erreur_abs / max_abs_sol_exacte)
    print("Maximum numerical solution = ", max_sol_num,
          " Minimum numerical solution = ", min_sol_num)

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, 1, 0], [1, 0, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteVolumes2DPoisson_SQUARE_" + meshType + str(nbCells) + '_0.vtu',
        "ResultField", 'CELLS',
        "FiniteVolumes2DPoisson_SQUARE_" + meshType + str(nbCells))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = erreur_abs
    test_desc["Relative_error"] = erreur_abs / max_abs_sol_exacte

    with open(
            'test_Poisson' + str(my_mesh.getMeshDimension()) + 'D_VF_' +
            str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return erreur_abs / max_abs_sol_exacte, nbCells, diag_data, min_sol_num, max_sol_num, end - start