Exemple #1
0
def test_validation3DVF_cubes():
    start = time.time()
    ### 3D FV rectangular mesh
    meshList = [11, 21, 41]
    meshType = "Regular_cubes"
    testColor = "Green"
    nbMeshes = len(meshList)
    error_tab = [0] * nbMeshes
    mesh_size_tab = [0] * nbMeshes
    mesh_name = 'meshCubeWithCuboids3DFV'
    diag_data = [0] * nbMeshes
    time_tab = [0] * nbMeshes
    resolution = 100
    curv_abs = np.linspace(0, sqrt(2), resolution + 1)
    plt.close('all')
    i = 0
    # Storing of numerical errors, mesh sizes and diagonal values
    i = 0
    # Computation of the numerical error
    for nx in meshList:
        my_mesh = cdmath.Mesh(0, 1, nx, 0, 1, nx, 0, 1, nx)
        error_tab[i], mesh_size_tab[i], diag_data[
            i], min_sol_num, max_sol_num, time_tab[
                i] = FiniteVolumes3DPoisson_CUBE.solve(
                    my_mesh,
                    str(nx) + 'x' + str(nx) + 'x' + str(nx), resolution,
                    meshType, testColor)
        assert min_sol_num > -0.01
        assert max_sol_num < 1.2
        plt.plot(curv_abs,
                 diag_data[i],
                 label=str(mesh_size_tab[i]) + ' cells')
        error_tab[i] = log10(error_tab[i])
        time_tab[i] = log10(time_tab[i])
        mesh_size_tab[i] = 1. / 3 * log10(mesh_size_tab[i])
        i = i + 1

    end = time.time()

    # Plot over diagonal line
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Value on diagonal line')
    plt.title(
        'Plot over diagonal line for finite volumes \n for Laplace operator on 3D cuboid meshes'
    )
    plt.savefig(mesh_name + "_3DPoissonVFs_PlotOverDiagonalLine.png")

    # Least square linear regression
    # Find the best a,b such that f(x)=ax+b best approximates the convergence curve
    # The vector X=(a,b) solves a symmetric linear system AX=B with A=(a1,a2\\a2,a3), B=(b1,b2)
    a1 = np.dot(mesh_size_tab, mesh_size_tab)
    a2 = np.sum(mesh_size_tab)
    a3 = nbMeshes
    b1 = np.dot(error_tab, mesh_size_tab)
    b2 = np.sum(error_tab)

    det = a1 * a3 - a2 * a2
    assert det != 0, 'test_validation3DVF_s() : Make sure you use distinct meshes and at least two meshes'
    a = (a3 * b1 - a2 * b2) / det
    b = (-a2 * b1 + a1 * b2) / det

    print "FV on 3D rectangular parallelepiped mesh : scheme order is ", -a
    assert abs(a + 2) < 0.01

    # Plot of convergence curve
    plt.close()
    plt.plot(mesh_size_tab, error_tab, label='log(|numerical-exact|)')
    plt.plot(mesh_size_tab,
             a * np.array(mesh_size_tab) + b,
             label='least square slope : ' + '%.3f' % a)
    plt.legend()
    plt.xlabel('1/3 log(number of cells)')
    plt.ylabel('log(error)')
    plt.title(
        'Convergence of finite volumes for Laplace operator on 3D cuboid meshes'
    )
    plt.savefig(mesh_name + "_3DPoissonVFs_ConvergenceCurve.png")

    # Plot of computational time
    plt.close()
    plt.plot(mesh_size_tab, time_tab, label='log(cpu time)')
    plt.legend()
    plt.xlabel('1/3 log(number of cells)')
    plt.ylabel('log(cpu time)')
    plt.title(
        'Computational time of finite volumes \n for Laplace operator on 3D cuboid meshes'
    )
    plt.savefig(mesh_name + "_3DPoissonVFs_ComputationalTime.png")

    plt.close('all')

    convergence_synthesis["Mesh_names"] = meshList
    convergence_synthesis["Mesh_type"] = meshType
    #convergence_synthesis["Mesh_path"]=mesh_path
    convergence_synthesis["Mesh_description"] = mesh_name
    convergence_synthesis["Mesh_sizes"] = [10**x for x in mesh_size_tab]
    convergence_synthesis["Space_dimension"] = 3
    convergence_synthesis["Mesh_dimension"] = 3
    convergence_synthesis["Mesh_cell_type"] = "Cubes"
    convergence_synthesis["Errors"] = [10**x for x in error_tab]
    convergence_synthesis["Scheme_order"] = -a
    convergence_synthesis["Test_color"] = testColor
    convergence_synthesis["Computational_time"] = end - start

    with open('Convergence_Poisson_3DFV_' + mesh_name + '.json',
              'w') as outfile:
        json.dump(convergence_synthesis, outfile)
    test_desc["Mesh_max_number_of_neighbours"]=10
    test_desc["Geometry"]="Square"
    test_desc["Boundary_conditions"]=test_bc
    test_desc["Initial_data"]=test_initial_data
    test_desc["Part_of_mesh_convergence_analysis"]=True
    test_desc["Numerical_parameter_cfl"]=cfl
    test_desc["Simulation_parameter_maximum_time_step"]=ntmax
    test_desc["Simulation_parameter_maximum_time"]=tmax
    test_desc["Simulation_output_frequency"]=output_freq
    test_desc["Simulation_final_time_after_run"]=t_final
    test_desc["Simulation_final_number_of_time_steps_after_run"]=ndt_final
    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Absolute_error"]=max(error_p*p0,error_u)
    test_desc["Relative_error"]=max(error_p,error_u)

    with open('test_WaveSystem'+str(my_mesh.getMeshDimension())+'DCentered_'+meshName+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)
    
    return error_p, error_u, nbCells, t_final, ndt_final, max_vel, diag_data_press, diag_data_vel, end - start, cond_number

def solve_file( filename,meshName, resolution,scaling, meshType, testColor,cfl):
    my_mesh = cdmath.Mesh(filename+".med")

    return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution,scaling, meshType, testColor,cfl)
    

if __name__ == """__main__""":
    M1=cdmath.Mesh(0,1,20,0,1,20)
    cfl=0.5
    solve(M1,"SquareWithSquares",100,2,"Regular squares","Green",cfl)
Exemple #3
0
        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"


def solve(my_mesh,filename,resolution):
    print("Resolution of the Wave system with Wall boundary conditions:")

    # Problem data
    tmax = 1.
    ntmax = 100
    cfl = 0.45
    output_freq = 100

    WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution)

def solve_file( filename,resolution):
    my_mesh = cdmath.Mesh(filename+".med")
    solve(my_mesh, filename,resolution)
    
if __name__ == """__main__""":
    if len(sys.argv) >1 :
        filename=sys.argv[1]
        my_mesh = cdmath.Mesh(filename)
        solve(my_mesh,filename,100)
    else :
        raise ValueError("WaveSystemUpwind.py expects a mesh file name")

Exemple #4
0
    #================
    # 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(
        "FiniteVolumes2D_square_ResultField" + str(nbCells) + '_0.vtu',
        "ResultField", 'CELLS',
        "FiniteVolumes2D_square_ResultField" + 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


def solve_file(filename, resolution, meshType, testColor):
    my_mesh = cdmath.Mesh(filename + ".med")
    return solve(my_mesh, filename, resolution, meshType, testColor)


if __name__ == """__main__""":
    mesh51 = cdmath.Mesh(0, 1, 51, 0, 1, 51)
    solve(mesh51, '51', 100, "Regular squares", "Green")
Exemple #5
0
    test_desc["Simulation_parameter_maximum_time"] = tmax
    test_desc["Simulation_output_frequency"] = output_freq
    test_desc["Simulation_final_time_after_run"] = t_final
    test_desc["Simulation_final_number_of_time_steps_after_run"] = ndt_final
    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = max(error_p * p0, error_u)
    test_desc["Relative_error"] = max(error_p, error_u)

    with open(
            'test_WaveSystem' + str(my_mesh.getMeshDimension()) + 'DUpwind_' +
            meshName + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return error_p, error_u, nbCells, t_final, ndt_final, max_vel, diag_data_press, diag_data_vel, end - start


def solve_file(filename, meshName, resolution, scaling, meshType, testColor,
               cfl, test_bc):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution, scaling, meshType, testColor, cfl, test_bc)


if __name__ == """__main__""":
    M1 = cdmath.Mesh(0., 1., 20, 0., 1., 20)
    cfl = 0.5
    scaling = 0
    solve(M1, "SquareRegularSquares", 100, scaling, "Regular_squares", "Green",
          cfl, "Periodic")
# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire
#               Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH
#               Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations
#                           on surfaces. SIAM J. Num. Anal., 47, p. 3355
#================================================================================================================================

import cdmath
from math import pow
import numpy as np
import PV_routines
import VTK_routines
import paraview.simple as pvs

#Chargement du maillage triangulaire de la sphère
#=======================================================================================
my_mesh = cdmath.Mesh("meshSphere.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()

print("Mesh building/loading done")
print("nb of nodes=", nbNodes)
print("nb of cells=", nbCells)
Exemple #7
0
# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage 1D quelconque
#		        Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH
#               Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x)
#================================================================================================================================

import cdmath
from math import sin, pi, sqrt
from numpy import linspace
import matplotlib.pyplot as plt
import PV_routines
import VTK_routines

#Création d'un maillage uniforme du segment [0,1], définition des bords
#======================================================================
nx=100
my_mesh = cdmath.Mesh(0,1,nx)
if( my_mesh.getSpaceDimension()!=1 or my_mesh.getMeshDimension()!=1) :
    raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 1")

eps=1e-6
my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE
my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT

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

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

#Discrétisation du second membre et détermination des noeuds intérieurs
    print "Numerical method : staggered scheme"
    print "Initial data : Spherical wave"
    print "Periodic boundary conditions"
    print "Mesh name : ", meshName, my_mesh.getNumberOfCells(), " cells"

    # Problem data
    tmax = 1000.
    ntmax = 500
    cfl = 1. / my_mesh.getSpaceDimension()
    output_freq = 1

    WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName,
                        resolution)


def solve_file(filename, meshName, resolution):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution)


if __name__ == """__main__""":
    if len(sys.argv) > 1:
        my_mesh = cdmath.Mesh(sys.argv[1])
        solve(my_mesh, my_mesh.getName(), 100)
    else:
        nx = 50
        my_mesh = cdmath.Mesh(0, 1, nx, 0, 1, nx)
        solve(my_mesh, my_mesh.getName(), 100)
def solve_file(filename, meshName, resolution):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution)
Exemple #10
0
def solve(my_mesh, meshName, resolution):
    print "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension(
    )
    print "Numerical method : implicit pseudo staggered"
    print "Initial data : constant pressure, divergence free velocity"
    print "Wall boundary conditions"
    print "Mesh name : ", meshName, my_mesh.getNumberOfCells(), " cells"

    # Problem data
    tmax = 1000.
    ntmax = 100
    cfl = 1. / my_mesh.getSpaceDimension()
    output_freq = 100

    WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution)


def solve_file(filename, meshName, resolution):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution)


if __name__ == """__main__""":
    if len(sys.argv) > 1:
        my_mesh = cdmath.Mesh(sys.argv[1])
        solve(my_mesh, my_mesh.getName(), 100)
    else:
        raise ValueError("WaveSystemPStag.py expects a mesh file name")
Exemple #11
0
# Copyright   : CEA Saclay 2017
# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage tétraédrique
#		        Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH
#               Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x)*sin(pi*y)*sin(pi*z)
#================================================================================================================================

import cdmath
from math import sin, pi, sqrt
import numpy as np
import matplotlib.pyplot as plt
import PV_routines
import VTK_routines

#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords
#==============================================================================================
my_mesh = cdmath.Mesh("meshCube.med")
if (my_mesh.getSpaceDimension() != 3 or my_mesh.getMeshDimension() != 3):
    raise ValueError(
        "Wrong space or mesh dimension : space and mesh dimensions should be 3"
    )
if (not my_mesh.isTetrahedral()):
    raise ValueError("Wrong cell types : mesh is not made of tetrahedra")
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

nbNodes = my_mesh.getNumberOfNodes()
def test_validation3DWaveSystemUpwind_cubes():
    start = time.time()
    #### 3D cubic mesh
    meshList=[6,11,21]
    meshType="Regular cubes"
    testColor="Green"
    nbMeshes=len(meshList)
    error_p_tab=[0]*nbMeshes
    error_u_tab=[0]*nbMeshes
    mesh_size_tab=[0]*nbMeshes
    mesh_name='CubeWithCubes'
    diag_data_press=[0]*nbMeshes
    diag_data_vel=[0]*nbMeshes
    time_tab=[0]*nbMeshes
    t_final=[0]*nbMeshes
    ndt_final=[0]*nbMeshes
    max_vel=[0]*nbMeshes
    resolution=100
    curv_abs=np.linspace(0,sqrt(3),resolution+1)

    plt.close('all')
    i=0
    cfl=1./3
    bctype="Periodic"
    
    # Storing of numerical errors, mesh sizes and diagonal values
    for nx in meshList:
        my_mesh=cdmath.Mesh(0,1,nx,0,1,nx,0,1,nx)
        error_p_tab[i], error_u_tab[i], mesh_size_tab[i], t_final[i], ndt_final[i], max_vel[i], diag_data_press[i], diag_data_vel[i], time_tab[i] =WaveSystemUpwind.solve(my_mesh, mesh_name+str(my_mesh.getNumberOfCells()), resolution,meshType,testColor,cfl,bctype)
        assert max_vel[i]>1.4 and max_vel[i]<2
        i=i+1
    
    end = time.time()

    # Plot over diagonal line
    for i in range(nbMeshes):
        plt.plot(curv_abs, diag_data_press[i], label= str(mesh_size_tab[i]) + ' cells')
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Pressure on diagonal line')
    plt.title('Plot over diagonal line for stationary wave system \n on 3D cube meshes')
    plt.savefig(mesh_name+'_Pressure_3DWaveSystem_'+"PlotOverDiagonalLine.png")
    plt.close()

    plt.clf()
    for i in range(nbMeshes):
        plt.plot(curv_abs, diag_data_vel[i],   label= str(mesh_size_tab[i]) + ' cells')
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Velocity on diagonal line')
    plt.title('Plot over diagonal line for the stationary wave system \n on 3D cube meshes')
    plt.savefig(mesh_name+"_Velocity_3DWaveSystem_"+"PlotOverDiagonalLine.png")    
    plt.close()

    # Least square linear regression
    # Find the best a,b such that f(x)=ax+b best approximates the convergence curve
    # The vector X=(a,b) solves a symmetric linear system AX=B with A=(a1,a2\\a2,a3), B=(b1,b2)
    a1=np.dot(mesh_size_tab,mesh_size_tab)
    a2=np.sum(mesh_size_tab)
    a3=nbMeshes
    
    det=a1*a3-a2*a2
    assert det!=0, 'test_validation3DWaveSystem_cubes() : Make sure you use distinct meshes and at least two meshes'

    b1p=np.dot(error_p_tab,mesh_size_tab)   
    b2p=np.sum(error_p_tab)
    ap=( a3*b1p-a2*b2p)/det
    bp=(-a2*b1p+a1*b2p)/det
    
    print "FV upwind on 3D cubee meshes : scheme order for pressure is ", -ap

    b1u=np.dot(error_u_tab,mesh_size_tab)   
    b2u=np.sum(error_u_tab)
    au=( a3*b1u-a2*b2u)/det
    bu=(-a2*b1u+a1*b2u)/det
    
    print "FV upwind on 3D cube meshes : scheme order for velocity is ", -au
    
    # Plot of number of time steps
    plt.close()
    plt.plot(mesh_size_tab, ndt_final, label='Number of time step to reach stationary regime')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('Max time steps for stationary regime')
    plt.title('Number of times steps required \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"_3DWaveSystem_"+"TimeSteps.png")
    
    # Plot of number of stationary time
    plt.close()
    plt.plot(mesh_size_tab, t_final, label='Time where stationary regime is reached')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('Max time for stationary regime')
    plt.title('Simulated time  \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"_3DWaveSystem_"+"TimeFinal.png")
    
    # Plot of number of maximal velocity norm
    plt.close()
    plt.plot(mesh_size_tab, max_vel, label='Maximum velocity norm')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('Max velocity norm')
    plt.title('Maximum velocity norm  \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"_3DWaveSystem_"+"MaxVelNorm.png")
    
    # Plot of convergence curves
    plt.close()
    plt.plot(mesh_size_tab, error_p_tab, label='|error on stationary pressure|')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('|error p|')
    plt.title('Convergence of finite volumes \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"_Pressure_3DWaveSystem_"+"ConvergenceCurve.png")
    
    plt.close()
    plt.plot(mesh_size_tab, error_u_tab, label='log(|error on stationary velocity|)')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('|error u|')
    plt.title('Convergence of finite volumes \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"_Velocity_3DWaveSystem_"+"ConvergenceCurve.png")
    
    # Plot of computational time
    plt.close()
    plt.plot(mesh_size_tab, time_tab, label='log(cpu time)')
    plt.legend()
    plt.xlabel('number of cells')
    plt.ylabel('cpu time')
    plt.title('Computational time of finite volumes \n for the stationary Wave System on 3D cube meshes')
    plt.savefig(mesh_name+"3DWaveSystem_ComputationalTime.png")

    plt.close('all')

    convergence_synthesis={}

    convergence_synthesis["PDE_model"]="Wave system"
    convergence_synthesis["PDE_is_stationary"]=False
    convergence_synthesis["PDE_search_for_stationary_solution"]=True
    convergence_synthesis["Numerical_method_name"]="Upwind"
    convergence_synthesis["Numerical_method_space_discretization"]="Finite volumes"
    convergence_synthesis["Numerical_method_time_discretization"]="Implicit"
    convergence_synthesis["Initial_data"]="Constant pressure, divergence free velocity"
    convergence_synthesis["Boundary_conditions"]="Periodic"
    convergence_synthesis["Numerical_parameter_cfl"]=cfl
    convergence_synthesis["Space_dimension"]=3
    convergence_synthesis["Mesh_dimension"]=3
    convergence_synthesis["Mesh_names"]=meshList
    convergence_synthesis["Mesh_type"]=meshType
    #convergence_synthesis["Mesh_path"]=mesh_path
    convergence_synthesis["Mesh_description"]=mesh_name
    convergence_synthesis["Mesh_sizes"]=mesh_size_tab
    convergence_synthesis["Mesh_cell_type"]="Cubes"
    convergence_synthesis["Numerical_error_velocity"]=error_u_tab
    convergence_synthesis["Numerical_error_pressure"]=error_p_tab
    convergence_synthesis["Max_vel_norm"]=max_vel
    convergence_synthesis["Final_time"]=t_final  
    convergence_synthesis["Final_time_step"]=ndt_final  
    convergence_synthesis["Scheme_order"]=min(-au,-ap)
    convergence_synthesis["Scheme_order_vel"]=-au
    convergence_synthesis["Scheme_order_press"]=-ap
    convergence_synthesis["Scaling_preconditioner"]="None"
    convergence_synthesis["Test_color"]=testColor
    convergence_synthesis["Computational_time"]=end-start

    with open('Convergence_WaveSystem_3DFV_Upwind_'+mesh_name+'.json', 'w') as outfile:  
        json.dump(convergence_synthesis, outfile)
Exemple #13
0
# Copyright   : CEA Saclay 2016
# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire
#		        Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH
#               Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x)*sin(pi*y)
#================================================================================================================================

import cdmath
from math import sin, pi, sqrt
import numpy as np
import matplotlib.pyplot as plt
import PV_routines
import VTK_routines

#Chargement du maillage triangulaire du domaine carré [0,1]x[0,1], définition des bords
#=======================================================================================
my_mesh = cdmath.Mesh("squareWithTriangles.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()
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 (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("FiniteElements2D_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(
        "FiniteElements2D_SQUARE_" + meshType + str(nbNodes) + '_0.vtu',
        "ResultField", 'NODES',
        "FiniteElements2D_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
Exemple #15
0
def test_validation2DWaveSystemCentered_squares(scaling):
    start = time.time()
    #### 2D square mesh
    meshList = [7, 15, 31, 51]  #,81,101
    #meshList=['squareWithSquares_1','squareWithSquares_2','squareWithSquares_3','squareWithSquares_4','squareWithSquares_5']
    mesh_path = '../../../ressources/2DCartesien/'
    meshType = "Regular squares"
    testColor = "Green"
    nbMeshes = len(meshList)
    mesh_size_tab = [0] * nbMeshes
    mesh_name = 'squareWithSquares'
    resolution = 100
    curv_abs = np.linspace(0, sqrt(2), resolution + 1)

    error_p_tab = [0] * nbMeshes
    error_u_tab = [0] * nbMeshes
    diag_data_press = [0] * nbMeshes
    diag_data_vel = [0] * nbMeshes
    time_tab = [0] * nbMeshes
    t_final = [0] * nbMeshes
    ndt_final = [0] * nbMeshes
    max_vel = [0] * nbMeshes
    cond_number = [0] * nbMeshes

    plt.close('all')
    i = 0
    cfl = 0.5
    # Storing of numerical errors, mesh sizes and diagonal values
    #for filename in meshList:
    for nx in meshList:
        my_mesh = cdmath.Mesh(0, 1, nx, 0, 1, nx)
        error_p_tab[i], error_u_tab[i], mesh_size_tab[i], t_final[
            i], ndt_final[i], max_vel[i], diag_data_press[i], diag_data_vel[
                i], time_tab[i], cond_number[i] = WaveSystemCentered.solve(
                    my_mesh, "square" + str(nx) + 'x' + str(nx), resolution,
                    scaling, meshType, testColor, cfl, "Periodic")
        #error_p_tab[i], error_u_tab[i], mesh_size_tab[i], t_final[i], ndt_final[i], max_vel[i], diag_data_press[i], diag_data_vel[i], time_tab[i], cond_number[i] =WaveSystemCentered.solve_file(mesh_path+filename, mesh_name, resolution,scaling,meshType,testColor,cfl)
        assert max_vel[i] > 0.8 and max_vel[i] < 1.03
        error_p_tab[i] = log10(error_p_tab[i])
        error_u_tab[i] = log10(error_u_tab[i])
        time_tab[i] = log10(time_tab[i])
        i = i + 1

    end = time.time()

    # Plot over diagonal line
    for i in range(nbMeshes):
        if (scaling == 0):
            plt.plot(curv_abs,
                     diag_data_press[i],
                     label=str(mesh_size_tab[i]) + ' cells - no scaling')
        else:
            plt.plot(curv_abs,
                     diag_data_press[i],
                     label=str(mesh_size_tab[i]) + ' cells - with  scaling')
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Pressure on diagonal line')
    plt.title(
        'Plot over diagonal line for stationary wave system \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + '_Pressure_2DWaveSystemCentered_' + "scaling" +
                str(scaling) + "_PlotOverDiagonalLine.png")
    plt.close()

    plt.clf()
    for i in range(nbMeshes):
        if (scaling == 0):
            plt.plot(curv_abs,
                     diag_data_vel[i],
                     label=str(mesh_size_tab[i]) + ' cells - no scaling')
        else:
            plt.plot(curv_abs,
                     diag_data_vel[i],
                     label=str(mesh_size_tab[i]) + ' cells - with scaling')
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Velocity on diagonal line')
    plt.title(
        'Plot over diagonal line for the stationary wave system \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_Velocity_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_PlotOverDiagonalLine.png")
    plt.close()

    # Plot of number of time steps
    plt.close()
    if (scaling == 0):
        plt.plot(
            mesh_size_tab,
            ndt_final,
            label='Number of time step to reach stationary regime - no scaling'
        )
    else:
        plt.plot(
            mesh_size_tab,
            ndt_final,
            label=
            'Number of time step to reach stationary regime - with scaling')
    plt.legend()
    plt.xlabel('Number of cells')
    plt.ylabel('Max time steps for stationary regime')
    plt.title(
        'Number of times steps required for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_TimeSteps.png")

    # Plot of number of stationary time
    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab,
                 t_final,
                 label='Time where stationary regime is reached - no scaling')
    else:
        plt.plot(
            mesh_size_tab,
            t_final,
            label='Time where stationary regime is reached - with scaling')
    plt.legend()
    plt.xlabel('Number of cells')
    plt.ylabel('Max time for stationary regime')
    plt.title(
        'Simulated time for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_FinalTime.png")

    # Plot of number of maximal velocity norm
    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab,
                 max_vel,
                 label='Maximum velocity norm - no scaling')
    else:
        plt.plot(mesh_size_tab,
                 max_vel,
                 label='Maximum velocity norm - with scaling')
    plt.legend()
    plt.xlabel('Number of cells')
    plt.ylabel('Max velocity norm')
    plt.title(
        'Maximum velocity norm for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_MaxVelNorm.png")

    # Plot of condition number
    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab,
                 cond_number,
                 label='Condition number - no scaling')
    else:
        plt.plot(mesh_size_tab,
                 cond_number,
                 label='Condition number - with scaling')
    plt.legend()
    plt.xlabel('Number of cells')
    plt.ylabel('Condition number')
    plt.title(
        'Condition number for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_condition_number.png")

    for i in range(nbMeshes):
        mesh_size_tab[i] = 0.5 * log10(mesh_size_tab[i])

    # Least square linear regression
    # Find the best a,b such that f(x)=ax+b best approximates the convergence curve
    # The vector X=(a,b) solves a symmetric linear system AX=B with A=(a1,a2\\a2,a3), B=(b1,b2)
    a1 = np.dot(mesh_size_tab, mesh_size_tab)
    a2 = np.sum(mesh_size_tab)
    a3 = nbMeshes

    det = a1 * a3 - a2 * a2
    assert det != 0, 'test_validation2DWaveSystemSquaresFVCentered_squares() : Make sure you use distinct meshes and at least two meshes'

    b1p = np.dot(error_p_tab, mesh_size_tab)
    b2p = np.sum(error_p_tab)
    ap = (a3 * b1p - a2 * b2p) / det
    bp = (-a2 * b1p + a1 * b2p) / det

    if (scaling == 0):
        print(
            "FV Centered on 2D square meshes : scheme order for pressure without scaling is ",
            -ap)
    else:
        print(
            "FV Centered on 2D square meshes : scheme order for pressure with    scaling is ",
            -ap)

    b1u = np.dot(error_u_tab, mesh_size_tab)
    b2u = np.sum(error_u_tab)
    au = (a3 * b1u - a2 * b2u) / det
    bu = (-a2 * b1u + a1 * b2u) / det

    if (scaling == 0):
        print(
            "FV Centered on 2D square meshes : scheme order for velocity without scaling is ",
            -au)
    else:
        print(
            "FV Centered on 2D square meshes : scheme order for velocity with    scaling is ",
            -au)

    # Plot of convergence curves
    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab,
                 error_p_tab,
                 label='|error on stationary pressure| - no scaling')
    else:
        plt.plot(mesh_size_tab,
                 error_p_tab,
                 label='|error on stationary pressure| - with scaling')
    plt.legend()
    plt.xlabel('1/2 log(number of cells)')
    plt.ylabel('log(|error p|)')
    plt.title(
        'Convergence of finite volumes for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_Pressure_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_ConvergenceCurve.png")

    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab,
                 error_u_tab,
                 label='log(|error on stationary velocity|) - no scaling')
    else:
        plt.plot(mesh_size_tab,
                 error_u_tab,
                 label='log(|error on stationary velocity|) - with scaling')
    plt.legend()
    plt.xlabel('1/2 log(number of cells)')
    plt.ylabel('log(|error u|)')
    plt.title(
        'Convergence of finite volumes for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "_Velocity_2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_ConvergenceCurve.png")

    # Plot of computational time
    plt.close()
    if (scaling == 0):
        plt.plot(mesh_size_tab, time_tab, label='log(cpu time) - no scaling')
    else:
        plt.plot(mesh_size_tab, time_tab, label='log(cpu time) - with scaling')
    plt.legend()
    plt.xlabel('1/2 log(number of cells)')
    plt.ylabel('log(cpu time)')
    plt.title(
        'Computational time of finite volumes for the stationary Wave System \n with centered scheme on 2D square meshes'
    )
    plt.savefig(mesh_name + "2DWaveSystemCentered_" + "scaling" +
                str(scaling) + "_ComputationalTimeSquares.png")

    plt.close('all')

    convergence_synthesis = {}

    convergence_synthesis["PDE_model"] = "Wave system"
    convergence_synthesis["PDE_is_stationary"] = False
    convergence_synthesis["PDE_search_for_stationary_solution"] = True
    if (scaling == 0):
        convergence_synthesis[
            "Numerical_method_name"] = "Centered scheme no scaling"
    else:
        convergence_synthesis[
            "Numerical_method_name"] = "Centered scheme scaling"
    convergence_synthesis[
        "Numerical_method_space_discretization"] = "Finite volumes"
    convergence_synthesis["Numerical_method_time_discretization"] = "Implicit"
    convergence_synthesis[
        "Initial_data"] = "Constant pressure, divergence free velocity"
    convergence_synthesis["Boundary_conditions"] = "Periodic"
    convergence_synthesis["Numerical_parameter_cfl"] = cfl
    convergence_synthesis["Space_dimension"] = 2
    convergence_synthesis["Mesh_dimension"] = 2
    convergence_synthesis["Mesh_names"] = meshList
    convergence_synthesis["Mesh_type"] = meshType
    convergence_synthesis["Mesh_path"] = mesh_path
    convergence_synthesis["Mesh_description"] = mesh_name
    convergence_synthesis["Mesh_sizes"] = mesh_size_tab
    convergence_synthesis["Mesh_cell_type"] = "Squares"
    convergence_synthesis["Numerical_error_velocity"] = error_u_tab
    convergence_synthesis["Numerical_error_pressure"] = error_p_tab
    convergence_synthesis["Max_vel_norm"] = max_vel
    convergence_synthesis["Final_time"] = t_final
    convergence_synthesis["Final_time_step"] = ndt_final
    convergence_synthesis["Scheme_order"] = min(-au, -ap)
    convergence_synthesis["Scheme_order_vel"] = -au
    convergence_synthesis["Scheme_order_press"] = -ap
    convergence_synthesis["Scaling_preconditioner"] = scaling
    convergence_synthesis["Condition_numbers"] = cond_number
    convergence_synthesis["Test_color"] = testColor
    convergence_synthesis["Computational_time"] = end - start

    with open('Convergence_WaveSystem_2DFV_Centered_' + mesh_name + '.json',
              'w') as outfile:
        json.dump(convergence_synthesis, outfile)
    for i in range(len(values)-1):
        matrices[i] = M.deepCopy()        
        for j in range(len(values)):
            matrices[i][j,i] = values[j]

    result = cdmath.Vector(len(values)-1)    
    for i in range(len(values)-1):
        result[i] = matrices[i].determinant()

    return result


#Chargement du maillage triangulaire du carré unité
#=======================================================================================
meshName="squareWithTriangles"
my_mesh = cdmath.Mesh(meshName+".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()

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)
Exemple #17
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 carré unité [0,1]x[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((x*x-y*y)/(2*x*y))
        if x<-eps or x>1+eps or y<-eps or y>1+eps :
            print("!!! Warning Mesh ", meshName," !!! Node is not in the unit square.",", eps=",eps, ", x= ",x, ", y= ",y)
            #raise ValueError("!!! Domain should be the unit square.")
        if abs(x*y) > eps :
            my_ExactSol[i] = atan((x*x-y*y)/(2*x*y))
        elif x**2-y**2>0 :
            my_ExactSol[i] = pi/2
        elif x**2-y**2<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_SQUARE_"+meshName+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
    #===========================================================
    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,0,0],[1,1,0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoissonStiffBC_SQUARE_"+meshName+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoissonStiffBC_SQUARE_"+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_'+"SQUARE_"+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
def test_validation2DVF_long_rectangles():
    start = time.time()
    ### 2D FV long rectangles mesh
    meshList=[5,11,21,31]
    #meshList=['squareWithFlatTriangles_0','squareWithLongRectangles_1','squareWithLongRectangles_2','squareWithLongRectangles_3','squareWithLongRectangles_4','squareWithLongRectangles_5']
    mesh_path='../../../ressources/2DLongRectangles/'
    meshType="Regular_long_rectangles"
    testColor="Green"
    nbMeshes=len(meshList)
    error_tab=[0]*nbMeshes
    mesh_size_tab=[0]*nbMeshes
    mesh_name='squareWithLongRectangles'
    diag_data=[0]*nbMeshes
    time_tab=[0]*nbMeshes
    resolution=100
    curv_abs=np.linspace(0,sqrt(2),resolution+1)
    plt.close('all')
    i=0
    # Storing of numerical errors, mesh sizes and diagonal values
    #for filename in meshList:
    for nx in meshList:
        my_mesh=cdmath.Mesh(0,1,nx,0,1,nx*nx)
        error_tab[i], mesh_size_tab[i], diag_data[i], min_sol_num, max_sol_num, time_tab[i] =FiniteVolumes2DPoisson_SQUARE.solve(my_mesh,str(nx)+'x'+str(nx),resolution,meshType,testColor)
#        error_tab[i], mesh_size_tab[i], diag_data[i], min_sol_num, max_sol_num, time_tab[i] =FiniteVolumes2DPoisson_SQUARE.solve_file(mesh_path+filename,resolution,meshType,testColor)
        assert min_sol_num>-0.01 
        assert max_sol_num<1.2
        plt.plot(curv_abs, diag_data[i], label= str(mesh_size_tab[i]) + ' cells')
        error_tab[i]=log10(error_tab[i])
        time_tab[i]=log10(time_tab[i])
        mesh_size_tab[i] = 0.5*log10(mesh_size_tab[i])
        i=i+1
        
    end = time.time()

    # Plot over diagonal line
    plt.legend()
    plt.xlabel('Position on diagonal line')
    plt.ylabel('Value on diagonal line')
    plt.title('Plot over diagonal line for finite volumes \n for Laplace operator on 2D long rectangles meshes')
    plt.savefig(mesh_name+"_2DPoissonFV_PlotOverDiagonalLine.png")

    # Least square linear regression
    # Find the best a,b such that f(x)=ax+b best approximates the convergence curve
    # The vector X=(a,b) solves a symmetric linear system AX=B with A=(a1,a2\\a2,a3), B=(b1,b2)
    a1=np.dot(mesh_size_tab,mesh_size_tab)
    a2=np.sum(mesh_size_tab)
    a3=nbMeshes
    b1=np.dot(error_tab,mesh_size_tab)   
    b2=np.sum(error_tab)
    
    det=a1*a3-a2*a2
    assert det!=0, 'test_validation2DVF_long_rectangles() : Make sure you use distinct meshes and at least two meshes'
    a=( a3*b1-a2*b2)/det
    b=(-a2*b1+a1*b2)/det
    
    print "FV on 2D long rectangles mesh : scheme order is ", -a
    assert abs(a+1.33)<0.1
    
    # Plot of convergence curve
    plt.close()
    plt.plot(mesh_size_tab, error_tab, label='log(|numerical-exact|)')
    plt.plot(mesh_size_tab, a*np.array(mesh_size_tab)+b,label='least square slope : '+'%.3f' % a)
    plt.legend()
    plt.plot(mesh_size_tab, error_tab)
    plt.xlabel('log(sqrt(number of cells))')
    plt.ylabel('log(error)')
    plt.title('Convergence of finite volumes for \n Laplace operator on 2D long rectangles meshes')
    plt.savefig(mesh_name+"_2DPoissonFV_ConvergenceCurve.png")

    # Plot of computational time
    plt.close()
    plt.plot(mesh_size_tab, time_tab, label='log(cpu time)')
    plt.legend()
    plt.xlabel('log(sqrt(number of cells))')
    plt.ylabel('log(cpu time)')
    plt.title('Computational time of finite volumes \n for Laplace operator on 2D long rectangles meshes')
    plt.savefig(mesh_name+"_2DPoissonFV_ComputationalTime.png")
    
    plt.close('all')

    convergence_synthesis["Mesh_names"]=meshList
    convergence_synthesis["Mesh_type"]=meshType
    convergence_synthesis["Mesh_path"]=mesh_path
    convergence_synthesis["Mesh_description"]=mesh_name
    convergence_synthesis["Mesh_sizes"]=[10**x for x in mesh_size_tab]
    convergence_synthesis["Space_dimension"]=2
    convergence_synthesis["Mesh_dimension"]=2
    convergence_synthesis["Mesh_cell_type"]="Long rectangles"
    convergence_synthesis["Errors"]=[10**x for x in error_tab]
    convergence_synthesis["Scheme_order"]=-a
    convergence_synthesis["Test_color"]=testColor
    convergence_synthesis["Computational_time"]=end-start

    with open('Convergence_Poisson_2DVF_'+mesh_name+'.json', 'w') as outfile:  
        json.dump(convergence_synthesis, outfile)

    import os
    os.system("jupyter-nbconvert --to notebook --execute Convergence_Poisson_FV5_SQUARE_long_rectangles.ipynb")
    os.system("jupyter-nbconvert --to html Convergence_Poisson_FV5_SQUARE_long_rectangles.ipynb")
    os.system("jupyter-nbconvert --to pdf Convergence_Poisson_FV5_SQUARE_long_rectangles.ipynb")
Exemple #19
0
# Copyright   : CEA Saclay 2016
# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque
#                Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH
#               Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y)
#================================================================================================================================

import cdmath
from math import sin, pi, sqrt
import numpy as np
import matplotlib.pyplot as plt
import PV_routines
import VTK_routines
import sys

if len(sys.argv) > 1:  #non rectangular mesh
    my_mesh = cdmath.Mesh(sys.argv[1])
else:  #rectangular mesh
    # Création d'un maillage cartésien du domaine carré [0,1]x[0,1], définition des bords
    #====================================================================================
    xmin = 0
    xmax = 1
    ymin = 0
    ymax = 1

    nx = 15
    ny = 15

    my_mesh = cdmath.Mesh(xmin, xmax, nx, ymin, ymax, ny)

    eps = 1e-6
    my_mesh.setGroupAtPlan(0, 0, eps, "DirichletBorder")  #Bord GAUCHE
# Copyright   : CEA Saclay 2018
# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire
#               Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH
#               Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations
#                           on surfaces. SIAM J. Num. Anal., 47, p. 3355
#================================================================================================================================

import cdmath
from math import sin, cos, atan2, sqrt
import PV_routines
import VTK_routines
import paraview.simple as pvs

#Chargement du maillage triangulaire du tore
#=======================================================================================
my_mesh = cdmath.Mesh("meshTorus.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()

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)
def solve_file( filename,meshName, resolution,meshType, testColor,cfl,test_bc,with_source=False):
    my_mesh = cdmath.Mesh(filename+".med")
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("FiniteElementsOnSphere_" + 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(
        "FiniteElementsOnSphere_" + meshType + str(nbNodes) + '_0.vtu',
        "ResultField", 'NODES',
        "FiniteElementsOnSphere_" + meshType + str(nbNodes))
    # save 3D clip
    VTK_routines.Clip_VTK_data_to_VTK(
        "FiniteElementsOnSphere_" + meshType + str(nbNodes) + '_0.vtu',
        "Clip_VTK_data_to_VTK_" + "FiniteElementsOnSphere_" + 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_" + "FiniteElementsOnSphere_" + meshType +
        str(nbNodes) + '_0.vtu', "ResultField", 'NODES',
        "Clip_VTK_data_to_VTK_" + "FiniteElementsOnSphere_" + meshType +
        str(nbNodes))
    # save plot around circumference
    finiteElementsOnSphere_0vtu = pvs.XMLUnstructuredGridReader(FileName=[
        "FiniteElementsOnSphere_" + 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("./FiniteElementsOnSphere" + "_Slice_" + meshType +
                       str(nbNodes) + '.png',
                       magnification=1,
                       quality=100,
                       view=renderView1)
    plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1)
    pvs.SaveData('./FiniteElementsOnSphere_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("./FiniteElementsOnSphere" + "_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
Exemple #23
0
def solve_file(filename, resolution, meshType, testColor):
    my_mesh = cdmath.Mesh(filename + ".med")
    return solve(my_mesh, filename, resolution, meshType, testColor)
Exemple #24
0
    output_freq = 1

    WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,
                 scaling, test_bc, with_source)

    return


def solve_file(filename,
               meshName,
               resolution,
               scaling,
               meshType,
               testColor,
               cfl,
               test_bc,
               with_source=False):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution, scaling, meshType, testColor, cfl, test_bc,
                 with_source)


if __name__ == """__main__""":
    M1 = cdmath.Mesh(0., 1., 50, 0., 1., 50)
    cfl = 0.5
    scaling = 0
    solve(M1, "SquareRegularSquares", 100, scaling, "RegularSquares", "Green",
          cfl, "Periodic", False)
Exemple #25
0
#				Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH
#               Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta)**2*cos(phi)
#================================================================================================================================

import cdmath
from math import sin, cos, pi, sqrt, atan2
import numpy as np
import matplotlib.pyplot as plt
import PV_routines
import VTK_routines

import sys

#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords
#==============================================================================================
my_mesh = cdmath.Mesh("ballWithTetrahedra.med")
if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) :
    raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3")

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)
    test_desc["Relative_error"] = max(error_p, error_u)

    with open(
            'test_WaveSystem' + str(my_mesh.getMeshDimension()) +
            'DCentered_' + meshName + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return error_p, error_u, nbCells, t_final, ndt_final, max_vel, diag_data_press, diag_data_vel, end - start, cond_number


def solve_file(filename, meshName, resolution, scaling, meshType, testColor,
               cfl, test_bc):
    my_mesh = cdmath.Mesh(filename + ".med")

    return solve(my_mesh, meshName + str(my_mesh.getNumberOfCells()),
                 resolution, scaling, meshType, testColor, cfl, test_bc)


if __name__ == """__main__""":
    M1 = cdmath.Mesh(0., 1., 20, 0., 1., 20)
    cfl = 0.5
    scaling = 0
    solve(M1, "SquareRegularSquares", 100, scaling, "Regular_squares", "Green",
          cfl, "Periodic")

    M2 = cdmath.Mesh(0., 1., 10, 0., 1., 10, 0., 1., 10, 6)
    cfl = 1. / 3
    scaling = 2
    solve(M2, "CubeRegularTetrahedra", 100, scaling, "Regular_tetrahedra",
          "Green", cfl, "Wall")
Exemple #27
0
def solve_file( filename,meshName, resolution,scaling, meshType, testColor,cfl):
    my_mesh = cdmath.Mesh(filename+".med")

    return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution,scaling, meshType, testColor,cfl)
import cdmath
import analyticalFunction_discretizer as anSol


def Density(x):
    return x * 2


def Pressure(x):
    return x * 3


var_dict = {
    'Density': Density,
    'Pressure': Pressure,
}

xMin = 0, xMax = 1.0, nx = 100
mesh = cdmath.Mesh(xMin, xMax, nx)
solution = anSol.analyticalFunction_discretizer(mesh,
                                                output_dir="./tmp",
                                                var_dict=var_dict)

print(solution.var_list)
for varName in solution.var_dict:
    print varName + "=", solution.var_eval[varName]

solution.save_all_variables()

print "done"
Exemple #29
0
def solve_file( filename,resolution):
    my_mesh = cdmath.Mesh(filename+".med")
    solve(my_mesh, filename,resolution)
Exemple #30
0
    test_desc["Space_dimension"]=my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"]=my_mesh.getMeshDimension()
    test_desc["Mesh_is_unstructured"]=False
    test_desc["Mesh_cell_type"]="Quadrangles"
    test_desc["Mesh_number_of_elements"]=my_mesh.getNumberOfCells()
    test_desc["Mesh_max_number_of_neighbours"]=2
    test_desc["Geometry"]="Interval"
    test_desc["Boundary_conditions"]=test_bc
    test_desc["Initial_data"]=test_initial_data
    test_desc["Part_of_mesh_convergence_analysis"]=True
    test_desc["Numerical_parameter_cfl"]=cfl
    test_desc["Simulation_parameter_maximum_time_step"]=ntmax
    test_desc["Simulation_parameter_maximum_time"]=tmax
    test_desc["Simulation_output_frequency"]=output_freq
    test_desc["Simulation_final_time_after_run"]=t_final
    test_desc["Simulation_final_number_of_time_steps_after_run"]=ndt_final
    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Part_of_mesh_convergence_analysis"]=True

    with open('test_Transport'+str(my_mesh.getMeshDimension())+'DFV_'+meshName+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)

if __name__ == """__main__""":

    xinf=0
    xsup=1
 
    M=cdmath.Mesh(xinf,xsup,50)

    solve(M,100)