def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc): nbCells = my_mesh.getNumberOfCells() dim=my_mesh.getMeshDimension() nbComp=dim+1 normal=cdmath.Vector(dim) implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) idMoinsJacCL=cdmath.Matrix(nbComp) for j in range(nbCells):#On parcourt les cellules Cj = my_mesh.getCell(j) nbFaces = Cj.getNumberOfFaces(); for k in range(nbFaces) : indexFace = Cj.getFacesId()[k]; Fk = my_mesh.getFace(indexFace); for i in range(dim) : normal[i] = Cj.getNormalVector(k, i);#normale sortante Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure()); cellAutre =-1 if ( not Fk.isBorder()) : # hypothese: La cellule d'index indexC1 est la cellule courante index j */ if (Fk.getCellsId()[0] == j) : # hypothese verifiée cellAutre = Fk.getCellsId()[1]; elif(Fk.getCellsId()[1] == j) : # hypothese non verifiée cellAutre = Fk.getCellsId()[0]; else : raise ValueError("computeFluxes: problem with mesh, unknown cel number") implMat.addValue(j*nbComp,cellAutre*nbComp,Am) implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) else : if( test_bc=="Periodic" and Fk.getGroupName() != "Wall" and Fk.getGroupName() != "Paroi" and Fk.getGroupName() != "Neumann"):#Periodic boundary condition unless Wall/Neumann specified explicitly test_desc["Boundary_conditions"]="Periodic" indexFP = my_mesh.getIndexFacePeriodic(indexFace) Fp = my_mesh.getFace(indexFP) cellAutre = Fp.getCellsId()[0] implMat.addValue(j*nbComp,cellAutre*nbComp,Am) implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) elif( test_bc=="Wall" or Fk.getGroupName() == "Wall" or Fk.getGroupName() == "Paroi"):#Wall boundary condition test_desc["Boundary_conditions"]="Wall" v=cdmath.Vector(dim+1) for i in range(dim) : v[i+1]=normal[i] idMoinsJacCL=v.tensProduct(v)*2 implMat.addValue(j*nbComp,j*nbComp,Am*(-1.)*idMoinsJacCL) elif(test_bc!="Neumann" and Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition print Fk.getGroupName() raise ValueError("computeFluxes: Unknown boundary condition name"); return implMat
def computeStaggeredDivergenceMatrix(a, b, nx, nbVoisinsMax, dt, scaling): nbCells = nx dx = (b - a) / nx dim = 1 nbComp = dim + 1 normal = cdmath.Vector(dim) implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) S1, S2 = staggeredMatrices(dt / dx, scaling) for k in range(nbCells): #On parcourt les cellules if (k == 0): implMat.addValue(k * nbComp, (k + 1) * nbComp, S1) implMat.addValue(k * nbComp, k * nbComp, S1 * (-1.)) elif (k == nbCells - 1): implMat.addValue(k * nbComp, k * nbComp, S2) implMat.addValue(k * nbComp, (k - 1) * nbComp, S2 * (-1.)) else: implMat.addValue(k * nbComp, (k + 1) * nbComp, S1) implMat.addValue(k * nbComp, k * nbComp, S1 * (-1.)) implMat.addValue(k * nbComp, k * nbComp, S2) implMat.addValue(k * nbComp, (k - 1) * nbComp, S2 * (-1.)) return implMat
def computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling): nbCells = nx dx=(b-a)/nx dim=1 nbComp=dim+1 normal=cdmath.Vector(dim) implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) A,absA= jacobianMatrices(dt/dx,scaling) for j in range(nbCells):#On parcourt les cellules if ( j==0) : implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)/2) implMat.addValue(j*nbComp, j*nbComp,(A-absA)/2*(-1.)) elif ( j==nbCells-1) : implMat.addValue(j*nbComp, j*nbComp,(A+absA)/2) implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)/2*(-1.)) else : implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)/2) implMat.addValue(j*nbComp, j*nbComp,(A-absA)/2*(-1.)) implMat.addValue(j*nbComp, j*nbComp,(A+absA)/2) implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)/2*(-1.)) return implMat
def computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, test_bc, velocity): nbCells = my_mesh.getNumberOfCells() dim = my_mesh.getMeshDimension() nbComp = 1 normal = cdmath.Vector(dim) implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) for j in range(nbCells): #On parcourt les cellules Cj = my_mesh.getCell(j) nbFaces = Cj.getNumberOfFaces() for k in range(nbFaces): indexFace = Cj.getFacesId()[k] Fk = my_mesh.getFace(indexFace) for i in range(dim): normal[i] = Cj.getNormalVector(k, i) #normale sortante Am = upwinding_coeff(normal, dt * Fk.getMeasure() / Cj.getMeasure(), velocity) cellAutre = -1 if (not Fk.isBorder()): # hypothese: La cellule d'index indexC1 est la cellule courante index j */ if (Fk.getCellsId()[0] == j): # hypothese verifiée cellAutre = Fk.getCellsId()[1] elif (Fk.getCellsId()[1] == j): # hypothese non verifiée cellAutre = Fk.getCellsId()[0] else: raise ValueError( "computeFluxes: problem with mesh, unknown cel number") implMat.addValue(j * nbComp, cellAutre * nbComp, Am) implMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) else: if ( test_bc == "Periodic" and Fk.getGroupName() != "Neumann" ): #Periodic boundary condition unless Wall/Neumann specified explicitly indexFP = my_mesh.getIndexFacePeriodic( indexFace, my_mesh.getName() == "squareWithBrickWall", my_mesh.getName() == "squareWithHexagons") Fp = my_mesh.getFace(indexFP) cellAutre = Fp.getCellsId()[0] implMat.addValue(j * nbComp, cellAutre * nbComp, Am) implMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) elif (test_bc != "Neumann" and Fk.getGroupName() != "Neumann" ): #Nothing to do for Neumann boundary condition print Fk.getGroupName() raise ValueError( "computeFluxes: Unknown boundary condition name") return implMat
def Flux(U): result = cdmath.Vector(2) result[0] = c0 * c0 * U[1] result[1] = U[0] return result
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
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 jacobianMatrices(normale, coeff, rho_l, q_l, rho_r, q_r): RoeMat = cdmath.Matrix(3, 3) AbsRoeMa = cdmath.Matrix(3, 3) tangent = cdmath.Vector(2) tangent[0] = normale[1] tangent[1] = -normale[0] u_l = q_l / rho_l u_r = q_r / rho_r if rho_l < 0 or rho_r < 0: print "rho_l=", rho_l, " rho_r= ", rho_r raise ValueError("Negative density") u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) un = u * normale RoeMat[0, 0] = 0 RoeMat[0, 1] = normale[0] RoeMat[0, 2] = normale[1] RoeMat[1, 0] = c0 * c0 * normale[0] - un * u[0] RoeMat[2, 0] = c0 * c0 * normale[1] - un * u[1] RoeMat[1, 1] = un + normale[0] * u[0] RoeMat[1, 2] = normale[1] * u[0] RoeMat[2, 2] = un + normale[1] * u[1] RoeMat[2, 1] = normale[0] * u[1] AbsRoeMa[0, 0] = (abs(un - c0) * (un + c0) + abs(un + c0) * (c0 - un)) / (2 * c0) AbsRoeMa[0, 1] = (abs(un + c0) - abs(un - c0)) / (2 * c0) * normale[0] AbsRoeMa[0, 2] = (abs(un + c0) - abs(un - c0)) / (2 * c0) * normale[1] AbsRoeMa[1, 0] = (abs(un - c0) * (un + c0) * (u[0] - c0 * normale[0]) - abs(un + c0) * (un - c0) * (u[0] + c0 * normale[0])) / (2 * c0) - abs(un) * ( u * tangent) * tangent[0] AbsRoeMa[2, 0] = (abs(un - c0) * (un + c0) * (u[1] - c0 * normale[1]) - abs(un + c0) * (un - c0) * (u[1] + c0 * normale[1])) / (2 * c0) - abs(un) * ( u * tangent) * tangent[1] #subMatrix=(abs(un+c0)*((u-c0*normale)^normale)-abs(un-c0)*((u-c0*normale)^normale))/(2*c0)+abs(un)*(tangent^tangent); AbsRoeMa[1, 1] = (abs(un + c0) * ((u[0] - c0 * normale[0]) * normale[0]) - abs(un - c0) * ((u[0] - c0 * normale[0]) * normale[0])) / ( 2 * c0) + abs(un) * (tangent[0] * tangent[0]) #subMatrix[0,0]; AbsRoeMa[1, 2] = (abs(un + c0) * ((u[0] - c0 * normale[0]) * normale[1]) - abs(un - c0) * ((u[0] - c0 * normale[0]) * normale[1])) / ( 2 * c0) + abs(un) * (tangent[0] * tangent[1]) #subMatrix[0,1]; AbsRoeMa[2, 1] = (abs(un + c0) * ((u[1] - c0 * normale[1]) * normale[0]) - abs(un - c0) * ((u[1] - c0 * normale[1]) * normale[0])) / ( 2 * c0) + abs(un) * (tangent[1] * tangent[0]) AbsRoeMa[2, 2] = (abs(un + c0) * ((u[1] - c0 * normale[1]) * normale[1]) - abs(un - c0) * ((u[1] - c0 * normale[1]) * normale[1])) / ( 2 * c0) + abs(un) * (tangent[1] * tangent[1]) return (RoeMat - AbsRoeMa) * coeff / 2, un
def computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling, test_bc): nbCells = my_mesh.getNumberOfCells() dim = my_mesh.getMeshDimension() nbComp = dim + 1 normal = cdmath.Vector(dim) implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) idMoinsJacCL = cdmath.Matrix(nbComp) for j in range(nbCells): #On parcourt les cellules Cj = my_mesh.getCell(j) nbFaces = Cj.getNumberOfFaces() for k in range(nbFaces): indexFace = Cj.getFacesId()[k] Fk = my_mesh.getFace(indexFace) for i in range(dim): normal[i] = Cj.getNormalVector(k, i) #normale sortante Am = jacobianMatrices(normal, dt * Fk.getMeasure() / Cj.getMeasure(), scaling) cellAutre = -1 if (not Fk.isBorder()): # hypothese: La cellule d'index indexC1 est la cellule courante index j */ if (Fk.getCellsId()[0] == j): # hypothese verifiée cellAutre = Fk.getCellsId()[1] elif (Fk.getCellsId()[1] == j): # hypothese non verifiée cellAutre = Fk.getCellsId()[0] else: raise ValueError( "computeFluxes: problem with mesh, unknown cell number" ) implMat.addValue(j * nbComp, cellAutre * nbComp, Am) implMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) else: indexFP = my_mesh.getIndexFacePeriodic( indexFace, my_mesh.getName() == "squareWithBrickWall", my_mesh.getName() == "squareWithHexagons") Fp = my_mesh.getFace(indexFP) cellAutre = Fp.getCellsId()[0] implMat.addValue(j * nbComp, cellAutre * nbComp, Am) implMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) return implMat
def Flux(U, normal): dim=normal.size() result=cdmath.Vector(dim+1) for i in range(dim): result[0] +=normal[i]*U[i+1] result[i+1] =normal[i]*U[0] result[0]=c0*c0*result[0] return result
def gradientNodal(M, values): matrices = [0] * (len(values) - 1) 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
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
def computeFluxes(U, SumFluxes): my_mesh = U.getMesh() nbCells = my_mesh.getNumberOfCells() dim = my_mesh.getMeshDimension() nbComp = U.getNumberOfComponents() Fj = cdmath.Vector(nbComp) Fjp1 = cdmath.Vector(nbComp) Fjm1 = cdmath.Vector(nbComp) Uj = cdmath.Vector(nbComp) Ujp1 = cdmath.Vector(nbComp) Ujm1 = cdmath.Vector(nbComp) normal = cdmath.Vector(dim) sumFluxCourant = cdmath.Vector(nbComp) sumFluxCourant2 = cdmath.Vector(nbComp) A, absA = jacobianMatrices() for j in range(nbCells): #On parcourt les cellules Cj = my_mesh.getCell(j) for i in range(nbComp): Uj[i] = U[j, i] sumFluxCourant[i] = 0 if (j == 0): for i in range(nbComp): Ujp1[i] = U[j + 1, i] Ujm1[i] = U[j, i] elif (j == nbCells - 1): for i in range(nbComp): Ujp1[i] = U[j, i] Ujm1[i] = U[j - 1, i] else: for i in range(nbComp): Ujp1[i] = U[j + 1, i] Ujm1[i] = U[j - 1, i] Fr = numericalFlux(Uj, Ujp1, absA) Fl = numericalFlux(Ujm1, Uj, absA) sumFluxCourant = (Fr - Fl) * 0.5 / Cj.getMeasure() #On divise par le volume de la cellule la contribution des flux au snd membre for i in range(nbComp): SumFluxes[j, i] = sumFluxCourant[i]
def computeFluxes(U, SumFluxes): my_mesh =U.getMesh(); nbCells = my_mesh.getNumberOfCells(); dim=my_mesh.getMeshDimension(); nbComp=U.getNumberOfComponents(); Fj=cdmath.Vector(nbComp) Fjp1=cdmath.Vector(nbComp) Fjm1=cdmath.Vector(nbComp) Uj=cdmath.Vector(nbComp) Ujp1=cdmath.Vector(nbComp) Ujm1=cdmath.Vector(nbComp) normal=cdmath.Vector(dim) sumFluxCourant=cdmath.Vector(nbComp) A, absA=jacobianMatrices(); for j in range(nbCells):#On parcourt les cellules for i in range(nbComp) : Uj[i]=U[j,i]; sumFluxCourant[i]=0; test_desc["Boundary_conditions"]="Neumann" if ( j==0) : for i in range(nbComp) : Ujp1[i]=U[j+1,i]; Ujm1[i]=U[j ,i]; elif ( j==nbCells-1) : for i in range(nbComp) : Ujp1[i]=U[j ,i]; Ujm1[i]=U[j-1,i]; else : for i in range(nbComp) : Ujp1[i]=U[j+1,i]; Ujm1[i]=U[j-1,i]; Fr=numericalFlux(Uj,Ujp1,absA) Fl=numericalFlux(Ujm1,Uj,absA) sumFluxCourant = (Fr - Fl)*0.5/Cj.getMeasure() Fcourant=Flux(Ucourant,normal); Fautre =Flux(Uautre, normal); A, absA=jacobianMatrices( normal); sumFluxCourant = sumFluxCourant + (Fcourant+Fautre +absA*(Ucourant-Uautre))*Fk.getMeasure()*0.5 #On divise par le volume de la cellule la contribution des flux au snd membre for i in range(nbComp): SumFluxes[j,i]=sumFluxCourant[i];
def solve(my_mesh, meshName, resolution, meshType, cfl, test_bc): print "Resolution of the Transport Equation in dimension ", my_mesh.getMeshDimension( ) print "Numerical method : ", "Upwind" print "Initial data : ", "Spherical shock" print "Mesh name : ", meshName, ", ", my_mesh.getNumberOfCells(), " cells" # Problem data tmax = 10000. ntmax = 30000 output_freq = 1000 isImplicit = True dim = my_mesh.getMeshDimension() velocity = cdmath.Vector(dim) for i in range(dim): velocity[i] = 1 nbCells, t_final, ndt_final, max_unknown, diag_data_u = TransportEquationVF( ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, test_bc, velocity, isImplicit) return nbCells, t_final, ndt_final, max_unknown, diag_data_u
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit): dim=my_mesh.getMeshDimension() nbCells = my_mesh.getNumberOfCells() meshName=my_mesh.getName() dt = 0. time = 0. it=0; isStationary=False; nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) # 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_vortex(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") #iteration vectors Un =cdmath.Vector(nbCells*(dim+1)) dUn=cdmath.Vector(nbCells*(dim+1)) 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] #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 divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) if( isImplicit): #Adding the identity matrix on the diagonal divMat.diagonalShift(1)#only after filling all coefficients iterGMRESMax=50 LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU") LS.setComputeConditionNumber() print("Starting computation of the linear wave system with an UPWIND scheme …") print "coucou2" # Starting time loop while (it<ntmax and time <= tmax and not isStationary): if(isImplicit): dUn=Un.deepCopy() LS.setSndMember(Un) Un=LS.solve(); if(not LS.getStatus()): print "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" raise ValueError("Pas de convergence du système linéaire"); dUn-=Un else: dUn=divMat*Un Un-=dUn 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)) 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 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 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"
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
nbInteriorNodes = nbInteriorNodes + 1 maxNbNeighbours = max( 1 + Ni.getNumberOfCells(), maxNbNeighbours ) #true only in 2D, otherwise use function Ni.getNumberOfEdges() print("Right hand side discretisation done") print("Number of interior nodes=", nbInteriorNodes) print("Number of boundary nodes=", nbBoundaryNodes) print("Maximum 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 max 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)
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
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, scaling, test_bc, with_source=False): dim = my_mesh.getMeshDimension() nbCells = my_mesh.getNumberOfCells() dt = 0. time = 0. it = 0 isStationary = False nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS) isImplicit = scaling > 0 #iteration vectors Un = cdmath.Vector(nbCells * (dim + 1)) dUn = cdmath.Vector(nbCells * (dim + 1)) # Initial conditions # print("Construction of the initial condition …") if (with_source): #Trivial initial datum if (meshName.find("square") == -1 and meshName.find("Square") == -1): raise ValueError( "Mesh name should contain substring square to use wave system with 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) else: #The initial datum is a stationary field if (meshName.find("square") > -1 or meshName.find("Square") > -1 or meshName.find("cube") > -1 or meshName.find("Cube") > -1): pressure_field, velocity_field = initial_conditions_square_vortex( my_mesh) stat_pressure, stat_velocity = initial_conditions_square_vortex( my_mesh) elif (meshName.find("disk") > -1 or meshName.find("Disk") > -1): pressure_field, velocity_field = initial_conditions_disk_vortex( my_mesh) stat_pressure, stat_velocity = initial_conditions_disk_vortex( my_mesh) else: print("Mesh name : ", meshName) raise ValueError( "Mesh name should contain substring square, cube or disk") S = cdmath.Vector(nbCells * (dim + 1)) #source term is zero 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) + "DUpwind" + meshName + "_pressure") velocity_field.setTime(time, it) velocity_field.writeVTK("WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure_initial") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DUpwind" + 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 if (with_source): for j in range(nbCells): for i in range(dim): divMat.addValue(j * (dim + 1) + 1 + i, j * (dim + 1) + 1 + i, dt) if (isImplicit): #Adding the identity matrix on the diagonal if (scaling == 0 or scaling == 2): divMat.diagonalShift(1) #only after filling all coefficients #for j in range(nbCells*(dim+1)): # divMat.addValue(j,j,1) 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) iterGMRESMax = 50 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 an Upwind scheme …" ) # Starting time loop while (it < ntmax and time <= tmax and not isStationary): if (isImplicit): 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 ", LS.getNumberOfIter(), " 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"]) else: dUn = divMat * Un - S * dt Un -= dUn maxVector = dUn.maxVector(dim + 1) if (with_source): isStationary = maxVector[0] < precision and maxVector[ 1] / rho0 < precision and maxVector[2] / rho0 < precision else: isStationary = maxVector[0] / p0 < 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) if (with_source): print("Variation temporelle relative : pressure ", maxVector[0], ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[2] / rho0) else: print("Variation temporelle relative : pressure ", maxVector[0] / p0, ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[2] / rho0) if (isImplicit): 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) + "DUpwind" + meshName + "_pressure", False) velocity_field.setTime(time, it) velocity_field.writeVTK( "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity", False) if (with_source): print("Ecart au stationnaire exact : error_p= ", delta_press, " error_||u||= ", delta_v.maxVector()[0]) else: print("Ecart au stationnaire exact : error_p= ", delta_press / p0, " error_||u||= ", delta_v.maxVector()[0]) print print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) if (with_source): print("Variation temporelle relative : pressure ", maxVector[0], ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[2] / rho0) else: 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") 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) if (not with_source): print("Mass loss: ", (total_pressure_initial - pressure_field.integral()).norm() / p0, " precision required= ", precision) print("Momentum loss: ", (total_velocity_initial - velocity_field.integral()).norm() / velocity_field.normL1().norm(), " precision required= ", precision) assert (total_pressure_initial - pressure_field.integral()).norm() / p0 < precision if (test_bc == "Periodic"): assert (total_velocity_initial - velocity_field.integral()).norm() < 2 * precision print( "------------------------------------------------------------------------------------" ) 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 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) + "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") if (not with_source): return delta_press / p0, delta_v.maxVector( )[0], nbCells, time, it, velocity_field.getNormEuclidean().max( ), diag_data_press, diag_data_vel else: return delta_press, delta_v.maxVector( )[0], nbCells, time, it, velocity_field.getNormEuclidean().max( ), diag_data_press, diag_data_vel else: print("Temps maximum Tmax= ", tmax, " atteint") raise ValueError( "Maximum time reached : Stationary state not found !!!!!!!")
raise ValueError("Mesh should not contain borders") else: maxNbNeighbours = max( 1 + Ni.getNumberOfCells(), maxNbNeighbours ) #true only for planar cells, otherwise use function Ni.getNumberOfEdges() 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é
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
def computeFluxes(U, SumFluxes): my_mesh =U.getMesh(); nbCells = my_mesh.getNumberOfCells(); dim=my_mesh.getMeshDimension(); nbComp=U.getNumberOfComponents(); Fcourant=cdmath.Vector(nbComp) Fautre=cdmath.Vector(nbComp) Ucourant=cdmath.Vector(nbComp) Uautre=cdmath.Vector(nbComp) normal=cdmath.Vector(dim) sumFluxCourant=cdmath.Vector(nbComp) for j in range(nbCells):#On parcourt les cellules Cj = my_mesh.getCell(j) nbFaces = Cj.getNumberOfFaces(); for i in range(nbComp) : Ucourant[i]=U[j,i]; sumFluxCourant[i]=0; for k in range(nbFaces) : indexFace = Cj.getFacesId()[k]; Fk = my_mesh.getFace(indexFace); for i in range(dim) : normal[i] = Cj.getNormalVector(k, i);#normale sortante cellAutre = -1; if ( not Fk.isBorder()) : # hypothese: La cellule d'index indexC1 est la cellule courante index j */ if (Fk.getCellsId()[0] == j) : # hypothese verifiée cellAutre = Fk.getCellsId()[1]; elif(Fk.getCellsId()[1] == j) : # hypothese non verifiée cellAutre = Fk.getCellsId()[0]; else : raise ValueError("computeFluxes: problem with mesh, unknown cel number"); for i in range(nbComp): Uautre[i]=U[cellAutre,i] else : if(Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Wall/Neumann specified explicitly for i in range(nbComp): Uautre[i]=Ucourant[i] qn=0# normal momentum for i in range(dim): qn+=Ucourant[i+1]*normal[i] for i in range(dim): Uautre[i+1]-=2*qn*normal[i] elif(Fk.getGroupName() == "Neumann"): for i in range(nbComp): Uautre[i]=Ucourant[i] else: print Fk.getGroupName() raise ValueError("computeFluxes: Unknown boundary condition name"); Fcourant=Flux(Ucourant,normal); Fautre =Flux(Uautre, normal); A, absA=jacobianMatrices( normal); sumFluxCourant = sumFluxCourant + (Fcourant+Fautre +absA*(Ucourant-Uautre))*Fk.getMeasure()*0.5 #On divise par le volume de la cellule la contribution des flux au snd membre for i in range(nbComp): SumFluxes[j,i]=sumFluxCourant[i]/Cj.getMeasure()
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 WaveSystemStaggered(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 data …") pressure_field, velocity_field = initial_conditions_wave_system_staggered( my_mesh) initial_pressure, initial_velocity = initial_conditions_wave_system_staggered( my_mesh) for k in range(nbCells): Un[k + 0 * nbCells] = initial_pressure[k] Un[k + 1 * nbCells] = rho0 * initial_velocity[k, 0] # value on the left face Un[k + 2 * nbCells] = rho0 * initial_velocity[k, 1] # value on the bottom face if (dim == 3): Un[k + 3 * nbCells] = rho0 * initial_velocity[k, 2] if (scaling > 0): Vn = Un.deepCopy() for k in range(nbCells): Vn[k] = Vn[k] / c0 #sauvegarde de la donnée initiale pressure_field.setTime(time, it) pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure") velocity_field.setTime(time, it) velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_initial") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + 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) if (scaling == 0): LS = cdmath.LinearSolver(divMat, Un, iterGMRESMax, precision, "GMRES", "ILU") else: LS = cdmath.LinearSolver(divMat, Vn, 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 pseudo staggered scheme …" ) # Starting time loop while (it < ntmax and time <= tmax and not isStationary): dUn = Un.deepCopy() if (scaling == 0): LS.setSndMember(Un) Un = LS.solve() else: #( scaling > 0) LS.setSndMember(Vn) Vn = LS.solve() Un = Vn.deepCopy() for k in range(nbCells): Un[k] = c0 * Vn[k] 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"]) max_dp = 0 max_dq = 0 for k in range(nbCells): max_dp = max(max_dp, abs(dUn[k])) for i in range(dim): max_dq = max(max_dq, abs(dUn[k + (1 + i) * nbCells])) isStationary = max_dp / p0 < precision and max_dq / rho0 < precision 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 ", max_dp / p0, ", velocity ", max_dq / 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] velocity_field[k, 0] = Un[k + 1 * nbCells] / rho0 if (dim > 1): velocity_field[k, 1] = Un[k + 2 * nbCells] / rho0 if (dim > 2): velocity_field[k, 2] = Un[k + 3 * nbCells] / rho0 if (abs(initial_pressure[k] - pressure_field[k]) > delta_press): delta_press = abs(initial_pressure[k] - pressure_field[k]) if (abs(initial_velocity[k, 0] - velocity_field[k, 0]) > delta_v[0]): delta_v[0] = abs(initial_velocity[k, 0] - velocity_field[k, 0]) if (abs(initial_velocity[k, 1] - velocity_field[k, 1]) > delta_v[1]): delta_v[1] = abs(initial_velocity[k, 1] - velocity_field[k, 1]) if (dim == 3): if (abs(initial_velocity[k, 2] - velocity_field[k, 2]) > delta_v[2]): delta_v[2] = abs(initial_velocity[k, 2] - velocity_field[k, 2]) pressure_field.setTime(time, it) pressure_field.writeVTK( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure", False) velocity_field.setTime(time, it) velocity_field.writeVTK( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity", False) print "Ecart au stationnaire exact : error_p= ", delta_press / p0, " error_||u||= ", delta_v.maxVector( )[0] print print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / 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 "Mass loss: ", (total_pressure_initial - pressure_field.integral() ).norm() / p0, " precision required= ", precision print "Momentum loss: ", ( total_velocity_initial - velocity_field.integral()).norm() / velocity_field.normL1().norm( ), " precision required= ", precision assert (total_pressure_initial - pressure_field.integral()).norm() / p0 < precision if (test_bc == "Periodic"): assert (total_velocity_initial - velocity_field.integral()).norm() < 2 * precision print "------------------------------------------------------------------------------------" pressure_field.setTime(time, 0) pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_Stat") velocity_field.setTime(time, 0) velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + 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) + "DStaggered" + meshName + "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_Stat") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_Stat" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_Stat") return delta_press / p0, 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 !!!!!!!")
def WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution): dim = my_mesh.getMeshDimension() nbCells = my_mesh.getNumberOfCells() dt = 0. time = 0. it = 0 isStationary = False scaling = 0 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 …") pressure_field, velocity_field = initial_conditions_wave_system(my_mesh) for k in range(nbCells): Un[k + 0 * nbCells] = pressure_field[k] Un[k + 1 * nbCells] = rho0 * velocity_field[k, 0] # value on the left face Un[k + 2 * nbCells] = rho0 * velocity_field[k, 1] # value on the bottom face if (dim == 3): Un[k + 3 * nbCells] = rho0 * initial_velocity[k, 2] if (scaling > 0): Vn = Un.deepCopy() for k in range(nbCells): Vn[k] = Vn[k] / c0 #sauvegarde de la donnée initiale pressure_field.setTime(time, it) pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure") velocity_field.setTime(time, it) velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_initial") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_initial") dx_min = my_mesh.minRatioVolSurf() dt = cfl * dx_min / c0 divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling) # Add the identity matrix on the diagonal for j in range(nbCells * (dim + 1)): divMat.addValue(j, j, 1.) LS = cdmath.LinearSolver(divMat, Un, iterGMRESMax, precision, "GMRES", "LU") print( "Starting computation of the linear wave system with an pseudo staggered scheme …" ) # Starting time loop while (it < ntmax and time <= tmax and not isStationary): dUn = Un.deepCopy() LS.setSndMember(Un) Un = LS.solve() cvgceLS = LS.getStatus() iterGMRES = LS.getNumberOfIter() if (not cvgceLS): print "Linear system did not converge ", iterGMRES, " GMRES iterations" raise ValueError("Pas de convergence du système linéaire") dUn -= Un max_dp = 0 max_dq = 0 for k in range(nbCells): max_dp = max(max_dp, abs(dUn[k])) for i in range(dim): max_dq = max(max_dq, abs(dUn[k + (1 + i) * nbCells])) isStationary = max_dp / p0 < precision and max_dq / rho0 < precision 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 ", max_dp / p0, ", velocity ", max_dq / rho0 print "Linear system converged in ", iterGMRES, " GMRES iterations" for k in range(nbCells): pressure_field[k] = Un[k] velocity_field[k, 0] = Un[k + 1 * nbCells] / rho0 if (dim > 1): velocity_field[k, 1] = Un[k + 2 * nbCells] / rho0 if (dim > 2): velocity_field[k, 2] = Un[k + 3 * nbCells] / rho0 pressure_field.setTime(time, it) pressure_field.writeVTK( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure", False) velocity_field.setTime(time, it) velocity_field.writeVTK( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity", False) print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / 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 print "------------------------------------------------------------------------------------" pressure_field.setTime(time, 0) pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_Stat") velocity_field.setTime(time, 0) velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_Stat") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure_Stat") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_Stat" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity_Stat") else: print "Temps maximum Tmax= ", tmax, " atteint"
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 stiff source term" ) else: S, stat_pressure, stat_momentum = source_term_and_stat_solution_wave_system( my_mesh) pressure_field = stat_pressure.deepCopy() momentum_field = stat_momentum.deepCopy() for k in range(nbCells): Un[k * (dim + 1) + 0] = pressure_field[k] Un[k * (dim + 1) + 1] = momentum_field[k, 0] Un[k * (dim + 1) + 2] = momentum_field[k, 1] if (dim == 3): Un[k * (dim + 1) + 3] = momentum_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) + "DPStag" + meshName + "_pressure") momentum_field.setTime(time, it) momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_initial") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum" + '_0.vtu', "Momentum", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_initial") total_pressure_initial = pressure_field.integral( ) #For conservation test later total_momentum_initial = momentum_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 pseudo staggered 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_q = cdmath.Vector(dim) for k in range(nbCells): pressure_field[k] = Un[k * (dim + 1) + 0] momentum_field[k, 0] = Un[k * (dim + 1) + 1] / rho0 if (dim > 1): momentum_field[k, 1] = Un[k * (dim + 1) + 2] / rho0 if (dim > 2): momentum_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_momentum[k, 0] - momentum_field[k, 0]) > delta_q[0]): delta_q[0] = abs(stat_momentum[k, 0] - momentum_field[k, 0]) if (abs(stat_momentum[k, 1] - momentum_field[k, 1]) > delta_q[1]): delta_q[1] = abs(stat_momentum[k, 1] - momentum_field[k, 1]) if (dim == 3): if (abs(stat_momentum[k, 2] - momentum_field[k, 2]) > delta_q[2]): delta_q[2] = abs(stat_momentum[k, 2] - momentum_field[k, 2]) pressure_field.setTime(time, it) pressure_field.writeVTK( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure", False) momentum_field.setTime(time, it) momentum_field.writeVTK( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum", False) print "Ecart au stationnaire exact : error_p= ", delta_press, " error_||q||= ", delta_q.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) + "DPStag" + meshName + "_pressure_Stat") momentum_field.setTime(time, 0) momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_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( momentum_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( momentum_field, [0, 0, 0], [1, 1, 1], resolution) #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat" + '_0.vtu', "Momentum", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat") return delta_press, delta_q.maxVector( )[0], nbCells, time, it, momentum_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 !!!!!!!")
def solve(nx,cfl,a,b, isSmooth): start = time.time() print "Transport equation, implicit scheme, nx= ", nx, " cfl= ", cfl ##################### Simulation parameters dx = (b - a) / nx #space step c = 0.25 # advection velocity tmax = (b-a)/c # runs the simulation for 0 <= t <= tMax dt = cfl * dx / c ntmax = ceil(tmax/dt) if(cfl>nx): raise("Impossible to run this simulation with cfl>nx. Choose another value for nx or cfl.") x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) ########################## Initial data if(isSmooth): print "Smooth initial data" u_initial = [ 0.5*(1+sin(2*pi*xi-pi*.5)) for xi in x];# to be used with a=0, b=1 u = [ 0.5*(1+sin(2*pi*xi-pi*.5)) for xi in x];# to be used with a=0, b=1 else: print "Stiff initial data" u_initial = [ int(1./3<xi)*int(xi<2./3) for xi in x];# to be used with a=0, b=1 u = [ int(1./3<xi)*int(xi<2./3) for xi in x];# to be used with a=0, b=1 max_initial=max(u_initial) min_initial=min(u_initial) total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)]) Time = 0. it = 0 output_freq = 50 #Linear system initialisation systemMat=centeredSchemeMatrix(nx,cfl) iterGMRESMax=50 precision=1.e-5 Un =cdmath.Vector(nx) for i in range(nx): Un[i]=u[i] LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU") ########################### Postprocessing initialisation # Picture frame plt.legend() plt.xlabel('x') plt.ylabel('u') plt.xlim(a,b) plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) ) plt.title('Centered implicit scheme for transport equation') line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma print("Starting time loop") print("-- Iter: " + str(it) + ", Time: " + str(Time) + ", dt: " + str(dt)) np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n") plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") ############################# Time loop while (it < ntmax and Time <= tmax): # Solve linear system for i in range(nx): Un[i]=u[i] LS.setSndMember(Un) Un=LS.solve() if(not LS.getStatus()): print "Linear system did not converge ", iterGMRES, " GMRES iterations" raise ValueError("Pas de convergence du système linéaire"); for i in range(nx): u[i]=Un[i] if ( max(u) > max_initial ): print "-- Iter: " + str(it) + " max principle violated : max(t) > max(0) : max(t)= ",max(u), " max(0)= ", max_initial if ( min(u) < min_initial ): print "-- Iter: " + str(it) + " min principle violated : min(t) < min(0) : min(t)= ",min(u), " min(0)= ", min_initial if ( np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) > total_var_initial ): print "-- Iter: " + str(it) + " total variation increased : var(t) > var(0) : var(t)= ", np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), " var(0)= ", total_var_initial Time += dt it += 1 # Postprocessing line1.set_ydata(u) if (it % output_freq == 0): print("-- Iter: " + str(it) + ", Time: " + str(Time) + ", dt: " + str(dt)) np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") #plt.show() pass pass print "Exact solution minimum : ", min(u_initial), "Numerical solution minimum : ", min(u) print "Exact solution maximum : ", max(u_initial), "Numerical solution maximum : ", max(u) print "Exact solution variation : ", np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)]), "Numerical solution variation : ", np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) print "l1 numerical error : ", dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)]) print("Simulation of transport equation with an implicit centered scheme done.") end = time.time() #return min, max, sol, total variation, l1 error and elapsed time return min(u), max(u), u, np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)]), end-start
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
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) # Construction de la matrice et du vecteur second membre du système linéaire #=========================================================================== Rigidite = cdmath.SparseMatrixPetsc( nbCells, nbCells, maxNbNeighbours ) # warning : third argument is max 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