From: michael Date: Mon, 13 Sep 2021 11:47:45 +0000 (+0200) Subject: Restructured example folder X-Git-Tag: V9_8_0~91 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=525f44dcc48adfb8bced4d34ba3db1f58a553436;p=tools%2Fsolverlab.git Restructured example folder --- diff --git a/CDMATH/tests/CMakeLists.txt b/CDMATH/tests/CMakeLists.txt index 8a98ca6..dc2db80 100755 --- a/CDMATH/tests/CMakeLists.txt +++ b/CDMATH/tests/CMakeLists.txt @@ -52,14 +52,14 @@ IF (CDMATH_WITH_TESTS) ENDIF (CDMATH_WITH_TESTS) ADD_SUBDIRECTORY(ressources) +SET(MED_MESHES ${CMAKE_CURRENT_SOURCE_DIR}/ressources ) FILE(COPY doc/ DESTINATION share/doc/) if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - # Examples tests - set (examples_dir ${CDMATH_SOURCE_DIR}/tests/examples) - add_subdirectory (${examples_dir}) - add_subdirectory (validation) + + add_subdirectory (examples) #basic test that run a single calculation + add_subdirectory (validation) # convergence studies (several runs) add_custom_target (tests_CDMATH COMMAND ctest -O testsCDMATH.log) add_custom_target (check COMMAND ctest -E 'validation|Example')# may be replace ctest -E with ctest -LE diff --git a/CDMATH/tests/examples/BurgersEquation1D/CMakeLists.txt b/CDMATH/tests/examples/BurgersEquation1D/CMakeLists.txt index 69df6ba..f20907b 100755 --- a/CDMATH/tests/examples/BurgersEquation1D/CMakeLists.txt +++ b/CDMATH/tests/examples/BurgersEquation1D/CMakeLists.txt @@ -1,3 +1,8 @@ +file(GLOB BurgersEquation_EXAMPLES_TO_INSTALL + BurgersEquation1D # 1D Burgers' equation +) + +install(DIRECTORY ${BurgersEquation_EXAMPLES_TO_INSTALL} DESTINATION share/examples/BurgersEquation) if (CDMATH_WITH_PYTHON ) diff --git a/CDMATH/tests/examples/EulerEquations/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/CMakeLists.txt new file mode 100644 index 0000000..6e94c5f --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/CMakeLists.txt @@ -0,0 +1,3 @@ + + ADD_SUBDIRECTORY(IsentropicEulerSystem) + ADD_SUBDIRECTORY( FullEulerSystem) diff --git a/CDMATH/tests/examples/EulerEquations/FullEulerSystem/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/CMakeLists.txt new file mode 100755 index 0000000..cb95639 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/CMakeLists.txt @@ -0,0 +1,12 @@ +file(GLOB FullEulerEquations_EXAMPLES_TO_INSTALL +EulerSystem1D/EulerSystem1DUpwind EulerSystem1D/EulerSystem1DUpwindEntrCorr EulerSystem1D/EulerSystem1DConservativeStaggered EulerSystem_Shock/EulerSystemStaggered EulerSystem_Shock/EulerSystemUpwind +) + +install(DIRECTORY ${FullEulerEquations_EXAMPLES_TO_INSTALL} DESTINATION share/examples/EulerEquations/FullEulerEquations) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + ADD_SUBDIRECTORY(EulerSystem1D_RiemannProblem) + ADD_SUBDIRECTORY(EulerSystem1D_HeatedChannel) +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/CMakeLists.txt new file mode 100755 index 0000000..8415053 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleFullEulerSystem_1DHeatedChannel_Roe ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Euler_complet_HeatedChanel.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/Euler_complet_HeatedChanel.py b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/Euler_complet_HeatedChanel.py new file mode 100644 index 0000000..e63c38c --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_HeatedChannel/Euler_complet_HeatedChanel.py @@ -0,0 +1,981 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +""" +Created on Mon Aug 30 2021 +@author: Michael NDJINGA, Katia Ait Ameur, Coraline Mounier + +Euler system with heating source term (phi) in one dimension on regular domain [a,b] +Riemann problemn with ghost cell boundary condition +Left : Inlet boundary condition (velocity and temperature imposed) +Right : Outlet boundary condition (pressure imposed) +Roe scheme +Regular square mesh + +State law Stiffened gaz : p = (gamma - 1) * rho * (e - q) - gamma * p0 +4 choices of parameters gamma and p0 are available : + - Lagrange interpolation (with q=0) + - Hermite interpolation with reference point at 575K (with q=0) + - Hermite interpolation with reference point at 590K (with q=0) + - Hermite interpolation with reference point at 617.94K (saturation at 155 bar) with q=0 + +Linearized enthalpy : h = h_sat + cp * (T - T_sat) +Values for cp and T_sat parameters are taken at the reference point chosen for the state law + +To do correct the computation of the time step : lambda_max (maximum eigenvalue) should be computed first) +""" + +import cdmath +import numpy as np +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from math import sqrt, atan, pi +from numpy import sign + + +#### Initial and boundary condition (T in K, v in m/s, p in Pa) +T_inlet = 565. +v_inlet = 5. +p_outlet = 155.0 * 10**5 + +#initial parameters are determined from boundary conditions +p_0 = p_outlet #initial pressure +v_0 = v_inlet #initial velocity +T_0 = T_inlet #initial temperature +### Heating source term +phi=1.e8 + +## Numerical parameter +precision = 1e-6 + +#state law parameter : can be 'Lagrange', 'Hermite590K', 'Hermite617K', or 'FLICA' +state_law = "Hermite575K" + +def state_law_parameters(state_law): + #state law Stiffened Gaz : p = (gamma - 1) * rho * e - gamma * p0 + global gamma + global p0 + global q + global c0 + global cp + global h_sat + global T_sat + + if state_law == "Lagrange": + # reference values for Lagrange interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + p1 = 153. * 10**5 # value of pressure at inlet of a 900 MWe PWR vessel + rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars + rho1 = 742.36 # value of density at inlet of a 900 MWe PWR vessel (T1 = 565K) + e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars + e1 = 1273.6 * 10**3 # value of internal energy at inlet of a 900 MWe PWR vessel + + gamma = (p1 - p_ref) / (rho1 * e1 - rho_ref *e_ref) + 1. + p0 = - 1. / gamma * ( - (gamma - 1) * rho_ref * e_ref + p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 8950. + h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars + T_sat = 617.94 + + elif state_law == "Hermite617K": + # reference values for Hermite interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 617.94 #Reference temperature for interpolation at 617.94K + rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars + e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 621.43 #sound speed for water at 155 bars and 617.94K + + gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 8950. # value at 155 bar and 617.94K + h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars + T_sat = 617.94 + + elif state_law == 'Hermite590K': + # reference values for Hermite interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 590. #Reference temperature for interpolation at 590K + rho_ref = 688.3 #density of water at 590K and 155 bars + e_ref = 1411.4 * 10**3 #internal energy of water at 590K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 866.29 #sound speed for water at 155 bars and 590K + + gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 5996.8 # value at 155 bar and 590K + h_sat = 1433.9 * 10 ** 3 # saturation enthalpy of water at 155 bars + T_sat = 590. + + elif state_law == 'Hermite575K': + # reference values for Hermite interpolation + p_ref = 155 * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 575 #Reference temperature at inlet in a REP 900 nuclear power plant + #Remaining values determined using iapws python package + rho_ref = 722.66 #density of water at 575K and 155 bars + e_ref = 1326552.66 #internal energy of water at 575K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 959.28 #sound speed for water at 155 bars and 575K + + gamma = 1 + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1 / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))#This is actually c_ref + + cp = 5504.05 # value at 155 bar and 590K + h_sat = h_ref # saturation enthalpy of water at 155 bars + T_sat = T_ref + else: + raise ValueError("Incorrect value for parameter state_law") + +def initial_conditions_Riemann_problem(a, b, nx): + print("Initial data Riemann problem") + dx = (b - a) / nx # space step + x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh) + + p_initial = np.array([ p_0 for xi in x]) + v_initial = np.array([ v_0 for xi in x]) + T_initial = np.array([ T_0 for xi in x]) + + rho_initial = p_to_rho_StiffenedGaz(p_initial, T_initial) + q_initial = rho_initial * v_initial + rho_E_initial = T_to_rhoE_StiffenedGaz(T_initial, rho_initial, q_initial) + + return rho_initial, q_initial, rho_E_initial, p_initial, v_initial, T_initial + +def p_to_rho_StiffenedGaz(p_field, T_field): + rho_field = (p_field + p0) * gamma / (gamma - 1) * 1. / (h_sat + cp * (T_field - T_sat)) + return rho_field + +def T_to_rhoE_StiffenedGaz(T_field, rho_field, q_field): + rho_E_field = 1. / 2. * (q_field) ** 2 / rho_field + p0 + rho_field / gamma * (h_sat + cp * (T_field- T_sat)) + return rho_E_field + +def rhoE_to_T_StiffenedGaz(rho_field, q_field, rho_E_field): + T_field = T_sat + 1 / cp * (gamma * (rho_E_field / rho_field - 1 / 2 * (q_field / rho_field) ** 2) - gamma * p0 / rho_field - h_sat) + return T_field + +def rho_to_p_StiffenedGaz(rho_field, q_field, rho_E_field): + p_field = (gamma - 1) * (rho_E_field - 1. / 2 * q_field ** 2 / rho_field) - gamma * p0 + return p_field + +def T_to_E_StiffenedGaz(p_field, T_field, v_field): + rho_field = p_to_rho_StiffenedGaz(p_field, T_field) + E_field = (p_field + gamma * p0) / ((gamma-1) * rho_field) + 0.5 * v_field **2 + return E_field + +def dp_drho_e_const_StiffenedGaz( e ): + return (gamma-1)*(e-q) + +def dp_de_rho_const_StiffenedGaz( rho ): + return (gamma-1)*rho + +def sound_speed_StiffenedGaz( h ): + return np.sqrt((gamma-1)*(h-q)) + +def rho_h_to_p_StiffenedGaz( rho, h ): + return (gamma - 1) * rho * ( h - q ) / gamma - p0 + +def MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + RoeMat = cdmath.Matrix(3, 3) + + u_l = q_l / rho_l + u_r = q_r / rho_r + p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l) + p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r) + H_l = rho_E_l / rho_l + p_l / rho_l + H_r = rho_E_r / rho_r + p_r / rho_r + + # Roe averages + rho = np.sqrt(rho_l * rho_r) + u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + + p = rho_h_to_p_StiffenedGaz( rho, H - u**2/2. ) + e = H - p / rho - 1./2 * u**2 + dp_drho = dp_drho_e_const_StiffenedGaz( e ) + dp_de = dp_de_rho_const_StiffenedGaz( rho ) + + RoeMat[0, 0] = 0 + RoeMat[0, 1] = 1 + RoeMat[0, 2] = 0 + RoeMat[1, 0] = dp_drho - u ** 2 + dp_de / rho * (u**2/2 - e) + RoeMat[1, 1] = 2 * u - u * dp_de / rho + RoeMat[1, 2] = dp_de / rho + RoeMat[2, 0] = -u * ( -dp_drho + H - dp_de / rho * (u**2/2 - e) ) + RoeMat[2, 1] = H - dp_de / rho * u ** 2 + RoeMat[2, 2] = (dp_de / rho +1) * u + + return(RoeMat) + + +def Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + Droe = cdmath.Matrix(3, 3) + + u_l = q_l / rho_l + u_r = q_r / rho_r + p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l) + p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r) + H_l = rho_E_l / rho_l + p_l / rho_l + H_r = rho_E_r / rho_r + p_r / rho_r + + # Roe averages + rho = np.sqrt(rho_l * rho_r) + u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + + c = sound_speed_StiffenedGaz( H - u**2/2. ) + + lamb = cdmath.Vector(3) + lamb[0] = u-c + lamb[1] = u + lamb[2] = u+c + + r = cdmath.Matrix(3, 3) + r[0,0] = 1. + r[1,0] = u-c + r[2,0] = H-u*c + r[0,1] = 1. + r[1,1] = u + r[2,1] = H-c**2/(gamma-1) + r[0,2] = 1. + r[1,2] = u+c + r[2,2] = H+u*c + + l = cdmath.Matrix(3, 3) + l[0,0] = (1./(2*c**2))*(0.5*(gamma-1)*u**2+u*c) + l[1,0] = (1./(2*c**2))*(-u*(gamma-1)-c) + l[2,0] = (1./(2*c**2))*(gamma-1) + l[0,1] = ((gamma-1)/c**2)*(H-u**2) + l[1,1] = ((gamma-1)/c**2)*u + l[2,1] = -((gamma-1)/c**2) + l[0,2] = (1./(2*c**2))*(0.5*(gamma-1)*u**2-u*c) + l[1,2] = (1./(2*c**2))*(c-u*(gamma-1)) + l[2,2] = (1./(2*c**2))*(gamma-1) + + M1 = cdmath.Matrix(3, 3) #abs(lamb[0])*r[:,0].tensProduct(l[:,0]) + M2 = cdmath.Matrix(3, 3) #abs(lamb[1])*r[:,1].tensProduct(l[:,1]) + M3 = cdmath.Matrix(3, 3) #abs(lamb[2])*r[:,2].tensProduct(l[:,2]) + for i in range(3): + for j in range(3): + M1[i,j] = abs(lamb[0])*r[i,0]*l[j,0] + M2[i,j] = abs(lamb[1])*r[i,1]*l[j,1] + M3[i,j] = abs(lamb[2])*r[i,2]*l[j,2] + + Droe = M1+M2+M3 + + return(Droe) + + +def jacobianMatricesm(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + + if rho_l < 0 or rho_r < 0: + print("rho_l=", rho_l, " rho_r= ", rho_r) + raise ValueError("Negative density") + if rho_E_l < 0 or rho_E_r < 0: + print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r) + raise ValueError("Negative total energy") + + RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + return (RoeMat - Droe) * coeff * 0.5 + + +def jacobianMatricesp(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + if rho_l < 0 or rho_r < 0: + print("rho_l=", rho_l, " rho_r= ", rho_r) + raise ValueError("Negative density") + if rho_E_l < 0 or rho_E_r < 0: + print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r) + raise ValueError("Negative total energy") + + RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + return (RoeMat + Droe) * coeff * 0.5 + + +def FillEdges(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit): + dUi1 = cdmath.Vector(3) + dUi2 = cdmath.Vector(3) + temp1 = cdmath.Vector(3) + temp2 = cdmath.Vector(3) + + if (j == 0): + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + + p_inlet = rho_to_p_StiffenedGaz(Uk[j * nbComp + 0], Uk[j * nbComp + 1], Uk[j * nbComp + 2])# We take p from inside the domain + rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure + #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain + q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet + rho_E_l = T_to_rhoE_StiffenedGaz(T_inlet, rho_l, q_l) #rhoE is obtained using the two boundary conditions v_inlet and e_inlet + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Ap) + + if(isImplicit): + dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp1 = Am * dUi1 + + dUi2[0] = rho_l - Uk[(j ) * nbComp + 0] + dUi2[1] = q_l - Uk[(j ) * nbComp + 1] + dUi2[2] = rho_E_l - Uk[(j ) * nbComp + 2] + temp2 = Ap * dUi2 + else: + dUi2[0] = rho_l + dUi2[1] = q_l + dUi2[2] = rho_E_l + temp2 = Ap * dUi2 + + elif (j == nx - 1): + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain + q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain + rho_E_r = (p_outlet+gamma*p0)/(gamma-1) + 0.5*q_r**2/rho_r # rhoE is obtained using the boundary condition p_outlet + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + + if(isImplicit): + dUi1[0] = rho_r - Uk[j * nbComp + 0] + dUi1[1] = q_r - Uk[j * nbComp + 1] + dUi1[2] = rho_E_r - Uk[j * nbComp + 2] + temp1 = Am * dUi1 + + dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp2 = Ap * dUi2 + else: + dUi1[0] = rho_r + dUi1[1] = q_r + dUi1[2] = rho_E_r + temp1 = Am * dUi1 + + if(isImplicit):#implicit scheme, contribution from the Newton scheme residual + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + else:#explicit scheme, contribution from the boundary data the right hand side + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] + +def FillInnerCell(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit): + + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + + if(isImplicit): + dUi1 = cdmath.Vector(3) + dUi2 = cdmath.Vector(3) + + dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + + dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + + temp1 = Am * dUi1 + temp2 = Ap * dUi2 + + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + else: + Rhs[j * nbComp + 0] = 0 + Rhs[j * nbComp + 1] = 0 + Rhs[j * nbComp + 2] = 0 + +def SetPicture(rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx): + max_initial_rho = max(rho_field_Roe) + min_initial_rho = min(rho_field_Roe) + max_initial_q = max(q_field_Roe) + min_initial_q = min(q_field_Roe) + min_initial_h = min(h_field_Roe) + max_initial_h = max(h_field_Roe) + max_initial_p = max(p_field_Roe) + min_initial_p = min(p_field_Roe) + max_initial_v = max(v_field_Roe) + min_initial_v = min(v_field_Roe) + max_initial_T = max(T_field_Roe) + min_initial_T = min(T_field_Roe) + + fig, ([axDensity, axMomentum, axh],[axPressure, axVitesse, axTemperature]) = plt.subplots(2, 3,sharex=True, figsize=(14,10)) + plt.gcf().subplots_adjust(wspace = 0.5) + + lineDensity_Roe, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field_Roe, label='Roe') + axDensity.set(xlabel='x (m)', ylabel='Densité (kg/m3)') + axDensity.set_xlim(a,b) + axDensity.set_ylim(680, 800) + axDensity.legend() + + lineMomentum_Roe, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field_Roe, label='Roe') + axMomentum.set(xlabel='x (m)', ylabel='Momentum (kg/(m2.s))') + axMomentum.set_xlim(a,b) + axMomentum.set_ylim(3500, 4000) + axMomentum.legend() + + lineh_Roe, = axh.plot([a+0.5*dx + i*dx for i in range(nx)], h_field_Roe, label='Roe') + axh.set(xlabel='x (m)', ylabel='h (J/m3)') + axh.set_xlim(a,b) + axh.set_ylim(1.2 * 10**6, 1.5*10**6) + axh.legend() + + linePressure_Roe, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field_Roe, label='Roe') + axPressure.set(xlabel='x (m)', ylabel='Pression (bar)') + axPressure.set_xlim(a,b) + axPressure.set_ylim(155, 155.5) + axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axPressure.legend() + + lineVitesse_Roe, = axVitesse.plot([a+0.5*dx + i*dx for i in range(nx)], v_field_Roe, label='Roe') + axVitesse.set(xlabel='x (m)', ylabel='Vitesse (m/s)') + axVitesse.set_xlim(a,b) + axVitesse.set_ylim(v_0-1, v_0+1) + axVitesse.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axVitesse.legend() + + lineTemperature_Roe, = axTemperature.plot([a+0.5*dx + i*dx for i in range(nx)], T_field_Roe, label='Roe') + axTemperature.set(xlabel='x (m)', ylabel='Température (K)') + axTemperature.set_xlim(a,b) + axTemperature.set_ylim(T_0-10, T_0+30) + axTemperature.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axTemperature.legend() + + return(fig, lineDensity_Roe, lineMomentum_Roe, lineh_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe) + + +def EulerSystemRoe(ntmax, tmax, cfl, a, b, nbCells, output_freq, meshName, state_law, isImplicit): + state_law_parameters(state_law) + dim = 1 + nbComp = 3 + dt = 0. + time = 0. + it = 0 + isStationary = False + dx = (b - a) / nx + dt = cfl * dx / c0 + #dt = 5*10**(-6) + nbVoisinsMax = 2 + + # iteration vectors + Un_Roe = cdmath.Vector(nbCells * (nbComp)) + dUn_Roe = cdmath.Vector(nbCells * (nbComp)) + dUk_Roe = cdmath.Vector(nbCells * (nbComp)) + Rhs_Roe = cdmath.Vector(nbCells * (nbComp)) + + # Initial conditions + print("Construction of the initial condition …") + + rho_field_Roe, q_field_Roe, rho_E_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe = initial_conditions_Riemann_problem(a, b, nx) + h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2 + p_field_Roe = p_field_Roe * 10 ** (-5) + + + for k in range(nbCells): + Un_Roe[k * nbComp + 0] = rho_field_Roe[k] + Un_Roe[k * nbComp + 1] = q_field_Roe[k] + Un_Roe[k * nbComp + 2] = rho_E_field_Roe[k] + + divMat_Roe = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) + + # Picture settings + fig, lineDensity_Roe, lineMomentum_Roe, lineRhoE_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe = SetPicture( rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx) + + plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "0" + ".png") + iterGMRESMax = 50 + newton_max = 100 + + print("Starting computation of the non linear Euler non isentropic system with Roe scheme …") + # STARTING TIME LOOP + while (it < ntmax and time <= tmax and not isStationary): + dUn_Roe = Un_Roe.deepCopy() + Uk_Roe = Un_Roe.deepCopy() + residu_Roe = 1. + + k_Roe = 0 + while (k_Roe < newton_max and residu_Roe > precision): + # STARTING NEWTON LOOP + divMat_Roe.zeroEntries() #sets the matrix coefficients to zero + for j in range(nbCells): + + # traitements des bords + if (j == 0): + FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + elif (j == nbCells - 1): + FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + + # traitement des cellules internes + else: + FillInnerCell(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + + Rhs_Roe[j * nbComp + 2] += phi*dt + + if(isImplicit): + #solving the linear system divMat * dUk = Rhs + divMat_Roe.diagonalShift(1.) + LS_Roe = cdmath.LinearSolver(divMat_Roe, Rhs_Roe, iterGMRESMax, precision, "GMRES", "LU") + dUk_Roe = LS_Roe.solve() + vector_residu_Roe = dUk_Roe.maxVector(nbComp) + residu_Roe = max(abs(vector_residu_Roe[0])/rho0, abs(vector_residu_Roe[1])/(rho0*v_0), abs(vector_residu_Roe[2])/rhoE0 ) + else: + dUk_Roe=Rhs_Roe - divMat_Roe*Un_Roe + residu_Roe = 0.#Convergence schéma Newton + + if (isImplicit and (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax)): + print("Residu Newton at iteration ",k_Roe, " : ", residu_Roe) + print("Linear system converged in ", LS_Roe.getNumberOfIter(), " GMRES iterations") + + #updates for Newton loop + Uk_Roe += dUk_Roe + k_Roe = k_Roe + 1 + if (isImplicit and not LS_Roe.getStatus()): + print("Linear system did not converge ", LS_Roe.getNumberOfIter(), " GMRES iterations") + raise ValueError("No convergence of the linear system") + + if k_Roe == newton_max: + raise ValueError("No convergence of Newton Roe Scheme") + + #updating fields + Un_Roe = Uk_Roe.deepCopy() + dUn_Roe -= Un_Roe + + #Testing stationarity + residu_stat = dUn_Roe.maxVector(nbComp)#On prend le max de chaque composante + if (it % output_freq == 0 ): + print("Test de stationarité : Un+1-Un= ", max(abs(residu_stat[0])/rho0, abs(residu_stat[1])/(rho0*v_0), abs(residu_stat[2])/rhoE0 )) + + if ( it>1 and abs(residu_stat[0])/rho0= ntmax or isStationary or time >= tmax): + + print("-- Time step : " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + + print("Temperature gain between inlet and outlet is ", T_field_Roe[nbCells-1]-T_field_Roe[0],"\n") + + plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "Implicit"+str(isImplicit)+ str(it) + '_time' + str(time) + ".png") + + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)+"\n") + + if (it >= ntmax): + print("Maximum number of time steps ntmax= ", ntmax, " reached") + return + + elif (isStationary): + print("Stationary regime reached at time step ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_rho_Stat.txt", rho_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_q_Stat.txt", q_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_rhoE_Stat.txt", rho_E_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_p_Stat.txt", p_field_Roe, delimiter="\n") + plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "Implicit"+str(isImplicit)+"_Stat.png") + return + else: + print("Maximum time Tmax= ", tmax, " reached") + return + + +def solve(a, b, nx, meshName, meshType, cfl, state_law, isImplicit): + print("Simulation of a heated channel in dimension 1 on " + str(nx) + " cells") + print("State Law Stiffened Gaz, " + state_law) + print("Initial data : ", "constant fields") + print("Boundary conditions : ", "Inlet (Left), Outlet (Right)") + print("Mesh name : ", meshName, ", ", nx, " cells") + # Problem data + tmax = 10. + ntmax = 100000 + output_freq = 1000 + EulerSystemRoe(ntmax, tmax, cfl, a, b, nx, output_freq, meshName, state_law, isImplicit) + return + +def FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx): + + if (j == 0): + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + + p_inlet = rho_to_p_StiffenedGaz(Uk[j * nbComp + 0], Uk[j * nbComp + 1], Uk[j * nbComp + 2])# We take p from inside the domain + rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure + #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain + q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet + rho_E_l = T_to_rhoE_StiffenedGaz(T_inlet, rho_l, q_l) #rhoE is obtained using the two boundary conditions v_inlet and e_inlet + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Ap) + + elif (j == nx - 1): + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain + q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain + rho_E_r = (p_outlet+gamma*p0)/(gamma-1) + 0.5*q_r**2/rho_r # rhoE is obtained using the boundary condition p_outlet + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + + +def FillMatrixFromInnerCell(j, Uk, nbComp, divMat, dt, dx): + + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + +def FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit): + dUi1 = cdmath.Vector(3) + dUi2 = cdmath.Vector(3) + temp1 = cdmath.Vector(3) + temp2 = cdmath.Vector(3) + + if (j == 0): + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + p_inlet = rho_to_p_StiffenedGaz(Uk[j * nbComp + 0], Uk[j * nbComp + 1], Uk[j * nbComp + 2])# We take p from inside the domain + rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure + #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain + q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet + rho_E_l = T_to_rhoE_StiffenedGaz(T_inlet, rho_l, q_l) #rhoE is obtained using the two boundary conditions v_inlet and e_inlet + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + if(isImplicit): + dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp1 = Am * dUi1 + + dUi2[0] = rho_l - Uk[(j ) * nbComp + 0] + dUi2[1] = q_l - Uk[(j ) * nbComp + 1] + dUi2[2] = rho_E_l - Uk[(j ) * nbComp + 2] + temp2 = Ap * dUi2 + else: + dUi2[0] = rho_l + dUi2[1] = q_l + dUi2[2] = rho_E_l + temp2 = Ap * dUi2 + + elif (j == nx - 1): + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain + q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain + rho_E_r = (p_outlet+gamma*p0)/(gamma-1) + 0.5*q_r**2/rho_r # rhoE is obtained using the boundary condition p_outlet + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + if(isImplicit): + dUi1[0] = rho_r - Uk[j * nbComp + 0] + dUi1[1] = q_r - Uk[j * nbComp + 1] + dUi1[2] = rho_E_r - Uk[j * nbComp + 2] + temp1 = Am * dUi1 + + dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp2 = Ap * dUi2 + else: + dUi1[0] = rho_r + dUi1[1] = q_r + dUi1[2] = rho_E_r + temp1 = Am * dUi1 + + if(isImplicit): + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + else:#explicit scheme, contribution from the boundary data the right hand side + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] + +def FillRHSFromInnerCell(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit): + + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + if(isImplicit):#Contribution to the right hand side if te scheme is implicit + dUi1 = cdmath.Vector(3) + dUi2 = cdmath.Vector(3) + + dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + + dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + + temp1 = Am * dUi1 + temp2 = Ap * dUi2 + + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + else: + Rhs[j * nbComp + 0] = 0 + Rhs[j * nbComp + 1] = 0 + Rhs[j * nbComp + 2] = 0 + + +def computeSystemMatrix(a,b,nx, cfl, Uk, isImplicit): + dim = 1 + nbComp = 3 + dx = (b - a) / nx + dt = cfl * dx / c0 + nbVoisinsMax = 2 + + nbCells = nx + divMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) + + divMat.zeroEntries() #sets the matrix coefficients to zero + for j in range(nbCells): + + # traitements des bords + if (j == 0): + FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx) + elif (j == nbCells - 1): + FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx) + # traitement des cellules internes + else: + FillMatrixFromInnerCell(j, Uk, nbComp, divMat, dt, dx) + + if(isImplicit): + divMat.diagonalShift(1.) # add one on the diagonal + else: + divMat*=-1. + divMat.diagonalShift(1.) # add one on the diagonal + + return divMat + +def computeRHSVector(a,b,nx, cfl, Uk, Un, isImplicit): + dim = 1 + nbComp = 3 + dx = (b - a) / nx + dt = cfl * dx / c0 + nbVoisinsMax = 2 + + nbCells = nx + Rhs = cdmath.Vector(nbCells * (nbComp)) + + for j in range(nbCells): + + # traitements des bords + if (j == 0): + FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit) + elif (j == nbCells - 1): + FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit) + # traitement des cellules internes + else: + FillRHSFromInnerCell(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit) + + return Rhs + + +if __name__ == """__main__""": + nbComp=3 # number of equations + a = 0.# domain is interval [a,b] + b = 4.2# domain is interval [a,b] + nx = 10# number of cells + dx = (b - a) / nx # space step + x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh) + state_law = "Hermite575K" + state_law_parameters(state_law) + rho0=p_to_rho_StiffenedGaz(p_0, T_0) + rhoE0=T_to_rhoE_StiffenedGaz(T_0, rho0, rho0*v_0) + + +#### initial condition (T in K, v in m/s, p in Pa) + p_initial = np.array([ p_outlet for xi in x]) + v_initial = np.array([ v_inlet for xi in x]) + T_initial = np.array([ T_inlet for xi in x]) + + rho_field = p_to_rho_StiffenedGaz(p_initial, T_initial) + q_field = rho_field * v_initial + rho_E_field = rho_field * T_to_E_StiffenedGaz(p_initial, T_initial, v_initial) + + U = cdmath.Vector(nx * (nbComp))#Inutile à terme mais nécessaire pour le moment + + for k in range(nx): + U[k * nbComp + 0] = rho_field[k] + U[k * nbComp + 1] = q_field[k] + U[k * nbComp + 2] = rho_E_field[k] + print("\n Testing function computeSystemMatrix \n") + cfl = 0.5 + computeSystemMatrix(a, b, nx, cfl, U,True) #Implicit matrix + computeSystemMatrix(a, b, nx, cfl, U,False) #Explicit matrix + + print("\n Testing function computeRHSVector \n") + cfl = 0.5 + computeRHSVector(a, b, nx, cfl, U, U,True) #Implicit RHS + computeRHSVector(a, b, nx, cfl, U, U,False) #Explicit RHS + + print("\n Testing function solve (Implicit scheme) \n") + isImplicit=True + cfl = 1000. + solve(a, b, nx, "RegularSquares", "", cfl, state_law, isImplicit) + + print("\n Testing function solve (Explicit scheme) \n") + isImplicit=False + cfl = 0.5 + solve(a, b, nx, "RegularSquares", "", cfl, state_law, isImplicit) + diff --git a/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/CMakeLists.txt new file mode 100755 index 0000000..895c803 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleFullEulerSystem_1DRiemammProblem_Roe ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Euler_complet_RP.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/Euler_complet_RP.py b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/Euler_complet_RP.py new file mode 100644 index 0000000..8785225 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/FullEulerSystem/EulerSystem1D_RiemannProblem/Euler_complet_RP.py @@ -0,0 +1,642 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +""" +Created on Mon Aug 30 2021 +@author: Michael NDJINGA, Katia Ait Ameur, Coraline Mounier + +Euler system without source term in one dimension on regular domain [a,b] +Riemann problemn with ghost cell boundary condition +Left and right: Neumann boundary condition +Roe scheme +Regular square mesh + +State law Stiffened gaz : p = (gamma - 1) * rho * (e - q) - gamma * p0 +4 choices of parameters gamma and p0 are available : + - Lagrange interpolation (with q=0) + - Hermite interpolation with reference point at 575K (with q=0) + - Hermite interpolation with reference point at 590K (with q=0) + - Hermite interpolation with reference point at 617.94K (saturation at 155 bar) with q=0 + +Linearized enthalpy : h = h_sat + cp * (T - T_sat) +Values for cp and T_sat parameters are taken at the reference point chosen for the state law + +To do correct the computation of the time step : lambda_max (maximum eigenvalue) should be computed first) +""" + +import cdmath +import numpy as np +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from math import sqrt, atan, pi +from numpy import sign + + +## Numerical parameter +precision = 1e-5 + +#state law parameter : can be 'Lagrange', 'Hermite590K', 'Hermite617K', or 'FLICA' +state_law = "Hermite590K" + +#indicates with test case is simulated to compare with FLICA5 results +#num_test = 0 means there are no FLICA5 results given here +num_test = 0 + +#def state_law_parameters(state_law): +#state law Stiffened Gaz : p = (gamma - 1) * rho * e - gamma * p0 +global gamma +global p0 +global q +global c0 +global cp +global h_sat +global T_sat + +if state_law == "Lagrange": + # reference values for Lagrange interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + p1 = 153. * 10**5 # value of pressure at inlet of a 900 MWe PWR vessel + rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars + rho1 = 742.36 # value of density at inlet of a 900 MWe PWR vessel (T1 = 565K) + e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars + e1 = 1273.6 * 10**3 # value of internal energy at inlet of a 900 MWe PWR vessel + + gamma = (p1 - p_ref) / (rho1 * e1 - rho_ref *e_ref) + 1. + p0 = - 1. / gamma * ( - (gamma - 1) * rho_ref * e_ref + p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 8950. + h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars + T_sat = 617.94 + +elif state_law == "Hermite617K": + # reference values for Hermite interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 617.94 #Reference temperature for interpolation at 617.94K + rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars + e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 621.43 #sound speed for water at 155 bars and 617.94K + + gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 8950. # value at 155 bar and 617.94K + h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars + T_sat = 617.94 + +elif state_law == 'Hermite590K': + # reference values for Hermite interpolation + p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 590. #Reference temperature for interpolation at 590K + rho_ref = 688.3 #density of water at 590K and 155 bars + e_ref = 1411.4 * 10**3 #internal energy of water at 590K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 866.29 #sound speed for water at 155 bars and 590K + + gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref)) + + cp = 5996.8 # value at 155 bar and 590K + h_sat = 1433.9 * 10 ** 3 # saturation enthalpy of water at 155 bars + T_sat = 590. + +elif state_law == 'Hermite575K': + # reference values for Hermite interpolation + p_ref = 155 * 10**5 #Reference pressure in a REP 900 nuclear power plant + T_ref = 575 #Reference temperature at inlet in a REP 900 nuclear power plant + #Remaining values determined using iapws python package + rho_ref = 722.66 #density of water at 575K and 155 bars + e_ref = 1326552.66 #internal energy of water at 575K and 155 bars + h_ref = e_ref + p_ref / rho_ref + c_ref = 959.28 #sound speed for water at 155 bars and 575K + + gamma = 1 + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula + p0 = 1 / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) + q=0. + c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))#This is actually c_ref + + cp = 5504.05 # value at 155 bar and 590K + h_sat = h_ref # saturation enthalpy of water at 155 bars + T_sat = T_ref +else: + raise ValueError("Incorrect value for parameter state_law") + + +#initial parameters for Riemann problem (p in Pa, v in m/s, T in K) +p_L = 155. * 10**5 +p_R = 150. * 10**5 +v_L = 0. +v_R = 0. +h_L = 1.4963*10**6 +h_R = 1.4963*10**6 + +T_L = (h_L - h_sat ) / cp + T_sat +T_R = (h_R - h_sat ) / cp + T_sat + +def initial_conditions_Riemann_problem(a, b, nx): + print("Initial data Riemann problem") + dx = (b - a) / nx # space step + x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh) + + p_initial = np.array([ (xi < (a + b) / 2) * p_L + (xi >= (a + b) / 2) * p_R for xi in x]) + v_initial = np.array([ (xi < (a + b) / 2) * v_L + (xi >= (a + b) / 2) * v_R for xi in x]) + T_initial = np.array([ (xi < (a + b) / 2) * T_L + (xi >= (a + b) / 2) * T_R for xi in x]) + + rho_initial = p_to_rho_StiffenedGaz(p_initial, T_initial) + q_initial = rho_initial * v_initial + rho_E_initial = T_to_rhoE_StiffenedGaz(T_initial, rho_initial, q_initial) + + return rho_initial, q_initial, rho_E_initial, p_initial, v_initial, T_initial + +def rho_to_p_StiffenedGaz(rho_field, q_field, rho_E_field): + p_field = (gamma - 1) * ( rho_E_field - 1. / 2 * q_field ** 2 / rho_field - rho_field * q) - gamma * p0 + return p_field + + +def p_to_rho_StiffenedGaz(p_field, T_field): + rho_field = (p_field + p0) * gamma / (gamma - 1) * 1 / (h_sat + cp * (T_field - T_sat) - q) + return rho_field + + +def T_to_rhoE_StiffenedGaz(T_field, rho_field, q_field): + rho_E_field = 1 / 2 * (q_field) ** 2 / rho_field + p0 + rho_field / gamma * (h_sat + cp * (T_field- T_sat) + (gamma - 1) * q) + return rho_E_field + + +def rhoE_to_T_StiffenedGaz(rho_field, q_field, rho_E_field): + T_field = T_sat + 1 / cp * (gamma * (rho_E_field / rho_field - 1 / 2 * (q_field / rho_field) ** 2) - gamma * p0 / rho_field - (gamma - 1) * q - h_sat) + return T_field + +def dp_drho_e_const_StiffenedGaz( e ): + return (gamma-1)*(e-q) + +def dp_de_rho_const_StiffenedGaz( rho ): + return (gamma-1)*rho + +def sound_speed_StiffenedGaz( h ): + return np.sqrt((gamma-1)*(h-q)) + +def rho_h_to_p_StiffenedGaz( rho, h ): + return (gamma - 1) * rho * ( h - q ) / gamma - p0 + +def MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + RoeMat = cdmath.Matrix(3, 3) + + u_l = q_l / rho_l + u_r = q_r / rho_r + p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l) + p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r) + H_l = rho_E_l / rho_l + p_l / rho_l + H_r = rho_E_r / rho_r + p_r / rho_r + + # Roe averages + rho = np.sqrt(rho_l * rho_r) + u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + + p = rho_h_to_p_StiffenedGaz( rho, H - u**2/2. ) + e = H - p / rho - 1./2 * u**2 + dp_drho = dp_drho_e_const_StiffenedGaz( e ) + dp_de = dp_de_rho_const_StiffenedGaz( rho ) + + RoeMat[0, 0] = 0 + RoeMat[0, 1] = 1 + RoeMat[0, 2] = 0 + RoeMat[1, 0] = dp_drho - u ** 2 + dp_de / rho * (u**2/2 - e) + RoeMat[1, 1] = 2 * u - u * dp_de / rho + RoeMat[1, 2] = dp_de / rho + RoeMat[2, 0] = -u * ( -dp_drho + H - dp_de / rho * (u**2/2 - e) ) + RoeMat[2, 1] = H - dp_de / rho * u ** 2 + RoeMat[2, 2] = (dp_de / rho +1) * u + + return(RoeMat) + + +def Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + Droe = cdmath.Matrix(3, 3) + + u_l = q_l / rho_l + u_r = q_r / rho_r + p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l) + p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r) + H_l = rho_E_l / rho_l + p_l / rho_l + H_r = rho_E_r / rho_r + p_r / rho_r + + # Roe averages + rho = np.sqrt(rho_l * rho_r) + u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r)) + + c = sound_speed_StiffenedGaz( H - u**2/2. ) + + lamb = cdmath.Vector(3) + lamb[0] = u-c + lamb[1] = u + lamb[2] = u+c + + r = cdmath.Matrix(3, 3) + r[0,0] = 1. + r[1,0] = u-c + r[2,0] = H-u*c + r[0,1] = 1. + r[1,1] = u + r[2,1] = H-c**2/(gamma-1) + r[0,2] = 1. + r[1,2] = u+c + r[2,2] = H+u*c + + l = cdmath.Matrix(3, 3) + l[0,0] = (1./(2*c**2))*(0.5*(gamma-1)*u**2+u*c) + l[1,0] = (1./(2*c**2))*(-u*(gamma-1)-c) + l[2,0] = (1./(2*c**2))*(gamma-1) + l[0,1] = ((gamma-1)/c**2)*(H-u**2) + l[1,1] = ((gamma-1)/c**2)*u + l[2,1] = -((gamma-1)/c**2) + l[0,2] = (1./(2*c**2))*(0.5*(gamma-1)*u**2-u*c) + l[1,2] = (1./(2*c**2))*(c-u*(gamma-1)) + l[2,2] = (1./(2*c**2))*(gamma-1) + + M1 = cdmath.Matrix(3, 3) #abs(lamb[0])*r[:,0].tensProduct(l[:,0]) + M2 = cdmath.Matrix(3, 3) #abs(lamb[1])*r[:,1].tensProduct(l[:,1]) + M3 = cdmath.Matrix(3, 3) #abs(lamb[2])*r[:,2].tensProduct(l[:,2]) + for i in range(3): + for j in range(3): + M1[i,j] = abs(lamb[0])*r[i,0]*l[j,0] + M2[i,j] = abs(lamb[1])*r[i,1]*l[j,1] + M3[i,j] = abs(lamb[2])*r[i,2]*l[j,2] + + Droe = M1+M2+M3 + + return(Droe) + + +def jacobianMatricesm(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + + if rho_l < 0 or rho_r < 0: + print("rho_l=", rho_l, " rho_r= ", rho_r) + raise ValueError("Negative density") + if rho_E_l < 0 or rho_E_r < 0: + print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r) + raise ValueError("Negative total energy") + + RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + return (RoeMat - Droe) * coeff * 0.5 + + +def jacobianMatricesp(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r): + if rho_l < 0 or rho_r < 0: + print("rho_l=", rho_l, " rho_r= ", rho_r) + raise ValueError("Negative density") + if rho_E_l < 0 or rho_E_r < 0: + print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r) + raise ValueError("Negative total energy") + + RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + return (RoeMat + Droe) * coeff * 0.5 + + +def FillEdges(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit): + dUi = cdmath.Vector(3) + + if (j == 0): + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + + dUi[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp = Am * dUi + + if(isImplicit): + Rhs[j * nbComp + 0] = -temp[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + + elif (j == nx - 1): + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + + dUi[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + + temp = Ap * dUi + + if(isImplicit): + Rhs[j * nbComp + 0] = temp[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = temp[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = temp[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + +def FillInnerCell(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit): + + rho_l = Uk[(j - 1) * nbComp + 0] + q_l = Uk[(j - 1) * nbComp + 1] + rho_E_l = Uk[(j - 1) * nbComp + 2] + rho_r = Uk[j * nbComp + 0] + q_r = Uk[j * nbComp + 1] + rho_E_r = Uk[j * nbComp + 2] + Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + rho_l = Uk[j * nbComp + 0] + q_l = Uk[j * nbComp + 1] + rho_E_l = Uk[j * nbComp + 2] + rho_r = Uk[(j + 1) * nbComp + 0] + q_r = Uk[(j + 1) * nbComp + 1] + rho_E_r = Uk[(j + 1) * nbComp + 2] + Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) + + divMat.addValue(j * nbComp, (j + 1) * nbComp, Am) + divMat.addValue(j * nbComp, j * nbComp, Am * (-1.)) + divMat.addValue(j * nbComp, j * nbComp, Ap) + divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.)) + dUi1 = cdmath.Vector(3) + dUi2 = cdmath.Vector(3) + dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2] + + dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0] + dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1] + dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2] + temp1 = Am * dUi1 + temp2 = Ap * dUi2 + + if(isImplicit): + Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0]) + Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1]) + Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2]) + +def SetPicture(rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx): + max_initial_rho = max(rho_field_Roe) + min_initial_rho = min(rho_field_Roe) + max_initial_q = max(q_field_Roe) + min_initial_q = min(q_field_Roe) + min_initial_h = min(h_field_Roe) + max_initial_h = max(h_field_Roe) + max_initial_p = max(p_field_Roe) + min_initial_p = min(p_field_Roe) + max_initial_v = max(v_field_Roe) + min_initial_v = min(v_field_Roe) + max_initial_T = max(T_field_Roe) + min_initial_T = min(T_field_Roe) + + fig, ([axDensity, axMomentum, axRhoE],[axPressure, axVitesse, axTemperature]) = plt.subplots(2, 3,sharex=True, figsize=(14,10)) + plt.gcf().subplots_adjust(wspace = 0.5) + + lineDensity_Roe, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field_Roe, label='Roe') + axDensity.set(xlabel='x (m)', ylabel='Densité (kg/m3)') + axDensity.set_xlim(a,b) + #axDensity.set_ylim(min_initial_rho - 0.1 * (max_initial_rho - min_initial_rho), 700.) + axDensity.set_ylim(657, 660.5) + axDensity.legend() + + lineMomentum_Roe, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field_Roe, label='Roe') + axMomentum.set(xlabel='x (m)', ylabel='Momentum (kg/(m2.s))') + axMomentum.set_xlim(a,b) + #axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q * 2.5) + axMomentum.set_ylim(-50, 500) + axMomentum.legend() + + lineRhoE_Roe, = axRhoE.plot([a+0.5*dx + i*dx for i in range(nx)], h_field_Roe, label='Roe') + axRhoE.set(xlabel='x (m)', ylabel='h (J/m3)') + axRhoE.set_xlim(a,b) + #axRhoE.set_ylim(min_initial_h - 0.05*abs(min_initial_h), max_initial_h + 0.5*(max_initial_h-min_initial_h)) + axRhoE.set_ylim(1.495 * 10**6, 1.5*10**6) + axRhoE.legend() + + linePressure_Roe, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field_Roe, label='Roe') + axPressure.set(xlabel='x (m)', ylabel='Pression (bar)') + axPressure.set_xlim(a,b) + #axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.5*(max_initial_p-min_initial_p)) + axPressure.set_ylim(149, 156) + axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axPressure.legend() + + lineVitesse_Roe, = axVitesse.plot([a+0.5*dx + i*dx for i in range(nx)], v_field_Roe, label='Roe') + axVitesse.set(xlabel='x (m)', ylabel='Vitesse (m/s)') + axVitesse.set_xlim(a,b) + #axVitesse.set_ylim(min_initial_v - 0.05*abs(min_initial_v), 15) + axVitesse.set_ylim(-0.5, 1) + axVitesse.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axVitesse.legend() + + lineTemperature_Roe, = axTemperature.plot([a+0.5*dx + i*dx for i in range(nx)], T_field_Roe, label='Roe') + axTemperature.set(xlabel='x (m)', ylabel='Température (K)') + axTemperature.set_xlim(a,b) + #axTemperature.set_ylim(min_initial_T - 0.005*abs(min_initial_T), 604) + axTemperature.set_ylim(600, 601) + axTemperature.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axTemperature.legend() + + return(fig, lineDensity_Roe, lineMomentum_Roe, lineRhoE_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe, lineDensity_Roe, lineMomentum_Roe, lineRhoE_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe) + + +def EulerSystemRoe(ntmax, tmax, cfl, a, b, nbCells, output_freq, meshName, state_law): + #state_law_parameters(state_law) + dim = 1 + nbComp = 3 + dt = 0. + time = 0. + it = 0 + isStationary = False + isImplicit = False + dx = (b - a) / nx + dt = cfl * dx / c0 + #dt = 5*10**(-6) + nbVoisinsMax = 2 + + # iteration vectors + Un_Roe = cdmath.Vector(nbCells * (nbComp)) + dUn_Roe = cdmath.Vector(nbCells * (nbComp)) + dUk_Roe = cdmath.Vector(nbCells * (nbComp)) + Rhs_Roe = cdmath.Vector(nbCells * (nbComp)) + + # Initial conditions + print("Construction of the initial condition …") + + rho_field_Roe, q_field_Roe, rho_E_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe = initial_conditions_Riemann_problem(a, b, nx) + h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2 + p_field_Roe = p_field_Roe * 10 ** (-5) + + + for k in range(nbCells): + Un_Roe[k * nbComp + 0] = rho_field_Roe[k] + Un_Roe[k * nbComp + 1] = q_field_Roe[k] + Un_Roe[k * nbComp + 2] = rho_E_field_Roe[k] + + divMat_Roe = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp) + + # Picture settings + fig, lineDensity, lineMomentum, lineRhoE, linePressure, lineVitesse, lineTemperature, lineDensity_Roe, lineMomentum_Roe, lineRhoE_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe = SetPicture( rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx) + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Roe scheme for the 1D Euler system", artist="CEA Saclay", comment="Shock tube") + writer = FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(fig, "1DEuler_complet_RP_Roe" + ".mp4", ntmax): + writer.grab_frame() + plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "0" + ".png") + np.savetxt( "EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rho" + "0" + ".txt", rho_field_Roe, delimiter="\n") + np.savetxt( "EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_q" + "0" + ".txt", q_field_Roe, delimiter="\n") + iterGMRESMax = 50 + newton_max = 100 + + print("Starting computation of the non linear Euler non isentropic system with Roe scheme …") + # STARTING TIME LOOP + while (it < ntmax and time <= tmax and not isStationary): + dUn_Roe = Un_Roe.deepCopy() + Uk_Roe = Un_Roe.deepCopy() + residu_Roe = 1. + + k_Roe = 0 + while (k_Roe < newton_max and residu_Roe > precision): + # STARTING NEWTON LOOP + divMat_Roe.zeroEntries() #sets the matrix coefficients to zero + for j in range(nbCells): + + # traitements des bords + if (j == 0): + FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + elif (j == nbCells - 1): + FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + + # traitement des cellules internes + else: + FillInnerCell(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit) + + #solving the linear system divMat * dUk = Rhs + + if(isImplicit): + divMat_Roe.diagonalShift(1.) + LS_Roe = cdmath.LinearSolver(divMat_Roe, Rhs_Roe, iterGMRESMax, precision, "GMRES", "LU") + dUk_Roe = LS_Roe.solve() + residu_Roe = dUk_Roe.norm() + else: + dUk_Roe=Rhs_Roe - divMat_Roe*Un_Roe + residu_Roe = 0.#Convergence schéma Newton + + if (isImplicit and (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax)): + print("Residu Newton : ", residu_Roe) + print("Linear system converged in ", LS_Roe.getNumberOfIter(), " GMRES iterations") + + #updates for Newton loop + Uk_Roe += dUk_Roe + k_Roe = k_Roe + 1 + if (isImplicit and not LS_Roe.getStatus()): + print("Linear system did not converge ", LS_Roe.getNumberOfIter(), " GMRES iterations") + raise ValueError("No convergence of the linear system") + + if k_Roe == newton_max: + raise ValueError("No convergence of Newton Roe Scheme") + + #updating fields + Un_Roe = Uk_Roe.deepCopy() + dUn_Roe -= Un_Roe + if (dUn_Roe.norm()= ntmax or isStationary or time >= tmax): + + print("-- Time step : " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + + plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + str(it) + '_time' + str(time) + ".png") + + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + if (it >= ntmax): + print("Maximum number of time steps ntmax= ", ntmax, " reached") + return + + elif (isStationary): + print("Stationary regime reached at time step ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rho_Stat.txt", rho_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_q_Stat.txt", q_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rhoE_Stat.txt", rho_E_field_Roe, delimiter="\n") + np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_p_Stat.txt", p_field_Roe, delimiter="\n") + plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_Stat.png") + return + else: + print("Maximum time Tmax= ", tmax, " reached") + return + + +def solve(a, b, nx, meshName, meshType, cfl, state_law): + print("Resolution of the Euler System in dimension 1 on " + str(nx) + " cells") + print("State Law Stiffened Gaz, " + state_law) + print("Initial data : ", "Riemann problem") + print("Boundary conditions : ", "Neumann") + print("Mesh name : ", meshName, ", ", nx, " cells") + # Problem data + tmax = 10. + ntmax = 25 + output_freq = 1 + EulerSystemRoe(ntmax, tmax, cfl, a, b, nx, output_freq, meshName, state_law) + return + + +if __name__ == """__main__""": + a = 0. + b = 1. + nx = 50 + cfl = 0.5 + #state_law = "Hermite590K" + #state_law_parameters(state_law) + solve(a, b, nx, "RegularSquares", "", cfl, state_law) diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/CMakeLists.txt new file mode 100755 index 0000000..0dfd1ee --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/CMakeLists.txt @@ -0,0 +1,15 @@ +file(GLOB IsentropicEulerEquations_EXAMPLES_TO_INSTALL +EulerSystem1D/EulerSystem1DUpwind EulerSystem1D/EulerSystem1DUpwindEntrCorr EulerSystem1D/EulerSystem1DConservativeStaggered EulerSystem_Shock/EulerSystemStaggered EulerSystem_Shock/EulerSystemUpwind +) + +install(DIRECTORY ${IsentropicEulerEquations_EXAMPLES_TO_INSTALL} DESTINATION share/examples/EulerEquations/IsentropicEulerEquations) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + ADD_SUBDIRECTORY(EulerSystem1D/EulerSystem1DUpwind) + ADD_SUBDIRECTORY(EulerSystem1D/EulerSystem1DUpwindEntrCorr) + ADD_SUBDIRECTORY(EulerSystem1D/EulerSystem1DConservativeStaggered) + ADD_SUBDIRECTORY(EulerSystem_Shock/EulerSystemUpwind) + ADD_SUBDIRECTORY(EulerSystem_Shock/EulerSystemStaggered) +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt new file mode 100755 index 0000000..04ce58c --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleIsentropicEulerSystem_1DShock_ConservativeStaggered ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DConservativeStaggered.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py new file mode 100644 index 0000000..c1158ac --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +# Isothermal Euler system +# d rho/d t + d q/d x =0 +# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho +# UU = (rho,q) : conservative variable +# Scheme : Conservative stagerred scheme (Ait Ameur et al) +# Author : Katia Ait Ameur +# Date : November 2020 + +import cdmath +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +from math import sqrt + +c0=330.#reference sound speed for water at 15 bars +precision=1e-5 +rho0=1 + +def initial_conditions_Riemann_problem(a,b,nx): + print("Initial data Riemann problem") + dx = (b - a) / nx #space step + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + rho_initial = [ (xi<(a+b)/2)*rho0 + (xi>=(a+b)/2)*rho0*2 for xi in x] + q_initial = [ (xi<(a+b)/2)*rho0*(-300) + (xi>=(a+b)/2)*rho0*2*(-300) for xi in x] + + return rho_initial, q_initial + +def matrix_coef(rho_l,q_l,rho_r,q_r): + m_coef = -0.5*(q_l-q_r)/rho_r + return m_coef + +def jacobianMatricesm(coeff,rho_l,q_l,rho_r,q_r): + RoeMat = cdmath.Matrix(2,2); + Dmac = cdmath.Matrix(2,2); + + u_l=q_l/rho_l + u_r=q_r/rho_r + Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_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)); + RoeMat[0,0] = 0 + RoeMat[0,1] = 1 + RoeMat[1,0] = c0*c0 - u*u + RoeMat[1,1] = 2*u + + Dmac[0,0]= abs(u)-u; + Dmac[0,1]= 1; + Dmac[1,0]= -c0*c0-u*u; + Dmac[1,1]= abs(u)+u; + + return (RoeMat-Dmac)*coeff*0.5 + +def jacobianMatricesp(coeff,rho_l,q_l,rho_r,q_r): + RoeMat = cdmath.Matrix(2,2); + Dmac = cdmath.Matrix(2,2); + + u_l=q_l/rho_l + u_r=q_r/rho_r + Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_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)); + RoeMat[0,0] = 0 + RoeMat[0,1] = 1 + RoeMat[1,0] = c0*c0 - u*u + RoeMat[1,1] = 2*u + + Dmac[0,0]= abs(u)-u; + Dmac[0,1]= 1; + Dmac[1,0]= -c0*c0-u*u; + Dmac[1,1]= abs(u)+u; + + return (RoeMat+Dmac)*coeff*0.5 + +def EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName): + dim=1 + nbComp=dim+1 + nbCells = nx + dt = 0. + dx=(b-a)/nx + dt = cfl * dx / c0 + nbVoisinsMax=2 + + time = 0. + it=0; + iterGMRESMax=50 + newton_max = 50 + isStationary=False + + #iteration vectors + Un =cdmath.Vector(nbCells*(dim+1)) + dUn=cdmath.Vector(nbCells*(dim+1)) + dUk=cdmath.Vector(nbCells*(dim+1)) + Rhs=cdmath.Vector(nbCells*(dim+1)) + + # Initial conditions # + print("Construction of the initial condition …") + rho_field, q_field = initial_conditions_Riemann_problem(a,b,nx) + v_field = [ q_field[i]/rho_field[i] for i in range(nx)] + p_field = [ rho_field[i]*(c0*c0) for i in range(nx)] + + max_initial_rho=max(rho_field) + min_initial_rho=min(rho_field) + max_initial_q=max(q_field) + min_initial_q=min(q_field) + max_initial_p=max(p_field) + min_initial_p=min(p_field) + max_initial_v=max(v_field) + min_initial_v=min(v_field) + + for k in range(nbCells): + Un[k*nbComp+0] = rho_field[k] + Un[k*nbComp+1] = q_field[k] + + print("Starting computation of the non linear Euler system with staggered scheme …") + divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) + + # Picture settings + fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) + fig.suptitle('Conservative staggered scheme') + lineDensity, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma + axDensity.set(xlabel='x (m)', ylabel='Density') + axDensity.set_xlim(a,b) + axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) + axDensity.legend() + lineMomentum, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') + axMomentum.set(xlabel='x (m)', ylabel='Momentum') + axMomentum.set_xlim(a,b) + axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) + axMomentum.legend() + lineVelocity, = axVelocity.plot([a+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') + axVelocity.set(xlabel='x (m)', ylabel='Velocity') + axVelocity.set_xlim(a,b) + axVelocity.set_ylim(min_initial_v - 0.4*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) + axVelocity.legend() + linePressure, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') + axPressure.set(xlabel='x (m)', ylabel='Pressure') + axPressure.set_xlim(a,b) + axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) + axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axPressure.legend() + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Conservative staggered scheme for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") + writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(fig, "1DEuler_System_ConservativeStaggered"+".mp4", ntmax): + writer.grab_frame() + plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_0"+".png") + + # Starting time loop + while (it precision ): + #DEBUT BOUCLE NEWTON + divMat.zeroEntries()#sets the matrix coefficients to zero + for j in range(nbCells):# + if ( j==0) : + rho_r = Uk[j*nbComp+0] + q_r = Uk[j*nbComp+1] + rho_l = rho_r # Conditions de Neumann + q_l = q_r + Am= jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r) + divMat.addValue(j*nbComp,(j+1)*nbComp,Am) + divMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + dUi=cdmath.Vector(2) + dUi[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0] + dUi[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1] + temp=cdmath.Vector(2) + temp = Am*dUi + #print("Bloc 0 matrix : ", Am) + Rhs[j*nbComp+0] = -temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0]) + Rhs[j*nbComp+1] = -temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1]) + elif ( j==nbCells-1) : + rho_l = Uk[j*nbComp+0] + q_l = Uk[j*nbComp+1] + rho_r = rho_l # Conditions de Neumann + q_r = q_l + Ap= jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r) + divMat.addValue(j*nbComp, j*nbComp,Ap) + divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.)) + dUi=cdmath.Vector(2) + dUi[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0] + dUi[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1] + temp=cdmath.Vector(2) + temp = Ap*dUi + Rhs[j*nbComp+0] = temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0]) + Rhs[j*nbComp+1] = temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1]) + else : + rho_l = Uk[(j-1)*nbComp+0] + q_l = Uk[(j-1)*nbComp+1] + rho_r = Uk[j*nbComp+0] + q_r = Uk[j*nbComp+1] + Ap = jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r) + ############################################################### + rho_l = Uk[j*nbComp+0] + q_l = Uk[j*nbComp+1] + rho_r = Uk[(j+1)*nbComp+0] + q_r = Uk[(j+1)*nbComp+1] + Am = jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r) + divMat.addValue(j*nbComp,(j+1)*nbComp,Am) + divMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + divMat.addValue(j*nbComp, j*nbComp,Ap) + divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.)) + dUi1=cdmath.Vector(2) + dUi2=cdmath.Vector(2) + dUi1[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0] + dUi1[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1] + dUi2[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0] + dUi2[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1] + temp1 = cdmath.Vector(2) + temp2 = cdmath.Vector(2) + temp1 = Am*dUi1 + temp2 = Ap*dUi2 + Rhs[j*nbComp+0] = -temp1[0] + temp2[0] -(Uk[j*nbComp+0]-Un[j*nbComp+0]) + Rhs[j*nbComp+1] = -temp1[1] + temp2[1] -(Uk[j*nbComp+1]-Un[j*nbComp+1]) + divMat.diagonalShift(1)#only after filling all coefficients + LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU") + dUk=LS.solve(); + residu = dUk.norm() + #stop + Uk+=dUk + if(not LS.getStatus()): + print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations") + raise ValueError("Pas de convergence du système linéaire"); + k=k+1 + Un = Uk.deepCopy() + dUn-=Un + for k in range(nbCells): + rho_field[k] = Un[k*(dim+1)+0] + q_field[k] = Un[k*(dim+1)+1] + v_field = [ q_field[i]/rho_field[i] for i in range(nx)] + p_field = [ rho_field[i]*(c0*c0) for i in range(nx)] + + lineDensity.set_ydata(rho_field) + lineMomentum.set_ydata(q_field) + lineVelocity.set_ydata(v_field) + linePressure.set_ydata(p_field) + writer.grab_frame() + + 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("Last linear system converged in ", LS.getNumberOfIter(), " GMRES iterations", ", residu final: ",residu) + + plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_"+str(it)+".png") + print + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + if(it>=ntmax): + print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + return + elif(isStationary): + print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + plt.savefig("EulerSystem"+str(dim)+"Staggered"+meshName+"_Stat.png") + return + else: + print("Temps maximum Tmax= ", tmax, " atteint") + return + +def solve( a,b,nx, meshName, meshType, cfl): + print("Resolution of the Euler system in dimension 1 on "+str(nx)+ " cells") + print("Initial data : ", "Riemann problem") + print("Boundary conditions : ", "Neumann") + print("Mesh name : ",meshName , ", ", nx, " cells") + # Problem data + tmax = 10. + ntmax = 50 + output_freq = 10 + EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName) + return + +if __name__ == """__main__""": + a=0. + b=1. + nx=100 + cfl=0.99 + solve( a,b,nx,"SquareRegularSquares","RegularSquares",cfl) diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt new file mode 100755 index 0000000..990582d --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleIsentropicEulerSystem_1DShock_UpwindExplicit ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DUpwind.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py new file mode 100644 index 0000000..ee66cd1 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py @@ -0,0 +1,199 @@ +# Isothermal Euler system +# d rho/d t + d q/d x =0 +# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho +# UU = (rho,q) : conservative variable +# Scheme : Roe scheme (without any entropy correction) +# Comment : the solution displays a non entropic (non physical) shock instead of a rarefaction wave +# Date : November 2020 + +from cdmath import * +import numpy as np +from math import sqrt + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation + +c0=330.#reference sound speed for water at 15 bars +precision=1e-5 + +def flux(rho,q): + fl = Vector(2); + fl[0] = q; + fl[1] = q*q/rho + c0*c0*rho; + return fl + +def compTimeStep(UU,dx,CFL): + M = UU.getMesh(); + maxAbsEigVa = 0; + for i in range(M.getNumberOfCells()): + maxAbsEigVa = max(maxAbsEigVa,abs(UU[i,1]/UU[i,0]+c0),abs(UU[i,1]/UU[i,0]-c0)); + pass + dt = CFL*dx/maxAbsEigVa; + return dt + +def AbsRoeMatrix(rho_l,q_l,rho_r,q_r): + AbsRoeMa = Matrix(2,2); + u_l = q_l/rho_l; + u_r = q_r/rho_r; + u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + AbsRoeMa[0,0]=(abs(u-c0)*(u+c0)+abs(u+c0)*(c0-u))/(2*c0); + AbsRoeMa[0,1]= (abs(u+c0)-abs(u-c0))/(2*c0); + AbsRoeMa[1,0]=(abs(u-c0)*(u*u-c0*c0)+abs(u+c0)*(c0*c0-u*u))/(2*c0); + AbsRoeMa[1,1]=((u+c0)*abs(u+c0)-(u-c0)*abs(u-c0))/(2*c0); + return AbsRoeMa; + +def main(meshName): + # mesh definition + xmin=.0; + xmax= 1; + nx=100#1000; + ntmax=50; + dx = (xmax-xmin)/nx; + M=Mesh(xmin,xmax,nx); + dim=1 + + # initial time + time=0.; + # maximum time T + tmax=0.01; + it=0; + freqSortie=10; + # CFL condition + CFL=0.99; + # conservative variable (unknown) + UU=Field("Conservative variables",CELLS,M,2); + + # initial condition for Riemann problem + print("Construction of the initial condition …") + rhoL=1 + vL=-300 + rhoR=1.45 + vR=-300 + for i in range(M.getNumberOfCells()): + x=M.getCell(i).x(); + if x < (xmax-xmin)/2: + UU[i,0] = rhoL; + UU[i,1] = rhoL*vL; + else: + UU[i,0] = rhoR; + UU[i,1] = rhoR*vR; + pass + + rho_field = [ UU[i,0] for i in range(nx)] + q_field = [ UU[i,1] for i in range(nx)] + v_field = [ UU[i,1]/UU[i,0] for i in range(nx)] + p_field = [ UU[i,0]*(c0*c0) for i in range(nx)] + + max_initial_rho=max(rhoL,rhoR) + min_initial_rho=min(rhoL,rhoR) + max_initial_p=max_initial_rho*c0*c0 + min_initial_p=min_initial_rho*c0*c0 + max_initial_v=max(vL,vR) + min_initial_v=min(vL,vR) + max_initial_q=max(vL*rhoL,vR*rhoR) + min_initial_q=min(vL*rhoL,vR*rhoR) + + print( "Numerical solution of the 1D Euler equation") + + # prepare some memory + UU_limL = Vector(2); + UU_limR = Vector(2); + Del_UU_RL = Vector(2); + UU_new = UU; + + # Picture settings + fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) + fig.suptitle('Explicit Upwind scheme') + lineDensity, = axDensity.plot([xmin+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma + axDensity.set(xlabel='x (m)', ylabel='Density') + axDensity.set_xlim(xmin,xmax) + axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) + axDensity.legend() + lineMomentum, = axMomentum.plot([xmin+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') + axMomentum.set(xlabel='x (m)', ylabel='Momentum') + axMomentum.set_xlim(xmin,xmax) + axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) + axMomentum.legend() + lineVelocity, = axVelocity.plot([xmin+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') + axVelocity.set(xlabel='x (m)', ylabel='Velocity') + axVelocity.set_xlim(xmin,xmax) + axVelocity.set_ylim(min_initial_v - 0.25*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) + axVelocity.legend() + linePressure, = axPressure.plot([xmin+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') + axPressure.set(xlabel='x (m)', ylabel='Pressure') + axPressure.set_xlim(xmin,xmax) + axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) + axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axPressure.legend() + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Upwind (Roe) scheme for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") + writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(fig, "1DEuler_System_Upwind"+".mp4", ntmax): + writer.grab_frame() + plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_0"+".png") + + # loop in time + while (it=ntmax): + print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + return + elif(isStationary): + print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_Stat.png") + return + else: + print("Temps maximum Tmax= ", tmax, " atteint") + + return + +if __name__ == '__main__': + main("SquareRegularSquares") diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt new file mode 100755 index 0000000..62fde1b --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleIsentropicEulerSystem_1DShock_UpwindExplicit_EntrCorr ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DUpwindEntrCorr.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py new file mode 100644 index 0000000..e1ae7f0 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py @@ -0,0 +1,199 @@ +# Isothermal Euler system +# d rho/d t + d q/d x =0 +# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho +# UU = (rho,q) : conservative variable +# Scheme : Roe scheme with entropy correction +# Comment : If one removes the entropic correction the result displays a non entropic (non physical) shock instead of a rarefaction wave +# Date : November 2020 + +from cdmath import * +import numpy as np +from math import sqrt + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation + +c0=330.#reference sound speed for water at 15 bars +precision=1e-5 + +def flux(rho,q): + fl = Vector(2); + fl[0] = q; + fl[1] = q*q/rho + c0*c0*rho; + return fl + +def compTimeStep(UU,dx,CFL): + M = UU.getMesh(); + maxAbsEigVa = 0; + for i in range(M.getNumberOfCells()): + maxAbsEigVa = max(maxAbsEigVa,abs(UU[i,1]/UU[i,0]+c0),abs(UU[i,1]/UU[i,0]-c0)); + pass + dt = CFL*dx/maxAbsEigVa; + return dt + +def AbsRoeMatrix(rho_l,q_l,rho_r,q_r): + AbsRoeMa = Matrix(2,2); + u_l = q_l/rho_l; + u_r = q_r/rho_r; + u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + AbsRoeMa[0,0]=(abs(u-c0)*(u+c0)+abs(u+c0)*(c0-u))/(2*c0); + AbsRoeMa[0,1]= (abs(u+c0)-abs(u-c0))/(2*c0); + AbsRoeMa[1,0]=(abs(u-c0)*(u*u-c0*c0)+abs(u+c0)*(c0*c0-u*u))/(2*c0); + AbsRoeMa[1,1]=((u+c0)*abs(u+c0)-(u-c0)*abs(u-c0))/(2*c0); + return AbsRoeMa; + +def main(meshName): + # mesh definition + xmin=.0; + xmax= 1; + nx=200#1000; + ntmax=100; + dx = (xmax-xmin)/nx; + M=Mesh(xmin,xmax,nx); + dim=1 + + # initial time + time=0.; + # maximum time T + tmax=0.01; + it=0; + freqSortie=10; + # CFL condition + CFL=0.9; + # conservative variable (unknown) + UU=Field("Conservative variables",CELLS,M,2); + + # initial condition for Riemann problem + print("Construction of the initial condition …") + rhoL=1 + vL=-300 + rhoR=2 + vR=-300 + for i in range(M.getNumberOfCells()): + x=M.getCell(i).x(); + if x < (xmax-xmin)/2: + UU[i,0] = rhoL; + UU[i,1] = rhoL*vL; + else: + UU[i,0] = rhoR; + UU[i,1] = rhoR*vR; + pass + + rho_field = [ UU[i,0] for i in range(nx)] + q_field = [ UU[i,1] for i in range(nx)] + v_field = [ UU[i,1]/UU[i,0] for i in range(nx)] + p_field = [ UU[i,0]*(c0*c0) for i in range(nx)] + + max_initial_rho=max(rhoL,rhoR) + min_initial_rho=min(rhoL,rhoR) + max_initial_p=max_initial_rho*c0*c0 + min_initial_p=min_initial_rho*c0*c0 + max_initial_v=max(vL,vR) + min_initial_v=min(vL,vR) + max_initial_q=max(vL*rhoL,vR*rhoR) + min_initial_q=min(vL*rhoL,vR*rhoR) + + print( "Numerical solution of the 1D Euler equation") + + # prepare some memory + UU_limL = Vector(2); + UU_limR = Vector(2); + Del_UU_RL = Vector(2); + UU_new = UU; + + # Picture settings + fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) + fig.suptitle('Explicit Upwind scheme') + lineDensity, = axDensity.plot([xmin+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma + axDensity.set(xlabel='x (m)', ylabel='Density') + axDensity.set_xlim(xmin,xmax) + axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) + axDensity.legend() + lineMomentum, = axMomentum.plot([xmin+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') + axMomentum.set(xlabel='x (m)', ylabel='Momentum') + axMomentum.set_xlim(xmin,xmax) + axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) + axMomentum.legend() + lineVelocity, = axVelocity.plot([xmin+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') + axVelocity.set(xlabel='x (m)', ylabel='Velocity') + axVelocity.set_xlim(xmin,xmax) + axVelocity.set_ylim(min_initial_v - 0.4*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) + axVelocity.legend() + linePressure, = axPressure.plot([xmin+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') + axPressure.set(xlabel='x (m)', ylabel='Pressure') + axPressure.set_xlim(xmin,xmax) + axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) + axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) + axPressure.legend() + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Upwind (Roe) scheme with entropic correction for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") + writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(fig, "1DEuler_System_Upwind"+".mp4", ntmax): + writer.grab_frame() + plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_0"+".png") + + # loop in time + while (it=ntmax): + print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + return + elif(isStationary): + print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_Stat.png") + return + else: + print("Temps maximum Tmax= ", tmax, " atteint") + + return + +if __name__ == '__main__': + main("SquareRegularSquares") diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt new file mode 100755 index 0000000..211c08d --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleEulerSystem_2DShock_ConservativeStaggered ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerIsothermal_2DConservativeStaggered.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py new file mode 100644 index 0000000..5480b7e --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py @@ -0,0 +1,798 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF des équations d'Euler isotherme 2D sans terme source +# \partial_t rho + \div q = 0 +# \partial_t q + \div q \otimes q/rho \grad p = 0 +# Author : Michaël Ndjinga, Coraline Mounier +# Copyright : CEA Saclay 2020 +# Description : Propagation d'une onde de choc droite +# Utilisation du schéma upwind explicite ou implicite sur un maillage général +# Initialisation par une discontinuité verticale +# Conditions aux limites de Neumann +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +import cdmath +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +from math import sqrt +import sys +import PV_routines + +p0=155.e5 #reference pressure in a pressurised nuclear vessel +c0=700. #reference sound speed for water at 155 bars +rho0=p0/(c0*c0) #reference density +precision=1e-5 + +def initial_conditions_Riemann_problem(my_mesh): + print( "Initial data : Riemann problem" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + xcentre = 0.5 + + density_field = cdmath.Field("Density", cdmath.CELLS, my_mesh, 1) + q_x_field = cdmath.Field("Momentum x", cdmath.CELLS, my_mesh, 1) + q_y_field = cdmath.Field("Momentum y", cdmath.CELLS, my_mesh, 1) + #Velocity field with 3 components should be created for streamlines to be drawn + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + + # Initial momentum is zero + q_x_field[i] = 0 + q_y_field[i] = 0 + + # Initial velocity is zero + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + if x < xcentre: + density_field[i] = rho0 + pass + else: + density_field[i] = rho0/2 + pass + pass + + return density_field, q_x_field, q_y_field, velocity_field + + +def jacobianMatricesm_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): + RoeMatx = cdmath.Matrix(3,3); + Dmacx = cdmath.Matrix(3,3); + + u_lx=q_lx/rho_l + u_rx=q_rx/rho_r + u_ly=q_ly/rho_l + u_ry=q_ry/rho_r + if rho_l<0 or rho_r<0: + print("rho_l=",rho_l, " rho_r= ",rho_r) + raise ValueError("Negative density") + ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + + RoeMatx[0,0] = 0 + RoeMatx[0,1] = 1 + RoeMatx[0,2] = 0 + RoeMatx[1,0] = c0*c0 - ux*ux + RoeMatx[1,1] = 2*ux + RoeMatx[1,2] = 0 + RoeMatx[2,0] = -ux*uy + RoeMatx[2,1] = uy + RoeMatx[2,2] = ux + + Dmacx[0,0] = abs(ux)-ux + Dmacx[0,1] = 1 + Dmacx[0,2] = 0 + Dmacx[1,0] = -c0*c0-ux*ux + Dmacx[1,1] = abs(ux)+ux + Dmacx[1,2] = 0 + Dmacx[2,0] = -ux*uy + Dmacx[2,1] = uy + Dmacx[2,2] = abs(ux) + + return (RoeMatx-Dmacx)*coeff*0.5 + +def jacobianMatricesp_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): + RoeMatx = cdmath.Matrix(3,3) + Dmacx = cdmath.Matrix(3,3) + + u_lx=q_lx/rho_l + u_rx=q_rx/rho_r + u_ly=q_ly/rho_l + u_ry=q_ry/rho_r + if rho_l<0 or rho_r<0: + print("rho_l=",rho_l, " rho_r= ",rho_r) + raise ValueError("Negative density") + ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + + RoeMatx[0,0] = 0 + RoeMatx[0,1] = 1 + RoeMatx[0,2] = 0 + RoeMatx[1,0] = c0*c0 - ux*ux + RoeMatx[1,1] = 2*ux + RoeMatx[1,2] = 0 + RoeMatx[2,0] = -ux*uy + RoeMatx[2,1] = uy + RoeMatx[2,2] = ux + + Dmacx[0,0] = abs(ux)-ux + Dmacx[0,1] = 1 + Dmacx[0,2] = 0 + Dmacx[1,0] = -c0*c0-ux*ux + Dmacx[1,1] = abs(ux)+ux + Dmacx[1,2] = 0 + Dmacx[2,0] = -ux*uy + Dmacx[2,1] = uy + Dmacx[2,2] = abs(ux) + + return (RoeMatx+Dmacx)*coeff*0.5 + +def jacobianMatricesm_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): + RoeMaty = cdmath.Matrix(3,3); + Dmacy = cdmath.Matrix(3,3); + + u_lx=q_lx/rho_l + u_rx=q_rx/rho_r + u_ly=q_ly/rho_l + u_ry=q_ry/rho_r + if rho_l<0 or rho_r<0: + print("rho_l=",rho_l, " rho_r= ",rho_r) + raise ValueError("Negative density") + ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + + RoeMaty[0,0] = 0 + RoeMaty[0,1] = 0 + RoeMaty[0,2] = 1 + RoeMaty[1,0] = -ux*uy + RoeMaty[1,1] = uy + RoeMaty[1,2] = ux + RoeMaty[2,0] = c0*c0-uy*uy + RoeMaty[2,1] = 0 + RoeMaty[2,2] = 2*uy + + Dmacy[0,0] = abs(uy)-uy + Dmacy[0,1] = 0 + Dmacy[0,2] = 1 + Dmacy[1,0] = -ux*uy + Dmacy[1,1] = abs(uy) + Dmacy[1,2] = ux + Dmacy[2,0] = -c0*c0-uy*uy + Dmacy[2,1] = 0 + Dmacy[2,2] = abs(uy)+uy + + return (RoeMaty-Dmacy)*coeff*0.5 + +def jacobianMatricesp_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): + RoeMaty = cdmath.Matrix(3,3); + Dmacy = cdmath.Matrix(3,3); + + u_lx=q_lx/rho_l + u_rx=q_rx/rho_r + u_ly=q_ly/rho_l + u_ry=q_ry/rho_r + if rho_l<0 or rho_r<0: + print("rho_l=",rho_l, " rho_r= ",rho_r) + raise ValueError("Negative density") + ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + + RoeMaty[0,0] = 0 + RoeMaty[0,1] = 0 + RoeMaty[0,2] = 1 + RoeMaty[1,0] = -ux*uy + RoeMaty[1,1] = uy + RoeMaty[1,2] = ux + RoeMaty[2,0] = c0*c0-uy*uy + RoeMaty[2,1] = 0 + RoeMaty[2,2] = 2*uy + + Dmacy[0,0] = abs(uy)-uy + Dmacy[0,1] = 0 + Dmacy[0,2] = 1 + Dmacy[1,0] = -ux*uy + Dmacy[1,1] = abs(uy) + Dmacy[1,2] = ux + Dmacy[2,0] = -c0*c0-uy*uy + Dmacy[2,1] = 0 + Dmacy[2,2] = abs(uy)+uy + + return (RoeMaty+Dmacy)*coeff*0.5 + +def EulerSystemStaggered(ntmax, tmax, cfl,output_freq, my_mesh, meshName): + + if not my_mesh.isStructured() : + raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a structured mesh") + + dim=my_mesh.getMeshDimension() + if dim != 2 : + raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a 2D mesh") + + nbComp=dim+1 + # Mesh parameters + nbCells = my_mesh.getNumberOfCells() + nbCells_x = my_mesh.getNx() + nbCells_y = my_mesh.getNy() + dx,dy = my_mesh.getDXYZ() + nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) + dx_min=my_mesh.minRatioVolSurf() + + # Time evolution parameters + time = 0. + it=0; + isStationary=False + iterGMRESMax = 50 + newton_max = 50 + + #iteration vectors + Un =cdmath.Vector(nbCells*nbComp) + dUn=cdmath.Vector(nbCells*nbComp) + dUk=cdmath.Vector(nbCells*nbComp) + Rhs=cdmath.Vector(nbCells*nbComp) + + dUi_x=cdmath.Vector(nbComp) + dUi_y=cdmath.Vector(nbComp) + dUi1_x=cdmath.Vector(nbComp) + dUi2_x=cdmath.Vector(nbComp) + dUi1_y=cdmath.Vector(nbComp) + dUi2_y=cdmath.Vector(nbComp) + + # Initial conditions # + print("Construction of the initial condition …") + rho_field, q_x_field, q_y_field, velocity_field= initial_conditions_Riemann_problem(my_mesh) + + for i in range(nbCells): + Un[nbComp*i] = rho_field[i] + Un[nbComp*i+1] = q_x_field[i] + Un[nbComp*i+2] = q_y_field[i] + + #Sauvegarde de la donnée initiale + rho_field.setTime(time,it); + rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density"); + q_x_field.setTime(time,it); + q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX"); + q_y_field.setTime(time,it); + q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity"); + + print("Starting computation of the isothermal Euler system with a conservative staggered scheme …") + divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) + + # Starting time loop + while (it 1/precision ): + + dt = cfl * dx_min / c0# This choice should be improved when possible by using the actual eigenvalue abs(u)+c0, that is the time step should be determined avec the computation of the jacobian matrices + #DEBUT BOUCLE NEWTON + for j in range(nbCells_y): + for i in range(nbCells_x): + #Traitement des coins + if ( j==0 and i==0) : + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)-Am_y) + + dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + + temp_x = Am_x*dUi_x + temp_y = Am_y*dUi_y + #print("Bloc 0 matrix : ", Am) + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0] - temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1] - temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2] - temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif(i==0 and j==nbCells_y-1): + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)+Ap_y) + + dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp_x = Am_x*dUi_x + temp_y = Ap_y*dUi_y + #print("Bloc 0 matrix : ", Am) + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]- temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]- temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]- temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif(i==nbCells_x-1 and j==0): + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_y) + + dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + + temp_x = Ap_x*dUi_x + temp_y= Am_y*dUi_y + #print("Bloc 0 matrix : ", Am) + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]- temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]- temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]- temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif ( j==nbCells_y-1 and i==nbCells_x-1) : + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y) + + dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp_x = Ap_x*dUi_x + temp_y = Ap_y*dUi_y + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + #Traitement des bords restants + elif i==0 : + + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #remplissage de la divMat + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y-Am_x-Am_y) + + #remplissage du membre de droite + dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp_x = Am_x*dUi_x + temp1_y = Am_y*dUi1_y + temp2_y = Ap_y*dUi2_y + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif i==nbCells_x-1: + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #remplissage de la divMat + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y+Ap_x-Am_y) + + #remplissage du membre de droite + dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp_x = Ap_x*dUi_x + temp1_y = Am_y*dUi1_y + temp2_y = Ap_y*dUi2_y + Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif j==0: + + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #remplissage de la divMat + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_x-Am_y) + + #remplissage du membre de droite + dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + + temp1_x = Am_x*dUi1_x + temp2_x = Ap_x*dUi2_x + temp_y = Am_y*dUi_y + Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + elif j==nbCells_y-1: + + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #remplissage de la divMat + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x) + + #remplissage du membre de droite + dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp1_x = Am_x*dUi1_x + temp2_x = Ap_x*dUi2_x + temp_y = Ap_y*dUi_y + Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + #Traitement des autres cellules + else: + + #Calcul de Am_x + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*(i+1)] + qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] + qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] + Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #Calcul de Ap_x + rho_l=Uk[3*nbCells_x*j+3*(i-1)] + qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] + qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Am_y + rho_l=Uk[3*nbCells_x*j+3*i] + qx_l =Uk[3*nbCells_x*j+3*i+1] + qy_l =Uk[3*nbCells_x*j+3*i+2] + rho_r=Uk[3*nbCells_x*(j+1)+3*i] + qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] + qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] + Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #calcul de Ap_y + rho_l=Uk[3*nbCells_x*(j-1)+3*i] + qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] + qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] + rho_r=Uk[3*nbCells_x*j+3*i] + qx_r =Uk[3*nbCells_x*j+3*i+1] + qy_r =Uk[3*nbCells_x*j+3*i+2] + Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) + + #remplissage de la divMat + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) + divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x-Am_y) + + #remplissage du membre de droite + + dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] + dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] + + dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] + dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] + dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] + + dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] + dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] + dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] + + dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] + dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] + dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] + + temp1_x = Am_x*dUi1_x + temp2_x = Ap_x*dUi2_x + temp1_y = Am_y*dUi1_y + temp2_y = Ap_y*dUi2_y + Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) + Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) + Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) + + divMat.diagonalShift(1) #only after filling all coefficients + LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU") + dUk=LS.solve(); + residu = dUk.norm() + Uk+=dUk + #print("Newton iteration number ",k, "residu = ",residu) + if(not LS.getStatus()): + print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations") + raise ValueError("Pas de convergence du système linéaire"); + k=k+1 + Un = Uk.deepCopy() + dUn-=Un + isStationary = dUn.norm()=ntmax or isStationary or time >=tmax): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) + ", Newton iterations: "+str(k)+", ||dUn|| = "+str(dUn.norm())) + print("Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations, résidu = ", residu) + for k in range(nbCells): + rho =rho_field[k] + velocity_field[k,0]=q_x_field[i]/rho + if(dim>1): + velocity_field[k,1]=q_y_field[k]/rho + print + rho_field.setTime(time,it); + rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density",False); + q_x_field.setTime(time,it); + q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX",False); + q_y_field.setTime(time,it); + q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity",False); + #Postprocessing : save 2D picture + PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density_" +str(it)+'.vtu',"Density", 'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density" +str(it)) + PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX_"+str(it)+'.vtu',"Momentum x",'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX"+str(it)) + PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY_"+str(it)+'.vtu',"Momentum y",'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY"+str(it)) + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + if(it>=ntmax): + print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + return + elif(isStationary): + print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print("------------------------------------------------------------------------------------") + return + else: + print("Temps maximum Tmax= ", tmax, " atteint") + return + +def solve( my_mesh,filename, resolution): + print("Resolution of the Isothermal Euler system in dimension 2 on "+str(my_mesh.getNumberOfCells())+ " cells") + print("Initial data : ", "Riemann problem") + print("Boundary conditions : ", "Neumann") + print("Mesh name : ",filename ) + # Problem data + tmax = 10. + ntmax = 10 + cfl=1 + output_freq = 1 + EulerSystemStaggered(ntmax, tmax, cfl, output_freq, my_mesh, filename) + return + +if __name__ == """__main__""": + if len(sys.argv) >1 : + filename=sys.argv[1] + my_mesh = cdmath.Mesh(filename) + else : + filename = "CartesianGrid" + ax=0;bx=1;nx=20; + ay=0;by=1;ny=10; + my_mesh = cdmath.Mesh(ax,bx,nx,ay,by,ny) + + solve(my_mesh,filename,100) diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt new file mode 100755 index 0000000..0e9b410 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt @@ -0,0 +1,81 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/EulerSystemUpwind) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(IMPLICIT_SCHEME 0 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + #ADD_TEST(ExampleEulerSystem_3DShock_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + #ADD_TEST(ExampleEulerSystem_3DShock_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshHexagonWithTriangles.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(IMPLICIT_SCHEME 1 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + #ADD_TEST(ExampleEulerSystem_3DShock_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + #ADD_TEST(ExampleEulerSystem_3DShock_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py new file mode 100755 index 0000000..0b3dff2 --- /dev/null +++ b/CDMATH/tests/examples/EulerEquations/IsentropicEulerSystem/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système Euler 2D barotrope sans terme source +# \partial_t rho + \div q = 0 +# \partial_t q + \div q\otimes q/rho + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc sphérique +# Utilisation du schéma de Roe upwind explicite ou implicite sur un maillage général +# Initialisation par une surpression sphérique +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel (used for initial data) +c0=700.#reference sound speed for water at 155 bars, 600K (used for eox p= rho c0**2 +precision=1e-5 + +def initial_conditions_shock(my_mesh, isCircle): + print( "Initial data : Spherical wave" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + rayon = 0.15 + if(not isCircle): + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + else: + xcentre = 0. + ycentre = 0. + zcentre = 0. + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + x = my_mesh.getCell(i).x() + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val = sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0 + pass + pass + + return pressure_field, velocity_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 = cdmath.Vector(2); u_l[0]*=q_l[0]/rho_l; u_l[1]*=q_l[1]/rho_l; + u_r = cdmath.Vector(2); u_r[0]*=q_r[0]/rho_r; u_r[1]*=q_r[1]/rho_r; + if rho_l<0 or rho_r<0 : + print( "rho_l=",rho_l, " rho_r= ",rho_r ) + raise ValueError("Negative density") + u=cdmath.Vector(2); + u[0] = (u_l[0]*sqrt(rho_l)+u_r[0]*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); + u[1] = (u_l[1]*sqrt(rho_l)+u_r[1]*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*0.5,un; + +def computeDivergenceMatrix(my_mesh,implMat,Un): + nbCells = my_mesh.getNumberOfCells() + dim=my_mesh.getMeshDimension() + nbComp=dim+1 + normal=cdmath.Vector(dim) + maxAbsEigVa = 0 + q_l=cdmath.Vector(2); + q_r=cdmath.Vector(2); + + 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 + + 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") + + q_l[0]=Un[j*nbComp+1] + q_l[1]=Un[j*nbComp+2] + q_r[0]=Un[cellAutre*nbComp+1] + q_r[1]=Un[cellAutre*nbComp+2] + Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],q_l,Un[cellAutre*nbComp],q_r); + + implMat.addValue(j*nbComp,cellAutre*nbComp,Am) + implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + else : + if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + q_l[0]=Un[j*nbComp+1] + q_l[1]=Un[j*nbComp+2] + q_r=q_l-normal*2*(q_l*normal) + Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],q_l,Un[j*nbComp],q_r); + + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + indexFP=my_mesh.getIndexFacePeriodic(indexFace) + Fp = my_mesh.getFace(indexFP) + cellAutre = Fp.getCellsId()[0] + + q_l[0]=Un[j*nbComp+1] + q_l[1]=Un[j*nbComp+2] + q_r[0]=Un[cellAutre*nbComp+1] + q_r[1]=Un[cellAutre*nbComp+2] + Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],q_l,Un[cellAutre*nbComp],q_r); + + implMat.addValue(j*nbComp,cellAutre*nbComp,Am) + implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + elif( Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + maxAbsEigVa = max(maxAbsEigVa,abs(un+c0),abs(un-c0)); + + return maxAbsEigVa + +def EulerSystemVF(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(dim==1 or 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_shock(my_mesh,False) + elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1 or filename.find("HEXAON")>-1): + pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) + else: + print( "Mesh name : ", filename ) + raise ValueError("Mesh name should contain substring square, cube, disk or hexagon") + + #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]/(c0*c0) + Un[k*(dim+1)+1] =Un[k*(dim+1)+0]*velocity_field[k,0] + if(dim>=2): + Un[k*(dim+1)+2] = Un[k*(dim+1)+0]*velocity_field[k,1] + if(dim==3): + Un[k*(dim+1)+3] = Un[k*(dim+1)+0]*velocity_field[k,2] + print(Un[k*(dim+1)+0],Un[k*(dim+1)+1],Un[k*(dim+1)+2]) + #sauvegarde de la donnée initiale + pressure_field.setTime(time,it); + pressure_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_velocity"); + + dx_min=my_mesh.minRatioVolSurf() + + divMat=cdmath.SparseMatrixPetsc(nbCells*(1+dim),nbCells*(1+dim),(nbVoisinsMax+1)*(1+dim)) + if( isImplicit): + iterGMRESMax=50 + LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU") + + print("Starting computation of the linear wave system with an explicit UPWIND scheme …") + + # Starting time loop + while (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]*c0*c0 + velocity_field[k,0]=Un[k*(dim+1)+1]/Un[k*(dim+1)+0] + if(dim>1): + velocity_field[k,1]=Un[k*(dim+1)+2]/Un[k*(dim+1)+0] + if(dim>2): + velocity_field[k,2]=Un[k*(dim+1)+3]/Un[k*(dim+1)+0] +# print(Un[k*(dim+1)+0],Un[k*(dim+1)+1],Un[k*(dim+1)+2]) + + pressure_field.setTime(time,it); + pressure_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"EulerSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat") + PV_routines.Save_PV_data_to_picture_file("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"EulerSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + + +def solve(my_mesh,filename,resolution, isImplicit): + print( "Resolution of the Euler system in dimension ", my_mesh.getSpaceDimension()) + if( my_mesh.getSpaceDimension()!=2): + raise ValueError("Only dimension 2 simulations allowed") + print( "Numerical method : upwind") + print( "Initial data : spherical wave") + print( "Wall boundary conditions") + print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") + + # Problem data + tmax = 1. + ntmax = 1 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + EulerSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) + +def solve_file( filename,resolution, isImplicit): + my_mesh = cdmath.Mesh(filename+".med") + solve(my_mesh, filename,resolution, isImplicit) + +if __name__ == """__main__""": + if len(sys.argv) >2 : + filename=sys.argv[1] + isImplicit=bool(int(sys.argv[2])) + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100, isImplicit) + else : + raise ValueError("EulerSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt deleted file mode 100755 index a4899a3..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleEulerSystem_1DShock_ConservativeStaggered ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DConservativeStaggered.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py deleted file mode 100644 index c1158ac..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DConservativeStaggered/EulerSystem1DConservativeStaggered.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -# Isothermal Euler system -# d rho/d t + d q/d x =0 -# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho -# UU = (rho,q) : conservative variable -# Scheme : Conservative stagerred scheme (Ait Ameur et al) -# Author : Katia Ait Ameur -# Date : November 2020 - -import cdmath -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -from math import sqrt - -c0=330.#reference sound speed for water at 15 bars -precision=1e-5 -rho0=1 - -def initial_conditions_Riemann_problem(a,b,nx): - print("Initial data Riemann problem") - dx = (b - a) / nx #space step - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - rho_initial = [ (xi<(a+b)/2)*rho0 + (xi>=(a+b)/2)*rho0*2 for xi in x] - q_initial = [ (xi<(a+b)/2)*rho0*(-300) + (xi>=(a+b)/2)*rho0*2*(-300) for xi in x] - - return rho_initial, q_initial - -def matrix_coef(rho_l,q_l,rho_r,q_r): - m_coef = -0.5*(q_l-q_r)/rho_r - return m_coef - -def jacobianMatricesm(coeff,rho_l,q_l,rho_r,q_r): - RoeMat = cdmath.Matrix(2,2); - Dmac = cdmath.Matrix(2,2); - - u_l=q_l/rho_l - u_r=q_r/rho_r - Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_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)); - RoeMat[0,0] = 0 - RoeMat[0,1] = 1 - RoeMat[1,0] = c0*c0 - u*u - RoeMat[1,1] = 2*u - - Dmac[0,0]= abs(u)-u; - Dmac[0,1]= 1; - Dmac[1,0]= -c0*c0-u*u; - Dmac[1,1]= abs(u)+u; - - return (RoeMat-Dmac)*coeff*0.5 - -def jacobianMatricesp(coeff,rho_l,q_l,rho_r,q_r): - RoeMat = cdmath.Matrix(2,2); - Dmac = cdmath.Matrix(2,2); - - u_l=q_l/rho_l - u_r=q_r/rho_r - Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_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)); - RoeMat[0,0] = 0 - RoeMat[0,1] = 1 - RoeMat[1,0] = c0*c0 - u*u - RoeMat[1,1] = 2*u - - Dmac[0,0]= abs(u)-u; - Dmac[0,1]= 1; - Dmac[1,0]= -c0*c0-u*u; - Dmac[1,1]= abs(u)+u; - - return (RoeMat+Dmac)*coeff*0.5 - -def EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName): - dim=1 - nbComp=dim+1 - nbCells = nx - dt = 0. - dx=(b-a)/nx - dt = cfl * dx / c0 - nbVoisinsMax=2 - - time = 0. - it=0; - iterGMRESMax=50 - newton_max = 50 - isStationary=False - - #iteration vectors - Un =cdmath.Vector(nbCells*(dim+1)) - dUn=cdmath.Vector(nbCells*(dim+1)) - dUk=cdmath.Vector(nbCells*(dim+1)) - Rhs=cdmath.Vector(nbCells*(dim+1)) - - # Initial conditions # - print("Construction of the initial condition …") - rho_field, q_field = initial_conditions_Riemann_problem(a,b,nx) - v_field = [ q_field[i]/rho_field[i] for i in range(nx)] - p_field = [ rho_field[i]*(c0*c0) for i in range(nx)] - - max_initial_rho=max(rho_field) - min_initial_rho=min(rho_field) - max_initial_q=max(q_field) - min_initial_q=min(q_field) - max_initial_p=max(p_field) - min_initial_p=min(p_field) - max_initial_v=max(v_field) - min_initial_v=min(v_field) - - for k in range(nbCells): - Un[k*nbComp+0] = rho_field[k] - Un[k*nbComp+1] = q_field[k] - - print("Starting computation of the non linear Euler system with staggered scheme …") - divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) - - # Picture settings - fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) - fig.suptitle('Conservative staggered scheme') - lineDensity, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma - axDensity.set(xlabel='x (m)', ylabel='Density') - axDensity.set_xlim(a,b) - axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) - axDensity.legend() - lineMomentum, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') - axMomentum.set(xlabel='x (m)', ylabel='Momentum') - axMomentum.set_xlim(a,b) - axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) - axMomentum.legend() - lineVelocity, = axVelocity.plot([a+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') - axVelocity.set(xlabel='x (m)', ylabel='Velocity') - axVelocity.set_xlim(a,b) - axVelocity.set_ylim(min_initial_v - 0.4*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) - axVelocity.legend() - linePressure, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') - axPressure.set(xlabel='x (m)', ylabel='Pressure') - axPressure.set_xlim(a,b) - axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) - axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) - axPressure.legend() - - # Video settings - FFMpegWriter = manimation.writers['ffmpeg'] - metadata = dict(title="Conservative staggered scheme for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") - writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') - with writer.saving(fig, "1DEuler_System_ConservativeStaggered"+".mp4", ntmax): - writer.grab_frame() - plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_0"+".png") - - # Starting time loop - while (it precision ): - #DEBUT BOUCLE NEWTON - divMat.zeroEntries()#sets the matrix coefficients to zero - for j in range(nbCells):# - if ( j==0) : - rho_r = Uk[j*nbComp+0] - q_r = Uk[j*nbComp+1] - rho_l = rho_r # Conditions de Neumann - q_l = q_r - Am= jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r) - divMat.addValue(j*nbComp,(j+1)*nbComp,Am) - divMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - dUi=cdmath.Vector(2) - dUi[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0] - dUi[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1] - temp=cdmath.Vector(2) - temp = Am*dUi - #print("Bloc 0 matrix : ", Am) - Rhs[j*nbComp+0] = -temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0]) - Rhs[j*nbComp+1] = -temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1]) - elif ( j==nbCells-1) : - rho_l = Uk[j*nbComp+0] - q_l = Uk[j*nbComp+1] - rho_r = rho_l # Conditions de Neumann - q_r = q_l - Ap= jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r) - divMat.addValue(j*nbComp, j*nbComp,Ap) - divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.)) - dUi=cdmath.Vector(2) - dUi[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0] - dUi[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1] - temp=cdmath.Vector(2) - temp = Ap*dUi - Rhs[j*nbComp+0] = temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0]) - Rhs[j*nbComp+1] = temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1]) - else : - rho_l = Uk[(j-1)*nbComp+0] - q_l = Uk[(j-1)*nbComp+1] - rho_r = Uk[j*nbComp+0] - q_r = Uk[j*nbComp+1] - Ap = jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r) - ############################################################### - rho_l = Uk[j*nbComp+0] - q_l = Uk[j*nbComp+1] - rho_r = Uk[(j+1)*nbComp+0] - q_r = Uk[(j+1)*nbComp+1] - Am = jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r) - divMat.addValue(j*nbComp,(j+1)*nbComp,Am) - divMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - divMat.addValue(j*nbComp, j*nbComp,Ap) - divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.)) - dUi1=cdmath.Vector(2) - dUi2=cdmath.Vector(2) - dUi1[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0] - dUi1[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1] - dUi2[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0] - dUi2[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1] - temp1 = cdmath.Vector(2) - temp2 = cdmath.Vector(2) - temp1 = Am*dUi1 - temp2 = Ap*dUi2 - Rhs[j*nbComp+0] = -temp1[0] + temp2[0] -(Uk[j*nbComp+0]-Un[j*nbComp+0]) - Rhs[j*nbComp+1] = -temp1[1] + temp2[1] -(Uk[j*nbComp+1]-Un[j*nbComp+1]) - divMat.diagonalShift(1)#only after filling all coefficients - LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU") - dUk=LS.solve(); - residu = dUk.norm() - #stop - Uk+=dUk - if(not LS.getStatus()): - print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations") - raise ValueError("Pas de convergence du système linéaire"); - k=k+1 - Un = Uk.deepCopy() - dUn-=Un - for k in range(nbCells): - rho_field[k] = Un[k*(dim+1)+0] - q_field[k] = Un[k*(dim+1)+1] - v_field = [ q_field[i]/rho_field[i] for i in range(nx)] - p_field = [ rho_field[i]*(c0*c0) for i in range(nx)] - - lineDensity.set_ydata(rho_field) - lineMomentum.set_ydata(q_field) - lineVelocity.set_ydata(v_field) - linePressure.set_ydata(p_field) - writer.grab_frame() - - 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("Last linear system converged in ", LS.getNumberOfIter(), " GMRES iterations", ", residu final: ",residu) - - plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_"+str(it)+".png") - print - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - if(it>=ntmax): - print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - return - elif(isStationary): - print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print("------------------------------------------------------------------------------------") - plt.savefig("EulerSystem"+str(dim)+"Staggered"+meshName+"_Stat.png") - return - else: - print("Temps maximum Tmax= ", tmax, " atteint") - return - -def solve( a,b,nx, meshName, meshType, cfl): - print("Resolution of the Euler system in dimension 1 on "+str(nx)+ " cells") - print("Initial data : ", "Riemann problem") - print("Boundary conditions : ", "Neumann") - print("Mesh name : ",meshName , ", ", nx, " cells") - # Problem data - tmax = 10. - ntmax = 50 - output_freq = 10 - EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName) - return - -if __name__ == """__main__""": - a=0. - b=1. - nx=100 - cfl=0.99 - solve( a,b,nx,"SquareRegularSquares","RegularSquares",cfl) diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt deleted file mode 100755 index 8b41b92..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleEulerSystem_1DShock_UpwindExplicit ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DUpwind.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py deleted file mode 100644 index ee66cd1..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwind/EulerSystem1DUpwind.py +++ /dev/null @@ -1,199 +0,0 @@ -# Isothermal Euler system -# d rho/d t + d q/d x =0 -# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho -# UU = (rho,q) : conservative variable -# Scheme : Roe scheme (without any entropy correction) -# Comment : the solution displays a non entropic (non physical) shock instead of a rarefaction wave -# Date : November 2020 - -from cdmath import * -import numpy as np -from math import sqrt - -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation - -c0=330.#reference sound speed for water at 15 bars -precision=1e-5 - -def flux(rho,q): - fl = Vector(2); - fl[0] = q; - fl[1] = q*q/rho + c0*c0*rho; - return fl - -def compTimeStep(UU,dx,CFL): - M = UU.getMesh(); - maxAbsEigVa = 0; - for i in range(M.getNumberOfCells()): - maxAbsEigVa = max(maxAbsEigVa,abs(UU[i,1]/UU[i,0]+c0),abs(UU[i,1]/UU[i,0]-c0)); - pass - dt = CFL*dx/maxAbsEigVa; - return dt - -def AbsRoeMatrix(rho_l,q_l,rho_r,q_r): - AbsRoeMa = Matrix(2,2); - u_l = q_l/rho_l; - u_r = q_r/rho_r; - u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - AbsRoeMa[0,0]=(abs(u-c0)*(u+c0)+abs(u+c0)*(c0-u))/(2*c0); - AbsRoeMa[0,1]= (abs(u+c0)-abs(u-c0))/(2*c0); - AbsRoeMa[1,0]=(abs(u-c0)*(u*u-c0*c0)+abs(u+c0)*(c0*c0-u*u))/(2*c0); - AbsRoeMa[1,1]=((u+c0)*abs(u+c0)-(u-c0)*abs(u-c0))/(2*c0); - return AbsRoeMa; - -def main(meshName): - # mesh definition - xmin=.0; - xmax= 1; - nx=100#1000; - ntmax=50; - dx = (xmax-xmin)/nx; - M=Mesh(xmin,xmax,nx); - dim=1 - - # initial time - time=0.; - # maximum time T - tmax=0.01; - it=0; - freqSortie=10; - # CFL condition - CFL=0.99; - # conservative variable (unknown) - UU=Field("Conservative variables",CELLS,M,2); - - # initial condition for Riemann problem - print("Construction of the initial condition …") - rhoL=1 - vL=-300 - rhoR=1.45 - vR=-300 - for i in range(M.getNumberOfCells()): - x=M.getCell(i).x(); - if x < (xmax-xmin)/2: - UU[i,0] = rhoL; - UU[i,1] = rhoL*vL; - else: - UU[i,0] = rhoR; - UU[i,1] = rhoR*vR; - pass - - rho_field = [ UU[i,0] for i in range(nx)] - q_field = [ UU[i,1] for i in range(nx)] - v_field = [ UU[i,1]/UU[i,0] for i in range(nx)] - p_field = [ UU[i,0]*(c0*c0) for i in range(nx)] - - max_initial_rho=max(rhoL,rhoR) - min_initial_rho=min(rhoL,rhoR) - max_initial_p=max_initial_rho*c0*c0 - min_initial_p=min_initial_rho*c0*c0 - max_initial_v=max(vL,vR) - min_initial_v=min(vL,vR) - max_initial_q=max(vL*rhoL,vR*rhoR) - min_initial_q=min(vL*rhoL,vR*rhoR) - - print( "Numerical solution of the 1D Euler equation") - - # prepare some memory - UU_limL = Vector(2); - UU_limR = Vector(2); - Del_UU_RL = Vector(2); - UU_new = UU; - - # Picture settings - fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) - fig.suptitle('Explicit Upwind scheme') - lineDensity, = axDensity.plot([xmin+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma - axDensity.set(xlabel='x (m)', ylabel='Density') - axDensity.set_xlim(xmin,xmax) - axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) - axDensity.legend() - lineMomentum, = axMomentum.plot([xmin+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') - axMomentum.set(xlabel='x (m)', ylabel='Momentum') - axMomentum.set_xlim(xmin,xmax) - axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) - axMomentum.legend() - lineVelocity, = axVelocity.plot([xmin+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') - axVelocity.set(xlabel='x (m)', ylabel='Velocity') - axVelocity.set_xlim(xmin,xmax) - axVelocity.set_ylim(min_initial_v - 0.25*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) - axVelocity.legend() - linePressure, = axPressure.plot([xmin+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') - axPressure.set(xlabel='x (m)', ylabel='Pressure') - axPressure.set_xlim(xmin,xmax) - axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) - axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) - axPressure.legend() - - # Video settings - FFMpegWriter = manimation.writers['ffmpeg'] - metadata = dict(title="Upwind (Roe) scheme for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") - writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') - with writer.saving(fig, "1DEuler_System_Upwind"+".mp4", ntmax): - writer.grab_frame() - plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_0"+".png") - - # loop in time - while (it=ntmax): - print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - return - elif(isStationary): - print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print("------------------------------------------------------------------------------------") - plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_Stat.png") - return - else: - print("Temps maximum Tmax= ", tmax, " atteint") - - return - -if __name__ == '__main__': - main("SquareRegularSquares") diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt deleted file mode 100755 index 655c40f..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleEulerSystem_1DShock_UpwindExplicit_EntrCorr ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystem1DUpwindEntrCorr.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py b/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py deleted file mode 100644 index e1ae7f0..0000000 --- a/CDMATH/tests/examples/EulerSystem1D/EulerSystem1DUpwindEntrCorr/EulerSystem1DUpwindEntrCorr.py +++ /dev/null @@ -1,199 +0,0 @@ -# Isothermal Euler system -# d rho/d t + d q/d x =0 -# d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho -# UU = (rho,q) : conservative variable -# Scheme : Roe scheme with entropy correction -# Comment : If one removes the entropic correction the result displays a non entropic (non physical) shock instead of a rarefaction wave -# Date : November 2020 - -from cdmath import * -import numpy as np -from math import sqrt - -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation - -c0=330.#reference sound speed for water at 15 bars -precision=1e-5 - -def flux(rho,q): - fl = Vector(2); - fl[0] = q; - fl[1] = q*q/rho + c0*c0*rho; - return fl - -def compTimeStep(UU,dx,CFL): - M = UU.getMesh(); - maxAbsEigVa = 0; - for i in range(M.getNumberOfCells()): - maxAbsEigVa = max(maxAbsEigVa,abs(UU[i,1]/UU[i,0]+c0),abs(UU[i,1]/UU[i,0]-c0)); - pass - dt = CFL*dx/maxAbsEigVa; - return dt - -def AbsRoeMatrix(rho_l,q_l,rho_r,q_r): - AbsRoeMa = Matrix(2,2); - u_l = q_l/rho_l; - u_r = q_r/rho_r; - u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - AbsRoeMa[0,0]=(abs(u-c0)*(u+c0)+abs(u+c0)*(c0-u))/(2*c0); - AbsRoeMa[0,1]= (abs(u+c0)-abs(u-c0))/(2*c0); - AbsRoeMa[1,0]=(abs(u-c0)*(u*u-c0*c0)+abs(u+c0)*(c0*c0-u*u))/(2*c0); - AbsRoeMa[1,1]=((u+c0)*abs(u+c0)-(u-c0)*abs(u-c0))/(2*c0); - return AbsRoeMa; - -def main(meshName): - # mesh definition - xmin=.0; - xmax= 1; - nx=200#1000; - ntmax=100; - dx = (xmax-xmin)/nx; - M=Mesh(xmin,xmax,nx); - dim=1 - - # initial time - time=0.; - # maximum time T - tmax=0.01; - it=0; - freqSortie=10; - # CFL condition - CFL=0.9; - # conservative variable (unknown) - UU=Field("Conservative variables",CELLS,M,2); - - # initial condition for Riemann problem - print("Construction of the initial condition …") - rhoL=1 - vL=-300 - rhoR=2 - vR=-300 - for i in range(M.getNumberOfCells()): - x=M.getCell(i).x(); - if x < (xmax-xmin)/2: - UU[i,0] = rhoL; - UU[i,1] = rhoL*vL; - else: - UU[i,0] = rhoR; - UU[i,1] = rhoR*vR; - pass - - rho_field = [ UU[i,0] for i in range(nx)] - q_field = [ UU[i,1] for i in range(nx)] - v_field = [ UU[i,1]/UU[i,0] for i in range(nx)] - p_field = [ UU[i,0]*(c0*c0) for i in range(nx)] - - max_initial_rho=max(rhoL,rhoR) - min_initial_rho=min(rhoL,rhoR) - max_initial_p=max_initial_rho*c0*c0 - min_initial_p=min_initial_rho*c0*c0 - max_initial_v=max(vL,vR) - min_initial_v=min(vL,vR) - max_initial_q=max(vL*rhoL,vR*rhoR) - min_initial_q=min(vL*rhoL,vR*rhoR) - - print( "Numerical solution of the 1D Euler equation") - - # prepare some memory - UU_limL = Vector(2); - UU_limR = Vector(2); - Del_UU_RL = Vector(2); - UU_new = UU; - - # Picture settings - fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10)) - fig.suptitle('Explicit Upwind scheme') - lineDensity, = axDensity.plot([xmin+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma - axDensity.set(xlabel='x (m)', ylabel='Density') - axDensity.set_xlim(xmin,xmax) - axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) ) - axDensity.legend() - lineMomentum, = axMomentum.plot([xmin+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum') - axMomentum.set(xlabel='x (m)', ylabel='Momentum') - axMomentum.set_xlim(xmin,xmax) - axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) ) - axMomentum.legend() - lineVelocity, = axVelocity.plot([xmin+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity') - axVelocity.set(xlabel='x (m)', ylabel='Velocity') - axVelocity.set_xlim(xmin,xmax) - axVelocity.set_ylim(min_initial_v - 0.4*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) ) - axVelocity.legend() - linePressure, = axPressure.plot([xmin+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure') - axPressure.set(xlabel='x (m)', ylabel='Pressure') - axPressure.set_xlim(xmin,xmax) - axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) ) - axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) - axPressure.legend() - - # Video settings - FFMpegWriter = manimation.writers['ffmpeg'] - metadata = dict(title="Upwind (Roe) scheme with entropic correction for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube") - writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') - with writer.saving(fig, "1DEuler_System_Upwind"+".mp4", ntmax): - writer.grab_frame() - plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_0"+".png") - - # loop in time - while (it=ntmax): - print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - return - elif(isStationary): - print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print("------------------------------------------------------------------------------------") - plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_Stat.png") - return - else: - print("Temps maximum Tmax= ", tmax, " atteint") - - return - -if __name__ == '__main__': - main("SquareRegularSquares") diff --git a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt deleted file mode 100755 index 211c08d..0000000 --- a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleEulerSystem_2DShock_ConservativeStaggered ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerIsothermal_2DConservativeStaggered.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py b/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py deleted file mode 100644 index 5480b7e..0000000 --- a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemStaggered/EulerIsothermal_2DConservativeStaggered.py +++ /dev/null @@ -1,798 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF des équations d'Euler isotherme 2D sans terme source -# \partial_t rho + \div q = 0 -# \partial_t q + \div q \otimes q/rho \grad p = 0 -# Author : Michaël Ndjinga, Coraline Mounier -# Copyright : CEA Saclay 2020 -# Description : Propagation d'une onde de choc droite -# Utilisation du schéma upwind explicite ou implicite sur un maillage général -# Initialisation par une discontinuité verticale -# Conditions aux limites de Neumann -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -import cdmath -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -from math import sqrt -import sys -import PV_routines - -p0=155.e5 #reference pressure in a pressurised nuclear vessel -c0=700. #reference sound speed for water at 155 bars -rho0=p0/(c0*c0) #reference density -precision=1e-5 - -def initial_conditions_Riemann_problem(my_mesh): - print( "Initial data : Riemann problem" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - xcentre = 0.5 - - density_field = cdmath.Field("Density", cdmath.CELLS, my_mesh, 1) - q_x_field = cdmath.Field("Momentum x", cdmath.CELLS, my_mesh, 1) - q_y_field = cdmath.Field("Momentum y", cdmath.CELLS, my_mesh, 1) - #Velocity field with 3 components should be created for streamlines to be drawn - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - - # Initial momentum is zero - q_x_field[i] = 0 - q_y_field[i] = 0 - - # Initial velocity is zero - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - if x < xcentre: - density_field[i] = rho0 - pass - else: - density_field[i] = rho0/2 - pass - pass - - return density_field, q_x_field, q_y_field, velocity_field - - -def jacobianMatricesm_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): - RoeMatx = cdmath.Matrix(3,3); - Dmacx = cdmath.Matrix(3,3); - - u_lx=q_lx/rho_l - u_rx=q_rx/rho_r - u_ly=q_ly/rho_l - u_ry=q_ry/rho_r - if rho_l<0 or rho_r<0: - print("rho_l=",rho_l, " rho_r= ",rho_r) - raise ValueError("Negative density") - ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - - RoeMatx[0,0] = 0 - RoeMatx[0,1] = 1 - RoeMatx[0,2] = 0 - RoeMatx[1,0] = c0*c0 - ux*ux - RoeMatx[1,1] = 2*ux - RoeMatx[1,2] = 0 - RoeMatx[2,0] = -ux*uy - RoeMatx[2,1] = uy - RoeMatx[2,2] = ux - - Dmacx[0,0] = abs(ux)-ux - Dmacx[0,1] = 1 - Dmacx[0,2] = 0 - Dmacx[1,0] = -c0*c0-ux*ux - Dmacx[1,1] = abs(ux)+ux - Dmacx[1,2] = 0 - Dmacx[2,0] = -ux*uy - Dmacx[2,1] = uy - Dmacx[2,2] = abs(ux) - - return (RoeMatx-Dmacx)*coeff*0.5 - -def jacobianMatricesp_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): - RoeMatx = cdmath.Matrix(3,3) - Dmacx = cdmath.Matrix(3,3) - - u_lx=q_lx/rho_l - u_rx=q_rx/rho_r - u_ly=q_ly/rho_l - u_ry=q_ry/rho_r - if rho_l<0 or rho_r<0: - print("rho_l=",rho_l, " rho_r= ",rho_r) - raise ValueError("Negative density") - ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - - RoeMatx[0,0] = 0 - RoeMatx[0,1] = 1 - RoeMatx[0,2] = 0 - RoeMatx[1,0] = c0*c0 - ux*ux - RoeMatx[1,1] = 2*ux - RoeMatx[1,2] = 0 - RoeMatx[2,0] = -ux*uy - RoeMatx[2,1] = uy - RoeMatx[2,2] = ux - - Dmacx[0,0] = abs(ux)-ux - Dmacx[0,1] = 1 - Dmacx[0,2] = 0 - Dmacx[1,0] = -c0*c0-ux*ux - Dmacx[1,1] = abs(ux)+ux - Dmacx[1,2] = 0 - Dmacx[2,0] = -ux*uy - Dmacx[2,1] = uy - Dmacx[2,2] = abs(ux) - - return (RoeMatx+Dmacx)*coeff*0.5 - -def jacobianMatricesm_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): - RoeMaty = cdmath.Matrix(3,3); - Dmacy = cdmath.Matrix(3,3); - - u_lx=q_lx/rho_l - u_rx=q_rx/rho_r - u_ly=q_ly/rho_l - u_ry=q_ry/rho_r - if rho_l<0 or rho_r<0: - print("rho_l=",rho_l, " rho_r= ",rho_r) - raise ValueError("Negative density") - ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - - RoeMaty[0,0] = 0 - RoeMaty[0,1] = 0 - RoeMaty[0,2] = 1 - RoeMaty[1,0] = -ux*uy - RoeMaty[1,1] = uy - RoeMaty[1,2] = ux - RoeMaty[2,0] = c0*c0-uy*uy - RoeMaty[2,1] = 0 - RoeMaty[2,2] = 2*uy - - Dmacy[0,0] = abs(uy)-uy - Dmacy[0,1] = 0 - Dmacy[0,2] = 1 - Dmacy[1,0] = -ux*uy - Dmacy[1,1] = abs(uy) - Dmacy[1,2] = ux - Dmacy[2,0] = -c0*c0-uy*uy - Dmacy[2,1] = 0 - Dmacy[2,2] = abs(uy)+uy - - return (RoeMaty-Dmacy)*coeff*0.5 - -def jacobianMatricesp_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry): - RoeMaty = cdmath.Matrix(3,3); - Dmacy = cdmath.Matrix(3,3); - - u_lx=q_lx/rho_l - u_rx=q_rx/rho_r - u_ly=q_ly/rho_l - u_ry=q_ry/rho_r - if rho_l<0 or rho_r<0: - print("rho_l=",rho_l, " rho_r= ",rho_r) - raise ValueError("Negative density") - ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - - RoeMaty[0,0] = 0 - RoeMaty[0,1] = 0 - RoeMaty[0,2] = 1 - RoeMaty[1,0] = -ux*uy - RoeMaty[1,1] = uy - RoeMaty[1,2] = ux - RoeMaty[2,0] = c0*c0-uy*uy - RoeMaty[2,1] = 0 - RoeMaty[2,2] = 2*uy - - Dmacy[0,0] = abs(uy)-uy - Dmacy[0,1] = 0 - Dmacy[0,2] = 1 - Dmacy[1,0] = -ux*uy - Dmacy[1,1] = abs(uy) - Dmacy[1,2] = ux - Dmacy[2,0] = -c0*c0-uy*uy - Dmacy[2,1] = 0 - Dmacy[2,2] = abs(uy)+uy - - return (RoeMaty+Dmacy)*coeff*0.5 - -def EulerSystemStaggered(ntmax, tmax, cfl,output_freq, my_mesh, meshName): - - if not my_mesh.isStructured() : - raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a structured mesh") - - dim=my_mesh.getMeshDimension() - if dim != 2 : - raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a 2D mesh") - - nbComp=dim+1 - # Mesh parameters - nbCells = my_mesh.getNumberOfCells() - nbCells_x = my_mesh.getNx() - nbCells_y = my_mesh.getNy() - dx,dy = my_mesh.getDXYZ() - nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) - dx_min=my_mesh.minRatioVolSurf() - - # Time evolution parameters - time = 0. - it=0; - isStationary=False - iterGMRESMax = 50 - newton_max = 50 - - #iteration vectors - Un =cdmath.Vector(nbCells*nbComp) - dUn=cdmath.Vector(nbCells*nbComp) - dUk=cdmath.Vector(nbCells*nbComp) - Rhs=cdmath.Vector(nbCells*nbComp) - - dUi_x=cdmath.Vector(nbComp) - dUi_y=cdmath.Vector(nbComp) - dUi1_x=cdmath.Vector(nbComp) - dUi2_x=cdmath.Vector(nbComp) - dUi1_y=cdmath.Vector(nbComp) - dUi2_y=cdmath.Vector(nbComp) - - # Initial conditions # - print("Construction of the initial condition …") - rho_field, q_x_field, q_y_field, velocity_field= initial_conditions_Riemann_problem(my_mesh) - - for i in range(nbCells): - Un[nbComp*i] = rho_field[i] - Un[nbComp*i+1] = q_x_field[i] - Un[nbComp*i+2] = q_y_field[i] - - #Sauvegarde de la donnée initiale - rho_field.setTime(time,it); - rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density"); - q_x_field.setTime(time,it); - q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX"); - q_y_field.setTime(time,it); - q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity"); - - print("Starting computation of the isothermal Euler system with a conservative staggered scheme …") - divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) - - # Starting time loop - while (it 1/precision ): - - dt = cfl * dx_min / c0# This choice should be improved when possible by using the actual eigenvalue abs(u)+c0, that is the time step should be determined avec the computation of the jacobian matrices - #DEBUT BOUCLE NEWTON - for j in range(nbCells_y): - for i in range(nbCells_x): - #Traitement des coins - if ( j==0 and i==0) : - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)-Am_y) - - dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - - temp_x = Am_x*dUi_x - temp_y = Am_y*dUi_y - #print("Bloc 0 matrix : ", Am) - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0] - temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1] - temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2] - temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif(i==0 and j==nbCells_y-1): - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)+Ap_y) - - dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp_x = Am_x*dUi_x - temp_y = Ap_y*dUi_y - #print("Bloc 0 matrix : ", Am) - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]- temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]- temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]- temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif(i==nbCells_x-1 and j==0): - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_y) - - dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - - temp_x = Ap_x*dUi_x - temp_y= Am_y*dUi_y - #print("Bloc 0 matrix : ", Am) - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]- temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]- temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]- temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif ( j==nbCells_y-1 and i==nbCells_x-1) : - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y) - - dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp_x = Ap_x*dUi_x - temp_y = Ap_y*dUi_y - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - #Traitement des bords restants - elif i==0 : - - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #remplissage de la divMat - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y-Am_x-Am_y) - - #remplissage du membre de droite - dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp_x = Am_x*dUi_x - temp1_y = Am_y*dUi1_y - temp2_y = Ap_y*dUi2_y - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif i==nbCells_x-1: - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #remplissage de la divMat - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y+Ap_x-Am_y) - - #remplissage du membre de droite - dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp_x = Ap_x*dUi_x - temp1_y = Am_y*dUi1_y - temp2_y = Ap_y*dUi2_y - Rhs[3*nbCells_x*j+3*i+0] = -temp_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif j==0: - - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #remplissage de la divMat - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_x-Am_y) - - #remplissage du membre de droite - dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - - temp1_x = Am_x*dUi1_x - temp2_x = Ap_x*dUi2_x - temp_y = Am_y*dUi_y - Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - elif j==nbCells_y-1: - - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #remplissage de la divMat - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x) - - #remplissage du membre de droite - dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp1_x = Am_x*dUi1_x - temp2_x = Ap_x*dUi2_x - temp_y = Ap_y*dUi_y - Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - #Traitement des autres cellules - else: - - #Calcul de Am_x - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*(i+1)] - qx_r =Uk[3*nbCells_x*j+3*(i+1)+1] - qy_r =Uk[3*nbCells_x*j+3*(i+1)+2] - Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #Calcul de Ap_x - rho_l=Uk[3*nbCells_x*j+3*(i-1)] - qx_l =Uk[3*nbCells_x*j+3*(i-1)+1] - qy_l =Uk[3*nbCells_x*j+3*(i-1)+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Am_y - rho_l=Uk[3*nbCells_x*j+3*i] - qx_l =Uk[3*nbCells_x*j+3*i+1] - qy_l =Uk[3*nbCells_x*j+3*i+2] - rho_r=Uk[3*nbCells_x*(j+1)+3*i] - qx_r =Uk[3*nbCells_x*(j+1)+3*i+1] - qy_r =Uk[3*nbCells_x*(j+1)+3*i+2] - Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #calcul de Ap_y - rho_l=Uk[3*nbCells_x*(j-1)+3*i] - qx_l =Uk[3*nbCells_x*(j-1)+3*i+1] - qy_l =Uk[3*nbCells_x*(j-1)+3*i+2] - rho_r=Uk[3*nbCells_x*j+3*i] - qx_r =Uk[3*nbCells_x*j+3*i+1] - qy_r =Uk[3*nbCells_x*j+3*i+2] - Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r) - - #remplissage de la divMat - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.)) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y) - divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x-Am_y) - - #remplissage du membre de droite - - dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i] - dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2] - - dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)] - dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1] - dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2] - - dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i] - dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1] - dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2] - - dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i] - dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1] - dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2] - - temp1_x = Am_x*dUi1_x - temp2_x = Ap_x*dUi2_x - temp1_y = Am_y*dUi1_y - temp2_y = Ap_y*dUi2_y - Rhs[3*nbCells_x*j+3*i+0] = -temp1_x[0]-temp2_x[0]-temp1_y[0]-temp2_y[0]-(Uk[3*nbCells_x*j+3*i+0]-Un[3*nbCells_x*j+3*i+0]) - Rhs[3*nbCells_x*j+3*i+1] = -temp1_x[1]-temp2_x[1]-temp1_y[1]-temp2_y[1]-(Uk[3*nbCells_x*j+3*i+1]-Un[3*nbCells_x*j+3*i+1]) - Rhs[3*nbCells_x*j+3*i+2] = -temp1_x[2]-temp2_x[2]-temp1_y[2]-temp2_y[2]-(Uk[3*nbCells_x*j+3*i+2]-Un[3*nbCells_x*j+3*i+2]) - - divMat.diagonalShift(1) #only after filling all coefficients - LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU") - dUk=LS.solve(); - residu = dUk.norm() - Uk+=dUk - #print("Newton iteration number ",k, "residu = ",residu) - if(not LS.getStatus()): - print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations") - raise ValueError("Pas de convergence du système linéaire"); - k=k+1 - Un = Uk.deepCopy() - dUn-=Un - isStationary = dUn.norm()=ntmax or isStationary or time >=tmax): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) + ", Newton iterations: "+str(k)+", ||dUn|| = "+str(dUn.norm())) - print("Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations, résidu = ", residu) - for k in range(nbCells): - rho =rho_field[k] - velocity_field[k,0]=q_x_field[i]/rho - if(dim>1): - velocity_field[k,1]=q_y_field[k]/rho - print - rho_field.setTime(time,it); - rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density",False); - q_x_field.setTime(time,it); - q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX",False); - q_y_field.setTime(time,it); - q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity",False); - #Postprocessing : save 2D picture - PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density_" +str(it)+'.vtu',"Density", 'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density" +str(it)) - PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX_"+str(it)+'.vtu',"Momentum x",'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX"+str(it)) - PV_routines.Save_PV_data_to_picture_file("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY_"+str(it)+'.vtu',"Momentum y",'CELLS',"EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY"+str(it)) - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - if(it>=ntmax): - print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - return - elif(isStationary): - print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print("------------------------------------------------------------------------------------") - return - else: - print("Temps maximum Tmax= ", tmax, " atteint") - return - -def solve( my_mesh,filename, resolution): - print("Resolution of the Isothermal Euler system in dimension 2 on "+str(my_mesh.getNumberOfCells())+ " cells") - print("Initial data : ", "Riemann problem") - print("Boundary conditions : ", "Neumann") - print("Mesh name : ",filename ) - # Problem data - tmax = 10. - ntmax = 10 - cfl=1 - output_freq = 1 - EulerSystemStaggered(ntmax, tmax, cfl, output_freq, my_mesh, filename) - return - -if __name__ == """__main__""": - if len(sys.argv) >1 : - filename=sys.argv[1] - my_mesh = cdmath.Mesh(filename) - else : - filename = "CartesianGrid" - ax=0;bx=1;nx=20; - ay=0;by=1;ny=10; - my_mesh = cdmath.Mesh(ax,bx,nx,ay,by,ny) - - solve(my_mesh,filename,100) diff --git a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt deleted file mode 100755 index 857c261..0000000 --- a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/EulerSystemUpwind) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(IMPLICIT_SCHEME 0 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - #ADD_TEST(ExampleEulerSystem_3DShock_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - #ADD_TEST(ExampleEulerSystem_3DShock_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshHexagonWithTriangles.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindExplicit_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(IMPLICIT_SCHEME 1 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - #ADD_TEST(ExampleEulerSystem_3DShock_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - #ADD_TEST(ExampleEulerSystem_3DShock_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleEulerSystem_2DShock_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/EulerSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py b/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py deleted file mode 100755 index b969762..0000000 --- a/CDMATH/tests/examples/EulerSystem_Shock/EulerSystemUpwind/EulerSystemUpwind.py +++ /dev/null @@ -1,337 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système Euler 2D barotrope sans terme source -# \partial_t rho + \div q = 0 -# \partial_t q + \div q\otimes q/rho + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc sphérique -# Utilisation du schéma de Roe upwind explicite ou implicite sur un maillage général -# Initialisation par une surpression sphérique -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_shock(my_mesh, isCircle): - print( "Initial data : Spherical wave" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - rayon = 0.15 - if(not isCircle): - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - else: - xcentre = 0. - ycentre = 0. - zcentre = 0. - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - x = my_mesh.getCell(i).x() - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val = sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - - -def 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 = cdmath.Vector(2); u_l[0]*=q_l[0]/rho_l; u_l[1]*=q_l[1]/rho_l; - u_r = cdmath.Vector(2); u_r[0]*=q_r[0]/rho_r; u_r[1]*=q_r[1]/rho_r; - if rho_l<0 or rho_r<0 : - print( "rho_l=",rho_l, " rho_r= ",rho_r ) - raise ValueError("Negative density") - u=cdmath.Vector(2); - u[0] = (u_l[0]*sqrt(rho_l)+u_r[0]*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r)); - u[1] = (u_l[1]*sqrt(rho_l)+u_r[1]*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*0.5,un; - -def computeDivergenceMatrix(my_mesh,implMat,Un): - nbCells = my_mesh.getNumberOfCells() - dim=my_mesh.getMeshDimension() - nbComp=dim+1 - normal=cdmath.Vector(dim) - maxAbsEigVa = 0 - q_l=cdmath.Vector(2); - q_r=cdmath.Vector(2); - - 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 - - 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") - - q_l[0]=Un[j*nbComp+1] - q_l[1]=Un[j*nbComp+2] - q_r[0]=Un[cellAutre*nbComp+1] - q_r[1]=Un[cellAutre*nbComp+2] - Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],q_l,Un[cellAutre*nbComp],q_r); - - implMat.addValue(j*nbComp,cellAutre*nbComp,Am) - implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - else : - if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - q_l[0]=Un[j*nbComp+1] - q_l[1]=Un[j*nbComp+2] - q_r=q_l-normal*2*(q_l*normal) - Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],q_l,Un[j*nbComp],q_r); - - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - q_l[0]=Un[j*nbComp+1] - q_l[1]=Un[j*nbComp+2] - q_r[0]=Un[cellAutre*nbComp+1] - q_r[1]=Un[cellAutre*nbComp+2] - Am, un=jacobianMatrices( normal,Fk.getMeasure()/Cj.getMeasure(),Un[j*nbComp],Un[j*nbComp+1],Un[j*nbComp+2],Un[cellAutre*nbComp],Un[cellAutre*nbComp+1],Un[cellAutre*nbComp+2]); - - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - maxAbsEigVa = max(maxAbsEigVa,abs(un+c0),abs(un-c0)); - - return maxAbsEigVa - -def EulerSystemVF(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(dim==1 or 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_shock(my_mesh,False) - elif(filename.find("disk")>-1 or filename.find("Disk")>-1): - pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) - 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]/(c0*c0) - Un[k*(dim+1)+1] =rho0*velocity_field[k,0] - if(dim>=2): - Un[k*(dim+1)+2] = rho0*velocity_field[k,1] # value on the bottom face - if(dim==3): - Un[k*(dim+1)+3] = rho0*initial_velocity[k,2] - - #sauvegarde de la donnée initiale - pressure_field.setTime(time,it); - pressure_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_velocity"); - - dx_min=my_mesh.minRatioVolSurf() - - divMat=cdmath.SparseMatrixPetsc(nbCells*(1+dim),nbCells*(1+dim),(nbVoisinsMax+1)*(1+dim)) - if( isImplicit): - iterGMRESMax=50 - LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU") - - print("Starting computation of the linear wave system with an explicit UPWIND scheme …") - - # Starting time loop - while (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]*c0*c0 - 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("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"EulerSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat") - PV_routines.Save_PV_data_to_picture_file("EulerSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"EulerSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - - -def solve(my_mesh,filename,resolution, isImplicit): - print( "Resolution of the Euler system in dimension ", my_mesh.getSpaceDimension()) - if( my_mesh.getSpaceDimension()!=2): - raise ValueError("Only dimension 2 simulations allowed") - print( "Numerical method : upwind") - print( "Initial data : spherical wave") - print( "Wall boundary conditions") - print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") - - # Problem data - tmax = 1. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - EulerSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) - -def solve_file( filename,resolution, isImplicit): - my_mesh = cdmath.Mesh(filename+".med") - solve(my_mesh, filename,resolution, isImplicit) - -if __name__ == """__main__""": - if len(sys.argv) >2 : - filename=sys.argv[1] - isImplicit=bool(int(sys.argv[2])) - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100, isImplicit) - else : - raise ValueError("EulerSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/HeatEquation/CMakeLists.txt b/CDMATH/tests/examples/HeatEquation/CMakeLists.txt new file mode 100755 index 0000000..d023248 --- /dev/null +++ b/CDMATH/tests/examples/HeatEquation/CMakeLists.txt @@ -0,0 +1,14 @@ +file(GLOB HeatEquation_EXAMPLES_TO_INSTALL + HeatEquation1DExplicit HeatEquation1DImplicit# 1D Heat equation +) + +install(DIRECTORY ${HeatEquation_EXAMPLES_TO_INSTALL} DESTINATION share/examples/HeatEquation) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_SUBDIRECTORY(HeatEquation1DExplicit) + ADD_SUBDIRECTORY(HeatEquation1DImplicit) + +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/CMakeLists.txt b/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/CMakeLists.txt new file mode 100755 index 0000000..117a131 --- /dev/null +++ b/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/CMakeLists.txt @@ -0,0 +1,16 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 100 )#Number of cells + + SET(CFL 0.99 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleHeatEquation_1DFV_Explicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DExplicit.py ${NX} ${CFL}) + + SET(CFL 2 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleHeatEquation_1DFV_Explicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DExplicit.py ${NX} ${CFL}) + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/HeatEquation1DExplicit.py b/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/HeatEquation1DExplicit.py new file mode 100755 index 0000000..658941e --- /dev/null +++ b/CDMATH/tests/examples/HeatEquation/HeatEquation1DExplicit/HeatEquation1DExplicit.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF de l'équation de la chaleur 1D \partial_t u = d \partial_xx u avec conditions aux limites périodiques +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Maillage 1D régulier +# Création et sauvegarde du champ résultant et des figures +# Génération d'une video sauvegardée dans un fichier .mp4 +#================================================================================================================================ + + +from math import sin, pi, ceil +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from copy import deepcopy + +def HeatEquation1DExplicit(nx,cfl): + print( "Simulation of 1D heat equation with an explicit scheme") + + ##################### Simulation parameters + a = 0.0 # space domain : a <= x <= b + b = 1.0 + dx = (b - a) / nx #space step + + d = 1. # thermal diffusivity + tmax = (b-a)/d # runs the simulation for 0 <= t <= tMax + dt = cfl * dx *dx/ (2*d) + ntmax = 100 + + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + + ########################## Initial data + + u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial + assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial + + # Postprocessing + line1.set_ydata(u) + writer.grab_frame() + if (it % output_freq == 0): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + np.savetxt( "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") + plt.savefig("HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") + #plt.show() + + 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 heat equation with explicit scheme done.") + + #return min, max, total variation and l1 error + return min(u), max(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)]) + + +if __name__ == """__main__""": + if len(sys.argv) >2 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + HeatEquation1DExplicit(nx,cfl) + else : + nx = 50 # number of cells + cfl = 1 # c*dt/(2*dx) <= CFL + HeatEquation1DExplicit(nx,cfl) + diff --git a/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/CMakeLists.txt b/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/CMakeLists.txt new file mode 100755 index 0000000..623bb85 --- /dev/null +++ b/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/CMakeLists.txt @@ -0,0 +1,16 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 100 )#Number of cells + + SET(CFL 1 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleHeatEquation_1DFV_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DImplicit.py ${NX} ${CFL}) + + SET(CFL 2 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleHeatEquation_1DFV_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DImplicit.py ${NX} ${CFL}) + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/HeatEquation1DImplicit.py b/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/HeatEquation1DImplicit.py new file mode 100755 index 0000000..0090e51 --- /dev/null +++ b/CDMATH/tests/examples/HeatEquation/HeatEquation1DImplicit/HeatEquation1DImplicit.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF implicite de l'équation de la chaleur 1D \partial_t u = d \partial_xx u avec conditions aux limites périodiques +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Maillage 1D régulier +# Création et sauvegarde du champ résultant et des figures +# Génération d'une video sauvegardée dans un fichier .mp4 +#================================================================================================================================ + + +from math import sin, pi, ceil +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +import cdmath + +def implicitSchemeMatrix(nx,cfl): + implMat=cdmath.SparseMatrixPetsc(nx,nx,3) + for i in range(nx): + implMat.setValue(i,(i+1)%nx,-cfl) + implMat.setValue(i,i,1.+2*cfl) + implMat.setValue(i,(i-1)%nx,-cfl) + + return implMat + +def HeatEquation1DImplicit(nx,cfl): + print( "Simulation of 1D heat equation with an implicit scheme") + + ##################### Simulation parameters + a = 0.0 # space domain : a <= x <= b + b = 1.0 + dx = (b - a) / nx #space step + + d = 1. # thermal diffusivity + tmax = (b-a)/d # runs the simulation for 0 <= t <= tMax + dt = cfl * dx *dx/ (2*d) + ntmax = 100 + + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + + ########################## Initial data + + u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial + assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial + + time += dt + it += 1 + + # Postprocessing + line1.set_ydata(u) + writer.grab_frame() + if (it % output_freq == 0): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") + plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") + #plt.show() + + 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 heat equation with implicit scheme done.") + + #return min, max, total variation and l1 error + return min(u), max(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)]) + + +if __name__ == """__main__""": + if len(sys.argv) >2 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + HeatEquation1DImplicit(nx,cfl) + else : + nx = 50 # number of cells + cfl = 1 # c*dt/(2*dx) <= CFL + HeatEquation1DImplicit(nx,cfl) + diff --git a/CDMATH/tests/examples/HeatEquation1DExplicit/CMakeLists.txt b/CDMATH/tests/examples/HeatEquation1DExplicit/CMakeLists.txt deleted file mode 100755 index 117a131..0000000 --- a/CDMATH/tests/examples/HeatEquation1DExplicit/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 100 )#Number of cells - - SET(CFL 0.99 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleHeatEquation_1DFV_Explicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DExplicit.py ${NX} ${CFL}) - - SET(CFL 2 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleHeatEquation_1DFV_Explicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DExplicit.py ${NX} ${CFL}) - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/HeatEquation1DExplicit/HeatEquation1DExplicit.py b/CDMATH/tests/examples/HeatEquation1DExplicit/HeatEquation1DExplicit.py deleted file mode 100755 index 658941e..0000000 --- a/CDMATH/tests/examples/HeatEquation1DExplicit/HeatEquation1DExplicit.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF de l'équation de la chaleur 1D \partial_t u = d \partial_xx u avec conditions aux limites périodiques -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Maillage 1D régulier -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -from math import sin, pi, ceil -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -from copy import deepcopy - -def HeatEquation1DExplicit(nx,cfl): - print( "Simulation of 1D heat equation with an explicit scheme") - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - dx = (b - a) / nx #space step - - d = 1. # thermal diffusivity - tmax = (b-a)/d # runs the simulation for 0 <= t <= tMax - dt = cfl * dx *dx/ (2*d) - ntmax = 100 - - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - - ########################## Initial data - - u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial - assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial - - # Postprocessing - line1.set_ydata(u) - writer.grab_frame() - if (it % output_freq == 0): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - np.savetxt( "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") - plt.savefig("HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") - #plt.show() - - 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 heat equation with explicit scheme done.") - - #return min, max, total variation and l1 error - return min(u), max(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)]) - - -if __name__ == """__main__""": - if len(sys.argv) >2 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - HeatEquation1DExplicit(nx,cfl) - else : - nx = 50 # number of cells - cfl = 1 # c*dt/(2*dx) <= CFL - HeatEquation1DExplicit(nx,cfl) - diff --git a/CDMATH/tests/examples/HeatEquation1DImplicit/CMakeLists.txt b/CDMATH/tests/examples/HeatEquation1DImplicit/CMakeLists.txt deleted file mode 100755 index 623bb85..0000000 --- a/CDMATH/tests/examples/HeatEquation1DImplicit/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 100 )#Number of cells - - SET(CFL 1 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleHeatEquation_1DFV_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DImplicit.py ${NX} ${CFL}) - - SET(CFL 2 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleHeatEquation_1DFV_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/HeatEquation1DImplicit.py ${NX} ${CFL}) - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/HeatEquation1DImplicit/HeatEquation1DImplicit.py b/CDMATH/tests/examples/HeatEquation1DImplicit/HeatEquation1DImplicit.py deleted file mode 100755 index 0090e51..0000000 --- a/CDMATH/tests/examples/HeatEquation1DImplicit/HeatEquation1DImplicit.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF implicite de l'équation de la chaleur 1D \partial_t u = d \partial_xx u avec conditions aux limites périodiques -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Maillage 1D régulier -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -from math import sin, pi, ceil -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -import cdmath - -def implicitSchemeMatrix(nx,cfl): - implMat=cdmath.SparseMatrixPetsc(nx,nx,3) - for i in range(nx): - implMat.setValue(i,(i+1)%nx,-cfl) - implMat.setValue(i,i,1.+2*cfl) - implMat.setValue(i,(i-1)%nx,-cfl) - - return implMat - -def HeatEquation1DImplicit(nx,cfl): - print( "Simulation of 1D heat equation with an implicit scheme") - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - dx = (b - a) / nx #space step - - d = 1. # thermal diffusivity - tmax = (b-a)/d # runs the simulation for 0 <= t <= tMax - dt = cfl * dx *dx/ (2*d) - ntmax = 100 - - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - - ########################## Initial data - - u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial - assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial - - time += dt - it += 1 - - # Postprocessing - line1.set_ydata(u) - writer.grab_frame() - if (it % output_freq == 0): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") - plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") - #plt.show() - - 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 heat equation with implicit scheme done.") - - #return min, max, total variation and l1 error - return min(u), max(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)]) - - -if __name__ == """__main__""": - if len(sys.argv) >2 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - HeatEquation1DImplicit(nx,cfl) - else : - nx = 50 # number of cells - cfl = 1 # c*dt/(2*dx) <= CFL - HeatEquation1DImplicit(nx,cfl) - diff --git a/CDMATH/tests/examples/Poisson1DEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson1DEF/CMakeLists.txt deleted file mode 100755 index 5be4ec4..0000000 --- a/CDMATH/tests/examples/Poisson1DEF/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ - -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson1DEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_1DEF ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements1DPoisson.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson1DEF/FiniteElements1DPoisson.py b/CDMATH/tests/examples/Poisson1DEF/FiniteElements1DPoisson.py deleted file mode 100755 index 712b614..0000000 --- a/CDMATH/tests/examples/Poisson1DEF/FiniteElements1DPoisson.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 1D -\triangle u = f avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage 1D quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x) -#================================================================================================================================ - -import cdmath -from math import sin, pi, sqrt -from numpy import linspace -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -#Création d'un maillage uniforme du segment [0,1], définition des bords -#====================================================================== -nx=100 -my_mesh = cdmath.Mesh(0,1,nx) -if( my_mesh.getSpaceDimension()!=1 or my_mesh.getMeshDimension()!=1) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 1") - -eps=1e-6 -my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading/building done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Discrétisation du second membre et détermination des noeuds intérieurs -#====================================================================== -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() - - my_RHSfield[i]=pi*pi*sin(pi*x)#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) - -print("Right hand side discretisation done") -print("nb of interior nodes=", nbInteriorNodes) -print("nb of boundary nodes=", nbBoundaryNodes) -print("Max nb 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 segment (hypothèse 1D) -GradShapeFunc0=cdmath.Vector(1) -GradShapeFunc1=cdmath.Vector(1) - -#On parcourt les segments 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) - - N0=my_mesh.getNode(nodeId0) - N1=my_mesh.getNode(nodeId1) - - #Formule des gradients voir EF P1 -> calcul déterminants - GradShapeFunc0[0]= 1 - GradShapeFunc1[0]=-1 - - #Création d'un tableau (numéro du noeud, gradient de la fonction de forme - GradShapeFuncs={nodeId0 : GradShapeFunc0} - GradShapeFuncs[nodeId1]=GradShapeFunc1 - - # Remplissage de la matrice de rigidité et du second membre - for j in [nodeId0,nodeId1] : - 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 i au second membre du noeud j - RHS[j_int]=Ci.getMeasure()/2*my_RHSfield[j]+RHS[j_int] # intégrale sur le segment du produit f x fonction de base - #Contribution de la cellule i à la ligne j_int du système linéaire - for k in [nodeId0,nodeId1] : - 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 -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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("FiniteElements1DPoisson_ResultField") - -# Postprocessing : -#================= -# save 1D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElements1DPoisson_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements1DPoisson_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=linspace(0,1,resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,0,0], resolution) -plt.plot(curv_abs, diag_data, label= '1D mesh with '+str(nbNodes) + ' nodes') -plt.legend() -plt.xlabel('Position') -plt.ylabel('Value') -plt.title('1D finite elements \n for Laplace operator') -plt.savefig("FiniteElements1DPoisson_ResultField_"+str(nbNodes) + '_nodes'+".png") - -print("Numerical solution of the 1D Poisson equation 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 pi*pi -max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(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]/(pi*pi) - my_ResultField[i]) : - erreur_abs = abs(my_RHSfield[i]/(pi*pi) - my_ResultField[i]) - -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) -print("Maximum exact solution = ", my_RHSfield.max()/(pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(pi*pi)) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson1DVF/CMakeLists.txt b/CDMATH/tests/examples/Poisson1DVF/CMakeLists.txt deleted file mode 100755 index 2bde45f..0000000 --- a/CDMATH/tests/examples/Poisson1DVF/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_1DVF_uniform ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes1DPoisson.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson1DVF/FiniteVolumes1DPoisson.py b/CDMATH/tests/examples/Poisson1DVF/FiniteVolumes1DPoisson.py deleted file mode 100755 index 0f18320..0000000 --- a/CDMATH/tests/examples/Poisson1DVF/FiniteVolumes1DPoisson.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson 1D -\triangle u = f avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage 1D quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x) -#================================================================================================================================ - -import cdmath -from math import sin, pi -from numpy import linspace -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines -import sys - -if len(sys.argv) >1 :#non uniform mesh - my_mesh = cdmath.Mesh(sys.argv[1]) -else : #rectangular mesh -#Création d'un maillage uniforme du segment [0,1], définition des bords -#====================================================================== - nx=100 - my_mesh = cdmath.Mesh(0,1,nx) - -if( my_mesh.getSpaceDimension()!=1 or my_mesh.getMeshDimension()!=1) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 1") - -eps=1e-6 -my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT - -nbCells = my_mesh.getNumberOfCells() - -print( "Mesh loading/building 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() - - my_RHSfield[i]=pi*pi*sin(pi*x)#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( "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 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.addValue(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() - RHS[i]+=coeff*sin(pi*x)#mettre ici la solution exacte de l'edp - 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,100,1.E-6,"GMRES","ILU") -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print( "Linear system solved") - -# 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("FiniteVolumes1DPoisson_ResultField") - -#Postprocessing : -#=============== -# save 1D picture -PV_routines.Save_PV_data_to_picture_file("FiniteVolumes1DPoisson_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes1DPoisson_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=linspace(0,1,resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,0,0], resolution) -plt.legend() -plt.xlabel('Position') -plt.ylabel('Value') -if len(sys.argv) >1 : - plt.title('Finite Volumes \n for Laplace operator in 1D'+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes1DPoisson_ResultField_"+str(nbCells)+ '_cells'+".png") -else : - plt.title('Finite Volumes \n for Laplace operator on a 1D regular grid') - plt.plot(curv_abs, diag_data, label= str(nx) + ' cells mesh') - plt.savefig("FiniteVolumes1DPoisson_ResultField_"+str(nx) + '_cells'+".png") - -print("Numerical solution of 1D Poisson equation using finite volumes 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 pi*pi -max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(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]/(pi*pi) - my_ResultField[i]) : - erreur_abs = abs(my_RHSfield[i]/(pi*pi) - my_ResultField[i]) - -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) -print("Maximum exact solution = ", my_RHSfield.max()/(pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(pi*pi)) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DEF/CMakeLists.txt deleted file mode 100755 index 47bd375..0000000 --- a/CDMATH/tests/examples/Poisson2DEF/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/squareWithTriangles.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_2DEF_SQUARE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_SQUARE.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py b/CDMATH/tests/examples/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py deleted file mode 100755 index eb28762..0000000 --- a/CDMATH/tests/examples/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py +++ /dev/null @@ -1,181 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = f avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2016 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y) -#================================================================================================================================ - -import cdmath -from math import sin, pi, sqrt -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -#Chargement du maillage triangulaire du domaine carré [0,1]x[0,1], définition des bords -#======================================================================================= -my_mesh = cdmath.Mesh("squareWithTriangles.med") -if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") -eps=1e-6 -my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT -my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS -my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -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, otherwise use function Ni.getNumberOfEdges() - -print("Right hand side discretisation done") -print("nb of interior nodes=", nbInteriorNodes) -print("nb of boundary nodes=", nbBoundaryNodes) -print("Max nb 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) - - 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") - -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber() -print("Condition number is ",cond) - -# 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 -SolSyst=LS.solve() - -print("Preconditioner used : ", LS.getNameOfPc()) -print("Number of iterations used : ", LS.getNumberOfIter()) -print("Final residual : ", LS.getResidu()) -print("Linear system solved") - -# 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_ResultField") - -# Postprocessing : -#================= -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_SQUARE_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_SQUARE_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(0,sqrt(2),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) -plt.plot(curv_abs, diag_data, label= '2D mesh with '+str(nbNodes) + ' nodes') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D square with triangular mesh') -plt.savefig("FiniteElements2DPoisson_SQUARE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a square 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 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("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) -print("Maximum exact solution = ", my_RHSfield.max()/(2*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(2*pi*pi) ) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DEF_DISK/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DEF_DISK/CMakeLists.txt deleted file mode 100755 index cfaa27b..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_DISK/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/diskWithTriangles.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_DISK) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_2DEF_DISK ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_DISK.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py b/CDMATH/tests/examples/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py deleted file mode 100755 index d133bdf..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py +++ /dev/null @@ -1,176 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = f sur le disque unité avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2018 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta) -#================================================================================================================================ - -import cdmath -from math import sin, sqrt, atan2 -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -#Chargement du maillage triangulaire du disque unité -#======================================================================================= -my_mesh = cdmath.Mesh("diskWithTriangles.med") -if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Discrétisation du second membre et détermination des noeuds intérieurs -#====================================================================== -my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) -my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) -nbInteriorNodes = 0 -nbBoundaryNodes = 0 -maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -interiorNodes=[] -boundaryNodes=[] - -#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud -for i in range(nbNodes): - Ni=my_mesh.getNode(i) - x = Ni.x() - y = Ni.y() - - r=sqrt(x*x+y*y) - theta=atan2(y,x) - - my_RHSfield[i]=(8*r-3)*sin(theta)#mettre la fonction definie au second membre de l'edp - my_ExactSol[i]=-(r-1)*r*r*sin(theta)#mettre la solution exacte 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, 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) - - 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 -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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_DISK_ResultField") - -# Postprocessing : -#================= -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_DISK_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_DISK_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(-1,1,resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[-0.5,-0.5,0],[0.5,0.5,0], resolution) -plt.plot(curv_abs, diag_data, label= '2D disk mesh with '+str(nbNodes) + ' nodes') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D disk triangular mesh') -plt.savefig("FiniteElements2DPoisson_DISK_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a disk using finite elements done") - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) -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_ExactSol[i] - my_ResultField[i]) : - erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) - -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) -print("Maximum exact solution = ", my_ExactSol.max(), " Minimum exact solution = ", my_ExactSol.min() ) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/CMakeLists.txt deleted file mode 100755 index fb390a0..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/diskWithTriangles.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_DISK_StiffBC) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_2DEF_DISK_StiffBC ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_DISK_StiffBC.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py b/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py deleted file mode 100755 index f160ce6..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py +++ /dev/null @@ -1,224 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = 0 sur le disque unité avec conditions aux limites de Dirichlet discontinues -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=atan(2*x/(x**2+y**2-1))=atan(2 r cos(theta)/(r*2-1)) -#================================================================================================================================ - -import cdmath -from math import atan, pi -from numpy import sign, linspace -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants -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 - - -#Chargement du maillage triangulaire du disque unité -#======================================================================================= -meshName="diskWithTriangles" -my_mesh = cdmath.Mesh(meshName+".med") -if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Détermination des noeuds intérieurs -#====================================================================== -my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) -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-10 - -#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("x**2+y**2 > 1 !!! 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, 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) - -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)*0.5 - GradShapeFunc1 = gradientNodal(M,values1)*0.5 - GradShapeFunc2 = gradientNodal(M,values2)*0.5 - - #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])*0.5 - 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","ILU")#Remplacer CG par CHOLESKY pour solveur direct -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print( "Linear system solved") - -# 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_ResultField") -my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_DISK") - -# Postprocessing : -#================= -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoissonStiffBC_DISK_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoissonStiffBC_DISK_ResultField") -PV_routines.Save_PV_data_to_picture_file("ExactSol2DPoissonStiffBC_DISK"+'_0.vtu',"Exact_field",'NODES',"ExactSol2DPoissonStiffBC_DISK") - -# extract and plot diagonal values -resolution=100 -curv_abs=linspace(-1,1,resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) -plt.plot(curv_abs, diag_data, label= '2D disk mesh with '+str(nbNodes) + ' nodes') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D disk triangular mesh') -plt.savefig("FiniteElements2DPoissonStiffBC_DISK_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a disk using finite elements done") - -#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) -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()) - -assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt deleted file mode 100755 index 99f13a4..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/squareWithTriangles.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_SQUARE_StiffBC) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_2DEF_SQUARE_StiffBC ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_SQUARE_StiffBC.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py b/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py deleted file mode 100755 index 1f2a44f..0000000 --- a/CDMATH/tests/examples/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py +++ /dev/null @@ -1,223 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = 0 sur le carré unité avec conditions aux limites de Dirichlet discontinues -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=atan((x*x-y*y)/(2*x*y)) -#================================================================================================================================ - -import cdmath -from math import atan, pi -from numpy import linspace -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants -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 - - -#Chargement du maillage triangulaire du carré unité -#======================================================================================= -meshName="squareWithTriangles" -my_mesh = cdmath.Mesh(meshName+".med") -if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Détermination des noeuds intérieurs -#====================================================================== -my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) -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-10 - -#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud -for i in range(nbNodes): - Ni=my_mesh.getNode(i) - x = Ni.x() - y = Ni.y() - - #Robust calculation of atan((x*x-y*y)/(2*x*y)) - if x<-eps or x>1+eps or y<-eps or y>1+eps : - print("!!! Warning Mesh ", meshName," !!! Node is not in the unit square.",", eps=",eps, ", x= ",x, ", y= ",y) - #raise ValueError("!!! Domain should be the unit square.") - if abs(x*y) > eps : - my_ExactSol[i] = atan((x*x-y*y)/(2*x*y)) - elif x**2-y**2>0 : - my_ExactSol[i] = pi/2 - elif x**2-y**2<0 : - my_ExactSol[i] = -pi/2 - else : #x=0 - my_ExactSol[i] = 0 - - if my_mesh.isBorderNode(i): # Détection des noeuds frontière - boundaryNodes.append(i) - nbBoundaryNodes=nbBoundaryNodes+1 - else: # Détection des noeuds intérieurs - interiorNodes.append(i) - nbInteriorNodes=nbInteriorNodes+1 - maxNbNeighbours= max(1+Ni.getNumberOfCells(),maxNbNeighbours) #true only in 2D, 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) - -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)*0.5 - GradShapeFunc1 = gradientNodal(M,values1)*0.5 - GradShapeFunc2 = gradientNodal(M,values2)*0.5 - - #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])*0.5 - 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","ILU")#Remplacer CG par CHOLESKY pour solveur direct -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print( "Linear system solved") - -# Création du champ résultat -#=========================== -my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1) -for j in range(nbInteriorNodes): - my_ResultField[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs -for j in range(nbBoundaryNodes): - my_ResultField[boundaryNodes[j]]=my_ExactSol[boundaryNodes[j]];#remplissage des valeurs pour les noeuds frontière (condition limite) -#sauvegarde sur le disque dur du résultat dans un fichier paraview -my_ResultField.writeVTK("FiniteElements2DPoissonStiffBC_SQUARE_ResultField") -my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_SQUARE") - -# Postprocessing : -#================= -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoissonStiffBC_SQUARE_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoissonStiffBC_SQUARE_ResultField") -PV_routines.Save_PV_data_to_picture_file("ExactSol2DPoissonStiffBC_SQUARE"+'_0.vtu',"Exact_field",'NODES',"ExactSol2DPoissonStiffBC_SQUARE") - -# extract and plot diagonal values -resolution=100 -curv_abs=linspace(-1,1,resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) -plt.plot(curv_abs, diag_data, label= '2D square mesh with '+str(nbNodes) + ' nodes') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D square triangular mesh') -plt.savefig("FiniteElements2DPoissonStiffBC_SQUARE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a square using finite elements done") - -#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) -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()) - -assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DVF/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DVF/CMakeLists.txt deleted file mode 100755 index e302ceb..0000000 --- a/CDMATH/tests/examples/Poisson2DVF/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py) - - SET(MESH_FILE ../../ressources/meshSquare.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/squareWithLocRefSquares.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/squareWithCheckerboardSquares.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/squareWithHexagons.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/squareWithBrickWall.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/squareWithDeformedQuadrangles.med ) - - ADD_TEST(ExamplePoisson_2DVF_SQUARE_deformed_quadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py b/CDMATH/tests/examples/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py deleted file mode 100755 index 877628c..0000000 --- a/CDMATH/tests/examples/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py +++ /dev/null @@ -1,152 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur un carré avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2016 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y) -#================================================================================================================================ - -import cdmath -from math import sin, pi, sqrt -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines -import sys - -if len(sys.argv) >1 :#non rectangular mesh - my_mesh = cdmath.Mesh(sys.argv[1]) -else : #rectangular mesh -# Création d'un maillage cartésien du domaine carré [0,1]x[0,1], définition des bords -#==================================================================================== - xmin=0 - xmax=1 - ymin=0 - ymax=1 - - nx=15 - ny=15 - - my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny) - - eps=1e-6 - my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE - 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 - -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") - -print("Mesh loading done") -print("Number of cells = ", nbCells) - -#Discrétisation du second membre et extraction du nb max de voisins d'une cellule -#================================================================================ -my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) -maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule -for i in range(nbCells): - Ci = my_mesh.getCell(i) - x = Ci.x() - y = Ci.y() - - 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) - -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 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.addValue(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 solution exacte de l'edp - 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,"GMRES","ILU") -SolSyst=LS.solve() - -print("Preconditioner used : ", LS.getNameOfPc()) -print("Number of iterations used : ", LS.getNumberOfIter()) -print("Final residual : ", LS.getResidu()) -print("Linear system solved") - -# 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_ResultField") - -#Postprocessing : -#=============== -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_SQUARE_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_SQUARE_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(0,sqrt(2),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -if len(sys.argv) >1 : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D square '+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_SQUARE_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") -else : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D square with a rectangular grid') - plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_SQUARE_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a square using finite volumes 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 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("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) -print("Maximum exact solution = ", my_RHSfield.max()/(2*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(2*pi*pi) ) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DVF_DISK/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DVF_DISK/CMakeLists.txt deleted file mode 100755 index 546f57e..0000000 --- a/CDMATH/tests/examples/Poisson2DVF_DISK/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../ressources/diskWithSquares.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_spiderweb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py b/CDMATH/tests/examples/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py deleted file mode 100755 index 9e13ad3..0000000 --- a/CDMATH/tests/examples/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py +++ /dev/null @@ -1,143 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur un disque avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2018 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta) -#================================================================================================================================ - -import cdmath -from math import sin, sqrt, atan2 -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines -import sys - -if len(sys.argv) >1 :#non rectangular mesh - my_mesh = cdmath.Mesh(sys.argv[1]) -else : - raise ValueError("Give an input mesh of the disk") - -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") - -print( "Mesh loading done" ) -print( "Number of cells = ", nbCells ) - -#Discrétisation du second membre et extraction du nb max de voisins d'une cellule -#================================================================================ -my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) -my_ExactSol = cdmath.Field("Exact_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() - - r=sqrt(x*x+y*y) - theta=atan2(y,x) - - my_RHSfield[i]=(8*r-3)*sin(theta)#mettre la fonction definie au second membre de l'edp - my_ExactSol[i]=-(r-1)*r*r*sin(theta)#mettre la solution exacte 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.addValue(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() - r=sqrt(x*x+y*y) - theta=atan2(y,x) - RHS[i]+=coeff*(-(r-1)*r*r*sin(theta))#mettre ici la solution exacte de l'edp - 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,"GMRES","ILU") -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print( "Linear system solved" ) - -# 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_DISK_square_ResultField") - -#Postprocessing : -#=============== -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_DISK_square_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_DISK_square_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(0,sqrt(2),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -if len(sys.argv) >1 : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk mesh '+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_DISK_square_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") -else : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk with a rectangular grid') - plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_DISK_square_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a disk using finite volumes done") - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) -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_ExactSol[i] - my_ResultField[i]) : - erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) - -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) -print("Maximum exact solution = ", my_ExactSol.max(), " Minimum exact solution = ", my_ExactSol.min() ) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/CMakeLists.txt deleted file mode 100755 index f580a63..0000000 --- a/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../ressources/diskWithSquares.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) - - SET(MESH_FILE ../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_spiderweb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py b/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py deleted file mode 100755 index 56355bd..0000000 --- a/CDMATH/tests/examples/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson -\triangle u = 0 sur un disque avec conditions aux limites de Dirichlet discontinues -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=atan(2*x/(x**2+y**2-1))=atan(2 r cos(theta)/(r*2-1)) -#================================================================================================================================ - -import cdmath -from math import atan, pi, sqrt -from numpy import linspace -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines -import sys - -if len(sys.argv) >1 :#non rectangular mesh - meshName=sys.argv[1] - my_mesh = cdmath.Mesh(sys.argv[1]) -else : - raise ValueError("Give an input mesh of the disk") - -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") - -print( "Mesh loading done" ) -print( "Number of cells = ", nbCells ) - -#Discrétisation du second membre et extraction du nb max de voisins d'une cellule -#================================================================================ -my_ExactSol = cdmath.Field("Exact_field", cdmath.CELLS, my_mesh, 1) -eps=1e-6#For coarse meshes - -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() - - #Robust calculation of atan(2x/(x**2+y**2-1) - if x**2+y**2-1 > eps : - print("!!! Warning Mesh ", meshName," !!! Cell is not in the unit disk."," eps=",eps, ", x**2+y**2-1=",x**2+y**2 - 1) - #raise ValueError("x**2+y**2 > 1 !!! 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) - -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): - 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.addValue(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 ", meshName," !!! 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,"GMRES","ILU") -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print( "Linear system solved" ) - -# 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_DISK_ResultField") - -#Postprocessing : -#=============== -# save 2D picture -PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_DISK_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_DISK_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=linspace(0,sqrt(2),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -if len(sys.argv) >1 : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk mesh '+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_DISK_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") -else : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk with a rectangular grid') - plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') - plt.savefig("FiniteVolumes2DPoisson_DISK_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 2D Poisson equation on a disk using finite volumes done") - -#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) -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() ) - -assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DCubeSkinEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DCubeSkinEF/CMakeLists.txt deleted file mode 100755 index 3765230..0000000 --- a/CDMATH/tests/examples/Poisson3DCubeSkinEF/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/meshCubeSkin.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DCubeSkinEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoissonBeltrami_3DFE_CUBESKIN ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonCubeSkin.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py b/CDMATH/tests/examples/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py deleted file mode 100644 index e167456..0000000 --- a/CDMATH/tests/examples/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py +++ /dev/null @@ -1,216 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur la frontière d'un cube -# Author : Michael Ndjinga -# Copyright : CEA Saclay 2021 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau -# Comparaison de la solution numérique avec la solution exacte définie face par face : u(x,y,z)= cos(2*pi*x)*cos(2*pi*y)*cos(2*pi*z) -#================================================================================================================================ - -import cdmath -from math import cos, pi -import numpy as np -import PV_routines -import VTK_routines -import paraview.simple as pvs - -#Chargement du maillage triangulaire de la frontière du cube unité [0,1]x[0,1]x[0,1] -#======================================================================================= -my_mesh = cdmath.Mesh("meshCubeSkin.med") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") -if(my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") -if(my_mesh.getSpaceDimension()!=3) : - raise ValueError("Wrong space dimension : expected a space of dimension 3") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh building/loading done") -print("nb of nodes=", nbNodes) -print("nb of cells=", nbCells) - -#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 - -eps=1e-6 -#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]= 8*pi*pi*cos(2*pi*x)*cos(2*pi*y)*cos(2*pi*z) - - 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) #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é - 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) - normalCell = normalCell*(1/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()*0.5 - GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 - GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 - GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 - GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 - GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 - GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 - GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 - GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 - - #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") - -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber(True) -print("Condition number is ",cond) - -# Résolution du système linéaire -#================================= -LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU") -LS.setMatrixIsSingular()#En raison de l'absence de bord -SolSyst=LS.solve() -print("Preconditioner used : ", LS.getNameOfPc() ) -print("Number of iterations used : ", LS.getNumberOfIter() ) -print("Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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 issues du système linéaire dans le champs résultat -#sauvegarde sur le disque dur du résultat dans un fichier paraview -my_ResultField.writeVTK("FiniteElementsOnCubeSkinPoisson") -my_RHSfield.writeVTK("RHS_CubeSkinPoisson") - -print("Integral of the numerical solution", my_ResultField.integral(0)) -print("Numerical solution of Poisson equation on a cube skin 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 8*pi*pi -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]/(8*pi*pi) - my_ResultField[i]) : - erreur_abs = abs(my_RHSfield[i]/(8*pi*pi) - 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/(8*pi*pi) - -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) -print("Maximum exact solution = ", my_RHSfield.max()/(8*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(8*pi*pi) ) - -#Postprocessing : -#================ -# save 3D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnCubeSkinPoisson") -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnCubeSkinPoisson"+'_0.vtu',[0.75,0.75,0.75], [0.,0.5,-0.5],resolution ) -PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnCubeSkinPoisson") - -# Plot over slice circle -finiteElementsOnCubeSkin_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnCubeSkinPoisson"+'_0.vtu']) -slice1 = pvs.Slice(Input=finiteElementsOnCubeSkin_0vtu) -slice1.SliceType.Normal = [0, 1, 0] -renderView1 = pvs.GetActiveViewOrCreate('RenderView') -finiteElementsOnCubeSkin_0vtuDisplay = pvs.Show(finiteElementsOnCubeSkin_0vtu, renderView1) -pvs.ColorBy(finiteElementsOnCubeSkin_0vtuDisplay, ('POINTS', 'ResultField')) -slice1Display = pvs.Show(slice1, renderView1) -pvs.SaveScreenshot("./FiniteElementsOnCubeSkinPoisson"+"_Slice"+'.png', magnification=1, quality=100, view=renderView1) -plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) -lineChartView2 = pvs.CreateView('XYChartView') -plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) -plotOnSortedLines1Display.UseIndexForXAxis = 0 -plotOnSortedLines1Display.XArrayName = 'arc_length' -plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)'] -pvs.SaveScreenshot("./FiniteElementsOnCubeSkinPoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) -pvs.Delete(lineChartView2) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DEF/CMakeLists.txt deleted file mode 100755 index 286cc1a..0000000 --- a/CDMATH/tests/examples/Poisson3DEF/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/meshCube.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_3DEF_CUBE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_CUBE.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DEF/FiniteElements3DPoisson_CUBE.py b/CDMATH/tests/examples/Poisson3DEF/FiniteElements3DPoisson_CUBE.py deleted file mode 100755 index 6043a1e..0000000 --- a/CDMATH/tests/examples/Poisson3DEF/FiniteElements3DPoisson_CUBE.py +++ /dev/null @@ -1,189 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 3D -\triangle u = f sur le cube avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga, Sédrick Kameni -# Copyright : CEA Saclay 2017 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage tétraédrique -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y)*sin(pi*z) -#================================================================================================================================ - -import cdmath -from math import sin, pi, sqrt -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords -#============================================================================================== -my_mesh = cdmath.Mesh("meshCube.med") -if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") -if(not my_mesh.isTetrahedral()) : - raise ValueError("Wrong cell types : mesh is not made of tetrahedra") -eps=1e-6 -my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT -my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS -my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT -my_mesh.setGroupAtPlan(0.,2,eps,"DirichletBorder")#Bord AVANT -my_mesh.setGroupAtPlan(1.,2,eps,"DirichletBorder")#Bord ARRIERE - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Discrétisation du second membre et détermination des noeuds intérieurs -#====================================================================== -my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) - -nbInteriorNodes = 0 -nbBoundaryNodes = 0 -maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -interiorNodes=[] -boundaryNodes=[] - -#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud -for i in range(nbNodes): - Ni=my_mesh.getNode(i) - x = Ni.x() - y = Ni.y() - z = Ni.z() - - 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 - 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.getNumberOfEdges(),maxNbNeighbours) - -print("Right hand side discretisation done") -print("Number of interior nodes=", nbInteriorNodes) -print("Number of boundary nodes=", nbBoundaryNodes) -print("Maximum number of neighbours per node=", 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 tétraèdre -GradShapeFunc0=cdmath.Vector(3) -GradShapeFunc1=cdmath.Vector(3) -GradShapeFunc2=cdmath.Vector(3) -GradShapeFunc3=cdmath.Vector(3) - -#On parcourt les tétraèdres du domaine -for i in range(nbCells): - - Ci=my_mesh.getCell(i) - - #Extraction des noeuds de la cellule - nodeId0=Ci.getNodeId(0) - nodeId1=Ci.getNodeId(1) - nodeId2=Ci.getNodeId(2) - nodeId3=Ci.getNodeId(3) - N0=my_mesh.getNode(nodeId0) - N1=my_mesh.getNode(nodeId1) - N2=my_mesh.getNode(nodeId2) - N3=my_mesh.getNode(nodeId3) - - #Formule des gradients voir EF P1 -> calcul déterminants - GradShapeFunc0[0]= (N2.y()*N3.z()-N2.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 - GradShapeFunc0[1]=-(N2.x()*N3.z()-N2.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 - GradShapeFunc0[2]=(N2.x()*N3.y()-N2.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 - GradShapeFunc1[0]=- (N2.y()*N3.z()-N2.z()*N3.y()-N0.y()*N3.z()+N3.y()*N0.z()+N0.y()*N2.z()-N2.y()*N0.z())/6 - GradShapeFunc1[1]=(N2.x()*N3.z()-N2.z()*N3.x()-N0.x()*N3.z()+N3.x()*N0.z()+N0.x()*N2.z()-N2.x()*N0.z())/6 - GradShapeFunc1[2]=-(N2.x()*N3.y()-N2.y()*N3.x()-N0.x()*N3.y()+N3.x()*N0.y()+N0.x()*N2.y()-N2.x()*N0.y())/6 - GradShapeFunc2[0]= -(N0.y()*N3.z()-N0.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N0.z()-N0.y()*N1.z())/6 - GradShapeFunc2[1]=(N0.x()*N3.z()-N0.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N0.z()-N0.x()*N1.z())/6 - GradShapeFunc2[2]= -(N0.x()*N3.y()-N0.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N0.y()-N0.x()*N1.y())/6 - GradShapeFunc3[0]=-(N2.y()*N0.z()-N2.z()*N0.y()-N1.y()*N0.z()+N0.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 - GradShapeFunc3[1]=(N2.x()*N0.z()-N2.z()*N0.x()-N1.x()*N0.z()+N0.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 - GradShapeFunc3[2]=-(N2.x()*N0.y()-N2.y()*N0.x()-N1.x()*N0.y()+N0.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 - - #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) - GradShapeFuncs={nodeId0 : GradShapeFunc0} - GradShapeFuncs[nodeId1]=GradShapeFunc1 - GradShapeFuncs[nodeId2]=GradShapeFunc2 - GradShapeFuncs[nodeId3]=GradShapeFunc3 - - # Remplissage de la matrice de rigidité et du second membre - for j in [nodeId0,nodeId1,nodeId2,nodeId3] : - 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()/4*my_RHSfield[j]+RHS[j_int] # intégrale dans le triangle du produit f x fonction de base - #Contribution de la cellule tétraédrique i à la ligne j_int du système linéaire - for k in [nodeId0,nodeId1,nodeId2,nodeId3] : - 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")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct -SolSyst=LS.solve() -print( "Preconditioner used : ", LS.getNameOfPc()) -print( "Number of iterations used : ", LS.getNumberOfIter()) -print( "Final residual : ", LS.getResidu()) -print("Linear system solved") - -# 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("FiniteElements3DPoisson_CUBE_ResultField") - -#Postprocessing : -#================ -# save 3D picture -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) -PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_CUBE_ResultField") - -# extract and plot diagonal values -curv_abs=np.linspace(0,sqrt(3),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,1,1], resolution) -plt.plot(curv_abs, diag_data, label= str(nbNodes) + ' nodes 3D mesh') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 3D tetrahedral mesh') -plt.savefig("FiniteElements3DPoisson_CUBE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 3D Poisson equation on a cube 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 3*pi*pi -max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(3*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]/(3*pi*pi) - my_ResultField[i]) : - erreur_abs = abs(my_RHSfield[i]/(3*pi*pi) - my_ResultField[i]) - -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) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DEF_BALL/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DEF_BALL/CMakeLists.txt deleted file mode 100755 index 1a05b09..0000000 --- a/CDMATH/tests/examples/Poisson3DEF_BALL/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF_BALL) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_3DEF_BALL ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_BALL.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py b/CDMATH/tests/examples/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py deleted file mode 100755 index 82fa4e8..0000000 --- a/CDMATH/tests/examples/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Poisson 3D -\triangle u = f sur la boule unité avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2018 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage tétraédrique -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta)**2*cos(phi) -#================================================================================================================================ - -import cdmath -from math import sin, cos, atan2, sqrt -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords -#============================================================================================== -my_mesh = cdmath.Mesh("ballWithTetrahedra.med") -if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") -if(not my_mesh.isTetrahedral()) : - raise ValueError("Wrong cell types : mesh is not made of tetrahedra") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Discrétisation du second membre et détermination des noeuds intérieurs -#====================================================================== -my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) -my_ExactSol = cdmath.Field("EXACT_SOL", cdmath.NODES, my_mesh, 1) -nbInteriorNodes = 0 -nbBoundaryNodes = 0 -maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -interiorNodes=[] -boundaryNodes=[] - -#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud -for i in range(nbNodes): - Ni=my_mesh.getNode(i) - x = Ni.x() - y = Ni.y() - z = Ni.z() - - r=sqrt(x*x+y*y+z*z) - phi=atan2(y,x) - theta=atan2(y,z*sin(phi)) - - my_RHSfield[i]=6*r*sin(theta)**2*cos(phi)+3*(r-1)*cos(phi)#mettre la fonction definie au second membre de l'edp - my_ExactSol[i]=-(r-1)*r**2*sin(theta)**2*cos(phi) - 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.getNumberOfEdges(),maxNbNeighbours) - -print("Right hand side discretisation done") -print("Number of interior nodes=", nbInteriorNodes) -print("Number of boundary nodes=", nbBoundaryNodes) -print("Maximum number of neighbours per node=", 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 hexaèdre -GradShapeFunc0=cdmath.Vector(3) -GradShapeFunc1=cdmath.Vector(3) -GradShapeFunc2=cdmath.Vector(3) -GradShapeFunc3=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) - nodeId3=Ci.getNodeId(3) - N0=my_mesh.getNode(nodeId0) - N1=my_mesh.getNode(nodeId1) - N2=my_mesh.getNode(nodeId2) - N3=my_mesh.getNode(nodeId3) - - #Formule des gradients voir EF P1 -> calcul déterminants - GradShapeFunc0[0]= (N2.y()*N3.z()-N2.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 - GradShapeFunc0[1]=-(N2.x()*N3.z()-N2.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 - GradShapeFunc0[2]=(N2.x()*N3.y()-N2.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 - GradShapeFunc1[0]=- (N2.y()*N3.z()-N2.z()*N3.y()-N0.y()*N3.z()+N3.y()*N0.z()+N0.y()*N2.z()-N2.y()*N0.z())/6 - GradShapeFunc1[1]=(N2.x()*N3.z()-N2.z()*N3.x()-N0.x()*N3.z()+N3.x()*N0.z()+N0.x()*N2.z()-N2.x()*N0.z())/6 - GradShapeFunc1[2]=-(N2.x()*N3.y()-N2.y()*N3.x()-N0.x()*N3.y()+N3.x()*N0.y()+N0.x()*N2.y()-N2.x()*N0.y())/6 - GradShapeFunc2[0]= -(N0.y()*N3.z()-N0.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N0.z()-N0.y()*N1.z())/6 - GradShapeFunc2[1]=(N0.x()*N3.z()-N0.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N0.z()-N0.x()*N1.z())/6 - GradShapeFunc2[2]= -(N0.x()*N3.y()-N0.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N0.y()-N0.x()*N1.y())/6 - GradShapeFunc3[0]=-(N2.y()*N0.z()-N2.z()*N0.y()-N1.y()*N0.z()+N0.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 - GradShapeFunc3[1]=(N2.x()*N0.z()-N2.z()*N0.x()-N1.x()*N0.z()+N0.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 - GradShapeFunc3[2]=-(N2.x()*N0.y()-N2.y()*N0.x()-N1.x()*N0.y()+N0.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 - - #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) - GradShapeFuncs={nodeId0 : GradShapeFunc0} - GradShapeFuncs[nodeId1]=GradShapeFunc1 - GradShapeFuncs[nodeId2]=GradShapeFunc2 - GradShapeFuncs[nodeId3]=GradShapeFunc3 - - # Remplissage de la matrice de rigidité et du second membre - for j in [nodeId0,nodeId1,nodeId2,nodeId3] : - 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()/4*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,nodeId3] : - 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")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct -SolSyst=LS.solve() -print("Preconditioner used : ", LS.getNameOfPc() ) -print("Number of iterations used : ", LS.getNumberOfIter() ) -print("Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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("FiniteElements3DPoisson_BALL_ResultField") - -#Postprocessing : -#================ -# save 3D picture -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) -PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_BALL_ResultField") - -# extract and plot diagonal values -curv_abs=np.linspace(0,sqrt(3),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[-0.577,-0.577,-0.577],[0.577,0.577,0.577], resolution) -plt.plot(curv_abs, diag_data, label= str(nbNodes) + ' nodes 3D mesh') -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 3D ball tetrahedral mesh') -plt.savefig("FiniteElements3DPoisson_BALL_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 3D Poisson equation on a 3D ball using finite elements done") - - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) -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_ExactSol[i] - my_ResultField[i]) : - erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) - -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) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt deleted file mode 100755 index f628489..0000000 --- a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ./Mesh_RadiatorAndWindow.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF_RadiatorAndWindow) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_3DEF_CUBE_RadiatorAndWindow ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py b/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py deleted file mode 100755 index f58010b..0000000 --- a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py +++ /dev/null @@ -1,199 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Laplace 3D -\Delta T = 0 avec conditions aux limites de Dirichlet u non nulle -# Authors : Michaël Ndjinga, Sédrick Kameni Ngwamou -# Copyright : CEA Saclay 2019 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u discrétisés aux noeuds d'un maillage tétraédrique -# Condition limites correspondant au refroidissement dû à une fenêtre et au chauffage dû à un radiateur -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -#================================================================================================================================ - -import cdmath -import numpy as np - -# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants -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 - -# Fonction qui calcule la valeur de la condition limite en un noeud donné -def boundaryValue(nodeId): - Ni=my_mesh.getNode(nodeId) - - # 4 groupes sont considérés sur le bord - if boundaryNodes.count(nodeId)==0: - return 0 - elif Ni.getGroupName()=='Fenetre': - return Tfenetre; - elif Ni.getGroupName()=='Radiateur_sous-fenetre': - return Tradiateur - #elif Ni.getGroupName()=='Radiateur_Devant': - #return Tradiateur; - #elif Ni.getGroupName()=='Radiateur_droit': - #return Tradiateur - else: - return Tmur; - -#Chargement du maillage tétraédrique du domaine -#============================================== -my_mesh = cdmath.Mesh("Mesh_RadiatorAndWindow.med") -if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") -if(not my_mesh.isTetrahedral()) : - raise ValueError("Wrong cell types : mesh is not made of tetrahedra") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("nb of nodes=", nbNodes) -print("nb of cells=", nbCells) - -#Conditions limites -Tmur=20 -Tfenetre=0 -Tradiateur=40 - -#Détermination des noeuds intérieurs -#====================================================================== -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) - - if my_mesh.isBorderNode(i): # Détection des noeuds frontière getGroupName my_mesh.getNode(i) - boundaryNodes.append(i) - else: # Détection des noeuds intérieurs - interiorNodes.append(i) - maxNbNeighbours= max(1+Ni.getNumberOfEdges(),maxNbNeighbours) - -nbInteriorNodes=len(interiorNodes) -nbBoundaryNodes=len(boundaryNodes) - - -print("nb of interior nodes=", nbInteriorNodes) -print("nb of Boundary nodes=", nbBoundaryNodes) -print("Max nb 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) -RHS=cdmath.Vector(nbInteriorNodes) - -# Vecteurs gradient de la fonction de forme associée à chaque noeud d'un tétrèdre (hypothèse 3D) -M=cdmath.Matrix(4,4) -GradShapeFunc0=cdmath.Vector(3) -GradShapeFunc1=cdmath.Vector(3) -GradShapeFunc2=cdmath.Vector(3) -GradShapeFunc3=cdmath.Vector(3) - -#On parcourt les tétraèdres du domaine pour remplir la matrice -for i in range(nbCells): - - Ci=my_mesh.getCell(i) - - #Extraction des noeuds de la cellule - nodeId0=Ci.getNodeId(0) - nodeId1=Ci.getNodeId(1) - nodeId2=Ci.getNodeId(2) - nodeId3=Ci.getNodeId(3) - N0=my_mesh.getNode(nodeId0) - N1=my_mesh.getNode(nodeId1) - N2=my_mesh.getNode(nodeId2) - N3=my_mesh.getNode(nodeId3) - - M[0,0]=N0.x() - M[0,1]=N0.y() - M[0,2]=N0.z() - M[0,3]=1 - M[1,0]=N1.x() - M[1,1]=N1.y() - M[1,2]=N1.z() - M[1,3]=1 - M[2,0]=N2.x() - M[2,1]=N2.y() - M[2,2]=N2.z() - M[2,3]=1 - M[3,0]=N3.x() - M[3,1]=N3.y() - M[3,2]=N3.z() - M[3,3]=1 - - #Values of each shape function at each node - values0=[1,0,0,0] - values1=[0,1,0,0] - values2=[0,0,1,0] - values3=[0,0,0,1] - - GradShapeFunc0 = gradientNodal(M,values0)*(1./6) - GradShapeFunc1 = gradientNodal(M,values1)*(1./6) - GradShapeFunc2 = gradientNodal(M,values2)*(1./6) - GradShapeFunc3 = gradientNodal(M,values3)*(1./6) - - #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) - GradShapeFuncs={nodeId0 : GradShapeFunc0} - GradShapeFuncs[nodeId1]=GradShapeFunc1 - GradShapeFuncs[nodeId2]=GradShapeFunc2 - GradShapeFuncs[nodeId3]=GradShapeFunc3 - - # Remplissage de la matrice de rigidité et du second membre - for j in [nodeId0,nodeId1,nodeId2,nodeId3] : - 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 - boundaryContributionAdded=False#Needed in case j is a border cell - #Ajout de la contribution de la cellule ttétraédrique i au second membre du noeud j - for k in [nodeId0,nodeId1,nodeId2,nodeId3] : - 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 - # Valeurs de g_h aux noeuds du tétraèdre - T0 = boundaryValue(nodeId0) - T1 = boundaryValue(nodeId1) - T2 = boundaryValue(nodeId2) - T3 = boundaryValue(nodeId3) - boundaryContributionAdded=True#Contribution from the boundary to matrix line j is done in one step - GradGh = gradientNodal(M,[T0,T1,T2,T3])*(1./6) - RHS[j_int] += -(GradGh*GradShapeFuncs[j])/Ci.getMeasure() - - - -print("Linear system matrix building done") - -LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"CG","ILU")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct - -SolSyst=LS.solve() - -# Création du champ résultat -#=========================== -my_Temperature = cdmath.Field("Temperature", cdmath.NODES, my_mesh, 1) -for j in range(nbInteriorNodes): - my_Temperature[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs SolSyst[j] -#Remplissage des valeurs pour les noeuds frontière (condition limite) -for j in boundaryNodes: - my_Temperature[j]=boundaryValue(j) - - -#sauvegarde sur le disque dur du résultat dans un fichier paraview -my_Temperature.writeVTK("FiniteElements3DTemperature") - -print( "Minimum temperature= ", my_Temperature.min(), ", maximum temperature= ", my_Temperature.max() ) -assert my_Temperature.min()>= min(Tmur,Tfenetre,Tradiateur) and my_Temperature.max()<= max(Tmur,Tfenetre,Tradiateur) - -print( "Numerical solution of 3D Laplace equation using finite elements done" ) - diff --git a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med b/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med deleted file mode 100644 index c22aec1..0000000 Binary files a/CDMATH/tests/examples/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med and /dev/null differ diff --git a/CDMATH/tests/examples/Poisson3DSphereEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DSphereEF/CMakeLists.txt deleted file mode 100755 index 1d8b478..0000000 --- a/CDMATH/tests/examples/Poisson3DSphereEF/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/meshSphere.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DSphereEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoissonBeltrami_3DFE_SPHERE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonSphere.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py b/CDMATH/tests/examples/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py deleted file mode 100755 index 9d07572..0000000 --- a/CDMATH/tests/examples/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur une sphere -# Author : Michael Ndjinga -# Copyright : CEA Saclay 2017 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations -# on surfaces. SIAM J. Num. Anal., 47, p. 3355 -# Solution exacte = f/12 : il s'agit d'un vecteur propre du laplacien sur la sphère -# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau -#================================================================================================================================ - -import cdmath -from math import pow -import numpy as np -import PV_routines -import VTK_routines -import paraview.simple as pvs - -#Chargement du maillage triangulaire de la sphère -#======================================================================================= -my_mesh = cdmath.Mesh("meshSphere.med") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") -if(my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") -if(my_mesh.getSpaceDimension()!=3) : - raise ValueError("Wrong space dimension : expected a space of dimension 3") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh building/loading done") -print("nb of nodes=", nbNodes) -print("nb of cells=", nbCells) - -#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) #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é - 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) - normalCell = normalCell*(1/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()*0.5 - GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 - GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 - GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 - GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 - GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 - GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 - GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 - GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 - - #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") - -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber(True) -print("Condition number is ",cond) - -# Résolution du système linéaire -#================================= -LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU") -LS.setMatrixIsSingular()#En raison de l'absence de bord -SolSyst=LS.solve() -print("Preconditioner used : ", LS.getNameOfPc() ) -print("Number of iterations used : ", LS.getNumberOfIter() ) -print("Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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") - -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("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) -print("Maximum exact solution = ", my_RHSfield.max()/12, " Minimum exact solution = ", my_RHSfield.min()/12 ) - -#Postprocessing : -#================ -# save 3D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnSpherePoisson"+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnSpherePoisson") -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnSpherePoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnSpherePoisson"+'_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"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson") - -# Plot over slice circle -finiteElementsOnSphere_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnSpherePoisson"+'_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"+'.png', magnification=1, quality=100, view=renderView1) -plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) -lineChartView2 = pvs.CreateView('XYChartView') -plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) -plotOnSortedLines1Display.UseIndexForXAxis = 0 -plotOnSortedLines1Display.XArrayName = 'arc_length' -plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)'] -pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) -pvs.Delete(lineChartView2) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DTorusEF/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DTorusEF/CMakeLists.txt deleted file mode 100755 index 7da0838..0000000 --- a/CDMATH/tests/examples/Poisson3DTorusEF/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(MESH_MED - ../../ressources/meshTorus.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DTorusEF) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoissonBeltrami_3DFE_TORUS ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonTorus.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py b/CDMATH/tests/examples/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py deleted file mode 100755 index 6de976e..0000000 --- a/CDMATH/tests/examples/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur un tore -# Author : Michael Ndjinga -# Copyright : CEA Saclay 2018 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH -# Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations -# on surfaces. SIAM J. Num. Anal., 47, p. 3355 -# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau -#================================================================================================================================ - -import cdmath -from math import sin, cos, atan2, sqrt -import PV_routines -import VTK_routines -import paraview.simple as pvs - -#Chargement du maillage triangulaire du tore -#======================================================================================= -my_mesh = cdmath.Mesh("meshTorus.med") -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") -if(my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") -if(my_mesh.getSpaceDimension()!=3) : - raise ValueError("Wrong space dimension : expected a space of dimension 3") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh building/loading done") -print("nb of nodes=", nbNodes) -print("nb of cells=", nbCells) - -# Torus radii (calculation will fail if the mesh is not correct) -R=1 #Grand rayon -r=0.6 #Petit rayon - -#Discrétisation du second membre, de la solution exacte et détermination des noeuds intérieurs -#====================================================================== -my_RHSfield = cdmath.Field("RHS field", cdmath.NODES, my_mesh, 1) -exactSolField = cdmath.Field("Exact solution field", cdmath.NODES, my_mesh, 1) - -maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix - -#parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud -for i in range(nbNodes): - Ni=my_mesh.getNode(i) - x = Ni.x() - y = Ni.y() - z = Ni.z() - - theta=atan2(z,sqrt(x*x+y*y)-R) - phi=atan2(y,x) - - exactSolField[i] = sin(3*phi)*cos(3*theta+ phi) # for the exact solution we use the funtion given in the article of Olshanskii, Reusken 2009, page 19 - my_RHSfield[i] = 9*sin(3*phi)*cos(3*theta+ phi)/(r*r) + (10*sin(3*phi)*cos(3*theta+ phi) + 6*cos(3*phi)*sin(3*theta+ phi))/((R+r*cos(theta))*(R+r*cos(theta))) - 3*sin(theta)*sin(3*phi)*sin(3*theta+ phi)/(r*(R+r*cos(theta))) #for the right hand side we use the function given in the article of Olshanskii, Reusken 2009, page 19 - 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) #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) -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) - normalCell = normalCell*(1/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()*0.5 - GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 - GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 - GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 - GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 - GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 - GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 - GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 - GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 - - #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") - -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber(True) -print("Condition number is ",cond) - -# Résolution du système linéaire -#================================= -LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU")#Remplacer CG par CHOLESKY pour solveur direct -LS.setMatrixIsSingular()#En raison de l'absence de bord -SolSyst=LS.solve() -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# Création du champ résultat -#=========================== -my_ResultField = cdmath.Field("Numerical result field", 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("FiniteElementsOnTorusPoisson") - -print("Integral of the numerical solution", my_ResultField.integral(0)) -print("Numerical solution of Poisson equation on a torus using finite elements done") - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -max_sol_exacte=exactSolField.normMax()[0] -erreur_max=(exactSolField - my_ResultField).normMax()[0] -max_sol_num=my_ResultField.max() -min_sol_num=my_ResultField.min() - -print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_max/max_sol_exacte) -print("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num) -print("Maximum exact solution = ", exactSolField.max(), " Minimum exact solution = ", exactSolField.min()) - -#Postprocessing : -#================ -# Save 3D picture -PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnTorusPoisson"+'_0.vtu',"Numerical result field",'NODES',"FiniteElementsOnTorusPoisson") -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnTorusPoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnTorusPoisson"+'_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_"+"FiniteElementsOnTorusPoisson"+'_0.vtu',"Numerical result field",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnTorusPoisson") - -# Plot over slice circle -finiteElementsOnTorus_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnTorusPoisson"+'_0.vtu']) -slice1 = pvs.Slice(Input=finiteElementsOnTorus_0vtu) -slice1.SliceType.Normal = [0.5, 0.5, 0.5] -renderView1 = pvs.GetActiveViewOrCreate('RenderView') -finiteElementsOnTorus_0vtuDisplay = pvs.Show(finiteElementsOnTorus_0vtu, renderView1) -pvs.ColorBy(finiteElementsOnTorus_0vtuDisplay, ('POINTS', 'Numerical result field')) -slice1Display = pvs.Show(slice1, renderView1) -pvs.SaveScreenshot("./FiniteElementsOnTorusPoisson"+"_Slice"+'.png', magnification=1, quality=100, view=renderView1) -plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) -lineChartView2 = pvs.CreateView('XYChartView') -plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) -plotOnSortedLines1Display.UseIndexForXAxis = 0 -plotOnSortedLines1Display.XArrayName = 'arc_length' -plotOnSortedLines1Display.SeriesVisibility = ['Numerical result field (1)'] -pvs.SaveScreenshot("./FiniteElementsOnTorusPoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) -pvs.Delete(lineChartView2) - -assert erreur_max/max_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DVF/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DVF/CMakeLists.txt deleted file mode 100755 index 25bb884..0000000 --- a/CDMATH/tests/examples/Poisson3DVF/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_3DVF_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) - - SET(MESH_FILE ../../ressources/meshCube.med ) - - ADD_TEST(ExamplePoisson_3DVF_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) - - SET(MESH_FILE ../../ressources/cubeWithLocRefCubes.med ) - - ADD_TEST(ExamplePoisson_3DVF_CUBE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) - - SET(MESH_FILE ../../ressources/3DCheckerboard/checkerboard_4x4x4.med ) - - ADD_TEST(ExamplePoisson_3DVF_CUBE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py b/CDMATH/tests/examples/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py deleted file mode 100755 index 066d1ff..0000000 --- a/CDMATH/tests/examples/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur unu cube avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2016 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y)*sin(pi*z) -#================================================================================================================================ - -import cdmath -from math import sin, pi, sqrt -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -import sys - -if len(sys.argv) >1 :#non rectangular mesh - my_mesh = cdmath.Mesh(sys.argv[1]) -else : #rectangular mesh -# Maillage du domaine cubique [0,1]x[0,1]x[0,1], définition des bords -#==================================================================================== - xmin=0 - xmax=1 - ymin=0 - ymax=1 - zmin=0 - zmax=1 - - nx=21 - ny=21 - nz=21 - - my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny,zmin,zmax,nz) - -if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") - -eps=1e-6 -my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1,0,eps,"DirichletBorder")#Bord DROIT -my_mesh.setGroupAtPlan(0,1,eps,"DirichletBorder")#Bord BAS -my_mesh.setGroupAtPlan(1,1,eps,"DirichletBorder")#Bord HAUT -my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder")#Bord AVANT -my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder")#Bord ARRIERE - -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of cells ", nbCells) - -#Discrétisation du second membre et extraction du nb max de voisins d'une cellule -#================================================================================ -my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) -maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule -for i in range(nbCells): - Ci = my_mesh.getCell(i) - x = Ci.x() - y = Ci.y() - z = Ci.z() - my_RHSfield[i]=3*pi*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)#mettre la fonction definie au second membre de l edp - # compute maximum number of neighbours - maxNbNeighbours= max(1+Ci.getNumberOfFaces(),maxNbNeighbours) - -print("Right hand side discretisation done") -print("Maximum number of neighbours=", maxNbNeighbours) - -# 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.addValue(i,k,-coeff) # terme extradiagonal - else: - coeff=Fj.getMeasure()/Ci.getMeasure()/Ci.getBarryCenter().distance(Fj.getBarryCenter()) - 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,"GMRES","ILU") -SolSyst=LS.solve() - -print("Preconditioner used : ", LS.getNameOfPc()) -print("Number of iterations used : ", LS.getNumberOfIter()) -print("Final residual : ", LS.getResidu()) -print("Linear system solved") - -# 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("FiniteVolumes3DPoisson_CUBE_ResultField") - -#Postprocessing -#============== -# save 3D picture -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) -PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',"ResultField",'CELLS',"Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_CUBE_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(0,sqrt(3),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -if len(sys.argv) >1 : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 3D cube with mesh '+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes3DPoisson_CUBE_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") -else : - plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 3D cube with a rectangular grid') - plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') - plt.savefig("FiniteVolumes3DPoisson_CUBE_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 3D poisson equation using finite volumes done") - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -#The following formulas use the fact that the exact solution is equal to the right hand side divided by 3*pi*pi -max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(3*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]/(3*pi*pi) - my_ResultField[i]) : - erreur_abs = abs(my_RHSfield[i]/(3*pi*pi) - my_ResultField[i]) - -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) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/Poisson3DVF_BALL/CMakeLists.txt b/CDMATH/tests/examples/Poisson3DVF_BALL/CMakeLists.txt deleted file mode 100755 index e89f81e..0000000 --- a/CDMATH/tests/examples/Poisson3DVF_BALL/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -SET(MESH_FILE ../../ressources/ballWithTetrahedra.med ) - -file(COPY ${MESH_FILE} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExamplePoisson_3DVF_BALL_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_BALL.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py b/CDMATH/tests/examples/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py deleted file mode 100755 index 2c32135..0000000 --- a/CDMATH/tests/examples/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur la boule unité avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2018 -# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH -# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta)**2*cos(phi) -#================================================================================================================================ - -import cdmath -from math import sin, cos, pi, sqrt, atan2 -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import PV_routines -import VTK_routines - -import sys - -#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords -#============================================================================================== -my_mesh = cdmath.Mesh("ballWithTetrahedra.med") -if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : - raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") - -eps=1e-6 -my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE -my_mesh.setGroupAtPlan(1,0,eps,"DirichletBorder")#Bord DROIT -my_mesh.setGroupAtPlan(0,1,eps,"DirichletBorder")#Bord BAS -my_mesh.setGroupAtPlan(1,1,eps,"DirichletBorder")#Bord HAUT -my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder")#Bord AVANT -my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder")#Bord ARRIERE - -nbCells = my_mesh.getNumberOfCells() - -print("Mesh loading done") -print("Number of cells ", nbCells) - -#Discrétisation du second membre et extraction du nb max de voisins d'une cellule -#================================================================================ -my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) -my_ExactSol = cdmath.Field("EXACT_SOL", cdmath.CELLS, my_mesh, 1) - -maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix -#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule -for i in range(nbCells): - Ci = my_mesh.getCell(i) - x = Ci.x() - y = Ci.y() - z = Ci.z() - - r=sqrt(x*x+y*y+z*z) - phi=atan2(y,x) - theta=atan2(y,z*sin(phi)) - - my_RHSfield[i]=6*r*sin(theta)**2*cos(phi)+3*(r-1)*cos(phi)#mettre la fonction definie au second membre de l'edp - my_ExactSol[i]=-(r-1)*r**2*sin(theta)**2*cos(phi) - # 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.addValue(i,k,-coeff) # terme extradiagonal - else: - coeff=Fj.getMeasure()/Ci.getMeasure()/Ci.getBarryCenter().distance(Fj.getBarryCenter()) - 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,"GMRES","ILU") -SolSyst=LS.solve() - -print( "Preconditioner used : ", LS.getNameOfPc() ) -print( "Number of iterations used : ", LS.getNumberOfIter() ) -print( "Final residual : ", LS.getResidu() ) -print("Linear system solved") - -# 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("FiniteVolumes3DPoisson_BALL_ResultField") - -#Postprocessing -#============== -# save 3D picture -resolution=100 -VTK_routines.Clip_VTK_data_to_VTK("FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) -PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',"ResultField",'CELLS',"Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_BALL_ResultField") - -# extract and plot diagonal values -resolution=100 -curv_abs=np.linspace(0,sqrt(3),resolution+1) -diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) -plt.legend() -plt.xlabel('Position on diagonal line') -plt.ylabel('Value on diagonal line') -if len(sys.argv) >1 : - plt.title('Plot over diagonal line for finite volumes \n for Laplace operator on a 3D BALL with mesh '+my_mesh.getName()) - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes3DPoisson_BALL_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") -else : - plt.title('Plot over diagonal line for finite volumes \n for Laplace operator on a 3D BALL with a rectangular grid') - plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') - plt.savefig("FiniteVolumes3DPoisson_BALL_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") - -print("Numerical solution of 3D poisson equation on a 3D ball using finite volumes done") - -#Calcul de l'erreur commise par rapport à la solution exacte -#=========================================================== -max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) -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_ExactSol[i] - my_ResultField[i]) : - erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) - -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) - -assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/CMakeLists.txt new file mode 100755 index 0000000..21334e7 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/CMakeLists.txt @@ -0,0 +1,30 @@ +file(GLOB PoissonEquation_EXAMPLES_TO_INSTALL + Poisson1DEF Poisson2DEF Poisson2DEF_DISK Poisson2DEF_DISK_StiffBC Poisson2DEF_SQUARE_StiffBC Poisson1DVF Poisson2DVF Poisson2DVF_DISK Poisson2DVF_DISK_StiffBC Poisson3DEF Poisson3DEF_BALL Poisson3DVF Poisson3DVF_BALL Poisson3DEF_RadiatorAndWindow + Poisson3DSphereEF Poisson3DTorusEF Poisson3DCubeSkinEF # Laplace-Beltrami on surface +) + +install(DIRECTORY ${PoissonEquation_EXAMPLES_TO_INSTALL} DESTINATION share/examples/PoissonEquation) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_SUBDIRECTORY(Poisson1DVF) + ADD_SUBDIRECTORY(Poisson1DEF) + ADD_SUBDIRECTORY(Poisson2DVF) + ADD_SUBDIRECTORY(Poisson2DVF_DISK) + ADD_SUBDIRECTORY(Poisson2DVF_DISK_StiffBC) + ADD_SUBDIRECTORY(Poisson2DEF) + ADD_SUBDIRECTORY(Poisson2DEF_DISK) + ADD_SUBDIRECTORY(Poisson2DEF_DISK_StiffBC) + ADD_SUBDIRECTORY(Poisson2DEF_SQUARE_StiffBC) + ADD_SUBDIRECTORY(Poisson3DSphereEF) + ADD_SUBDIRECTORY(Poisson3DTorusEF) + ADD_SUBDIRECTORY(Poisson3DCubeSkinEF) + ADD_SUBDIRECTORY(Poisson3DEF) + ADD_SUBDIRECTORY(Poisson3DEF_RadiatorAndWindow) + ADD_SUBDIRECTORY(Poisson3DEF_BALL) + ADD_SUBDIRECTORY(Poisson3DVF) + ADD_SUBDIRECTORY(Poisson3DVF_BALL) + +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/CMakeLists.txt new file mode 100755 index 0000000..5be4ec4 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/CMakeLists.txt @@ -0,0 +1,10 @@ + +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson1DEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_1DEF ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements1DPoisson.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/FiniteElements1DPoisson.py b/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/FiniteElements1DPoisson.py new file mode 100755 index 0000000..712b614 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson1DEF/FiniteElements1DPoisson.py @@ -0,0 +1,164 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 1D -\triangle u = f avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage 1D quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x) +#================================================================================================================================ + +import cdmath +from math import sin, pi, sqrt +from numpy import linspace +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +#Création d'un maillage uniforme du segment [0,1], définition des bords +#====================================================================== +nx=100 +my_mesh = cdmath.Mesh(0,1,nx) +if( my_mesh.getSpaceDimension()!=1 or my_mesh.getMeshDimension()!=1) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 1") + +eps=1e-6 +my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading/building done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Discrétisation du second membre et détermination des noeuds intérieurs +#====================================================================== +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() + + my_RHSfield[i]=pi*pi*sin(pi*x)#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) + +print("Right hand side discretisation done") +print("nb of interior nodes=", nbInteriorNodes) +print("nb of boundary nodes=", nbBoundaryNodes) +print("Max nb 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 segment (hypothèse 1D) +GradShapeFunc0=cdmath.Vector(1) +GradShapeFunc1=cdmath.Vector(1) + +#On parcourt les segments 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) + + N0=my_mesh.getNode(nodeId0) + N1=my_mesh.getNode(nodeId1) + + #Formule des gradients voir EF P1 -> calcul déterminants + GradShapeFunc0[0]= 1 + GradShapeFunc1[0]=-1 + + #Création d'un tableau (numéro du noeud, gradient de la fonction de forme + GradShapeFuncs={nodeId0 : GradShapeFunc0} + GradShapeFuncs[nodeId1]=GradShapeFunc1 + + # Remplissage de la matrice de rigidité et du second membre + for j in [nodeId0,nodeId1] : + 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 i au second membre du noeud j + RHS[j_int]=Ci.getMeasure()/2*my_RHSfield[j]+RHS[j_int] # intégrale sur le segment du produit f x fonction de base + #Contribution de la cellule i à la ligne j_int du système linéaire + for k in [nodeId0,nodeId1] : + 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 +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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("FiniteElements1DPoisson_ResultField") + +# Postprocessing : +#================= +# save 1D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElements1DPoisson_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements1DPoisson_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=linspace(0,1,resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,0,0], resolution) +plt.plot(curv_abs, diag_data, label= '1D mesh with '+str(nbNodes) + ' nodes') +plt.legend() +plt.xlabel('Position') +plt.ylabel('Value') +plt.title('1D finite elements \n for Laplace operator') +plt.savefig("FiniteElements1DPoisson_ResultField_"+str(nbNodes) + '_nodes'+".png") + +print("Numerical solution of the 1D Poisson equation 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 pi*pi +max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(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]/(pi*pi) - my_ResultField[i]) : + erreur_abs = abs(my_RHSfield[i]/(pi*pi) - my_ResultField[i]) + +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) +print("Maximum exact solution = ", my_RHSfield.max()/(pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(pi*pi)) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/CMakeLists.txt new file mode 100755 index 0000000..2bde45f --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_1DVF_uniform ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes1DPoisson.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/FiniteVolumes1DPoisson.py b/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/FiniteVolumes1DPoisson.py new file mode 100755 index 0000000..0f18320 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson1DVF/FiniteVolumes1DPoisson.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson 1D -\triangle u = f avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage 1D quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-sin(pi*x) +#================================================================================================================================ + +import cdmath +from math import sin, pi +from numpy import linspace +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines +import sys + +if len(sys.argv) >1 :#non uniform mesh + my_mesh = cdmath.Mesh(sys.argv[1]) +else : #rectangular mesh +#Création d'un maillage uniforme du segment [0,1], définition des bords +#====================================================================== + nx=100 + my_mesh = cdmath.Mesh(0,1,nx) + +if( my_mesh.getSpaceDimension()!=1 or my_mesh.getMeshDimension()!=1) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 1") + +eps=1e-6 +my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT + +nbCells = my_mesh.getNumberOfCells() + +print( "Mesh loading/building 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() + + my_RHSfield[i]=pi*pi*sin(pi*x)#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( "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 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.addValue(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() + RHS[i]+=coeff*sin(pi*x)#mettre ici la solution exacte de l'edp + 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,100,1.E-6,"GMRES","ILU") +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print( "Linear system solved") + +# 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("FiniteVolumes1DPoisson_ResultField") + +#Postprocessing : +#=============== +# save 1D picture +PV_routines.Save_PV_data_to_picture_file("FiniteVolumes1DPoisson_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes1DPoisson_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=linspace(0,1,resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,0,0], resolution) +plt.legend() +plt.xlabel('Position') +plt.ylabel('Value') +if len(sys.argv) >1 : + plt.title('Finite Volumes \n for Laplace operator in 1D'+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes1DPoisson_ResultField_"+str(nbCells)+ '_cells'+".png") +else : + plt.title('Finite Volumes \n for Laplace operator on a 1D regular grid') + plt.plot(curv_abs, diag_data, label= str(nx) + ' cells mesh') + plt.savefig("FiniteVolumes1DPoisson_ResultField_"+str(nx) + '_cells'+".png") + +print("Numerical solution of 1D Poisson equation using finite volumes 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 pi*pi +max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(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]/(pi*pi) - my_ResultField[i]) : + erreur_abs = abs(my_RHSfield[i]/(pi*pi) - my_ResultField[i]) + +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) +print("Maximum exact solution = ", my_RHSfield.max()/(pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(pi*pi)) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/CMakeLists.txt new file mode 100755 index 0000000..4948b54 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/squareWithTriangles.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_2DEF_SQUARE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_SQUARE.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py new file mode 100755 index 0000000..eb28762 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF/FiniteElements2DPoisson_SQUARE.py @@ -0,0 +1,181 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = f avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2016 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y) +#================================================================================================================================ + +import cdmath +from math import sin, pi, sqrt +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +#Chargement du maillage triangulaire du domaine carré [0,1]x[0,1], définition des bords +#======================================================================================= +my_mesh = cdmath.Mesh("squareWithTriangles.med") +if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") +eps=1e-6 +my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT +my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS +my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +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, otherwise use function Ni.getNumberOfEdges() + +print("Right hand side discretisation done") +print("nb of interior nodes=", nbInteriorNodes) +print("nb of boundary nodes=", nbBoundaryNodes) +print("Max nb 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) + + 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") + +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber() +print("Condition number is ",cond) + +# 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 +SolSyst=LS.solve() + +print("Preconditioner used : ", LS.getNameOfPc()) +print("Number of iterations used : ", LS.getNumberOfIter()) +print("Final residual : ", LS.getResidu()) +print("Linear system solved") + +# 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_ResultField") + +# Postprocessing : +#================= +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_SQUARE_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_SQUARE_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(0,sqrt(2),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) +plt.plot(curv_abs, diag_data, label= '2D mesh with '+str(nbNodes) + ' nodes') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D square with triangular mesh') +plt.savefig("FiniteElements2DPoisson_SQUARE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a square 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 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("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) +print("Maximum exact solution = ", my_RHSfield.max()/(2*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(2*pi*pi) ) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/CMakeLists.txt new file mode 100755 index 0000000..e9da83e --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/diskWithTriangles.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_DISK) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_2DEF_DISK ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_DISK.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py new file mode 100755 index 0000000..d133bdf --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK/FiniteElements2DPoisson_DISK.py @@ -0,0 +1,176 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = f sur le disque unité avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2018 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta) +#================================================================================================================================ + +import cdmath +from math import sin, sqrt, atan2 +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +#Chargement du maillage triangulaire du disque unité +#======================================================================================= +my_mesh = cdmath.Mesh("diskWithTriangles.med") +if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Discrétisation du second membre et détermination des noeuds intérieurs +#====================================================================== +my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) +my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) +nbInteriorNodes = 0 +nbBoundaryNodes = 0 +maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +interiorNodes=[] +boundaryNodes=[] + +#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud +for i in range(nbNodes): + Ni=my_mesh.getNode(i) + x = Ni.x() + y = Ni.y() + + r=sqrt(x*x+y*y) + theta=atan2(y,x) + + my_RHSfield[i]=(8*r-3)*sin(theta)#mettre la fonction definie au second membre de l'edp + my_ExactSol[i]=-(r-1)*r*r*sin(theta)#mettre la solution exacte 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, 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) + + 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 +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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_DISK_ResultField") + +# Postprocessing : +#================= +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_DISK_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_DISK_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(-1,1,resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[-0.5,-0.5,0],[0.5,0.5,0], resolution) +plt.plot(curv_abs, diag_data, label= '2D disk mesh with '+str(nbNodes) + ' nodes') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D disk triangular mesh') +plt.savefig("FiniteElements2DPoisson_DISK_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a disk using finite elements done") + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) +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_ExactSol[i] - my_ResultField[i]) : + erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) + +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) +print("Maximum exact solution = ", my_ExactSol.max(), " Minimum exact solution = ", my_ExactSol.min() ) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/CMakeLists.txt new file mode 100755 index 0000000..b9ca72d --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/diskWithTriangles.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_DISK_StiffBC) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_2DEF_DISK_StiffBC ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_DISK_StiffBC.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py new file mode 100755 index 0000000..f160ce6 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_DISK_StiffBC/FiniteElements2DPoisson_DISK_StiffBC.py @@ -0,0 +1,224 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = 0 sur le disque unité avec conditions aux limites de Dirichlet discontinues +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=atan(2*x/(x**2+y**2-1))=atan(2 r cos(theta)/(r*2-1)) +#================================================================================================================================ + +import cdmath +from math import atan, pi +from numpy import sign, linspace +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants +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 + + +#Chargement du maillage triangulaire du disque unité +#======================================================================================= +meshName="diskWithTriangles" +my_mesh = cdmath.Mesh(meshName+".med") +if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Détermination des noeuds intérieurs +#====================================================================== +my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) +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-10 + +#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("x**2+y**2 > 1 !!! 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, 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) + +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)*0.5 + GradShapeFunc1 = gradientNodal(M,values1)*0.5 + GradShapeFunc2 = gradientNodal(M,values2)*0.5 + + #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])*0.5 + 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","ILU")#Remplacer CG par CHOLESKY pour solveur direct +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print( "Linear system solved") + +# 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_ResultField") +my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_DISK") + +# Postprocessing : +#================= +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoissonStiffBC_DISK_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoissonStiffBC_DISK_ResultField") +PV_routines.Save_PV_data_to_picture_file("ExactSol2DPoissonStiffBC_DISK"+'_0.vtu',"Exact_field",'NODES',"ExactSol2DPoissonStiffBC_DISK") + +# extract and plot diagonal values +resolution=100 +curv_abs=linspace(-1,1,resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) +plt.plot(curv_abs, diag_data, label= '2D disk mesh with '+str(nbNodes) + ' nodes') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D disk triangular mesh') +plt.savefig("FiniteElements2DPoissonStiffBC_DISK_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a disk using finite elements done") + +#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) +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()) + +assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt new file mode 100755 index 0000000..2c176f8 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/squareWithTriangles.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson2DEF_SQUARE_StiffBC) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_2DEF_SQUARE_StiffBC ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements2DPoisson_SQUARE_StiffBC.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py new file mode 100755 index 0000000..1f2a44f --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DEF_SQUARE_StiffBC/FiniteElements2DPoisson_SQUARE_StiffBC.py @@ -0,0 +1,223 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 2D -\triangle u = 0 sur le carré unité avec conditions aux limites de Dirichlet discontinues +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=atan((x*x-y*y)/(2*x*y)) +#================================================================================================================================ + +import cdmath +from math import atan, pi +from numpy import linspace +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants +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 + + +#Chargement du maillage triangulaire du carré unité +#======================================================================================= +meshName="squareWithTriangles" +my_mesh = cdmath.Mesh(meshName+".med") +if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Détermination des noeuds intérieurs +#====================================================================== +my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1) +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-10 + +#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud +for i in range(nbNodes): + Ni=my_mesh.getNode(i) + x = Ni.x() + y = Ni.y() + + #Robust calculation of atan((x*x-y*y)/(2*x*y)) + if x<-eps or x>1+eps or y<-eps or y>1+eps : + print("!!! Warning Mesh ", meshName," !!! Node is not in the unit square.",", eps=",eps, ", x= ",x, ", y= ",y) + #raise ValueError("!!! Domain should be the unit square.") + if abs(x*y) > eps : + my_ExactSol[i] = atan((x*x-y*y)/(2*x*y)) + elif x**2-y**2>0 : + my_ExactSol[i] = pi/2 + elif x**2-y**2<0 : + my_ExactSol[i] = -pi/2 + else : #x=0 + my_ExactSol[i] = 0 + + if my_mesh.isBorderNode(i): # Détection des noeuds frontière + boundaryNodes.append(i) + nbBoundaryNodes=nbBoundaryNodes+1 + else: # Détection des noeuds intérieurs + interiorNodes.append(i) + nbInteriorNodes=nbInteriorNodes+1 + maxNbNeighbours= max(1+Ni.getNumberOfCells(),maxNbNeighbours) #true only in 2D, 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) + +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)*0.5 + GradShapeFunc1 = gradientNodal(M,values1)*0.5 + GradShapeFunc2 = gradientNodal(M,values2)*0.5 + + #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])*0.5 + 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","ILU")#Remplacer CG par CHOLESKY pour solveur direct +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print( "Linear system solved") + +# Création du champ résultat +#=========================== +my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1) +for j in range(nbInteriorNodes): + my_ResultField[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs +for j in range(nbBoundaryNodes): + my_ResultField[boundaryNodes[j]]=my_ExactSol[boundaryNodes[j]];#remplissage des valeurs pour les noeuds frontière (condition limite) +#sauvegarde sur le disque dur du résultat dans un fichier paraview +my_ResultField.writeVTK("FiniteElements2DPoissonStiffBC_SQUARE_ResultField") +my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_SQUARE") + +# Postprocessing : +#================= +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoissonStiffBC_SQUARE_ResultField"+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoissonStiffBC_SQUARE_ResultField") +PV_routines.Save_PV_data_to_picture_file("ExactSol2DPoissonStiffBC_SQUARE"+'_0.vtu',"Exact_field",'NODES',"ExactSol2DPoissonStiffBC_SQUARE") + +# extract and plot diagonal values +resolution=100 +curv_abs=linspace(-1,1,resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) +plt.plot(curv_abs, diag_data, label= '2D square mesh with '+str(nbNodes) + ' nodes') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 2D square triangular mesh') +plt.savefig("FiniteElements2DPoissonStiffBC_SQUARE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a square using finite elements done") + +#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) +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()) + +assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/CMakeLists.txt new file mode 100755 index 0000000..750392c --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/CMakeLists.txt @@ -0,0 +1,32 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithLocRefSquares.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithCheckerboardSquares.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithHexagons.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithBrickWall.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithDeformedQuadrangles.med ) + + ADD_TEST(ExamplePoisson_2DVF_SQUARE_deformed_quadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_SQUARE.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py new file mode 100755 index 0000000..877628c --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF/FiniteVolumes2DPoisson_SQUARE.py @@ -0,0 +1,152 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur un carré avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2016 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y) +#================================================================================================================================ + +import cdmath +from math import sin, pi, sqrt +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines +import sys + +if len(sys.argv) >1 :#non rectangular mesh + my_mesh = cdmath.Mesh(sys.argv[1]) +else : #rectangular mesh +# Création d'un maillage cartésien du domaine carré [0,1]x[0,1], définition des bords +#==================================================================================== + xmin=0 + xmax=1 + ymin=0 + ymax=1 + + nx=15 + ny=15 + + my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny) + + eps=1e-6 + my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE + 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 + +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") + +print("Mesh loading done") +print("Number of cells = ", nbCells) + +#Discrétisation du second membre et extraction du nb max de voisins d'une cellule +#================================================================================ +my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) +maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule +for i in range(nbCells): + Ci = my_mesh.getCell(i) + x = Ci.x() + y = Ci.y() + + 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) + +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 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.addValue(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 solution exacte de l'edp + 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,"GMRES","ILU") +SolSyst=LS.solve() + +print("Preconditioner used : ", LS.getNameOfPc()) +print("Number of iterations used : ", LS.getNumberOfIter()) +print("Final residual : ", LS.getResidu()) +print("Linear system solved") + +# 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_ResultField") + +#Postprocessing : +#=============== +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_SQUARE_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_SQUARE_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(0,sqrt(2),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +if len(sys.argv) >1 : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D square '+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_SQUARE_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") +else : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D square with a rectangular grid') + plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_SQUARE_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a square using finite volumes 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 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("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) +print("Maximum exact solution = ", my_RHSfield.max()/(2*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(2*pi*pi) ) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/CMakeLists.txt new file mode 100755 index 0000000..25d1467 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/CMakeLists.txt @@ -0,0 +1,22 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_spiderweb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py new file mode 100755 index 0000000..9e13ad3 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK/FiniteVolumes2DPoisson_DISK.py @@ -0,0 +1,143 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur un disque avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2018 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta) +#================================================================================================================================ + +import cdmath +from math import sin, sqrt, atan2 +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines +import sys + +if len(sys.argv) >1 :#non rectangular mesh + my_mesh = cdmath.Mesh(sys.argv[1]) +else : + raise ValueError("Give an input mesh of the disk") + +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") + +print( "Mesh loading done" ) +print( "Number of cells = ", nbCells ) + +#Discrétisation du second membre et extraction du nb max de voisins d'une cellule +#================================================================================ +my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) +my_ExactSol = cdmath.Field("Exact_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() + + r=sqrt(x*x+y*y) + theta=atan2(y,x) + + my_RHSfield[i]=(8*r-3)*sin(theta)#mettre la fonction definie au second membre de l'edp + my_ExactSol[i]=-(r-1)*r*r*sin(theta)#mettre la solution exacte 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.addValue(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() + r=sqrt(x*x+y*y) + theta=atan2(y,x) + RHS[i]+=coeff*(-(r-1)*r*r*sin(theta))#mettre ici la solution exacte de l'edp + 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,"GMRES","ILU") +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print( "Linear system solved" ) + +# 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_DISK_square_ResultField") + +#Postprocessing : +#=============== +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_DISK_square_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_DISK_square_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(0,sqrt(2),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +if len(sys.argv) >1 : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk mesh '+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_DISK_square_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") +else : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk with a rectangular grid') + plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_DISK_square_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a disk using finite volumes done") + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) +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_ExactSol[i] - my_ResultField[i]) : + erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) + +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) +print("Maximum exact solution = ", my_ExactSol.max(), " Minimum exact solution = ", my_ExactSol.min() ) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/CMakeLists.txt new file mode 100755 index 0000000..0762aca --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/CMakeLists.txt @@ -0,0 +1,22 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExamplePoisson_2DVF_DISK_StiffBC_spiderweb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes2DPoisson_DISK_StiffBC.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py new file mode 100755 index 0000000..56355bd --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson2DVF_DISK_StiffBC/FiniteVolumes2DPoisson_DISK_StiffBC.py @@ -0,0 +1,155 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson -\triangle u = 0 sur un disque avec conditions aux limites de Dirichlet discontinues +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=atan(2*x/(x**2+y**2-1))=atan(2 r cos(theta)/(r*2-1)) +#================================================================================================================================ + +import cdmath +from math import atan, pi, sqrt +from numpy import linspace +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines +import sys + +if len(sys.argv) >1 :#non rectangular mesh + meshName=sys.argv[1] + my_mesh = cdmath.Mesh(sys.argv[1]) +else : + raise ValueError("Give an input mesh of the disk") + +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") + +print( "Mesh loading done" ) +print( "Number of cells = ", nbCells ) + +#Discrétisation du second membre et extraction du nb max de voisins d'une cellule +#================================================================================ +my_ExactSol = cdmath.Field("Exact_field", cdmath.CELLS, my_mesh, 1) +eps=1e-6#For coarse meshes + +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() + + #Robust calculation of atan(2x/(x**2+y**2-1) + if x**2+y**2-1 > eps : + print("!!! Warning Mesh ", meshName," !!! Cell is not in the unit disk."," eps=",eps, ", x**2+y**2-1=",x**2+y**2 - 1) + #raise ValueError("x**2+y**2 > 1 !!! 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) + +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): + 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.addValue(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 ", meshName," !!! 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,"GMRES","ILU") +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print( "Linear system solved" ) + +# 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_DISK_ResultField") + +#Postprocessing : +#=============== +# save 2D picture +PV_routines.Save_PV_data_to_picture_file("FiniteVolumes2DPoisson_DISK_ResultField"+'_0.vtu',"ResultField",'CELLS',"FiniteVolumes2DPoisson_DISK_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=linspace(0,sqrt(2),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,-1,0],[0,1,0], resolution) +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +if len(sys.argv) >1 : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk mesh '+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_DISK_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") +else : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 2D disk with a rectangular grid') + plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') + plt.savefig("FiniteVolumes2DPoisson_DISK_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 2D Poisson equation on a disk using finite volumes done") + +#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 absolute error = norm( exact solution - numerical solution ) = ",l2_error ) +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() ) + +assert l2_error/l2_norm_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/CMakeLists.txt new file mode 100755 index 0000000..3720053 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/meshCubeSkin.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DCubeSkinEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoissonBeltrami_3DFE_CUBESKIN ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonCubeSkin.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py new file mode 100644 index 0000000..e167456 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DCubeSkinEF/FiniteElements3DPoissonCubeSkin.py @@ -0,0 +1,216 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur la frontière d'un cube +# Author : Michael Ndjinga +# Copyright : CEA Saclay 2021 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau +# Comparaison de la solution numérique avec la solution exacte définie face par face : u(x,y,z)= cos(2*pi*x)*cos(2*pi*y)*cos(2*pi*z) +#================================================================================================================================ + +import cdmath +from math import cos, pi +import numpy as np +import PV_routines +import VTK_routines +import paraview.simple as pvs + +#Chargement du maillage triangulaire de la frontière du cube unité [0,1]x[0,1]x[0,1] +#======================================================================================= +my_mesh = cdmath.Mesh("meshCubeSkin.med") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") +if(my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") +if(my_mesh.getSpaceDimension()!=3) : + raise ValueError("Wrong space dimension : expected a space of dimension 3") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh building/loading done") +print("nb of nodes=", nbNodes) +print("nb of cells=", nbCells) + +#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 + +eps=1e-6 +#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]= 8*pi*pi*cos(2*pi*x)*cos(2*pi*y)*cos(2*pi*z) + + 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) #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é + 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) + normalCell = normalCell*(1/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()*0.5 + GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 + GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 + GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 + GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 + GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 + GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 + GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 + GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 + + #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") + +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber(True) +print("Condition number is ",cond) + +# Résolution du système linéaire +#================================= +LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU") +LS.setMatrixIsSingular()#En raison de l'absence de bord +SolSyst=LS.solve() +print("Preconditioner used : ", LS.getNameOfPc() ) +print("Number of iterations used : ", LS.getNumberOfIter() ) +print("Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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 issues du système linéaire dans le champs résultat +#sauvegarde sur le disque dur du résultat dans un fichier paraview +my_ResultField.writeVTK("FiniteElementsOnCubeSkinPoisson") +my_RHSfield.writeVTK("RHS_CubeSkinPoisson") + +print("Integral of the numerical solution", my_ResultField.integral(0)) +print("Numerical solution of Poisson equation on a cube skin 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 8*pi*pi +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]/(8*pi*pi) - my_ResultField[i]) : + erreur_abs = abs(my_RHSfield[i]/(8*pi*pi) - 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/(8*pi*pi) + +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) +print("Maximum exact solution = ", my_RHSfield.max()/(8*pi*pi), " Minimum exact solution = ", my_RHSfield.min()/(8*pi*pi) ) + +#Postprocessing : +#================ +# save 3D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnCubeSkinPoisson") +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnCubeSkinPoisson"+'_0.vtu',[0.75,0.75,0.75], [0.,0.5,-0.5],resolution ) +PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElementsOnCubeSkinPoisson"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnCubeSkinPoisson") + +# Plot over slice circle +finiteElementsOnCubeSkin_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnCubeSkinPoisson"+'_0.vtu']) +slice1 = pvs.Slice(Input=finiteElementsOnCubeSkin_0vtu) +slice1.SliceType.Normal = [0, 1, 0] +renderView1 = pvs.GetActiveViewOrCreate('RenderView') +finiteElementsOnCubeSkin_0vtuDisplay = pvs.Show(finiteElementsOnCubeSkin_0vtu, renderView1) +pvs.ColorBy(finiteElementsOnCubeSkin_0vtuDisplay, ('POINTS', 'ResultField')) +slice1Display = pvs.Show(slice1, renderView1) +pvs.SaveScreenshot("./FiniteElementsOnCubeSkinPoisson"+"_Slice"+'.png', magnification=1, quality=100, view=renderView1) +plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) +lineChartView2 = pvs.CreateView('XYChartView') +plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) +plotOnSortedLines1Display.UseIndexForXAxis = 0 +plotOnSortedLines1Display.XArrayName = 'arc_length' +plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)'] +pvs.SaveScreenshot("./FiniteElementsOnCubeSkinPoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) +pvs.Delete(lineChartView2) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/CMakeLists.txt new file mode 100755 index 0000000..e9c8165 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/meshCube.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_3DEF_CUBE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_CUBE.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/FiniteElements3DPoisson_CUBE.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/FiniteElements3DPoisson_CUBE.py new file mode 100755 index 0000000..6043a1e --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF/FiniteElements3DPoisson_CUBE.py @@ -0,0 +1,189 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 3D -\triangle u = f sur le cube avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga, Sédrick Kameni +# Copyright : CEA Saclay 2017 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage tétraédrique +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y)*sin(pi*z) +#================================================================================================================================ + +import cdmath +from math import sin, pi, sqrt +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords +#============================================================================================== +my_mesh = cdmath.Mesh("meshCube.med") +if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") +if(not my_mesh.isTetrahedral()) : + raise ValueError("Wrong cell types : mesh is not made of tetrahedra") +eps=1e-6 +my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT +my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS +my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT +my_mesh.setGroupAtPlan(0.,2,eps,"DirichletBorder")#Bord AVANT +my_mesh.setGroupAtPlan(1.,2,eps,"DirichletBorder")#Bord ARRIERE + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Discrétisation du second membre et détermination des noeuds intérieurs +#====================================================================== +my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) + +nbInteriorNodes = 0 +nbBoundaryNodes = 0 +maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +interiorNodes=[] +boundaryNodes=[] + +#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud +for i in range(nbNodes): + Ni=my_mesh.getNode(i) + x = Ni.x() + y = Ni.y() + z = Ni.z() + + 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 + 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.getNumberOfEdges(),maxNbNeighbours) + +print("Right hand side discretisation done") +print("Number of interior nodes=", nbInteriorNodes) +print("Number of boundary nodes=", nbBoundaryNodes) +print("Maximum number of neighbours per node=", 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 tétraèdre +GradShapeFunc0=cdmath.Vector(3) +GradShapeFunc1=cdmath.Vector(3) +GradShapeFunc2=cdmath.Vector(3) +GradShapeFunc3=cdmath.Vector(3) + +#On parcourt les tétraèdres du domaine +for i in range(nbCells): + + Ci=my_mesh.getCell(i) + + #Extraction des noeuds de la cellule + nodeId0=Ci.getNodeId(0) + nodeId1=Ci.getNodeId(1) + nodeId2=Ci.getNodeId(2) + nodeId3=Ci.getNodeId(3) + N0=my_mesh.getNode(nodeId0) + N1=my_mesh.getNode(nodeId1) + N2=my_mesh.getNode(nodeId2) + N3=my_mesh.getNode(nodeId3) + + #Formule des gradients voir EF P1 -> calcul déterminants + GradShapeFunc0[0]= (N2.y()*N3.z()-N2.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 + GradShapeFunc0[1]=-(N2.x()*N3.z()-N2.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 + GradShapeFunc0[2]=(N2.x()*N3.y()-N2.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 + GradShapeFunc1[0]=- (N2.y()*N3.z()-N2.z()*N3.y()-N0.y()*N3.z()+N3.y()*N0.z()+N0.y()*N2.z()-N2.y()*N0.z())/6 + GradShapeFunc1[1]=(N2.x()*N3.z()-N2.z()*N3.x()-N0.x()*N3.z()+N3.x()*N0.z()+N0.x()*N2.z()-N2.x()*N0.z())/6 + GradShapeFunc1[2]=-(N2.x()*N3.y()-N2.y()*N3.x()-N0.x()*N3.y()+N3.x()*N0.y()+N0.x()*N2.y()-N2.x()*N0.y())/6 + GradShapeFunc2[0]= -(N0.y()*N3.z()-N0.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N0.z()-N0.y()*N1.z())/6 + GradShapeFunc2[1]=(N0.x()*N3.z()-N0.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N0.z()-N0.x()*N1.z())/6 + GradShapeFunc2[2]= -(N0.x()*N3.y()-N0.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N0.y()-N0.x()*N1.y())/6 + GradShapeFunc3[0]=-(N2.y()*N0.z()-N2.z()*N0.y()-N1.y()*N0.z()+N0.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 + GradShapeFunc3[1]=(N2.x()*N0.z()-N2.z()*N0.x()-N1.x()*N0.z()+N0.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 + GradShapeFunc3[2]=-(N2.x()*N0.y()-N2.y()*N0.x()-N1.x()*N0.y()+N0.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 + + #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) + GradShapeFuncs={nodeId0 : GradShapeFunc0} + GradShapeFuncs[nodeId1]=GradShapeFunc1 + GradShapeFuncs[nodeId2]=GradShapeFunc2 + GradShapeFuncs[nodeId3]=GradShapeFunc3 + + # Remplissage de la matrice de rigidité et du second membre + for j in [nodeId0,nodeId1,nodeId2,nodeId3] : + 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()/4*my_RHSfield[j]+RHS[j_int] # intégrale dans le triangle du produit f x fonction de base + #Contribution de la cellule tétraédrique i à la ligne j_int du système linéaire + for k in [nodeId0,nodeId1,nodeId2,nodeId3] : + 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")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct +SolSyst=LS.solve() +print( "Preconditioner used : ", LS.getNameOfPc()) +print( "Number of iterations used : ", LS.getNumberOfIter()) +print( "Final residual : ", LS.getResidu()) +print("Linear system solved") + +# 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("FiniteElements3DPoisson_CUBE_ResultField") + +#Postprocessing : +#================ +# save 3D picture +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) +PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_CUBE_ResultField"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_CUBE_ResultField") + +# extract and plot diagonal values +curv_abs=np.linspace(0,sqrt(3),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,0,0],[1,1,1], resolution) +plt.plot(curv_abs, diag_data, label= str(nbNodes) + ' nodes 3D mesh') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 3D tetrahedral mesh') +plt.savefig("FiniteElements3DPoisson_CUBE_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 3D Poisson equation on a cube 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 3*pi*pi +max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(3*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]/(3*pi*pi) - my_ResultField[i]) : + erreur_abs = abs(my_RHSfield[i]/(3*pi*pi) - my_ResultField[i]) + +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) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/CMakeLists.txt new file mode 100755 index 0000000..3adada4 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/ballWithTetrahedra.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF_BALL) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_3DEF_BALL ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_BALL.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py new file mode 100755 index 0000000..82fa4e8 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_BALL/FiniteElements3DPoisson_BALL.py @@ -0,0 +1,186 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Poisson 3D -\triangle u = f sur la boule unité avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2018 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage tétraédrique +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta)**2*cos(phi) +#================================================================================================================================ + +import cdmath +from math import sin, cos, atan2, sqrt +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords +#============================================================================================== +my_mesh = cdmath.Mesh("ballWithTetrahedra.med") +if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") +if(not my_mesh.isTetrahedral()) : + raise ValueError("Wrong cell types : mesh is not made of tetrahedra") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Discrétisation du second membre et détermination des noeuds intérieurs +#====================================================================== +my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1) +my_ExactSol = cdmath.Field("EXACT_SOL", cdmath.NODES, my_mesh, 1) +nbInteriorNodes = 0 +nbBoundaryNodes = 0 +maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +interiorNodes=[] +boundaryNodes=[] + +#parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud +for i in range(nbNodes): + Ni=my_mesh.getNode(i) + x = Ni.x() + y = Ni.y() + z = Ni.z() + + r=sqrt(x*x+y*y+z*z) + phi=atan2(y,x) + theta=atan2(y,z*sin(phi)) + + my_RHSfield[i]=6*r*sin(theta)**2*cos(phi)+3*(r-1)*cos(phi)#mettre la fonction definie au second membre de l'edp + my_ExactSol[i]=-(r-1)*r**2*sin(theta)**2*cos(phi) + 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.getNumberOfEdges(),maxNbNeighbours) + +print("Right hand side discretisation done") +print("Number of interior nodes=", nbInteriorNodes) +print("Number of boundary nodes=", nbBoundaryNodes) +print("Maximum number of neighbours per node=", 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 hexaèdre +GradShapeFunc0=cdmath.Vector(3) +GradShapeFunc1=cdmath.Vector(3) +GradShapeFunc2=cdmath.Vector(3) +GradShapeFunc3=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) + nodeId3=Ci.getNodeId(3) + N0=my_mesh.getNode(nodeId0) + N1=my_mesh.getNode(nodeId1) + N2=my_mesh.getNode(nodeId2) + N3=my_mesh.getNode(nodeId3) + + #Formule des gradients voir EF P1 -> calcul déterminants + GradShapeFunc0[0]= (N2.y()*N3.z()-N2.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 + GradShapeFunc0[1]=-(N2.x()*N3.z()-N2.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 + GradShapeFunc0[2]=(N2.x()*N3.y()-N2.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 + GradShapeFunc1[0]=- (N2.y()*N3.z()-N2.z()*N3.y()-N0.y()*N3.z()+N3.y()*N0.z()+N0.y()*N2.z()-N2.y()*N0.z())/6 + GradShapeFunc1[1]=(N2.x()*N3.z()-N2.z()*N3.x()-N0.x()*N3.z()+N3.x()*N0.z()+N0.x()*N2.z()-N2.x()*N0.z())/6 + GradShapeFunc1[2]=-(N2.x()*N3.y()-N2.y()*N3.x()-N0.x()*N3.y()+N3.x()*N0.y()+N0.x()*N2.y()-N2.x()*N0.y())/6 + GradShapeFunc2[0]= -(N0.y()*N3.z()-N0.z()*N3.y()-N1.y()*N3.z()+N3.y()*N1.z()+N1.y()*N0.z()-N0.y()*N1.z())/6 + GradShapeFunc2[1]=(N0.x()*N3.z()-N0.z()*N3.x()-N1.x()*N3.z()+N3.x()*N1.z()+N1.x()*N0.z()-N0.x()*N1.z())/6 + GradShapeFunc2[2]= -(N0.x()*N3.y()-N0.y()*N3.x()-N1.x()*N3.y()+N3.x()*N1.y()+N1.x()*N0.y()-N0.x()*N1.y())/6 + GradShapeFunc3[0]=-(N2.y()*N0.z()-N2.z()*N0.y()-N1.y()*N0.z()+N0.y()*N1.z()+N1.y()*N2.z()-N2.y()*N1.z())/6 + GradShapeFunc3[1]=(N2.x()*N0.z()-N2.z()*N0.x()-N1.x()*N0.z()+N0.x()*N1.z()+N1.x()*N2.z()-N2.x()*N1.z())/6 + GradShapeFunc3[2]=-(N2.x()*N0.y()-N2.y()*N0.x()-N1.x()*N0.y()+N0.x()*N1.y()+N1.x()*N2.y()-N2.x()*N1.y())/6 + + #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) + GradShapeFuncs={nodeId0 : GradShapeFunc0} + GradShapeFuncs[nodeId1]=GradShapeFunc1 + GradShapeFuncs[nodeId2]=GradShapeFunc2 + GradShapeFuncs[nodeId3]=GradShapeFunc3 + + # Remplissage de la matrice de rigidité et du second membre + for j in [nodeId0,nodeId1,nodeId2,nodeId3] : + 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()/4*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,nodeId3] : + 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")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct +SolSyst=LS.solve() +print("Preconditioner used : ", LS.getNameOfPc() ) +print("Number of iterations used : ", LS.getNumberOfIter() ) +print("Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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("FiniteElements3DPoisson_BALL_ResultField") + +#Postprocessing : +#================ +# save 3D picture +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) +PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_BALL_ResultField"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElements3DPoisson_BALL_ResultField") + +# extract and plot diagonal values +curv_abs=np.linspace(0,sqrt(3),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[-0.577,-0.577,-0.577],[0.577,0.577,0.577], resolution) +plt.plot(curv_abs, diag_data, label= str(nbNodes) + ' nodes 3D mesh') +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +plt.title('Plot over diagonal line for finite elements \n for Laplace operator on a 3D ball tetrahedral mesh') +plt.savefig("FiniteElements3DPoisson_BALL_ResultField_"+str(nbNodes) + '_nodes'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 3D Poisson equation on a 3D ball using finite elements done") + + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) +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_ExactSol[i] - my_ResultField[i]) : + erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) + +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) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt new file mode 100755 index 0000000..f628489 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ./Mesh_RadiatorAndWindow.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DEF_RadiatorAndWindow) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_3DEF_CUBE_RadiatorAndWindow ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py new file mode 100755 index 0000000..f58010b --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/FiniteElements3DPoisson_CUBE_RadiatorAndWindow.py @@ -0,0 +1,199 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Laplace 3D -\Delta T = 0 avec conditions aux limites de Dirichlet u non nulle +# Authors : Michaël Ndjinga, Sédrick Kameni Ngwamou +# Copyright : CEA Saclay 2019 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u discrétisés aux noeuds d'un maillage tétraédrique +# Condition limites correspondant au refroidissement dû à une fenêtre et au chauffage dû à un radiateur +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +#================================================================================================================================ + +import cdmath +import numpy as np + +# Fonction qui remplace successivement les colonnes d'une matrices par un vecteur donné et retourne la liste des déterminants +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 + +# Fonction qui calcule la valeur de la condition limite en un noeud donné +def boundaryValue(nodeId): + Ni=my_mesh.getNode(nodeId) + + # 4 groupes sont considérés sur le bord + if boundaryNodes.count(nodeId)==0: + return 0 + elif Ni.getGroupName()=='Fenetre': + return Tfenetre; + elif Ni.getGroupName()=='Radiateur_sous-fenetre': + return Tradiateur + #elif Ni.getGroupName()=='Radiateur_Devant': + #return Tradiateur; + #elif Ni.getGroupName()=='Radiateur_droit': + #return Tradiateur + else: + return Tmur; + +#Chargement du maillage tétraédrique du domaine +#============================================== +my_mesh = cdmath.Mesh("Mesh_RadiatorAndWindow.med") +if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") +if(not my_mesh.isTetrahedral()) : + raise ValueError("Wrong cell types : mesh is not made of tetrahedra") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("nb of nodes=", nbNodes) +print("nb of cells=", nbCells) + +#Conditions limites +Tmur=20 +Tfenetre=0 +Tradiateur=40 + +#Détermination des noeuds intérieurs +#====================================================================== +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) + + if my_mesh.isBorderNode(i): # Détection des noeuds frontière getGroupName my_mesh.getNode(i) + boundaryNodes.append(i) + else: # Détection des noeuds intérieurs + interiorNodes.append(i) + maxNbNeighbours= max(1+Ni.getNumberOfEdges(),maxNbNeighbours) + +nbInteriorNodes=len(interiorNodes) +nbBoundaryNodes=len(boundaryNodes) + + +print("nb of interior nodes=", nbInteriorNodes) +print("nb of Boundary nodes=", nbBoundaryNodes) +print("Max nb 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) +RHS=cdmath.Vector(nbInteriorNodes) + +# Vecteurs gradient de la fonction de forme associée à chaque noeud d'un tétrèdre (hypothèse 3D) +M=cdmath.Matrix(4,4) +GradShapeFunc0=cdmath.Vector(3) +GradShapeFunc1=cdmath.Vector(3) +GradShapeFunc2=cdmath.Vector(3) +GradShapeFunc3=cdmath.Vector(3) + +#On parcourt les tétraèdres du domaine pour remplir la matrice +for i in range(nbCells): + + Ci=my_mesh.getCell(i) + + #Extraction des noeuds de la cellule + nodeId0=Ci.getNodeId(0) + nodeId1=Ci.getNodeId(1) + nodeId2=Ci.getNodeId(2) + nodeId3=Ci.getNodeId(3) + N0=my_mesh.getNode(nodeId0) + N1=my_mesh.getNode(nodeId1) + N2=my_mesh.getNode(nodeId2) + N3=my_mesh.getNode(nodeId3) + + M[0,0]=N0.x() + M[0,1]=N0.y() + M[0,2]=N0.z() + M[0,3]=1 + M[1,0]=N1.x() + M[1,1]=N1.y() + M[1,2]=N1.z() + M[1,3]=1 + M[2,0]=N2.x() + M[2,1]=N2.y() + M[2,2]=N2.z() + M[2,3]=1 + M[3,0]=N3.x() + M[3,1]=N3.y() + M[3,2]=N3.z() + M[3,3]=1 + + #Values of each shape function at each node + values0=[1,0,0,0] + values1=[0,1,0,0] + values2=[0,0,1,0] + values3=[0,0,0,1] + + GradShapeFunc0 = gradientNodal(M,values0)*(1./6) + GradShapeFunc1 = gradientNodal(M,values1)*(1./6) + GradShapeFunc2 = gradientNodal(M,values2)*(1./6) + GradShapeFunc3 = gradientNodal(M,values3)*(1./6) + + #Création d'un tableau (numéro du noeud, gradient de la fonction de forme) + GradShapeFuncs={nodeId0 : GradShapeFunc0} + GradShapeFuncs[nodeId1]=GradShapeFunc1 + GradShapeFuncs[nodeId2]=GradShapeFunc2 + GradShapeFuncs[nodeId3]=GradShapeFunc3 + + # Remplissage de la matrice de rigidité et du second membre + for j in [nodeId0,nodeId1,nodeId2,nodeId3] : + 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 + boundaryContributionAdded=False#Needed in case j is a border cell + #Ajout de la contribution de la cellule ttétraédrique i au second membre du noeud j + for k in [nodeId0,nodeId1,nodeId2,nodeId3] : + 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 + # Valeurs de g_h aux noeuds du tétraèdre + T0 = boundaryValue(nodeId0) + T1 = boundaryValue(nodeId1) + T2 = boundaryValue(nodeId2) + T3 = boundaryValue(nodeId3) + boundaryContributionAdded=True#Contribution from the boundary to matrix line j is done in one step + GradGh = gradientNodal(M,[T0,T1,T2,T3])*(1./6) + RHS[j_int] += -(GradGh*GradShapeFuncs[j])/Ci.getMeasure() + + + +print("Linear system matrix building done") + +LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"CG","ILU")#,"ILU" Remplacer CG par CHOLESKY pour solveur direct + +SolSyst=LS.solve() + +# Création du champ résultat +#=========================== +my_Temperature = cdmath.Field("Temperature", cdmath.NODES, my_mesh, 1) +for j in range(nbInteriorNodes): + my_Temperature[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs SolSyst[j] +#Remplissage des valeurs pour les noeuds frontière (condition limite) +for j in boundaryNodes: + my_Temperature[j]=boundaryValue(j) + + +#sauvegarde sur le disque dur du résultat dans un fichier paraview +my_Temperature.writeVTK("FiniteElements3DTemperature") + +print( "Minimum temperature= ", my_Temperature.min(), ", maximum temperature= ", my_Temperature.max() ) +assert my_Temperature.min()>= min(Tmur,Tfenetre,Tradiateur) and my_Temperature.max()<= max(Tmur,Tfenetre,Tradiateur) + +print( "Numerical solution of 3D Laplace equation using finite elements done" ) + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med new file mode 100755 index 0000000..c22aec1 Binary files /dev/null and b/CDMATH/tests/examples/PoissonEquation/Poisson3DEF_RadiatorAndWindow/Mesh_RadiatorAndWindow.med differ diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/CMakeLists.txt new file mode 100755 index 0000000..efd716b --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/meshSphere.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DSphereEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoissonBeltrami_3DFE_SPHERE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonSphere.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py new file mode 100755 index 0000000..9d07572 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DSphereEF/FiniteElements3DPoissonSphere.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur une sphere +# Author : Michael Ndjinga +# Copyright : CEA Saclay 2017 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations +# on surfaces. SIAM J. Num. Anal., 47, p. 3355 +# Solution exacte = f/12 : il s'agit d'un vecteur propre du laplacien sur la sphère +# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau +#================================================================================================================================ + +import cdmath +from math import pow +import numpy as np +import PV_routines +import VTK_routines +import paraview.simple as pvs + +#Chargement du maillage triangulaire de la sphère +#======================================================================================= +my_mesh = cdmath.Mesh("meshSphere.med") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") +if(my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") +if(my_mesh.getSpaceDimension()!=3) : + raise ValueError("Wrong space dimension : expected a space of dimension 3") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh building/loading done") +print("nb of nodes=", nbNodes) +print("nb of cells=", nbCells) + +#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) #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é + 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) + normalCell = normalCell*(1/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()*0.5 + GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 + GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 + GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 + GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 + GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 + GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 + GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 + GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 + + #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") + +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber(True) +print("Condition number is ",cond) + +# Résolution du système linéaire +#================================= +LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU") +LS.setMatrixIsSingular()#En raison de l'absence de bord +SolSyst=LS.solve() +print("Preconditioner used : ", LS.getNameOfPc() ) +print("Number of iterations used : ", LS.getNumberOfIter() ) +print("Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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") + +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("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) +print("Maximum exact solution = ", my_RHSfield.max()/12, " Minimum exact solution = ", my_RHSfield.min()/12 ) + +#Postprocessing : +#================ +# save 3D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnSpherePoisson"+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnSpherePoisson") +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnSpherePoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnSpherePoisson"+'_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"+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson") + +# Plot over slice circle +finiteElementsOnSphere_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnSpherePoisson"+'_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"+'.png', magnification=1, quality=100, view=renderView1) +plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) +lineChartView2 = pvs.CreateView('XYChartView') +plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) +plotOnSortedLines1Display.UseIndexForXAxis = 0 +plotOnSortedLines1Display.XArrayName = 'arc_length' +plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)'] +pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) +pvs.Delete(lineChartView2) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/CMakeLists.txt new file mode 100755 index 0000000..c56320b --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/CMakeLists.txt @@ -0,0 +1,15 @@ + +SET(MESH_MED + ${MED_MESHES}/meshTorus.med + ) + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/Poisson3DTorusEF) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoissonBeltrami_3DFE_TORUS ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteElements3DPoissonTorus.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py new file mode 100755 index 0000000..6de976e --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DTorusEF/FiniteElements3DPoissonTorus.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution EF de l'équation de Laplace-Beltrami -\triangle u = f sur un tore +# Author : Michael Ndjinga +# Copyright : CEA Saclay 2018 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs u et f discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant la librairie CDMATH +# Référence : M. A. Olshanskii, A. Reusken, and J. Grande. A finite element method for elliptic equations +# on surfaces. SIAM J. Num. Anal., 47, p. 3355 +# Résolution d'un système linéaire à matrice singulière : les vecteurs constants sont dans le noyau +#================================================================================================================================ + +import cdmath +from math import sin, cos, atan2, sqrt +import PV_routines +import VTK_routines +import paraview.simple as pvs + +#Chargement du maillage triangulaire du tore +#======================================================================================= +my_mesh = cdmath.Mesh("meshTorus.med") +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") +if(my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") +if(my_mesh.getSpaceDimension()!=3) : + raise ValueError("Wrong space dimension : expected a space of dimension 3") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh building/loading done") +print("nb of nodes=", nbNodes) +print("nb of cells=", nbCells) + +# Torus radii (calculation will fail if the mesh is not correct) +R=1 #Grand rayon +r=0.6 #Petit rayon + +#Discrétisation du second membre, de la solution exacte et détermination des noeuds intérieurs +#====================================================================== +my_RHSfield = cdmath.Field("RHS field", cdmath.NODES, my_mesh, 1) +exactSolField = cdmath.Field("Exact solution field", cdmath.NODES, my_mesh, 1) + +maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix + +#parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud +for i in range(nbNodes): + Ni=my_mesh.getNode(i) + x = Ni.x() + y = Ni.y() + z = Ni.z() + + theta=atan2(z,sqrt(x*x+y*y)-R) + phi=atan2(y,x) + + exactSolField[i] = sin(3*phi)*cos(3*theta+ phi) # for the exact solution we use the funtion given in the article of Olshanskii, Reusken 2009, page 19 + my_RHSfield[i] = 9*sin(3*phi)*cos(3*theta+ phi)/(r*r) + (10*sin(3*phi)*cos(3*theta+ phi) + 6*cos(3*phi)*sin(3*theta+ phi))/((R+r*cos(theta))*(R+r*cos(theta))) - 3*sin(theta)*sin(3*phi)*sin(3*theta+ phi)/(r*(R+r*cos(theta))) #for the right hand side we use the function given in the article of Olshanskii, Reusken 2009, page 19 + 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) #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) +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) + normalCell = normalCell*(1/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()*0.5 + GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 + GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 + GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 + GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 + GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 + GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 + GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 + GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 + + #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") + +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber(True) +print("Condition number is ",cond) + +# Résolution du système linéaire +#================================= +LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"GMRES","ILU")#Remplacer CG par CHOLESKY pour solveur direct +LS.setMatrixIsSingular()#En raison de l'absence de bord +SolSyst=LS.solve() +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# Création du champ résultat +#=========================== +my_ResultField = cdmath.Field("Numerical result field", 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("FiniteElementsOnTorusPoisson") + +print("Integral of the numerical solution", my_ResultField.integral(0)) +print("Numerical solution of Poisson equation on a torus using finite elements done") + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +max_sol_exacte=exactSolField.normMax()[0] +erreur_max=(exactSolField - my_ResultField).normMax()[0] +max_sol_num=my_ResultField.max() +min_sol_num=my_ResultField.min() + +print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_max/max_sol_exacte) +print("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num) +print("Maximum exact solution = ", exactSolField.max(), " Minimum exact solution = ", exactSolField.min()) + +#Postprocessing : +#================ +# Save 3D picture +PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnTorusPoisson"+'_0.vtu',"Numerical result field",'NODES',"FiniteElementsOnTorusPoisson") +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnTorusPoisson"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnTorusPoisson"+'_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_"+"FiniteElementsOnTorusPoisson"+'_0.vtu',"Numerical result field",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnTorusPoisson") + +# Plot over slice circle +finiteElementsOnTorus_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnTorusPoisson"+'_0.vtu']) +slice1 = pvs.Slice(Input=finiteElementsOnTorus_0vtu) +slice1.SliceType.Normal = [0.5, 0.5, 0.5] +renderView1 = pvs.GetActiveViewOrCreate('RenderView') +finiteElementsOnTorus_0vtuDisplay = pvs.Show(finiteElementsOnTorus_0vtu, renderView1) +pvs.ColorBy(finiteElementsOnTorus_0vtuDisplay, ('POINTS', 'Numerical result field')) +slice1Display = pvs.Show(slice1, renderView1) +pvs.SaveScreenshot("./FiniteElementsOnTorusPoisson"+"_Slice"+'.png', magnification=1, quality=100, view=renderView1) +plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1) +lineChartView2 = pvs.CreateView('XYChartView') +plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2) +plotOnSortedLines1Display.UseIndexForXAxis = 0 +plotOnSortedLines1Display.XArrayName = 'arc_length' +plotOnSortedLines1Display.SeriesVisibility = ['Numerical result field (1)'] +pvs.SaveScreenshot("./FiniteElementsOnTorusPoisson"+"_PlotOnSortedLine_"+'.png', magnification=1, quality=100, view=lineChartView2) +pvs.Delete(lineChartView2) + +assert erreur_max/max_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/CMakeLists.txt new file mode 100755 index 0000000..caef0fe --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/CMakeLists.txt @@ -0,0 +1,20 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_3DVF_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExamplePoisson_3DVF_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) + + SET(MESH_FILE ${MED_MESHES}/cubeWithLocRefCubes.med ) + + ADD_TEST(ExamplePoisson_3DVF_CUBE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) + + SET(MESH_FILE ${MED_MESHES}/3DCheckerboard/checkerboard_4x4x4.med ) + + ADD_TEST(ExamplePoisson_3DVF_CUBE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_CUBE.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py new file mode 100755 index 0000000..066d1ff --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF/FiniteVolumes3DPoisson_CUBE.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur unu cube avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2016 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=sin(pi*x)*sin(pi*y)*sin(pi*z) +#================================================================================================================================ + +import cdmath +from math import sin, pi, sqrt +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +import sys + +if len(sys.argv) >1 :#non rectangular mesh + my_mesh = cdmath.Mesh(sys.argv[1]) +else : #rectangular mesh +# Maillage du domaine cubique [0,1]x[0,1]x[0,1], définition des bords +#==================================================================================== + xmin=0 + xmax=1 + ymin=0 + ymax=1 + zmin=0 + zmax=1 + + nx=21 + ny=21 + nz=21 + + my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny,zmin,zmax,nz) + +if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") + +eps=1e-6 +my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1,0,eps,"DirichletBorder")#Bord DROIT +my_mesh.setGroupAtPlan(0,1,eps,"DirichletBorder")#Bord BAS +my_mesh.setGroupAtPlan(1,1,eps,"DirichletBorder")#Bord HAUT +my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder")#Bord AVANT +my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder")#Bord ARRIERE + +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of cells ", nbCells) + +#Discrétisation du second membre et extraction du nb max de voisins d'une cellule +#================================================================================ +my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) +maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule +for i in range(nbCells): + Ci = my_mesh.getCell(i) + x = Ci.x() + y = Ci.y() + z = Ci.z() + my_RHSfield[i]=3*pi*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)#mettre la fonction definie au second membre de l edp + # compute maximum number of neighbours + maxNbNeighbours= max(1+Ci.getNumberOfFaces(),maxNbNeighbours) + +print("Right hand side discretisation done") +print("Maximum number of neighbours=", maxNbNeighbours) + +# 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.addValue(i,k,-coeff) # terme extradiagonal + else: + coeff=Fj.getMeasure()/Ci.getMeasure()/Ci.getBarryCenter().distance(Fj.getBarryCenter()) + 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,"GMRES","ILU") +SolSyst=LS.solve() + +print("Preconditioner used : ", LS.getNameOfPc()) +print("Number of iterations used : ", LS.getNumberOfIter()) +print("Final residual : ", LS.getResidu()) +print("Linear system solved") + +# 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("FiniteVolumes3DPoisson_CUBE_ResultField") + +#Postprocessing +#============== +# save 3D picture +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) +PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_CUBE_ResultField"+'_0.vtu',"ResultField",'CELLS',"Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_CUBE_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(0,sqrt(3),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +if len(sys.argv) >1 : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 3D cube with mesh '+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes3DPoisson_CUBE_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") +else : + plt.title('Plot over diagonal line for finite Volumes \n for Laplace operator on a 3D cube with a rectangular grid') + plt.plot(curv_abs, diag_data, label= str(nx) +'x'+str(ny)+ ' cells mesh') + plt.savefig("FiniteVolumes3DPoisson_CUBE_ResultField_"+str(nx) +'x'+str(ny)+ '_cells'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 3D poisson equation using finite volumes done") + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +#The following formulas use the fact that the exact solution is equal to the right hand side divided by 3*pi*pi +max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(3*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]/(3*pi*pi) - my_ResultField[i]) : + erreur_abs = abs(my_RHSfield[i]/(3*pi*pi) - my_ResultField[i]) + +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) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/CMakeLists.txt b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/CMakeLists.txt new file mode 100755 index 0000000..3a41485 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/CMakeLists.txt @@ -0,0 +1,11 @@ +SET(MESH_FILE ${MED_MESHES}/ballWithTetrahedra.med ) + +file(COPY ${MESH_FILE} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExamplePoisson_3DVF_BALL_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/FiniteVolumes3DPoisson_BALL.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py new file mode 100755 index 0000000..2c32135 --- /dev/null +++ b/CDMATH/tests/examples/PoissonEquation/Poisson3DVF_BALL/FiniteVolumes3DPoisson_BALL.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Résolution VF de l'équation de Poisson -\triangle u = f sur la boule unité avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2018 +# Description : Utilisation de la méthode des volumes finis avec champs u et f discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde du champ résultant ainsi que du champ second membre en utilisant CDMATH +# Comparaison de la solution numérique avec la solution exacte u=-(r-1)*r**2*sin(theta)**2*cos(phi) +#================================================================================================================================ + +import cdmath +from math import sin, cos, pi, sqrt, atan2 +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import PV_routines +import VTK_routines + +import sys + +#Chargement du maillage tétraédrique du domaine cubique [0,1]x[0,1]x[0,1], définition des bords +#============================================================================================== +my_mesh = cdmath.Mesh("ballWithTetrahedra.med") +if( my_mesh.getSpaceDimension()!=3 or my_mesh.getMeshDimension()!=3) : + raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 3") + +eps=1e-6 +my_mesh.setGroupAtPlan(0,0,eps,"DirichletBorder")#Bord GAUCHE +my_mesh.setGroupAtPlan(1,0,eps,"DirichletBorder")#Bord DROIT +my_mesh.setGroupAtPlan(0,1,eps,"DirichletBorder")#Bord BAS +my_mesh.setGroupAtPlan(1,1,eps,"DirichletBorder")#Bord HAUT +my_mesh.setGroupAtPlan(0,2,eps,"DirichletBorder")#Bord AVANT +my_mesh.setGroupAtPlan(1,2,eps,"DirichletBorder")#Bord ARRIERE + +nbCells = my_mesh.getNumberOfCells() + +print("Mesh loading done") +print("Number of cells ", nbCells) + +#Discrétisation du second membre et extraction du nb max de voisins d'une cellule +#================================================================================ +my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1) +my_ExactSol = cdmath.Field("EXACT_SOL", cdmath.CELLS, my_mesh, 1) + +maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix +#parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule +for i in range(nbCells): + Ci = my_mesh.getCell(i) + x = Ci.x() + y = Ci.y() + z = Ci.z() + + r=sqrt(x*x+y*y+z*z) + phi=atan2(y,x) + theta=atan2(y,z*sin(phi)) + + my_RHSfield[i]=6*r*sin(theta)**2*cos(phi)+3*(r-1)*cos(phi)#mettre la fonction definie au second membre de l'edp + my_ExactSol[i]=-(r-1)*r**2*sin(theta)**2*cos(phi) + # 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.addValue(i,k,-coeff) # terme extradiagonal + else: + coeff=Fj.getMeasure()/Ci.getMeasure()/Ci.getBarryCenter().distance(Fj.getBarryCenter()) + 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,"GMRES","ILU") +SolSyst=LS.solve() + +print( "Preconditioner used : ", LS.getNameOfPc() ) +print( "Number of iterations used : ", LS.getNumberOfIter() ) +print( "Final residual : ", LS.getResidu() ) +print("Linear system solved") + +# 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("FiniteVolumes3DPoisson_BALL_ResultField") + +#Postprocessing +#============== +# save 3D picture +resolution=100 +VTK_routines.Clip_VTK_data_to_VTK("FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',[0.5,0.5,0.5], [-0.5,-0.5,-0.5],resolution ) +PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_BALL_ResultField"+'_0.vtu',"ResultField",'CELLS',"Clip_VTK_data_to_VTK_"+"FiniteVolumes3DPoisson_BALL_ResultField") + +# extract and plot diagonal values +resolution=100 +curv_abs=np.linspace(0,sqrt(3),resolution+1) +diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution) +plt.legend() +plt.xlabel('Position on diagonal line') +plt.ylabel('Value on diagonal line') +if len(sys.argv) >1 : + plt.title('Plot over diagonal line for finite volumes \n for Laplace operator on a 3D BALL with mesh '+my_mesh.getName()) + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes3DPoisson_BALL_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") +else : + plt.title('Plot over diagonal line for finite volumes \n for Laplace operator on a 3D BALL with a rectangular grid') + plt.plot(curv_abs, diag_data, label= str(nbCells)+ ' cells mesh') + plt.savefig("FiniteVolumes3DPoisson_BALL_ResultField_"+str(nbCells)+ '_cells'+"_PlotOverDiagonalLine.png") + +print("Numerical solution of 3D poisson equation on a 3D ball using finite volumes done") + +#Calcul de l'erreur commise par rapport à la solution exacte +#=========================================================== +max_abs_sol_exacte=max(my_ExactSol.max(),-my_ExactSol.min()) +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_ExactSol[i] - my_ResultField[i]) : + erreur_abs = abs(my_ExactSol[i] - my_ResultField[i]) + +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) + +assert erreur_abs/max_abs_sol_exacte <1. diff --git a/CDMATH/tests/examples/SpectrumLaplace/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace/CMakeLists.txt new file mode 100755 index 0000000..547d871 --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/CMakeLists.txt @@ -0,0 +1,15 @@ +file(GLOB SpectrumLaplace_EXAMPLES_TO_INSTALL + SpectrumLaplace2DEF SpectrumLaplace2DVF SpectrumLaplaceBeltrami3DEF #Spectrum of Laplace operator +) + +install(DIRECTORY ${SpectrumLaplace_EXAMPLES_TO_INSTALL} DESTINATION share/examples/SpectrumLaplace) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_SUBDIRECTORY(SpectrumLaplace2DEF) + ADD_SUBDIRECTORY(SpectrumLaplace2DVF) + ADD_SUBDIRECTORY(SpectrumLaplaceBeltrami3DEF) + +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/CMakeLists.txt new file mode 100755 index 0000000..1f49db1 --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/CMakeLists.txt @@ -0,0 +1,21 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + #Cartesian cells split into right triangles + ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_rightTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + SET(MESH_NAME "DelaunayTriangles" ) + ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_DelaunayTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/2DFlatCrossTriangles/squareWithFlatCrossTriangles_0.med ) + SET(MESH_NAME "flatCrossTriangles" ) + ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_flatCrossTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/2DSkinnyTriangles/squareWithSkinnyTriangles_0.med ) + SET(MESH_NAME "skinnyTriangles" ) + ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_skinnyTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py new file mode 100755 index 0000000..3301a1d --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py @@ -0,0 +1,147 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Calcul EF du spectre de l'opérateur de Laplace 2D -\triangle avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2020 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH +#================================================================================================================================ + +import cdmath +import sys + +if len(sys.argv) >2 :#load a mesh file + my_mesh = cdmath.Mesh(sys.argv[1]) + mesh_name=sys.argv[2] +else : #rectangular mesh split into triangles + xmin=0 + xmax=1 + ymin=0 + ymax=1 + + nx=15 + ny=15 + + my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny,0) + mesh_name="RightTriangles" + +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() + +print("Mesh loading done") +print("Number of nodes=", nbNodes) +print("Number of cells=", nbCells) + +#Détermination des noeuds intérieurs +#=================================== +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) + 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, otherwise use function Ni.getNumberOfEdges() + +print("nb of interior nodes=", nbInteriorNodes) +print("nb of boundary nodes=", nbBoundaryNodes) +print("Max nb of neighbours=", maxNbNeighbours) + +# Construction de la matrice de rigidité +#======================================== +Rigidite=cdmath.SparseMatrixPetsc(nbInteriorNodes,nbInteriorNodes,maxNbNeighbours)# warning : third argument is max number of non zero coefficients per line of the matrix + +# 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) + +nodal_volumes=cdmath.Vector(nbInteriorNodes) + +#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())*0.5 + GradShapeFunc0[1]=-(N1.x()-N2.x())*0.5 + GradShapeFunc1[0]=-(N0.y()-N2.y())*0.5 + GradShapeFunc1[1]= (N0.x()-N2.x())*0.5 + GradShapeFunc2[0]= (N0.y()-N1.y())*0.5 + GradShapeFunc2[1]=-(N0.x()-N1.x())*0.5 + + #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 + nodal_volumes[j_int]+=Ci.getMeasure()/3 + #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("Stiffness matrix construction done") +quit() +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber() +print("Condition number is ",cond) + +# Spectre de la matrice de rigidité +#================================== +#Homogénéisation de la matrice de rigidité (sinon elle tend vers zero de meme que ses valeurs propres) +for i in range(nbInteriorNodes): + nodal_volumes[i]=1/nodal_volumes[i] +Rigidite.leftDiagonalScale(nodal_volumes) + +nev=10 +d=Rigidite.getEigenvectorsDataArrayDouble(nev) +my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.NODES, my_mesh, nev) +for j in range(nbInteriorNodes): + for k in range(nev): + my_eigenfield[interiorNodes[j],k]=d[j,k];#remplissage des valeurs pour les noeuds intérieurs +for j in range(nbBoundaryNodes): + for k in range(nev): + my_eigenfield[boundaryNodes[j],k]=0;#remplissage des valeurs pour les noeuds frontière (condition limite) +for k in range(nev): + my_eigenfield.setInfoOnComponent(k,d.getInfoOnComponent(k)) + +# Sauvegarde du champ résultat +#=========================== +my_eigenfield.writeVTK("spectrumFiniteElementsOn"+mesh_name+"Laplace") diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/CMakeLists.txt new file mode 100755 index 0000000..a4c51ae --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/CMakeLists.txt @@ -0,0 +1,33 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ) + +# SET(MESH_FILE ${MED_MESHES}/squareWithLocRefSquares.med ) +# SET(MESH_NAME "LocRefSquares" ) + +# ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithCheckerboardSquares.med ) + SET(MESH_NAME "Checkerboard" ) + + ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + SET(MESH_NAME "DelaunayTriangles" ) + + ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_DelaunayTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/2DFlatCrossTriangles/squareWithFlatCrossTriangles_0.med ) + SET(MESH_NAME "flatCrossTriangles" ) + + ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_flatCrossTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + + SET(MESH_FILE ${MED_MESHES}/2DSkinnyTriangles/squareWithSkinnyTriangles_0.med ) + SET(MESH_NAME "skinnyTriangles" ) + + ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_skinnyTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py new file mode 100755 index 0000000..a60054c --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py @@ -0,0 +1,92 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Calcul VF du spectre de l'opérateur de Laplace 2D -\triangle avec conditions aux limites de Dirichlet u=0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2020 +# Description : Utilisation de la méthode des volumes finis P1 avec champs discrétisés aux cellules d'un maillage quelconque +# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH +#================================================================================================================================ + +import cdmath +import sys + +if len(sys.argv) >2 :#non rectangular mesh + my_mesh = cdmath.Mesh(sys.argv[1]) + mesh_name=sys.argv[2] +else : #rectangular mesh +# Création d'un maillage cartésien du domaine carré [0,1]x[0,1], définition des bords +#==================================================================================== + xmin=0 + xmax=1 + ymin=0 + ymax=1 + + nx=15 + ny=15 + + my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny) + mesh_name="RegularGrid" + + 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 + +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") + +print("Mesh loading done") +print("Number of cells = ", nbCells) + +#Détermination du nb max de voisins d'une cellule +#================================================ +maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite volumes rigidity matrix +#parcours des cellules pour extraction du nb max de voisins d'une cellule +for i in range(nbCells): + Ci=my_mesh.getCell(i) + # compute maximum number of neighbours + maxNbNeighbours= max(1+Ci.getNumberOfFaces(),maxNbNeighbours) + +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 max number of non zero coefficients per line of the matrix +#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.addValue(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 + Rigidite.addValue(i,i,coeff) # terme diagonal + +print("Stiffness matrix construction done") + +# Conditionnement de la matrice de rigidité +#================================= +cond = Rigidite.getConditionNumber() +print("Condition number is ",cond) + +# Spectre de la matrice de rigidité +#================================== +nev=10 +d=Rigidite.getEigenvectorsDataArrayDouble(nev) +my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.CELLS, my_mesh, nev) +my_eigenfield.setFieldByDataArrayDouble(d) + +# Sauvegarde du champ résultat +#=========================== +my_eigenfield.writeVTK("spectrumFiniteVolumesOn"+mesh_name+"Laplace") diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt new file mode 100755 index 0000000..0be7f11 --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt @@ -0,0 +1,21 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/meshSphere.med ) + SET(MESH_NAME "Sphere" ) + + ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_SPHERE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) + + SET(MESH_FILE ${MED_MESHES}/meshTorus.med ) + SET(MESH_NAME "Torus" ) + + ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_TORUS ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) + + SET(MESH_FILE ${MED_MESHES}/meshCubeSkin.med ) + SET(MESH_NAME "CubeSkin" ) + + ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_CUBESKIN ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py new file mode 100755 index 0000000..a6b3f3e --- /dev/null +++ b/CDMATH/tests/examples/SpectrumLaplace/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py @@ -0,0 +1,133 @@ +# -*-coding:utf-8 -* +#=============================================================================================================================== +# Name : Calcul EF du spectre de l'opérateur de Laplace-Beltrami -\triangle sur une surface en 3D +# Author : Michael Ndjinga +# Copyright : CEA Saclay 2020 +# Description : Utilisation de la méthode des éléménts finis P1 avec champs discrétisés aux noeuds d'un maillage triangulaire +# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH +#================================================================================================================================ + +import cdmath +import sys + +#Chargement du maillage triangulaire de la surface +#================================================= +my_mesh = cdmath.Mesh(sys.argv[1]) +mesh_name=sys.argv[2] +if(not my_mesh.isTriangular()) : + raise ValueError("Wrong cell types : mesh is not made of triangles") +if(my_mesh.getMeshDimension()!=2) : + raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") +if(my_mesh.getSpaceDimension()!=3) : + raise ValueError("Wrong space dimension : expected a space of dimension 3") + +nbNodes = my_mesh.getNumberOfNodes() +nbCells = my_mesh.getNumberOfCells() + +print("Mesh building/loading done") +print("nb of nodes=", nbNodes) +print("nb of cells=", nbCells) + +maxNbNeighbours = my_mesh.getMaxNbNeighbours(cdmath.NODES)+1#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix + +# Construction de la matrice de rigidité +#======================================= +Rigidite=cdmath.SparseMatrixPetsc(nbNodes,nbNodes,maxNbNeighbours)# warning : third argument is number of non zero coefficients per line + +# 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) + +nodal_volumes=cdmath.Vector(nbNodes) + +#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) + normalCell = normalCell*(1/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()*0.5 + GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 + GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 + GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 + GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 + GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 + GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 + GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 + GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 + + #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] : + nodal_volumes[j]+=Ci.getMeasure()/3 + #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") + +# Conditionnement de la matrice de rigidité +#========================================== +cond = Rigidite.getConditionNumber(True) +print("Condition number is ",cond) + +# Spectre de la matrice de rigidité +#================================== +#Homogénéisation de la matrice de rigidité (sinon elle tend vers zero de meme que ses valeurs propres) +for i in range(nbNodes): + nodal_volumes[i]=1/nodal_volumes[i] +Rigidite.leftDiagonalScale(nodal_volumes) + +nev=9 +d=Rigidite.getEigenvectorsDataArrayDouble(nev) +my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.NODES, my_mesh, nev) +my_eigenfield.setFieldByDataArrayDouble(d) + +# Sauvegarde du champ résultat +#=========================== +my_eigenfield.writeVTK("spectrumFiniteElementsOn"+mesh_name+"LaplaceBeltrami") diff --git a/CDMATH/tests/examples/SpectrumLaplace2DEF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace2DEF/CMakeLists.txt deleted file mode 100755 index 23bcad0..0000000 --- a/CDMATH/tests/examples/SpectrumLaplace2DEF/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - #Cartesian cells split into right triangles - ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_rightTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py) - - SET(MESH_FILE ../../ressources/meshSquare.med ) - SET(MESH_NAME "DelaunayTriangles" ) - ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_DelaunayTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/2DFlatCrossTriangles/squareWithFlatCrossTriangles_0.med ) - SET(MESH_NAME "flatCrossTriangles" ) - ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_flatCrossTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/2DSkinnyTriangles/squareWithSkinnyTriangles_0.med ) - SET(MESH_NAME "skinnyTriangles" ) - ADD_TEST(ExampleSpectrumLaplace_2DEF_SQUARE_skinnyTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DEF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py b/CDMATH/tests/examples/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py deleted file mode 100755 index 3301a1d..0000000 --- a/CDMATH/tests/examples/SpectrumLaplace2DEF/SpectrumLaplace2DEF_SQUARE.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Calcul EF du spectre de l'opérateur de Laplace 2D -\triangle avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2020 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH -#================================================================================================================================ - -import cdmath -import sys - -if len(sys.argv) >2 :#load a mesh file - my_mesh = cdmath.Mesh(sys.argv[1]) - mesh_name=sys.argv[2] -else : #rectangular mesh split into triangles - xmin=0 - xmax=1 - ymin=0 - ymax=1 - - nx=15 - ny=15 - - my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny,0) - mesh_name="RightTriangles" - -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() - -print("Mesh loading done") -print("Number of nodes=", nbNodes) -print("Number of cells=", nbCells) - -#Détermination des noeuds intérieurs -#=================================== -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) - 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, otherwise use function Ni.getNumberOfEdges() - -print("nb of interior nodes=", nbInteriorNodes) -print("nb of boundary nodes=", nbBoundaryNodes) -print("Max nb of neighbours=", maxNbNeighbours) - -# Construction de la matrice de rigidité -#======================================== -Rigidite=cdmath.SparseMatrixPetsc(nbInteriorNodes,nbInteriorNodes,maxNbNeighbours)# warning : third argument is max number of non zero coefficients per line of the matrix - -# 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) - -nodal_volumes=cdmath.Vector(nbInteriorNodes) - -#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())*0.5 - GradShapeFunc0[1]=-(N1.x()-N2.x())*0.5 - GradShapeFunc1[0]=-(N0.y()-N2.y())*0.5 - GradShapeFunc1[1]= (N0.x()-N2.x())*0.5 - GradShapeFunc2[0]= (N0.y()-N1.y())*0.5 - GradShapeFunc2[1]=-(N0.x()-N1.x())*0.5 - - #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 - nodal_volumes[j_int]+=Ci.getMeasure()/3 - #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("Stiffness matrix construction done") -quit() -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber() -print("Condition number is ",cond) - -# Spectre de la matrice de rigidité -#================================== -#Homogénéisation de la matrice de rigidité (sinon elle tend vers zero de meme que ses valeurs propres) -for i in range(nbInteriorNodes): - nodal_volumes[i]=1/nodal_volumes[i] -Rigidite.leftDiagonalScale(nodal_volumes) - -nev=10 -d=Rigidite.getEigenvectorsDataArrayDouble(nev) -my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.NODES, my_mesh, nev) -for j in range(nbInteriorNodes): - for k in range(nev): - my_eigenfield[interiorNodes[j],k]=d[j,k];#remplissage des valeurs pour les noeuds intérieurs -for j in range(nbBoundaryNodes): - for k in range(nev): - my_eigenfield[boundaryNodes[j],k]=0;#remplissage des valeurs pour les noeuds frontière (condition limite) -for k in range(nev): - my_eigenfield.setInfoOnComponent(k,d.getInfoOnComponent(k)) - -# Sauvegarde du champ résultat -#=========================== -my_eigenfield.writeVTK("spectrumFiniteElementsOn"+mesh_name+"Laplace") diff --git a/CDMATH/tests/examples/SpectrumLaplace2DVF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplace2DVF/CMakeLists.txt deleted file mode 100755 index 115277c..0000000 --- a/CDMATH/tests/examples/SpectrumLaplace2DVF/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ) - -# SET(MESH_FILE ../../ressources/squareWithLocRefSquares.med ) -# SET(MESH_NAME "LocRefSquares" ) - -# ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_loc_ref ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/squareWithCheckerboardSquares.med ) - SET(MESH_NAME "Checkerboard" ) - - ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/meshSquare.med ) - SET(MESH_NAME "DelaunayTriangles" ) - - ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_DelaunayTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/2DFlatCrossTriangles/squareWithFlatCrossTriangles_0.med ) - SET(MESH_NAME "flatCrossTriangles" ) - - ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_flatCrossTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - - SET(MESH_FILE ../../ressources/2DSkinnyTriangles/squareWithSkinnyTriangles_0.med ) - SET(MESH_NAME "skinnyTriangles" ) - - ADD_TEST(ExampleSpectrumLaplace_2DVF_SQUARE_skinnyTriangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumLaplace2DVF_SQUARE.py ${MESH_FILE} ${MESH_NAME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py b/CDMATH/tests/examples/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py deleted file mode 100755 index a60054c..0000000 --- a/CDMATH/tests/examples/SpectrumLaplace2DVF/SpectrumLaplace2DVF_SQUARE.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Calcul VF du spectre de l'opérateur de Laplace 2D -\triangle avec conditions aux limites de Dirichlet u=0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2020 -# Description : Utilisation de la méthode des volumes finis P1 avec champs discrétisés aux cellules d'un maillage quelconque -# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH -#================================================================================================================================ - -import cdmath -import sys - -if len(sys.argv) >2 :#non rectangular mesh - my_mesh = cdmath.Mesh(sys.argv[1]) - mesh_name=sys.argv[2] -else : #rectangular mesh -# Création d'un maillage cartésien du domaine carré [0,1]x[0,1], définition des bords -#==================================================================================== - xmin=0 - xmax=1 - ymin=0 - ymax=1 - - nx=15 - ny=15 - - my_mesh = cdmath.Mesh(xmin,xmax,nx,ymin,ymax,ny) - mesh_name="RegularGrid" - - 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 - -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") - -print("Mesh loading done") -print("Number of cells = ", nbCells) - -#Détermination du nb max de voisins d'une cellule -#================================================ -maxNbNeighbours=0#This is to determine the number of non zero coefficients in the sparse finite volumes rigidity matrix -#parcours des cellules pour extraction du nb max de voisins d'une cellule -for i in range(nbCells): - Ci=my_mesh.getCell(i) - # compute maximum number of neighbours - maxNbNeighbours= max(1+Ci.getNumberOfFaces(),maxNbNeighbours) - -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 max number of non zero coefficients per line of the matrix -#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.addValue(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 - Rigidite.addValue(i,i,coeff) # terme diagonal - -print("Stiffness matrix construction done") - -# Conditionnement de la matrice de rigidité -#================================= -cond = Rigidite.getConditionNumber() -print("Condition number is ",cond) - -# Spectre de la matrice de rigidité -#================================== -nev=10 -d=Rigidite.getEigenvectorsDataArrayDouble(nev) -my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.CELLS, my_mesh, nev) -my_eigenfield.setFieldByDataArrayDouble(d) - -# Sauvegarde du champ résultat -#=========================== -my_eigenfield.writeVTK("spectrumFiniteVolumesOn"+mesh_name+"Laplace") diff --git a/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt b/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt deleted file mode 100755 index cf124a8..0000000 --- a/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../ressources/meshSphere.med ) - SET(MESH_NAME "Sphere" ) - - ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_SPHERE ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) - - SET(MESH_FILE ../../ressources/meshTorus.med ) - SET(MESH_NAME "Torus" ) - - ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_TORUS ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) - - SET(MESH_FILE ../../ressources/meshCubeSkin.med ) - SET(MESH_NAME "CubeSkin" ) - - ADD_TEST(ExampleSpectrumLaplaceBeltrami_3DFE_CUBESKIN ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SpectrumFiniteElements3DLaplace-Beltrami.py ${MESH_FILE} ${MESH_NAME} ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py b/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py deleted file mode 100755 index a6b3f3e..0000000 --- a/CDMATH/tests/examples/SpectrumLaplaceBeltrami3DEF/SpectrumFiniteElements3DLaplace-Beltrami.py +++ /dev/null @@ -1,133 +0,0 @@ -# -*-coding:utf-8 -* -#=============================================================================================================================== -# Name : Calcul EF du spectre de l'opérateur de Laplace-Beltrami -\triangle sur une surface en 3D -# Author : Michael Ndjinga -# Copyright : CEA Saclay 2020 -# Description : Utilisation de la méthode des éléménts finis P1 avec champs discrétisés aux noeuds d'un maillage triangulaire -# Création et sauvegarde des champs résultant en utilisant la librairie CDMATH -#================================================================================================================================ - -import cdmath -import sys - -#Chargement du maillage triangulaire de la surface -#================================================= -my_mesh = cdmath.Mesh(sys.argv[1]) -mesh_name=sys.argv[2] -if(not my_mesh.isTriangular()) : - raise ValueError("Wrong cell types : mesh is not made of triangles") -if(my_mesh.getMeshDimension()!=2) : - raise ValueError("Wrong mesh dimension : expected a surface of dimension 2") -if(my_mesh.getSpaceDimension()!=3) : - raise ValueError("Wrong space dimension : expected a space of dimension 3") - -nbNodes = my_mesh.getNumberOfNodes() -nbCells = my_mesh.getNumberOfCells() - -print("Mesh building/loading done") -print("nb of nodes=", nbNodes) -print("nb of cells=", nbCells) - -maxNbNeighbours = my_mesh.getMaxNbNeighbours(cdmath.NODES)+1#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix - -# Construction de la matrice de rigidité -#======================================= -Rigidite=cdmath.SparseMatrixPetsc(nbNodes,nbNodes,maxNbNeighbours)# warning : third argument is number of non zero coefficients per line - -# 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) - -nodal_volumes=cdmath.Vector(nbNodes) - -#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) - normalCell = normalCell*(1/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()*0.5 - GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()*0.5 - GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()*0.5 - GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()*0.5 - GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()*0.5 - GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()*0.5 - GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()*0.5 - GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()*0.5 - GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()*0.5 - - #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] : - nodal_volumes[j]+=Ci.getMeasure()/3 - #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") - -# Conditionnement de la matrice de rigidité -#========================================== -cond = Rigidite.getConditionNumber(True) -print("Condition number is ",cond) - -# Spectre de la matrice de rigidité -#================================== -#Homogénéisation de la matrice de rigidité (sinon elle tend vers zero de meme que ses valeurs propres) -for i in range(nbNodes): - nodal_volumes[i]=1/nodal_volumes[i] -Rigidite.leftDiagonalScale(nodal_volumes) - -nev=9 -d=Rigidite.getEigenvectorsDataArrayDouble(nev) -my_eigenfield = cdmath.Field("Eigenvectors field", cdmath.NODES, my_mesh, nev) -my_eigenfield.setFieldByDataArrayDouble(d) - -# Sauvegarde du champ résultat -#=========================== -my_eigenfield.writeVTK("spectrumFiniteElementsOn"+mesh_name+"LaplaceBeltrami") diff --git a/CDMATH/tests/examples/TransportEquation/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/CMakeLists.txt index de60200..e7a8915 100755 --- a/CDMATH/tests/examples/TransportEquation/CMakeLists.txt +++ b/CDMATH/tests/examples/TransportEquation/CMakeLists.txt @@ -1,8 +1,18 @@ +file(GLOB TransportEquation_EXAMPLES_TO_INSTALL + TransportEquation1DUpwindExplicit TransportEquation1DUpwindImplicit TransportEquation1DCenteredImplicit TransportEquation1DCenteredExplicit # 1D Transport equation + TransportEquation +) -if (CDMATH_WITH_PYTHON ) +install(DIRECTORY ${TransportEquation_EXAMPLES_TO_INSTALL} DESTINATION share/examples/TransportEquation) - ADD_TEST(ExampleTransportEquation_2DUpwind_Explicit ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/TransportEquationUpwind.py) +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) -endif (CDMATH_WITH_PYTHON ) + ADD_SUBDIRECTORY(TransportEquation1DUpwindExplicit) + ADD_SUBDIRECTORY(TransportEquation1DUpwindImplicit) + ADD_SUBDIRECTORY(TransportEquation1DCenteredImplicit) + ADD_SUBDIRECTORY(TransportEquation1DCenteredExplicit) + ADD_SUBDIRECTORY(TransportEquation) + +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/TransportEquation/CMakeLists.txt new file mode 100755 index 0000000..de60200 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON ) + + ADD_TEST(ExampleTransportEquation_2DUpwind_Explicit ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/TransportEquationUpwind.py) + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation/TransportEquationUpwind.py b/CDMATH/tests/examples/TransportEquation/TransportEquation/TransportEquationUpwind.py new file mode 100755 index 0000000..7047c70 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation/TransportEquationUpwind.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +from math import sin, cos, pi, sqrt +import time, json +import cdmath +import PV_routines +import VTK_routines + +precision=1e-5 + +def initial_conditions_transport_equation(my_mesh): + print( "Initial_data","Shock") + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + initial_field = cdmath.Field("unknown", cdmath.CELLS, my_mesh, 1) + + rayon = 0.15 + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val=sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + initial_field[i] = 1 + pass + else: + initial_field[i] = 0 + pass + pass + + return initial_field + +def upwinding_coeff(normal, coeff, velocity): + dim=normal.size() + + if(velocity*normal<0.): + return velocity*normal*coeff + else: + return 0. + + +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 TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,test_bc,velocity,isImplicit): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + dt = 0. + time = 0. + it=0; + isStationary=False + + nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) + + #iteration vectors + Un =cdmath.Vector(nbCells) + dUn=cdmath.Vector(nbCells) + + # Initial conditions # + print("Construction of the initial condition …") + stat_field = initial_conditions_transport_equation(my_mesh) + for k in range(nbCells): + Un[k] = stat_field[k] + unknown_field = initial_conditions_transport_equation(my_mesh) + S = cdmath.Vector(nbCells)#source term is zero + + total_mass_initial=unknown_field.integral()#For conservation test later + + #sauvegarde de la donnée initiale + unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName); + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / velocity.norm() + + divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc,velocity) + if(isImplicit): + #Adding the identity matrix on the diagonal + divMat.diagonalShift(1)#only after filling all coefficients + #for j in range(nbCells*(dim+1)): + # divMat.addValue(j,j,1) + + iterGMRESMax=50 + LS=cdmath.LinearSolver(divMat,Un+S*dt,iterGMRESMax, precision, "GMRES","ILU") + LS.setComputeConditionNumber() + + print("Starting computation of the linear transport equation with an Upwind scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : ", maxVector[0] ) + if(isImplicit): + print( "Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations" ) + + for k in range(nbCells): + unknown_field[k] =Un[k] + + unknown_field.setTime(time,it); + unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName,False); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : ", maxVector[0] ) + + 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(test_bc=="Periodic"): + print( "Mass loss: ", (total_mass_initial-unknown_field.integral()).norm(), " precision required= ", precision ) + assert (total_mass_initial-unknown_field.integral()).norm()3 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + isSmooth=bool(int(sys.argv[3])) + Transport1DCenteredExplicit(nx,cfl,isSmooth) + else : + nx = 50 # number of cells + cfl = 0.99 # c*dt/dx <= CFL + isSmooth=True + Transport1DCenteredExplicit(nx,cfl,isSmooth) + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredExplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredExplicit/CMakeLists.txt new file mode 100755 index 0000000..cc7cf3a --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredExplicit/CMakeLists.txt @@ -0,0 +1,29 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 50 )#Number of cells + + SET(SMOOTHNESS 0 ) + + SET(CFL 0.99 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Stiff_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) + + SET(CFL 0.5 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Stiff_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) + + + SET(SMOOTHNESS 1 ) + + SET(CFL 0.99 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Smooth_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) + + SET(CFL 0.5 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Smooth_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py new file mode 100755 index 0000000..af12e79 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques +# Author : Michaël Ndjinga, Katia Ait Ameur +# Copyright : CEA Saclay 2018 +# Description : Utilisation du schéma centré implicite sur un maillage 1D régulier +# Schéma à 3 points implicite +# Création et sauvegarde du champ résultant et des figures +# Génération d'une video sauvegardée dans un fichier .mp4 +#================================================================================================================================ + + +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from math import sin, pi, ceil +import cdmath + +def centeredSchemeMatrix(nx,cfl): + centeredMat=cdmath.SparseMatrixPetsc(nx,nx,3) + for i in range(nx): + centeredMat.setValue(i,(i+1)%nx,cfl/2) + centeredMat.setValue(i,i,1.) + centeredMat.setValue(i,(i-1)%nx,-cfl/2.) + + return centeredMat + +def Transport1DCenteredImplicit(nx,cfl): + print( "Simulation of 1D transport equation with implicit centered scheme" ) + + ##################### Simulation parameters + a = 0.0 # space domain : a <= x <= b + b = 1.0 + 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 + + u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0 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) + writer.grab_frame() + if (it % output_freq == 0): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") + plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") + #plt.show() + + 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 implicit centered scheme done.") + + #return min, max, total variation and l1 error + return min(u), max(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)]) + + +if __name__ == """__main__""": + if len(sys.argv) >2 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + Transport1DCenteredImplicit(nx,cfl) + else : + nx = 50 # number of cells + cfl = 0.99 # c*dt/dx <= CFL + Transport1DCenteredImplicit(nx,cfl) + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/CMakeLists.txt new file mode 100755 index 0000000..b2ffc39 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DCenteredImplicit/CMakeLists.txt @@ -0,0 +1,17 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 50 )#Number of cells + + SET(CFL 1 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Centered_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredImplicit.py ${NX} ${CFL}) + + SET(CFL 2 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Centered_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredImplicit.py ${NX} ${CFL}) + + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py new file mode 100755 index 0000000..d49da95 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques +# Author : Michaël Ndjinga, Katia Ait Ameur +# Copyright : CEA Saclay 2018 +# Description : Utilisation du schéma upwind explicite sur un maillage 1D régulier +# Création et sauvegarde du champ résultant et des figures +# Génération d'une video sauvegardée dans un fichier .mp4 +#================================================================================================================================ + + +from math import sin, pi, ceil +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from copy import deepcopy + +def Transport1DUpwindExplicit(nx,cfl): + print( "Simulation of 1D transport equation with explicit upwind scheme" ) + + ##################### Simulation parameters + a = 0.0 # space domain : a <= x <= b + b = 1.0 + 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) + + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + + ########################## Initial data + + u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial + assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial + 1e-15#Tiny margin required + + # Postprocessing + line1.set_ydata(u) + writer.grab_frame() + if (it % output_freq == 0): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + np.savetxt( "TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") + plt.savefig("TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") + #plt.show() + + 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 explicit upwind scheme done.") + + #return min, max, total variation and l1 error + return min(u), max(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)]) + + +if __name__ == """__main__""": + if len(sys.argv) >2 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + Transport1DUpwindExplicit(nx,cfl) + else : + nx = 50 # number of cells + cfl = 0.99 # c*dt/dx <= CFL + Transport1DUpwindExplicit(nx,cfl) + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/CMakeLists.txt new file mode 100755 index 0000000..f1fe640 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindExplicit/CMakeLists.txt @@ -0,0 +1,20 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 100 )#Number of cells + + SET(CFL 0.9999 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) + + SET(CFL 0.5 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) + + SET(CFL 2 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py new file mode 100755 index 0000000..6f990fb --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques +# Author : Michaël Ndjinga, Katia Ait Ameur +# Copyright : CEA Saclay 2018 +# Description : Utilisation du schéma upwind implicite sur un maillage 1D régulier +# Création et sauvegarde du champ résultant et des figures +# Génération d'une video sauvegardée dans un fichier .mp4 +#================================================================================================================================ + + +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys +from math import sin, pi, ceil +import cdmath + +precision=1.e-5 + +def upwindSchemeMatrix(nx,cfl): + upwindMat=cdmath.SparseMatrixPetsc(nx,nx,2) + for i in range(nx): + upwindMat.setValue(i,i,1+cfl) + upwindMat.setValue(i,(i-1)%nx,-cfl) + + return upwindMat + +def Transport1DUpwindImplicit(nx,cfl): + print( "Simulation of 1D transport equation with implicit upwind scheme" ) + + ##################### Simulation parameters + a = 0.0 # space domain : a <= x <= b + b = 1.0 + 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 + + u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial + assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial + + # Postprocessing + line1.set_ydata(u) + writer.grab_frame() + if (it % output_freq == 0): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + np.savetxt( "TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") + plt.savefig("TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") + #plt.show() + + 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 implicit upwind scheme done.") + + #return min, max, total variation and l1 error + return min(u), max(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)]) + + +if __name__ == """__main__""": + if len(sys.argv) >2 : + nx = int(sys.argv[1]) + cfl = float(sys.argv[2]) + Transport1DUpwindImplicit(nx,cfl) + else : + nx = 50 # number of cells + cfl = 0.99 # c*dt/dx <= CFL + Transport1DUpwindImplicit(nx,cfl) + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/CMakeLists.txt new file mode 100755 index 0000000..1045385 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/TransportEquation1DUpwindImplicit/CMakeLists.txt @@ -0,0 +1,17 @@ + +if (CDMATH_WITH_PYTHON ) + + SET(NX 50 )#Number of cells + + SET(CFL 1 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindImplicit.py ${NX} ${CFL}) + + SET(CFL 2 )#Courant Friedrichs Lewy number + + ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindImplicit.py ${NX} ${CFL}) + + +endif (CDMATH_WITH_PYTHON ) + + diff --git a/CDMATH/tests/examples/TransportEquation/TransportEquationUpwind.py b/CDMATH/tests/examples/TransportEquation/TransportEquationUpwind.py deleted file mode 100755 index 7047c70..0000000 --- a/CDMATH/tests/examples/TransportEquation/TransportEquationUpwind.py +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -from math import sin, cos, pi, sqrt -import time, json -import cdmath -import PV_routines -import VTK_routines - -precision=1e-5 - -def initial_conditions_transport_equation(my_mesh): - print( "Initial_data","Shock") - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - initial_field = cdmath.Field("unknown", cdmath.CELLS, my_mesh, 1) - - rayon = 0.15 - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val=sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - initial_field[i] = 1 - pass - else: - initial_field[i] = 0 - pass - pass - - return initial_field - -def upwinding_coeff(normal, coeff, velocity): - dim=normal.size() - - if(velocity*normal<0.): - return velocity*normal*coeff - else: - return 0. - - -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 TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,test_bc,velocity,isImplicit): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - dt = 0. - time = 0. - it=0; - isStationary=False - - nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) - - #iteration vectors - Un =cdmath.Vector(nbCells) - dUn=cdmath.Vector(nbCells) - - # Initial conditions # - print("Construction of the initial condition …") - stat_field = initial_conditions_transport_equation(my_mesh) - for k in range(nbCells): - Un[k] = stat_field[k] - unknown_field = initial_conditions_transport_equation(my_mesh) - S = cdmath.Vector(nbCells)#source term is zero - - total_mass_initial=unknown_field.integral()#For conservation test later - - #sauvegarde de la donnée initiale - unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName); - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / velocity.norm() - - divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc,velocity) - if(isImplicit): - #Adding the identity matrix on the diagonal - divMat.diagonalShift(1)#only after filling all coefficients - #for j in range(nbCells*(dim+1)): - # divMat.addValue(j,j,1) - - iterGMRESMax=50 - LS=cdmath.LinearSolver(divMat,Un+S*dt,iterGMRESMax, precision, "GMRES","ILU") - LS.setComputeConditionNumber() - - print("Starting computation of the linear transport equation with an Upwind scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : ", maxVector[0] ) - if(isImplicit): - print( "Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations" ) - - for k in range(nbCells): - unknown_field[k] =Un[k] - - unknown_field.setTime(time,it); - unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName,False); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : ", maxVector[0] ) - - 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(test_bc=="Periodic"): - print( "Mass loss: ", (total_mass_initial-unknown_field.integral()).norm(), " precision required= ", precision ) - assert (total_mass_initial-unknown_field.integral()).norm() +#include +//#include + +//#include "Matrix.hxx" +#include "Vector.hxx" +#include "LinearSolver.hxx" +#include "Mesh.hxx" +#include "Field.hxx" +#include "Cell.hxx" +//#include "Face.hxx" +//#include "Node.hxx" +#include "CdmathException.hxx" + +using namespace std; + + +void champ_heaviside(Field& Temp, double milieu, double TempLeft, double TempRight) +{ + Mesh M=Temp.getMesh(); + int nbCells=M.getNumberOfCells(); + double x; + for (int j=0 ; jepsilon) + { + d= ScndMbre;//contiendra le second membre du système + /*cout<< " Debut itération d= "< e(n-1); + for(int i=0;i a(n-1,-1),b(n,2),c(n-1,-0.5); + Mesh M(0,1,n); + Field d("Test",CELLS,M,1); + int nbCells=M.getNumberOfCells(); + for(int i=0;i +#include + +#include "Cell.hxx" +#include "Mesh.hxx" +#include "Field.hxx" + +using namespace std; + + +int main( void ) +{ + double a=-5.0; + double b=5.0; + int nx=1000; + int ntmax=3; + double dx = (b-a)/nx; + double pi=3.1415927; + // Transport velocity + double cfl=0.5; + double u=3.; + double dt=cfl*dx/u; + + Mesh myMesh(a,b,nx); + + Field conc("Concentration",CELLS,myMesh,1); + + // Initial conditions + double sigma=sqrt(0.2); + for (int i=0 ; i +#include +#include + +#include "Mesh.hxx" +#include "Cell.hxx" +#include "Face.hxx" +#include "Field.hxx" + +using namespace std; + + +void conditions_initiales(Field& yField) +{ + double rayon=0.15; + double xcentre=0.25; + double ycentre=0.25; + Mesh myMesh=yField.getMesh(); + int nbCells=myMesh.getNumberOfCells(); + for (int j=0 ; j0 : rien a faire sinon inverser la gauche et la droite + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(cellAutre); + }else + { + /* conditions aux limites neumann homogene */ + if (Fk.getGroupName().compare("GAUCHE")==0 || Fk.getGroupName().compare("DROITE")==0) + { + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=0.0; + } + /* conditions aux limites periodiques */ + if (Fk.getGroupName().compare("BAS")==0 || Fk.getGroupName().compare("HAUT")==0) + { + int indexFP=indexFacesPerio[indexFace]; + /* une autre manière de recuperer l'index de la face periodique */ + //int indexFP=M.getIndexFacePeriodic(indexFace); + Face Fp=myMesh.getFace(indexFP); + int indexCp=Fp.getCellsId()[0]; + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(indexCp); + } + } + SumF=SumF+UN*LengthFk*conc; + } + dt=cfl*minlengthFk/normU; + SumFlux(j)=dt*SumF/Cj.getMeasure(); + } +} + +void EquationTransport2D(double tmax, double VitesseX, double VitesseY, double cfl, int freqSortie, const Mesh& myMesh, const string file) +{ + /* Initial conditions */ + cout << "Construction of the initial condition …" << endl; + Field yField("Y field",CELLS,myMesh,1) ; + conditions_initiales(yField); + + /* + * MED output of the initial condition at t=0 and iter = 0 + */ + int iter=0; + double time=0.; + cout << "Saving the solution at T=" << time << "…" << endl; + yField.setTime(time,iter); + yField.writeMED(file); + yField.writeVTK(file); + yField.writeCSV(file); + /* --------------------------------------------- */ + + /* Time loop */ + cout << "Resolution of the transport equation with an UPWIND scheme …" << endl; + int ntmax=3; + double dt; + IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); + while (iter0: nothing to do, else invert left and right + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = y_field[cellAutre] + pass + pass + else: + # homogeneous Neumann boundary conditions # + if (Fk.getGroupName() == "GAUCHE" or Fk.getGroupName() == "DROITE"): + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = 0.0 + pass + pass + # periodical boundary conditions # + if (Fk.getGroupName() == "BAS" or Fk.getGroupName() == "HAUT"): + indexFP = indexFacesPerio[indexFace] + # another way to get the index of the periodical face # + # int indexFP=my_mesh.getIndexFacePeriodic(indexFace); + Fp = my_mesh.getFace(indexFP) + indexCp = Fp.getCellsId()[0] + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = y_field[indexCp] + pass + pass + pass + SumF = SumF + UN * LengthFk * conc + pass + dt = cfl * minlengthFk / normU + SumFlux[j] = dt * SumF / Cj.getMeasure() + pass + return dt, SumFlux + + +def EquationTransport2D(tmax, VitesseX, VitesseY, cfl, freqSortie, my_mesh, output_filename): + + # Initial conditions # + print("Construction of the initial condition …") + y_field = initial_conditions(my_mesh) + # + # MED output of the initial condition at t=0 and iter = 0 + # + + it = 0 + time = 0. + print("Saving the solution at T=" + str(time) + "…") + y_field.setTime(time, it) + y_field.writeMED(output_filename) + y_field.writeVTK(output_filename) + y_field.writeCSV(output_filename) + + # Time loop # + print("Resolution of the transport equation with an UPWIND scheme…") + ntmax = 3 + indexFacesPerio = my_mesh.getIndexFacePeriodic() + dt = 0. + while (it < ntmax and time <= tmax): + dt, SumFlux = sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio) + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + + # Advancing one time step # + y_field -= SumFlux + time += dt + it += 1 + # Output every freq times + if (it % freqSortie == 0): + y_field.setTime(time, it) + y_field.writeMED(output_filename, False) + y_field.writeVTK(output_filename, False) + y_field.writeCSV(output_filename) + pass + pass + return + + +def main(): + print("Resolution of the 2D transport equation:") + print("- DOMAIN: SQUARE") + print("- MESH: TRIANGULAR, GENERATED WITH SALOME") + print("- PERIODICAL BC UP AND DOWN") + print("- HOMOGENEOUS NEUMANN BC LEFT AND RIGHT") + + # Problem data + cfl = 0.4 + VitesseX = 1.0 + VitesseY = 1.0 + tmax = 1. + freqSortie = 10 + + print("Loading triangular mesh …") + my_mesh = cdmath.Mesh("../../tests/ressources/meshSquare.med") + output_filename = "Exercice2PyTest" + EquationTransport2D(tmax, VitesseX, VitesseY, cfl, freqSortie, my_mesh, output_filename) + print("CDMATH calculation done.") + return + + +if __name__ == """__main__""": + main() diff --git a/CDMATH/tests/examples/TransportEquation/transport2d_ns/main2.cxx b/CDMATH/tests/examples/TransportEquation/transport2d_ns/main2.cxx new file mode 100755 index 0000000..ff6845e --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/transport2d_ns/main2.cxx @@ -0,0 +1,243 @@ +//============================================================================ +// Author : Anouar MEKKAS +// Version : +// Description : Equation de transport lineaire 2D non structure +//============================================================================ + +#include +#include +#include + +#include "Mesh.hxx" +#include "Cell.hxx" +#include "Face.hxx" +#include "Field.hxx" + +using namespace std; + +struct parameters { + double cfl; + double VitesseX; + double VitesseY; + int freqSortie; + std::string outFile; +}; + +void conditions_initiales(Field& yField) +{ + double rayon=0.15; + double xcentre=0.25; + double ycentre=0.25; + Mesh myMesh=yField.getMesh(); + int nbCells=myMesh.getNumberOfCells(); + for (int j=0 ; j0 : rien a faire sinon inverser la gauche et la droite + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(cellAutre); + }else + { + /* conditions aux limites neumann homogene */ + if (Fk.getGroupName().compare("GAUCHE")==0 || Fk.getGroupName().compare("DROITE")==0) + { + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=0.0; + } + /* conditions aux limites periodiques */ + if (Fk.getGroupName().compare("BAS")==0 || Fk.getGroupName().compare("HAUT")==0) + { + int indexFP=indexFacesPerio[indexFace]; + /* une autre manière de recuperer l'index de la face periodique */ + //int indexFP=M.getIndexFacePeriodic(indexFace); + Face Fp=myMesh.getFace(indexFP); + int indexCp=Fp.getCellsId()[0]; + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(indexCp); + } + } + SumF=SumF+UN*LengthFk*conc; + } + dt=p.cfl*minlengthFk/normU; + SumFlux(j)=dt*SumF/Cj.getMeasure(); + } +} + +void EquationTransport2D(int &iter, double tmin, double & tmax, + const parameters & p, Field & yField) +{ + + /* + * MED output of the initial condition at t=0 and iter = 0 + */ + double time=tmin; + const Mesh& myMesh = yField.getMesh(); + + yField.setTime(time,iter); + yField.writeMED(p.outFile,true); + yField.writeVTK(p.outFile); + yField.writeCSV(p.outFile); + /* --------------------------------------------- */ + + /* Time loop */ + cout << "Resolution of the transport equation with an UPWIND scheme…" << endl; + int ntmax=3 + iter; + double dt; + IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); + while (iter +#include +#include + +#include "Mesh.hxx" +#include "Cell.hxx" +#include "Face.hxx" +#include "Field.hxx" + +using namespace std; + + +void initial_conditions(Field& yField) +{ + double rayon=0.15; + double xcentre=0.25; + double ycentre=0.25; + Mesh myMesh=yField.getMesh(); + int nbCells=myMesh.getNumberOfCells(); + for (int j=0 ; j0, then nothing to do, else invert left and right + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(cellAutre); + }else + { + /* Homogeneous Neumann boundary conditions */ + if (Fk.getGroupName().compare("LeftEdge")==0 || Fk.getGroupName().compare("RightEdge")==0) + { + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=0.0; + } + /* Periodic boundary conditions */ + if (Fk.getGroupName().compare("BottomEdge")==0 || Fk.getGroupName().compare("TopEdge")==0) + { + int indexFP=indexFacesPerio[indexFace]; + /* une autre manière de recuperer l'index de la face periodique */ + //int indexFP=myMesh.getIndexFacePeriodic(indexFace); + Face Fp=myMesh.getFace(indexFP); + int indexCp=Fp.getCellsId()[0]; + if (UN>1.E-15) + conc=yField(cellCourante); + else + conc=yField(indexCp); + } + } + SumF=SumF+UN*LengthFk*conc; + } + dt=cfl*minlengthFk/normU; + SumFlux(j)=dt*SumF/Cj.getMeasure(); + } +} + +void EquationTransport2D(double tmax, double VitesseX, double VitesseY, double cfl, int freqSortie, const Mesh& myMesh, const string file) +{ + /* Initial conditions */ + cout << "Construction of the initial condition …" << endl; + Field yField("Y field",CELLS,myMesh,1) ; + initial_conditions(yField); + + /* + * MED output of the initial condition at t=0 and iter = 0 + */ + int iter=0; + double time=0.; + cout << "Saving the solution at T=" << time << "…" << endl; + yField.setTime(time,iter); + yField.writeMED(file); + yField.writeVTK(file); + yField.writeCSV(file); + /* --------------------------------------------- */ + + /* Time loop */ + cout << "Resolution of the transport equation with an UPWIND scheme …" << endl; + int ntmax=3; + double dt; + IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); + while (iter0 : rien a faire sinon inverser la gauche et la droite + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = y_field[cellAutre] + pass + pass + else: + # conditions aux limites neumann homogene # + if (Fk.getGroupName() == "LeftEdge" or Fk.getGroupName() == "RightEdge"): + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = 0.0 + pass + pass + # conditions aux limites periodiques # + if (Fk.getGroupName() == "BottomEdge" or Fk.getGroupName() == "TopEdge"): + indexFP = indexFacesPerio[indexFace] + # une autre manière de recuperer l'index de la face periodique # + # int indexFP=my_mesh.getIndexFacePeriodic(indexFace); + Fp = my_mesh.getFace(indexFP) + indexCp = Fp.getCellsId()[0] + if (UN > 1.E-15): + conc = y_field[cellCourante] + pass + else: + conc = y_field[indexCp] + pass + pass + pass + SumF = SumF + UN * LengthFk * conc + pass + dt = cfl * minlengthFk / normU + SumFlux[j] = dt * SumF / Cj.getMeasure() + pass + return dt, SumFlux + + +def EquationTransport2D(tmax, VitesseX, VitesseY, cfl, output_freq, my_mesh, file): + + # Initial conditions # + print("Construction of the initial condition …") + y_field = initial_conditions(my_mesh) + # + # MED output of the initial conditions at t=0 and iteration = 0 + # + + iteration = 0 + time = 0. + print("Saving the solution at T=" + str(time) + "…") + y_field.setTime(time, iteration) + y_field.writeMED(file) + y_field.writeVTK(file) + y_field.writeCSV(file) + + # Time loop # + print("Resolution of the transport equation with an UPWIND scheme …") + ntmax = 3 + indexFacesPerio = my_mesh.getIndexFacePeriodic() + dt = 0. + while (iteration < ntmax and time <= tmax): + dt, SumFlux = sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio) + print("-- Iter: " + str(iteration) + ", Time: " + str(time) + ", dt: " + str(dt)) + + # Advancing time step # + y_field -= SumFlux + time += dt + iteration += 1 + # Output every output_freq iterations + if (iteration % output_freq == 0): + y_field.setTime(time, iteration) + y_field.writeMED(file, False) + y_field.writeVTK(file, False) + y_field.writeCSV(file) + pass + pass + return + + +def main(): + print("RESOLUTION OF THE 2D TRANSPORT EQUATION:") + print("- DOMAIN: SQUARE [0,1]x[0,1]") + print("- MESH: CARTESIAN, INTERNAL GENERATION WITH CDMATH") + print("- PERIODIC BC ON TOP AND BOTTOM") + print("- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT") + + # Problem data + cfl = 0.4 + VitesseX = 1.0 + VitesseY = 1.0 + tmax = 1. + output_freq = 10 + + print("Construction of a cartesian mesh …") + xinf = 0.0 + xsup = 1.0 + yinf = 0.0 + ysup = 1.0 + nx = 100 + ny = 100 + my_mesh = cdmath.Mesh(xinf, xsup, nx, yinf, ysup, ny) + eps = 1.E-10 + my_mesh.setGroupAtPlan(xsup, 0, eps, "RightEdge") + my_mesh.setGroupAtPlan(xinf, 0, eps, "LeftEdge") + my_mesh.setGroupAtPlan(yinf, 1, eps, "BottomEdge") + my_mesh.setGroupAtPlan(ysup, 1, eps, "TopEdge") + fileOutPutCart = "Exercice1PyTest" + EquationTransport2D(tmax, VitesseX, VitesseY, cfl, output_freq, my_mesh, fileOutPutCart) + print("CDMATH calculation done.") + return + + +if __name__ == """__main__""": + main() diff --git a/CDMATH/tests/examples/TransportEquation/transport2d_s/makefile b/CDMATH/tests/examples/TransportEquation/transport2d_s/makefile new file mode 100755 index 0000000..3ef2bc7 --- /dev/null +++ b/CDMATH/tests/examples/TransportEquation/transport2d_s/makefile @@ -0,0 +1,26 @@ +# Transport2D_S makefile + +CC = g++ +# Adapt the following line to your own system: +CDMATHDIR = ../../../../.. +IFLAG = -I$(CDMATHDIR)/include -I. +LFLAG = -L$(CDMATHDIR)/lib +LIBS =-linterpkernel -lmedC -lmedloader -lmedcoupling -lbase -lmesh -llinearsolver +OBJ = main.o + +all: $(OBJ) + $(CC) -o main $^ $(IFLAG) $(LFLAG) $(LIBS) + +%.o: %.cxx + $(CC) -c -o $@ $< $(CFLAGS) $(IFLAG) $(LFLAG) $(LIBS) + +.PHONY: clean + +clean: + rm -f *.o *~ core $(INCDIR)/*~ + +sweep: + rm -f *.vtu + rm -f *.pvd + rm -f *.csv + rm -f Exercie1*.med diff --git a/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/1DTransportEquationCenteredExplicit.py b/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/1DTransportEquationCenteredExplicit.py deleted file mode 100755 index 9b4336e..0000000 --- a/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/1DTransportEquationCenteredExplicit.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques -# Author : Michaël Ndjinga, Katia Ait Ameur -# Copyright : CEA Saclay 2018 -# Description : Utilisation du schéma centré explicite sur un maillage 1D régulier -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -from math import sin, pi, ceil -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -from copy import deepcopy - -def Transport1DCenteredExplicit(nx,cfl, isSmooth): - print( "Simulation of 1D transport equation with explicit centered scheme" ) - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - dx = (b - a) / nx #space step - - c = 0.25 # advection velocity - dt = cfl * dx / c - - 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 = [ sin(2*pi*xi) for xi in x];# to be used with a=0, b=1 - tmax = 3*(b-a)/c # runs the simulation for 0 <= t <= tMax - else: - print( "Stiff initial data" ) - u_initial = [ int(1./33 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - isSmooth=bool(int(sys.argv[3])) - Transport1DCenteredExplicit(nx,cfl,isSmooth) - else : - nx = 50 # number of cells - cfl = 0.99 # c*dt/dx <= CFL - isSmooth=True - Transport1DCenteredExplicit(nx,cfl,isSmooth) - diff --git a/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/CMakeLists.txt deleted file mode 100755 index cc7cf3a..0000000 --- a/CDMATH/tests/examples/TransportEquation1DCenteredExplicit/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 50 )#Number of cells - - SET(SMOOTHNESS 0 ) - - SET(CFL 0.99 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Stiff_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) - - SET(CFL 0.5 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Stiff_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) - - - SET(SMOOTHNESS 1 ) - - SET(CFL 0.99 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Smooth_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) - - SET(CFL 0.5 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_CenteredExplicit_Smooth_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredExplicit.py ${NX} ${CFL} ${SMOOTHNESS} ) - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py b/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py deleted file mode 100755 index af12e79..0000000 --- a/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/1DTransportEquationCenteredImplicit.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques -# Author : Michaël Ndjinga, Katia Ait Ameur -# Copyright : CEA Saclay 2018 -# Description : Utilisation du schéma centré implicite sur un maillage 1D régulier -# Schéma à 3 points implicite -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -from math import sin, pi, ceil -import cdmath - -def centeredSchemeMatrix(nx,cfl): - centeredMat=cdmath.SparseMatrixPetsc(nx,nx,3) - for i in range(nx): - centeredMat.setValue(i,(i+1)%nx,cfl/2) - centeredMat.setValue(i,i,1.) - centeredMat.setValue(i,(i-1)%nx,-cfl/2.) - - return centeredMat - -def Transport1DCenteredImplicit(nx,cfl): - print( "Simulation of 1D transport equation with implicit centered scheme" ) - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - 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 - - u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0 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) - writer.grab_frame() - if (it % output_freq == 0): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") - plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") - #plt.show() - - 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 implicit centered scheme done.") - - #return min, max, total variation and l1 error - return min(u), max(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)]) - - -if __name__ == """__main__""": - if len(sys.argv) >2 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - Transport1DCenteredImplicit(nx,cfl) - else : - nx = 50 # number of cells - cfl = 0.99 # c*dt/dx <= CFL - Transport1DCenteredImplicit(nx,cfl) - diff --git a/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/CMakeLists.txt deleted file mode 100755 index b2ffc39..0000000 --- a/CDMATH/tests/examples/TransportEquation1DCenteredImplicit/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 50 )#Number of cells - - SET(CFL 1 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Centered_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredImplicit.py ${NX} ${CFL}) - - SET(CFL 2 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Centered_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationCenteredImplicit.py ${NX} ${CFL}) - - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py b/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py deleted file mode 100755 index d49da95..0000000 --- a/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/1DTransportEquationUpwindExplicit.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques -# Author : Michaël Ndjinga, Katia Ait Ameur -# Copyright : CEA Saclay 2018 -# Description : Utilisation du schéma upwind explicite sur un maillage 1D régulier -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -from math import sin, pi, ceil -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -from copy import deepcopy - -def Transport1DUpwindExplicit(nx,cfl): - print( "Simulation of 1D transport equation with explicit upwind scheme" ) - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - 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) - - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - - ########################## Initial data - - u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial - assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial + 1e-15#Tiny margin required - - # Postprocessing - line1.set_ydata(u) - writer.grab_frame() - if (it % output_freq == 0): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - np.savetxt( "TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") - plt.savefig("TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") - #plt.show() - - 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 explicit upwind scheme done.") - - #return min, max, total variation and l1 error - return min(u), max(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)]) - - -if __name__ == """__main__""": - if len(sys.argv) >2 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - Transport1DUpwindExplicit(nx,cfl) - else : - nx = 50 # number of cells - cfl = 0.99 # c*dt/dx <= CFL - Transport1DUpwindExplicit(nx,cfl) - diff --git a/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/CMakeLists.txt deleted file mode 100755 index f1fe640..0000000 --- a/CDMATH/tests/examples/TransportEquation1DUpwindExplicit/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 100 )#Number of cells - - SET(CFL 0.9999 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) - - SET(CFL 0.5 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL0.5 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) - - SET(CFL 2 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Explicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindExplicit.py ${NX} ${CFL}) - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py b/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py deleted file mode 100755 index 6f990fb..0000000 --- a/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/1DTransportEquationUpwindImplicit.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF de l'équation du transport 1D \partial_t u + c \partial_x u = 0 avec conditions aux limites périodiques -# Author : Michaël Ndjinga, Katia Ait Ameur -# Copyright : CEA Saclay 2018 -# Description : Utilisation du schéma upwind implicite sur un maillage 1D régulier -# Création et sauvegarde du champ résultant et des figures -# Génération d'une video sauvegardée dans un fichier .mp4 -#================================================================================================================================ - - -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys -from math import sin, pi, ceil -import cdmath - -precision=1.e-5 - -def upwindSchemeMatrix(nx,cfl): - upwindMat=cdmath.SparseMatrixPetsc(nx,nx,2) - for i in range(nx): - upwindMat.setValue(i,i,1+cfl) - upwindMat.setValue(i,(i-1)%nx,-cfl) - - return upwindMat - -def Transport1DUpwindImplicit(nx,cfl): - print( "Simulation of 1D transport equation with implicit upwind scheme" ) - - ##################### Simulation parameters - a = 0.0 # space domain : a <= x <= b - b = 1.0 - 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 - - u_initial = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0= min_initial - assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial - - # Postprocessing - line1.set_ydata(u) - writer.grab_frame() - if (it % output_freq == 0): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - np.savetxt( "TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n") - plt.savefig("TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png") - #plt.show() - - 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 implicit upwind scheme done.") - - #return min, max, total variation and l1 error - return min(u), max(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)]) - - -if __name__ == """__main__""": - if len(sys.argv) >2 : - nx = int(sys.argv[1]) - cfl = float(sys.argv[2]) - Transport1DUpwindImplicit(nx,cfl) - else : - nx = 50 # number of cells - cfl = 0.99 # c*dt/dx <= CFL - Transport1DUpwindImplicit(nx,cfl) - diff --git a/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/CMakeLists.txt b/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/CMakeLists.txt deleted file mode 100755 index 1045385..0000000 --- a/CDMATH/tests/examples/TransportEquation1DUpwindImplicit/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ - -if (CDMATH_WITH_PYTHON ) - - SET(NX 50 )#Number of cells - - SET(CFL 1 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Implicit_CFL1 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindImplicit.py ${NX} ${CFL}) - - SET(CFL 2 )#Courant Friedrichs Lewy number - - ADD_TEST(ExampleTransportEquation_1DFV_Upwind_Implicit_CFL2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/1DTransportEquationUpwindImplicit.py ${NX} ${CFL}) - - -endif (CDMATH_WITH_PYTHON ) - - diff --git a/CDMATH/tests/examples/WaveSystem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/CMakeLists.txt new file mode 100755 index 0000000..a4f396f --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/CMakeLists.txt @@ -0,0 +1,36 @@ +file(GLOB WaveSystem_EXAMPLES_TO_INSTALL + + WaveSystem1DUpwind WaveSystem1DUpwind_RiemannProblem WaveSystem1Staggered_RiemannProblem WaveSystem2DUpwind_RiemannProblem + WaveSystem_Stationary/WaveSystemUpwind WaveSystem_Stationary/WaveSystemCentered WaveSystem_Stationary/WaveSystemPStag WaveSystem_Stationary/WaveSystemStaggered + WaveSystem_Shock/WaveSystemUpwind WaveSystem_Shock/WaveSystemCentered WaveSystem_Shock/WaveSystemPStag WaveSystem_Shock/WaveSystemStaggered +) + +install(DIRECTORY ${WaveSystem_EXAMPLES_TO_INSTALL} DESTINATION share/examples/WaveSystem) + +SET(MESH_MED + ${MED_MESHES}/squareWithTriangles.med + ${MED_MESHES}/squareWithSquares.med + ${MED_MESHES}/squareWithBrickWall.med + ${MED_MESHES}/squareWithCheckerboardSquares.med + ${MED_MESHES}/squareWithDeformedQuadrangles.med + ${MED_MESHES}/squareWithHexagons.med + ) + +IF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_SUBDIRECTORY(WaveSystem1DUpwind) + ADD_SUBDIRECTORY(WaveSystem1DStaggered_RiemannProblem) + ADD_SUBDIRECTORY(WaveSystem1DUpwind_RiemannProblem) + ADD_SUBDIRECTORY(WaveSystem2DUpwind_RiemannProblem) + ADD_SUBDIRECTORY(WaveSystem_Stationary/WaveSystemUpwind) + ADD_SUBDIRECTORY(WaveSystem_Stationary/WaveSystemPStag) + ADD_SUBDIRECTORY(WaveSystem_Stationary/WaveSystemStaggered) + ADD_SUBDIRECTORY(WaveSystem_Stationary/WaveSystemCentered) + ADD_SUBDIRECTORY(WaveSystem_Shock/WaveSystemUpwind) + ADD_SUBDIRECTORY(WaveSystem_Shock/WaveSystemPStag) + ADD_SUBDIRECTORY(WaveSystem_Shock/WaveSystemStaggered) + ADD_SUBDIRECTORY(WaveSystem_Shock/WaveSystemCentered) + +ENDIF (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt new file mode 100755 index 0000000..2ab500a --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt @@ -0,0 +1,9 @@ + + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleWaveSystem_1DStaggered_RiemannProblem ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DStaggered_RiemannProblem.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py b/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py new file mode 100755 index 0000000..3603977 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +import cdmath +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys + +p0=155.e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_Riemann_problem(a,b,nx): + print( "Initial data Riemann problem" ) + + dx = (b - a) / nx #space step + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + + u_initial = [ 0 ]*nx + p_initial = [ (xi<(a+b)/2)*p0 + (xi>=(a+b)/2)*p0/2 for xi in x] + + return p_initial, u_initial + +def staggeredMatrices(coeff,scaling): + dim=1 + S1=cdmath.Matrix(dim+1,dim+1) + S2=cdmath.Matrix(dim+1,dim+1) + + for i in range(dim): + if( scaling==0): + S1[0,i+1]=c0*c0*coeff + S2[i+1,0]= coeff + else: + S1[0,i+1]= c0*coeff + S2[i+1,0]= c0*coeff + + return S1,S2 + +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 WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName,scaling): + dim=1 + nbCells = nx + + dt = 0. + time = 0. + it=0; + isStationary=False + + dx=(b-a)/nx + dt = cfl * dx / c0 + + nbVoisinsMax=2 + + #iteration vectors + Un_staggered =cdmath.Vector(nbCells*(dim+1)) + dUn_staggered=cdmath.Vector(nbCells*(dim+1)) + + # Initial conditions # + print("Construction of the initial condition …") + pressure_field_staggered, velocity_field_staggered = initial_conditions_Riemann_problem(a,b,nx) + max_initial_p=max(pressure_field_staggered) + min_initial_p=min(pressure_field_staggered) + max_initial_v=max(velocity_field_staggered) + min_initial_v=min(velocity_field_staggered) + + for k in range(nbCells): + Un_staggered[k*(dim+1)+0] = pressure_field_staggered[k] + Un_staggered[k*(dim+1)+1] =rho0*velocity_field_staggered[k] + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Finite volumes schemes for the 2D Wave System", artist = "CEA Saclay", comment="Shock propagation") + writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(plt.figure(), "2DWaveSystem_Staggered"+".mp4", ntmax): + #sauvegarde de la donnée initiale + plt.xlabel('x (m)') + plt.ylabel('Pressure -Pa)') + plt.xlim(a,b) + plt.ylim( min_initial_p - 0.1*(max_initial_p-min_initial_p), max_initial_p + 0.1*(max_initial_p-min_initial_p) ) + plt.title("Riemann problem for Wave system on " + str(nx) + " cells") + line2, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field_staggered, label='Staggered scheme') #new picture for video # Returns a tuple of line objects, thus the comma + plt.legend() + writer.grab_frame() + plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+"_0"+".png") + np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+"_0"+".txt", pressure_field_staggered, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity"+"_0"+".txt", velocity_field_staggered, delimiter="\n") + + divMat_staggered=computeStaggeredDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) + + iterGMRESMax=50 + + divMat_staggered.diagonalShift(1)#only after filling all coefficients + LS_staggered=cdmath.LinearSolver(divMat_staggered,Un_staggered,iterGMRESMax, precision, "GMRES","ILU") + + print("Starting computation of the linear wave system with staggered scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Linear system converged in ", LS_staggered.getNumberOfIter(), " GMRES iterations" ) + + np.savetxt("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+str(it)+".txt", pressure_field_staggered, delimiter="\n") + np.savetxt("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity"+str(it)+".txt", velocity_field_staggered, delimiter="\n") + plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+str(it)+".png") + + print() + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) + return + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print( "------------------------------------------------------------------------------------") + + np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat.txt", pressure_field_staggered, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat.txt", velocity_field_staggered, delimiter="\n") + plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat.png") + + return + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + return + + +def solve( a,b,nx, meshName, scaling, meshType, cfl): + + print( "Resolution of the Wave system in dimension 1 on "+str(nx)+ " cells, staggered scheme") + print( "Initial data : ", "Riemann problem") + print( "Boundary conditions : ", "Neumann") + print( "Mesh name : ",meshName , ", ", nx, " cells") + + # Problem data + tmax = 10000. + ntmax = 50 + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName, scaling) + + return + + +if __name__ == """__main__""": + a=0. + b=1. + nx=100 + cfl=0.99 + scaling=0 + solve( a,b,nx,"SquareRegularSquares",scaling,"RegularSquares",cfl) diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/CMakeLists.txt new file mode 100755 index 0000000..9026531 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleWaveSystem_1DFV_Upwind ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DUpwind.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/WaveSystem1DUpwind.py b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/WaveSystem1DUpwind.py new file mode 100755 index 0000000..945f163 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind/WaveSystem1DUpwind.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +import cdmath + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_wave_system(my_mesh): + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + if(dim!=1): + raise ValueError("initial_conditions_wave_system: Mesh dimension should be 1") + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, dim) + U = cdmath.Field("Conservative vector", cdmath.CELLS, my_mesh, dim+1) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + + + pressure_field[i] = p0 + if(x>0.5): + velocity_field[i,0] = 1 + else: + velocity_field[i,0] = -1 + + U[i,0] = p0 + U[i,1] = rho0*velocity_field[i,0] + + return U, pressure_field, velocity_field + +def jacobianMatrices(): + A=cdmath.Matrix(2,2) + absA=cdmath.Matrix(2,2) + + absA[0,0]=c0 + absA[1,1]=c0 + A[1,0]=1 + A[0,1]=c0*c0 + + return A, absA + +def Flux(U): + + result=cdmath.Vector(2) + result[0] = c0*c0*U[1] + result[1] = U[0] + + return result + +def numericalFlux(Uj,Ujp1,absA): + + Fj = Flux(Uj) + Fjp1 = Flux(Ujp1) + + return Fj+Fjp1 +absA*(Uj-Ujp1) + +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*(1./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 WaveSystem1DVF(ntmax, tmax, cfl, my_mesh, output_freq, resolution): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + dt = 0. + time = 0. + it=0; + isStationary=False; + + SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim+1) + + # Initial conditions # + print("Construction of the initial condition …") + U, pressure_field, velocity_field = initial_conditions_wave_system(my_mesh) + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / c0 + + print("Starting computation of the linear wave system with an UPWIND explicit scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ) + print() + + for k in range(nbCells): + pressure_field[k]=U[k,0] + velocity_field[k,0]=U[k,1]/rho0 + + pressure_field.setTime(time,it); + pressure_field.writeCSV("WaveSystem1DUpwind_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeCSV("WaveSystem1DUpwind_velocity"); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "|| Un+1 - Un || : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ) + print() + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) + raise ValueError("Maximum number of time steps reached : Stationary state not found !!!!!!!") + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) + for k in range(nbCells): + pressure_field[k]=U[k,0] + velocity_field[k,0]=U[k,1]/rho0 + + pressure_field.setTime(time,0); + pressure_field.writeCSV("WaveSystem1DUpwind_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeCSV("WaveSystem1DUpwind_velocity_Stat"); + + else: + print( "Temps maximum Tmax= ", tmax, " atteint" ) + raise ValueError("Maximum time reached : Stationary state not found !!!!!!!") + + +def solve(my_mesh,resolution): + print("Resolution of the 1D Riemann problem for the Wave system with Upwind explicit scheme:") + + # Problem data + tmax = 1. + ntmax = 100 + cfl = 0.95 + output_freq = 10 + + WaveSystem1DVF(ntmax, tmax, cfl, my_mesh, output_freq,resolution) + +if __name__ == """__main__""": + + xinf=0 + xsup=1 + + M=cdmath.Mesh(xinf,xsup,10) + + solve(M,100) diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt new file mode 100755 index 0000000..51c6c6b --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt @@ -0,0 +1,9 @@ + + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleWaveSystem_1DUpwind_RiemannProblem ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DUpwind_RiemannProblem.py) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py new file mode 100755 index 0000000..ad3f8d6 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +import cdmath +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.animation as manimation +import sys + +p0=155.e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_Riemann_problem(a,b,nx): + print( "Initial data Riemann problem" ) + + dx = (b - a) / nx #space step + x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) + + u_initial = [ 0 ]*nx + p_initial = [ (xi<(a+b)/2)*p0 + (xi>=(a+b)/2)*p0/2 for xi in x] + + return p_initial, u_initial + +def jacobianMatrices(coeff,scaling): + dim=1 + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + absA[0,0]=c0*coeff + for i in range(dim): + for j in range(dim): + absA[i+1,j+1]=c0*coeff + if( scaling==0): + A[0,i+1]=c0*c0*coeff + A[i+1,0]= coeff + elif( scaling==1): + A[0,i+1]= coeff + A[i+1,0]= coeff + else: + A[0,i+1]= c0*coeff + A[i+1,0]= c0*coeff + + return A,absA + + +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)*(1./2)) + implMat.addValue(j*nbComp, j*nbComp,(A-absA)*(-1./2)) + elif ( j==nbCells-1) : + implMat.addValue(j*nbComp, j*nbComp,(A+absA)*(1./2)) + implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)*(-1./2)) + else : + implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)*(1./2)) + implMat.addValue(j*nbComp, j*nbComp,(A-absA)*(-1./2)) + + implMat.addValue(j*nbComp, j*nbComp,(A+absA)*(1./2)) + implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)*(-1./2)) + + return implMat + +def WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName,scaling): + dim=1 + nbCells = nx + + dt = 0. + time = 0. + it=0; + isStationary=False + + dx=(b-a)/nx + dt = cfl * dx / c0 + + nbVoisinsMax=2 + + #iteration vectors + Un =cdmath.Vector(nbCells*(dim+1)) + dUn=cdmath.Vector(nbCells*(dim+1)) + + Un_implicite =cdmath.Vector(nbCells*(dim+1)) + dUn_implicite=cdmath.Vector(nbCells*(dim+1)) + + # Initial conditions # + print("Construction of the initial condition …") + pressure_field, velocity_field = initial_conditions_Riemann_problem(a,b,nx) + pressure_field_implicite, velocity_field_implicite = initial_conditions_Riemann_problem(a,b,nx) + max_initial_p=max(pressure_field) + min_initial_p=min(pressure_field) + max_initial_v=max(velocity_field) + min_initial_v=min(velocity_field) + + for k in range(nbCells): + Un[k*(dim+1)+0] = pressure_field[k] + Un[k*(dim+1)+1] =rho0*velocity_field[k] + Un_implicite[k*(dim+1)+0] = pressure_field_implicite[k] + Un_implicite[k*(dim+1)+1] =rho0*velocity_field_implicite[k] + + # Video settings + FFMpegWriter = manimation.writers['ffmpeg'] + metadata = dict(title="Finite volumes schemes for the 2D Wave System", artist = "CEA Saclay", comment="Shock propagation") + writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') + with writer.saving(plt.figure(), "2DWaveSystem_Upwind"+".mp4", ntmax): + #sauvegarde de la donnée initiale + plt.xlabel('x (m)') + plt.ylabel('Pressure -Pa)') + plt.xlim(a,b) + plt.ylim( min_initial_p - 0.1*(max_initial_p-min_initial_p), max_initial_p + 0.1*(max_initial_p-min_initial_p) ) + plt.title("Riemann problem for Wave system on " + str(nx) + " cells") + line1, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field, label='Explicit upwind scheme') #new picture for video # Returns a tuple of line objects, thus the comma + line3, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field_implicite, label='Implicit upwind scheme') #new picture for video # Returns a tuple of line objects, thus the comma + plt.legend() + writer.grab_frame() + np.savetxt( "WaveSystem"+str(dim)+"DUpwindExplicit"+meshName+"_pressure"+"_0"+".txt", pressure_field, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DUpwindExplicit"+meshName+"_velocity"+"_0"+".txt", velocity_field, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DUpwindImplicit"+meshName+"_pressure"+"_0"+".txt", pressure_field_implicite, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DUpwindImplicit"+meshName+"_velocity"+"_0"+".txt", velocity_field_implicite, delimiter="\n") + plt.savefig("WaveSystem"+str(dim)+"DUpwind" +meshName+"_pressure"+"_0"+".png") + + divMat=computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) + divMat_implicit=computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) + + iterGMRESMax=50 + + divMat_implicit.diagonalShift(1)#only after filling all coefficients + if( scaling==0): + LS=cdmath.LinearSolver(divMat_implicit,Un,iterGMRESMax, precision, "GMRES","ILU") + else: + LS=cdmath.LinearSolver(divMat_implicit,Vn,iterGMRESMax, precision, "GMRES","ILU") + + print("Starting computation of the linear wave system with an upwind scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations" ) + + np.savetxt("WaveSystem" +str(dim)+"DUpwindExplicit"+meshName+"_pressure"+str(it)+".txt", pressure_field , delimiter="\n") + np.savetxt("WaveSystem" +str(dim)+"DUpwindExplicit"+meshName+"_velocity"+str(it)+".txt", velocity_field , delimiter="\n") + np.savetxt("WaveSystem" +str(dim)+"DUpwindImplicit"+meshName+"_pressure"+str(it)+".txt", pressure_field , delimiter="\n") + np.savetxt("WaveSystem" +str(dim)+"DUpwindImplicit"+meshName+"_velocity"+str(it)+".txt", velocity_field , delimiter="\n") + plt.savefig("WaveSystem"+str(dim)+"DUpwind" +meshName+"_pressure"+str(it)+".png") + + print() + print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) + return + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) + print( "------------------------------------------------------------------------------------") + + np.savetxt( "WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat.txt", pressure_field, delimiter="\n") + np.savetxt( "WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat.txt", velocity_field, delimiter="\n") + plt.savefig("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat.png") + + return + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + return + + +def solve( a,b,nx, meshName, scaling, meshType, cfl): + + print( "Resolution of the Wave system in dimension 1 on "+str(nx)+ " cells, upwind scheme") + print( "Initial data : ", "Riemann problem") + print( "Boundary conditions : ", "Neumann") + print( "Mesh name : ",meshName , ", ", nx, " cells") + + # Problem data + tmax = 10000. + ntmax = 50 + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName, scaling) + + return + + +if __name__ == """__main__""": + a=0. + b=1. + nx=100 + cfl=0.99 + scaling=0 + solve( a,b,nx,"SquareRegularSquares",scaling,"RegularSquares",cfl) diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt new file mode 100755 index 0000000..d271c53 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt @@ -0,0 +1,61 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(IMPLICIT_SCHEME 0 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithBrickWall.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithCheckerboardSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithDeformedQuadrangles.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_deformedQuadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(IMPLICIT_SCHEME 1 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithBrickWall.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithCheckerboardSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithDeformedQuadrangles.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_deformedQuadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py new file mode 100755 index 0000000..9d3abde --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc droite +# Utilisation du schéma upwind explicite ou implicite sur un maillage général +# Initialisation par une discontinuité verticale +# Conditions aux limites de Neumann +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sin, cos, pi, sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_RiemannProblem(my_mesh): + print( "Initial data : Riemann problem" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + xcentre = 0 + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + if x < xcentre: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0/2 + pass + pass + + return pressure_field, velocity_field + +def jacobianMatrices(normal,coeff): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + absA[0,0]=c0*coeff + for i in range(dim): + A[i+1,0]= normal[i]*coeff + A[0,i+1]=c0*c0*normal[i]*coeff + for j in range(dim): + absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff + + return (A - absA)*(1./2) + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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 cell number") + + implMat.addValue(j*nbComp,cellAutre*nbComp,Am) + implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + + return implMat + +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) + + SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim+1) + + # Initial conditions # + print("Construction of the initial condition …") + pressure_field, velocity_field = initial_conditions_RiemannProblem(my_mesh) + + #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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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 explicit UPWIND scheme …") + + # Starting time loop + while (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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + + +def solve(my_mesh,filename,resolution, isImplicit): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : upwind") + print( "Initial data : single straight discontinuity (Riemann problem)") + print( "Neumann boundary conditions") + print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") + + # Problem data + tmax = 1. + ntmax = 50 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) + +def solve_file( filename,resolution, isImplicit): + my_mesh = cdmath.Mesh(filename+".med") + solve(my_mesh, filename,resolution, isImplicit) + +if __name__ == """__main__""": + if len(sys.argv) >2 : + filename=sys.argv[1] + isImplicit=bool(int(sys.argv[2])) + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100, isImplicit) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt new file mode 100755 index 0000000..f21cbe8 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt @@ -0,0 +1,45 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemCentered) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_Centered_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_Centered_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshHexagonWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_Centered_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py new file mode 100755 index 0000000..95fa24f --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc sphérique +# Utilisation du schéma centré (implicite) sur un maillage général +# Initialisation par une surpression sphérique +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sqrt +from numpy import sign +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_shock(my_mesh, isCircle): + print( "Initial data : Spherical wave" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + rayon = 0.15 + if(not isCircle): + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + else: + xcentre = 0. + ycentre = 0. + zcentre = 0. + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + x = my_mesh.getCell(i).x() + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val = sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0/2 + pass + pass + + return pressure_field, velocity_field + +def jacobianMatrices(normal, coeff, signun): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + + for i in range(dim): + A[i+1,0]=normal[i]*coeff + A[0,i+1]=c0*c0*normal[i]*coeff + + return A*(1./2) + + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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) + + v0=cdmath.Vector(dim) + for i in range(dim) : + v0[i] = 1. + + 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 + + signun=sign(normal*v0) + Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); + + 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + meshName=my_mesh.getName() + + dt = 0. + time = 0. + it=0; + isStationary=False; + + 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(dim==1 or 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_shock(my_mesh,False) + elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): + pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) + else: + print( "Mesh name : ", filename ) + raise ValueError("Mesh name should contain substring square, cube, Hexagon or disk") + + for k in range(nbCells): + Un[k*(dim+1)+0] = pressure_field[k] + Un[k*(dim+1)+1] = rho0*velocity_field[k,0] + if(dim>=2): + Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face + if(dim==3): + Un[k + 3*nbCells] = rho0*velocity_field[k,2] + + #sauvegarde de la donnée initiale + pressure_field.setTime(time,it); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"); + #Postprocessing : save 2D picture + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_initial") + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_initial") + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / c0 + + divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) + + # 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 a centered scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) + + 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)+"DCentered"+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity",False); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print() + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) + print( "------------------------------------------------------------------------------------" ) + + pressure_field.setTime(time,0); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"); + + #Postprocessing : save 2D picture + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat") + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint" ) + + +def solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : implicit centered") + print( "Initial data : spherical wave") + print( "Wall boundary conditions") + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells") + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + filename=sys.argv[1] + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt new file mode 100755 index 0000000..61c7332 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt @@ -0,0 +1,45 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemPStag) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_PStag_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_PStag_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshHexagonWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_PStag_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py new file mode 100755 index 0000000..1130af8 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc sphérique +# Utilisation du schéma MAC sur un maillage cartésien +# Initialisation par une surpression sphérique +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sqrt +from numpy import sign +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_shock(my_mesh, isCircle): + print( "Initial data : Spherical wave" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + rayon = 0.15 + if(not isCircle): + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + else: + xcentre = 0. + ycentre = 0. + zcentre = 0. + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + x = my_mesh.getCell(i).x() + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val = sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0/2 + pass + pass + + return pressure_field, velocity_field + +def jacobianMatrices(normal, coeff, signun): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + for i in range(dim): + A[i+1,0]=normal[i]*coeff + absA[i+1,0]=-signun*A[i+1,0] + A[0,i+1]=c0*c0*normal[i]*coeff + absA[0,i+1]=signun*A[0,i+1] + + return (A-absA)*(1./2) + + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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) + + v0=cdmath.Vector(dim) + for i in range(dim) : + v0[i] = 1. + + 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 + + signun=sign(normal*v0) + Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); + + 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + meshName=my_mesh.getName() + + dt = 0. + time = 0. + it=0; + isStationary=False; + + 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(dim==1 or 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_shock(my_mesh,False) + elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): + pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) + else: + print( "Mesh name : ", filename ) + raise ValueError("Mesh name should contain substring square, cube, Hexagon or disk") + + for k in range(nbCells): + Un[k*(dim+1)+0] = pressure_field[k] + Un[k*(dim+1)+1] = rho0*velocity_field[k,0] + if(dim>=2): + Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face + if(dim==3): + Un[k + 3*nbCells] = rho0*velocity_field[k,2] + + #sauvegarde de la donnée initiale + pressure_field.setTime(time,it); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity"); + #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+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_initial") + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / c0 + + divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) + + # 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 or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) + + 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)+"DPStag"+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity",False); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0) + print() + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print( "------------------------------------------------------------------------------------") + + pressure_field.setTime(time,0); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat"); + + #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+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint" ) + + +def solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : implicit pseudo staggered" ) + print( "Initial data : spherical wave" ) + print( "Wall boundary conditions" ) + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + filename=sys.argv[1] + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt new file mode 100755 index 0000000..5fc4636 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleWaveSystem_2DShock_Staggered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemStaggered.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py new file mode 100755 index 0000000..752c378 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc sphérique +# Utilisation du schéma MAC sur un maillage cartésien +# Initialisation par une surpression sphérique +# Conditions aux limites périodiques +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_shock(my_mesh, isCircle): + print( "Initial data : Spherical wave") + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + rayon = 0.15 + if(not isCircle): + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + else: + xcentre = 0. + ycentre = 0. + zcentre = 0. + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + x = my_mesh.getCell(i).x() + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val = sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0/2 + pass + pass + + return pressure_field, velocity_field + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling): + nbCells = my_mesh.getNumberOfCells() + dim=my_mesh.getMeshDimension() + nbComp=dim+1 + + if(not my_mesh.isStructured()): + raise ValueError("WaveSystemStaggered: the mesh should be structured"); + + NxNyNz=my_mesh.getCellGridStructure() + DxDyDz=my_mesh.getDXYZ() + + implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) + + idMoinsJacCL=cdmath.Matrix(nbComp) + + if( dim == 1) : + nx=NxNyNz[0] + dx=DxDyDz[0] + + if( scaling==0 ): + for k in range(nbCells): + implMat.addValue(k,1*nbCells + k , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + (k+1)%nx, c0*c0*dt/dx) + + implMat.addValue( 1*nbCells + k ,k, dt/dx) + implMat.addValue( 1*nbCells + (k+1)%nx,k, -dt/dx) + else : # scaling >0 + for k in range(nbCells): + implMat.addValue(k,1*nbCells + k , -c0*dt/dx) + implMat.addValue(k,1*nbCells + (k+1)%nx, c0*dt/dx) + + implMat.addValue( 1*nbCells + k ,k, c0*dt/dx) + implMat.addValue( 1*nbCells + (k+1)%nx,k, -c0*dt/dx) + + elif( dim == 2) :# k = j*nx+i + nx=NxNyNz[0] + ny=NxNyNz[1] + dx=DxDyDz[0] + dy=DxDyDz[1] + + if( scaling==0 ): + for k in range(nbCells): + i = k % nx + j = k //nx + + implMat.addValue(k,1*nbCells + j*nx + i , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*c0*dt/dx) + + implMat.addValue(k,2*nbCells + j *nx + i, -c0*c0*dt/dy) + implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*c0*dt/dy) + + implMat.addValue( 1*nbCells + j*nx + i , k, dt/dx) + implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -dt/dx) + + implMat.addValue( 2*nbCells + j *nx + i,k, dt/dy) + implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -dt/dy) + + else :# scaling >0 + for k in range(nbCells): + i = k % nx + j = k //nx + + implMat.addValue(k,1*nbCells + j*nx + i , -c0*dt/dx) + implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*dt/dx) + + implMat.addValue(k,2*nbCells + j *nx + i, -c0*dt/dy) + implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*dt/dy) + + implMat.addValue( 1*nbCells + j*nx + i , k, c0*dt/dx) + implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -c0*dt/dx) + + implMat.addValue( 2*nbCells + j *nx + i,k, c0*dt/dy) + implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -c0*dt/dy) + + elif( dim == 3) :# k = l*nx*ny+j*nx+i + nx=NxNyNz[0] + ny=NxNyNz[1] + nz=NxNyNz[2] + dx=DxDyDz[0] + dy=DxDyDz[1] + dz=DxDyDz[2] + + if( scaling==0 ): + for k in range(nbCells): + i = k % nx + j = (k //nx)%ny + l = k //(nx*ny) + + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*c0*dt/dx) + + implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*c0*dt/dy) + implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*c0*dt/dy) + + implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*c0*dt/dz) + implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*c0*dt/dz) + + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, dt/dx) + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -dt/dx) + + implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, dt/dy) + implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -dt/dy) + + implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, dt/dz) + implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -dt/dz) + + else:# scaling >0 + for k in range(nbCells): + i = k % nx + j = (k //nx)%ny + l = k //(nx*ny) + + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*dt/dx) + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*dt/dx) + + implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*dt/dy) + implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*dt/dy) + + implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*dt/dz) + implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*dt/dz) + + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, c0*dt/dx) + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -c0*dt/dx) + + implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, c0*dt/dy) + implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -c0*dt/dy) + + implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, c0*dt/dz) + implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -c0*dt/dz) + + return implMat + +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 …") + if(dim==1 or 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_shock(my_mesh,False) + elif(meshName.find("disk")>-1 or meshName.find("Disk")>-1): + pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) + else: + print( "Mesh name : ", meshName ) + raise ValueError("Mesh name should contain substring square, cube or disk") + + 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 + if(dim>=2): + Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face + if(dim==3): + Un[k + 3*nbCells] = rho0*velocity_field[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 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 solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : staggered scheme" ) + print( "Initial data : Spherical wave" ) + print( "Periodic boundary conditions" ) + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + my_mesh = cdmath.Mesh(sys.argv[1]) + solve(my_mesh,my_mesh.getName(),100) + else : + nx=50 + my_mesh = cdmath.Mesh(0,1,nx,0,1,nx) + solve(my_mesh,"square",100) diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt new file mode 100755 index 0000000..68313a5 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt @@ -0,0 +1,81 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(IMPLICIT_SCHEME 0 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshHexagonWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(IMPLICIT_SCHEME 1 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DShock_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py new file mode 100755 index 0000000..10b55c9 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Propagation d'une onde de choc sphérique +# Utilisation du schéma upwind explicite ou implicite sur un maillage général +# Initialisation par une surpression sphérique +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_shock(my_mesh, isCircle): + print( "Initial data : Spherical wave" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + rayon = 0.15 + if(not isCircle):#Case of a square domain + xcentre = 0.5 + ycentre = 0.5 + zcentre = 0.5 + else:#Case of a disk or a hexagonal domain + xcentre = 0. + ycentre = 0. + zcentre = 0. + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + velocity_field[i,0] = 0 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + + x = my_mesh.getCell(i).x() + valX = (x - xcentre) * (x - xcentre) + + if(dim==1): + val = sqrt(valX) + if(dim==2): + y = my_mesh.getCell(i).y() + valY = (y - ycentre) * (y - ycentre) + val = sqrt(valX + valY) + if(dim==3): + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + valY = (y - ycentre) * (y - ycentre) + valZ = (z - zcentre) * (z - zcentre) + val = sqrt(valX + valY + valZ) + + if val < rayon: + pressure_field[i] = p0 + pass + else: + pressure_field[i] = p0/2 + pass + pass + + return pressure_field, velocity_field + +def jacobianMatrices(normal,coeff): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + absA[0,0]=c0*coeff + for i in range(dim): + A[i+1,0]= normal[i]*coeff + A[0,i+1]=c0*c0*normal[i]*coeff + for j in range(dim): + absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff + + return (A - absA)*(1./2) + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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 cell number") + + implMat.addValue(j*nbComp,cellAutre*nbComp,Am) + implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + else : + if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +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(dim==1 or 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_shock(my_mesh,False) + elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): + pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) + else: + print( "Mesh name : ", filename ) + raise ValueError("Mesh name should contain substring square, cube, hexagon 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] + if(dim>=2): + Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face + if(dim==3): + Un[k + 3*nbCells] = rho0*velocity_field[k,2] + + #sauvegarde de la donnée initiale + pressure_field.setTime(time,it); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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 explicit UPWIND scheme …") + + # Starting time loop + while (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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + + +def solve(my_mesh,filename,resolution, isImplicit): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : upwind" ) + print( "Initial data : spherical wave" ) + print( "Wall boundary conditions" ) + print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells" ) + + # Problem data + tmax = 1. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 1 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) + +def solve_file( filename,resolution, isImplicit): + my_mesh = cdmath.Mesh(filename+".med") + solve(my_mesh, filename,resolution, isImplicit) + +if __name__ == """__main__""": + if len(sys.argv) >2 : + filename=sys.argv[1] + isImplicit=bool(int(sys.argv[2])) + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100, isImplicit) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt new file mode 100755 index 0000000..51f79f6 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt @@ -0,0 +1,41 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemCentered) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_Centered_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_Centered_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py new file mode 100755 index 0000000..c6c6fa8 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Test de préservation d'un état stationnaire +# Utilisation du schéma centré (implicite) sur un maillage général +# Initialisation par un vortex stationnaire +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sin, cos, pi, sqrt +from numpy import sign +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_disk_vortex(my_mesh): + print( "Disk vortex initial data") + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + if(dim!=2): + raise ValueError("Wave system on disk : mesh dimension should be 2") + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + + pressure_field[i] = p0 + + velocity_field[i,0] = -y + velocity_field[i,1] = x + velocity_field[i,2] = 0 + + return pressure_field, velocity_field + +def initial_conditions_square_vortex(my_mesh): + print( "Initial data : Square vortex (Constant pressure, divergence free velocity)") + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + + pressure_field[i] = p0 + if(dim==1): + velocity_field[i,0] = 1 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + elif(dim==2): + velocity_field[i,0] = sin(pi*x)*cos(pi*y) + velocity_field[i,1] = -sin(pi*y)*cos(pi*x) + velocity_field[i,2] = 0 + elif(dim==3): + velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) + velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) + velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) + + return pressure_field, velocity_field + +def jacobianMatrices(normal, coeff, signun): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + + for i in range(dim): + A[i+1,0]=normal[i]*coeff + A[0,i+1]=c0*c0*normal[i]*coeff + + return A*(1./2) + + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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) + + v0=cdmath.Vector(dim) + for i in range(dim) : + v0[i] = 1. + + 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 + + signun=sign(normal*v0) + Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); + + 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + meshName=my_mesh.getName() + + dt = 0. + time = 0. + it=0; + isStationary=False; + + 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(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 or filename.find("Hexagon")>-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, Hexagon or disk") + + 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)+"DCentered"+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"); + #Postprocessing : save 2D picture + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_initial") + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_initial") + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / c0 + + divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) + + # 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 a centered scheme …") + + # Starting time loop + while (it=ntmax or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print( "Linear system converged in ", iterGMRES, " GMRES iterations") + + 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)+"DCentered"+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity",False); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print() + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print( "------------------------------------------------------------------------------------") + + pressure_field.setTime(time,0); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"); + + #Postprocessing : save 2D picture + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat") + PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + + +def solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) + print( "Numerical method : implicit centered" ) + print( "Initial data : stationary solution (constant pressure, divergence free velocity)" ) + print( "Wall boundary conditions" ) + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 100 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + filename=sys.argv[1] + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt new file mode 100755 index 0000000..c272a17 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt @@ -0,0 +1,41 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemPStag) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_PStag_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_PStag_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py new file mode 100755 index 0000000..f73e2b4 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py @@ -0,0 +1,303 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Test de préservation d'un état stationnaire +# Utilisation du schéma pseudo décalé (implicite) sur un maillage général +# Initialisation par un vortex stationnaire +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sin, cos, pi, sqrt +from numpy import sign +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_disk_vortex(my_mesh): + print( "Disk vortex initial data" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + if(dim!=2): + raise ValueError("Wave system on disk : mesh dimension should be 2") + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + + pressure_field[i] = p0 + + velocity_field[i,0] = -y + velocity_field[i,1] = x + velocity_field[i,2] = 0 + + return pressure_field, velocity_field + +def initial_conditions_square_vortex(my_mesh): + print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + + pressure_field[i] = p0 + if(dim==1): + velocity_field[i,0] = 1 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + elif(dim==2): + velocity_field[i,0] = sin(pi*x)*cos(pi*y) + velocity_field[i,1] = -sin(pi*y)*cos(pi*x) + velocity_field[i,2] = 0 + elif(dim==3): + velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) + velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) + velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) + + return pressure_field, velocity_field + +def jacobianMatrices(normal, coeff, signun): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + for i in range(dim): + A[i+1,0]=normal[i]*coeff + absA[i+1,0]=-signun*A[i+1,0] + A[0,i+1]=c0*c0*normal[i]*coeff + absA[0,i+1]=signun*A[0,i+1] + + return (A-absA)*(1./2) + + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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) + + v0=cdmath.Vector(dim) + for i in range(dim) : + v0[i] = 1. + + 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 + + signun=sign(normal*v0) + Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); + + 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): + dim=my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + meshName=my_mesh.getName() + + dt = 0. + time = 0. + it=0; + isStationary=False; + + 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(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") + + 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)+"DPStag"+meshName+"_pressure"); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity"); + #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+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_initial") + + dx_min=my_mesh.minRatioVolSurf() + + dt = cfl * dx_min / c0 + + divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) + + # 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 or isStationary or time >=tmax): + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) + + 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)+"DPStag"+meshName+"_pressure",False); + velocity_field.setTime(time,it); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity",False); + + print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) + print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) + print() + + if(it>=ntmax): + print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") + elif(isStationary): + print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) + print( "------------------------------------------------------------------------------------") + + pressure_field.setTime(time,0); + pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure_Stat"); + velocity_field.setTime(time,0); + velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat"); + + #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+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat") + + else: + print( "Temps maximum Tmax= ", tmax, " atteint") + + +def solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) + print( "Numerical method : implicit pseudo staggered") + print( "Initial data : stationary solution (constant pressure, divergence free velocity)") + print( "Wall boundary conditions") + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 100 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + filename=sys.argv[1] + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt new file mode 100755 index 0000000..c30f344 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + ADD_TEST(ExampleWaveSystem_2DVortex_Staggered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemStaggered.py ) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py new file mode 100755 index 0000000..092ab28 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py @@ -0,0 +1,339 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Test de préservation d'un état stationnaire +# Utilisation du schéma MAC sur un maillage cartésien +# Initialisation par un vortex stationnaire +# Conditions aux limites périodiques +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sin, cos, pi, sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_square_vortex(my_mesh): + print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + + pressure_field[i] = p0 + if(dim==1): + velocity_field[i,0] = 1 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + elif(dim==2): + velocity_field[i,0] = sin(pi*x)*cos(pi*y) + velocity_field[i,1] = -sin(pi*y)*cos(pi*x) + velocity_field[i,2] = 0 + elif(dim==3): + velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) + velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) + velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) + + return pressure_field, velocity_field + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling): + nbCells = my_mesh.getNumberOfCells() + dim=my_mesh.getMeshDimension() + nbComp=dim+1 + + if(not my_mesh.isStructured()): + raise ValueError("WaveSystemStaggered: the mesh should be structured"); + + NxNyNz=my_mesh.getCellGridStructure() + DxDyDz=my_mesh.getDXYZ() + + implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) + + idMoinsJacCL=cdmath.Matrix(nbComp) + + if( dim == 1) : + nx=NxNyNz[0] + dx=DxDyDz[0] + + if( scaling==0 ): + for k in range(nbCells): + implMat.addValue(k,1*nbCells + k , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + (k+1)%nx, c0*c0*dt/dx) + + implMat.addValue( 1*nbCells + k ,k, dt/dx) + implMat.addValue( 1*nbCells + (k+1)%nx,k, -dt/dx) + else : # scaling >0 + for k in range(nbCells): + implMat.addValue(k,1*nbCells + k , -c0*dt/dx) + implMat.addValue(k,1*nbCells + (k+1)%nx, c0*dt/dx) + + implMat.addValue( 1*nbCells + k ,k, c0*dt/dx) + implMat.addValue( 1*nbCells + (k+1)%nx,k, -c0*dt/dx) + + elif( dim == 2) :# k = j*nx+i + nx=NxNyNz[0] + ny=NxNyNz[1] + dx=DxDyDz[0] + dy=DxDyDz[1] + + if( scaling==0 ): + for k in range(nbCells): + i = k % nx + j = k //nx + + implMat.addValue(k,1*nbCells + j*nx + i , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*c0*dt/dx) + + implMat.addValue(k,2*nbCells + j *nx + i, -c0*c0*dt/dy) + implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*c0*dt/dy) + + implMat.addValue( 1*nbCells + j*nx + i , k, dt/dx) + implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -dt/dx) + + implMat.addValue( 2*nbCells + j *nx + i,k, dt/dy) + implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -dt/dy) + + else :# scaling >0 + for k in range(nbCells): + i = k % nx + j = k //nx + + implMat.addValue(k,1*nbCells + j*nx + i , -c0*dt/dx) + implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*dt/dx) + + implMat.addValue(k,2*nbCells + j *nx + i, -c0*dt/dy) + implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*dt/dy) + + implMat.addValue( 1*nbCells + j*nx + i , k, c0*dt/dx) + implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -c0*dt/dx) + + implMat.addValue( 2*nbCells + j *nx + i,k, c0*dt/dy) + implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -c0*dt/dy) + + elif( dim == 3) :# k = l*nx*ny+j*nx+i + nx=NxNyNz[0] + ny=NxNyNz[1] + nz=NxNyNz[2] + dx=DxDyDz[0] + dy=DxDyDz[1] + dz=DxDyDz[2] + + if( scaling==0 ): + for k in range(nbCells): + i = k % nx + j = (k //nx)%ny + l = k //(nx*ny) + + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*c0*dt/dx) + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*c0*dt/dx) + + implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*c0*dt/dy) + implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*c0*dt/dy) + + implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*c0*dt/dz) + implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*c0*dt/dz) + + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, dt/dx) + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -dt/dx) + + implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, dt/dy) + implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -dt/dy) + + implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, dt/dz) + implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -dt/dz) + + else:# scaling >0 + for k in range(nbCells): + i = k % nx + j = (k //nx)%ny + l = k //(nx*ny) + + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*dt/dx) + implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*dt/dx) + + implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*dt/dy) + implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*dt/dy) + + implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*dt/dz) + implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*dt/dz) + + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, c0*dt/dx) + implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -c0*dt/dx) + + implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, c0*dt/dy) + implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -c0*dt/dy) + + implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, c0*dt/dz) + implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -c0*dt/dz) + + return implMat + +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_square_vortex(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 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 solve(my_mesh,meshName,resolution): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) + print( "Numerical method : staggered scheme") + print( "Initial data : stationary solution (constant pressure, divergence free velocity)") + print( "Periodic boundary conditions") + print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells") + + # Problem data + tmax = 1000. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 100 + + WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) + +def solve_file( filename,meshName, resolution): + my_mesh = cdmath.Mesh(filename+".med") + + return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution) + + +if __name__ == """__main__""": + if len(sys.argv) >1 : + my_mesh = cdmath.Mesh(sys.argv[1]) + solve(my_mesh,my_mesh.getName(),100) + else : + nx=50 + my_mesh = cdmath.Mesh(0,1,nx,0,1,nx) + solve(my_mesh,my_mesh.getName(),100) diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt new file mode 100755 index 0000000..912b52c --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt @@ -0,0 +1,77 @@ + +file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) + +if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + SET(IMPLICIT_SCHEME 0 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(IMPLICIT_SCHEME 0 ) + + SET(MESH_FILE ${MED_MESHES}/meshSquare.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/squareWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/meshCube.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/cubeWithCubes.med ) + + ADD_TEST(ExampleWaveSystem_3DVortex_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithTriangles.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSquares.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithSpiderWeb.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + + SET(MESH_FILE ${MED_MESHES}/diskWithHexagons.med ) + + ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) + +endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) + + diff --git a/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py new file mode 100755 index 0000000..bb190e0 --- /dev/null +++ b/CDMATH/tests/examples/WaveSystem/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python3 +# -*-coding:utf-8 -* + +#=============================================================================================================================== +# Name : Résolution VF du système des ondes 2D sans terme source +# \partial_t p + c^2 \div q = 0 +# \partial_t q + \grad p = 0 +# Author : Michaël Ndjinga +# Copyright : CEA Saclay 2019 +# Description : Test de préservation d'un état stationnaire +# Utilisation du schéma upwind explicite ou implicite sur un maillage général +# Initialisation par une vortex stationnaire +# Conditions aux limites parois +# Création et sauvegarde du champ résultant et des figures +#================================================================================================================================ + + +from math import sin, cos, pi, sqrt +import cdmath +import PV_routines +import VTK_routines +import sys + +p0=155e5#reference pressure in a pressurised nuclear vessel +c0=700.#reference sound speed for water at 155 bars, 600K +rho0=p0/c0*c0#reference density +precision=1e-5 + +def initial_conditions_disk_vortex(my_mesh): + print( "Disk vortex initial data") + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + if(dim!=2): + raise ValueError("Wave system on disk : mesh dimension should be 2") + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + + pressure_field[i] = p0 + + velocity_field[i,0] = -y + velocity_field[i,1] = x + velocity_field[i,2] = 0 + + return pressure_field, velocity_field + +def initial_conditions_square_vortex(my_mesh): + print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) + dim = my_mesh.getMeshDimension() + nbCells = my_mesh.getNumberOfCells() + + pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) + velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) + + for i in range(nbCells): + x = my_mesh.getCell(i).x() + y = my_mesh.getCell(i).y() + z = my_mesh.getCell(i).z() + + pressure_field[i] = p0 + if(dim==1): + velocity_field[i,0] = 1 + velocity_field[i,1] = 0 + velocity_field[i,2] = 0 + elif(dim==2): + velocity_field[i,0] = sin(pi*x)*cos(pi*y) + velocity_field[i,1] = -sin(pi*y)*cos(pi*x) + velocity_field[i,2] = 0 + elif(dim==3): + velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) + velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) + velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) + + return pressure_field, velocity_field + +def jacobianMatrices(normal,coeff): + dim=normal.size() + A=cdmath.Matrix(dim+1,dim+1) + absA=cdmath.Matrix(dim+1,dim+1) + + absA[0,0]=c0*coeff + for i in range(dim): + A[i+1,0]= normal[i]*coeff + A[0,i+1]=c0*c0*normal[i]*coeff + for j in range(dim): + absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff + + return (A - absA)*(1./2) + +def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): + 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 cell number") + + implMat.addValue(j*nbComp,cellAutre*nbComp,Am) + implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) + else : + if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly + 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition + 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition + print( Fk.getGroupName() ) + raise ValueError("computeFluxes: Unknown boundary condition name"); + + return implMat + +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 …") + + # Starting time loop + while (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(my_mesh,filename,resolution, isImplicit): + print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) + print( "Numerical method : upwind") + print( "Initial data : stationary solution (constant pressure, divergence free velocity)") + print( "Wall boundary conditions") + print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") + + # Problem data + tmax = 1. + ntmax = 100 + cfl = 1./my_mesh.getSpaceDimension() + output_freq = 100 + + WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) + +def solve_file( filename,resolution): + my_mesh = cdmath.Mesh(filename+".med") + solve(my_mesh, filename,resolution, isImplicit) + +if __name__ == """__main__""": + if len(sys.argv) >2 : + filename=sys.argv[1] + isImplicit=bool(int(sys.argv[2])) + my_mesh = cdmath.Mesh(filename) + solve(my_mesh,filename,100, isImplicit) + else : + raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt deleted file mode 100755 index 2ab500a..0000000 --- a/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ - - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleWaveSystem_1DStaggered_RiemannProblem ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DStaggered_RiemannProblem.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py b/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py deleted file mode 100755 index 3603977..0000000 --- a/CDMATH/tests/examples/WaveSystem1DStaggered_RiemannProblem/WaveSystem1DStaggered_RiemannProblem.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -import cdmath -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys - -p0=155.e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_Riemann_problem(a,b,nx): - print( "Initial data Riemann problem" ) - - dx = (b - a) / nx #space step - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - - u_initial = [ 0 ]*nx - p_initial = [ (xi<(a+b)/2)*p0 + (xi>=(a+b)/2)*p0/2 for xi in x] - - return p_initial, u_initial - -def staggeredMatrices(coeff,scaling): - dim=1 - S1=cdmath.Matrix(dim+1,dim+1) - S2=cdmath.Matrix(dim+1,dim+1) - - for i in range(dim): - if( scaling==0): - S1[0,i+1]=c0*c0*coeff - S2[i+1,0]= coeff - else: - S1[0,i+1]= c0*coeff - S2[i+1,0]= c0*coeff - - return S1,S2 - -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 WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName,scaling): - dim=1 - nbCells = nx - - dt = 0. - time = 0. - it=0; - isStationary=False - - dx=(b-a)/nx - dt = cfl * dx / c0 - - nbVoisinsMax=2 - - #iteration vectors - Un_staggered =cdmath.Vector(nbCells*(dim+1)) - dUn_staggered=cdmath.Vector(nbCells*(dim+1)) - - # Initial conditions # - print("Construction of the initial condition …") - pressure_field_staggered, velocity_field_staggered = initial_conditions_Riemann_problem(a,b,nx) - max_initial_p=max(pressure_field_staggered) - min_initial_p=min(pressure_field_staggered) - max_initial_v=max(velocity_field_staggered) - min_initial_v=min(velocity_field_staggered) - - for k in range(nbCells): - Un_staggered[k*(dim+1)+0] = pressure_field_staggered[k] - Un_staggered[k*(dim+1)+1] =rho0*velocity_field_staggered[k] - - # Video settings - FFMpegWriter = manimation.writers['ffmpeg'] - metadata = dict(title="Finite volumes schemes for the 2D Wave System", artist = "CEA Saclay", comment="Shock propagation") - writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') - with writer.saving(plt.figure(), "2DWaveSystem_Staggered"+".mp4", ntmax): - #sauvegarde de la donnée initiale - plt.xlabel('x (m)') - plt.ylabel('Pressure -Pa)') - plt.xlim(a,b) - plt.ylim( min_initial_p - 0.1*(max_initial_p-min_initial_p), max_initial_p + 0.1*(max_initial_p-min_initial_p) ) - plt.title("Riemann problem for Wave system on " + str(nx) + " cells") - line2, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field_staggered, label='Staggered scheme') #new picture for video # Returns a tuple of line objects, thus the comma - plt.legend() - writer.grab_frame() - plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+"_0"+".png") - np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+"_0"+".txt", pressure_field_staggered, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity"+"_0"+".txt", velocity_field_staggered, delimiter="\n") - - divMat_staggered=computeStaggeredDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) - - iterGMRESMax=50 - - divMat_staggered.diagonalShift(1)#only after filling all coefficients - LS_staggered=cdmath.LinearSolver(divMat_staggered,Un_staggered,iterGMRESMax, precision, "GMRES","ILU") - - print("Starting computation of the linear wave system with staggered scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Linear system converged in ", LS_staggered.getNumberOfIter(), " GMRES iterations" ) - - np.savetxt("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+str(it)+".txt", pressure_field_staggered, delimiter="\n") - np.savetxt("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity"+str(it)+".txt", velocity_field_staggered, delimiter="\n") - plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure"+str(it)+".png") - - print() - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) - return - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print( "------------------------------------------------------------------------------------") - - np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat.txt", pressure_field_staggered, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat.txt", velocity_field_staggered, delimiter="\n") - plt.savefig("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat.png") - - return - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - return - - -def solve( a,b,nx, meshName, scaling, meshType, cfl): - - print( "Resolution of the Wave system in dimension 1 on "+str(nx)+ " cells, staggered scheme") - print( "Initial data : ", "Riemann problem") - print( "Boundary conditions : ", "Neumann") - print( "Mesh name : ",meshName , ", ", nx, " cells") - - # Problem data - tmax = 10000. - ntmax = 50 - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName, scaling) - - return - - -if __name__ == """__main__""": - a=0. - b=1. - nx=100 - cfl=0.99 - scaling=0 - solve( a,b,nx,"SquareRegularSquares",scaling,"RegularSquares",cfl) diff --git a/CDMATH/tests/examples/WaveSystem1DUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem1DUpwind/CMakeLists.txt deleted file mode 100755 index 9026531..0000000 --- a/CDMATH/tests/examples/WaveSystem1DUpwind/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleWaveSystem_1DFV_Upwind ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DUpwind.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem1DUpwind/WaveSystem1DUpwind.py b/CDMATH/tests/examples/WaveSystem1DUpwind/WaveSystem1DUpwind.py deleted file mode 100755 index 945f163..0000000 --- a/CDMATH/tests/examples/WaveSystem1DUpwind/WaveSystem1DUpwind.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -import cdmath - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_wave_system(my_mesh): - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - if(dim!=1): - raise ValueError("initial_conditions_wave_system: Mesh dimension should be 1") - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, dim) - U = cdmath.Field("Conservative vector", cdmath.CELLS, my_mesh, dim+1) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - - - pressure_field[i] = p0 - if(x>0.5): - velocity_field[i,0] = 1 - else: - velocity_field[i,0] = -1 - - U[i,0] = p0 - U[i,1] = rho0*velocity_field[i,0] - - return U, pressure_field, velocity_field - -def jacobianMatrices(): - A=cdmath.Matrix(2,2) - absA=cdmath.Matrix(2,2) - - absA[0,0]=c0 - absA[1,1]=c0 - A[1,0]=1 - A[0,1]=c0*c0 - - return A, absA - -def Flux(U): - - result=cdmath.Vector(2) - result[0] = c0*c0*U[1] - result[1] = U[0] - - return result - -def numericalFlux(Uj,Ujp1,absA): - - Fj = Flux(Uj) - Fjp1 = Flux(Ujp1) - - return Fj+Fjp1 +absA*(Uj-Ujp1) - -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*(1./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 WaveSystem1DVF(ntmax, tmax, cfl, my_mesh, output_freq, resolution): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - dt = 0. - time = 0. - it=0; - isStationary=False; - - SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim+1) - - # Initial conditions # - print("Construction of the initial condition …") - U, pressure_field, velocity_field = initial_conditions_wave_system(my_mesh) - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / c0 - - print("Starting computation of the linear wave system with an UPWIND explicit scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ) - print() - - for k in range(nbCells): - pressure_field[k]=U[k,0] - velocity_field[k,0]=U[k,1]/rho0 - - pressure_field.setTime(time,it); - pressure_field.writeCSV("WaveSystem1DUpwind_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeCSV("WaveSystem1DUpwind_velocity"); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "|| Un+1 - Un || : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ) - print() - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) - raise ValueError("Maximum number of time steps reached : Stationary state not found !!!!!!!") - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) - for k in range(nbCells): - pressure_field[k]=U[k,0] - velocity_field[k,0]=U[k,1]/rho0 - - pressure_field.setTime(time,0); - pressure_field.writeCSV("WaveSystem1DUpwind_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeCSV("WaveSystem1DUpwind_velocity_Stat"); - - else: - print( "Temps maximum Tmax= ", tmax, " atteint" ) - raise ValueError("Maximum time reached : Stationary state not found !!!!!!!") - - -def solve(my_mesh,resolution): - print("Resolution of the 1D Riemann problem for the Wave system with Upwind explicit scheme:") - - # Problem data - tmax = 1. - ntmax = 100 - cfl = 0.95 - output_freq = 10 - - WaveSystem1DVF(ntmax, tmax, cfl, my_mesh, output_freq,resolution) - -if __name__ == """__main__""": - - xinf=0 - xsup=1 - - M=cdmath.Mesh(xinf,xsup,10) - - solve(M,100) diff --git a/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt deleted file mode 100755 index 51c6c6b..0000000 --- a/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ - - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleWaveSystem_1DUpwind_RiemannProblem ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem1DUpwind_RiemannProblem.py) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py b/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py deleted file mode 100755 index ad3f8d6..0000000 --- a/CDMATH/tests/examples/WaveSystem1DUpwind_RiemannProblem/WaveSystem1DUpwind_RiemannProblem.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -import cdmath -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as manimation -import sys - -p0=155.e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_Riemann_problem(a,b,nx): - print( "Initial data Riemann problem" ) - - dx = (b - a) / nx #space step - x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh) - - u_initial = [ 0 ]*nx - p_initial = [ (xi<(a+b)/2)*p0 + (xi>=(a+b)/2)*p0/2 for xi in x] - - return p_initial, u_initial - -def jacobianMatrices(coeff,scaling): - dim=1 - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - absA[0,0]=c0*coeff - for i in range(dim): - for j in range(dim): - absA[i+1,j+1]=c0*coeff - if( scaling==0): - A[0,i+1]=c0*c0*coeff - A[i+1,0]= coeff - elif( scaling==1): - A[0,i+1]= coeff - A[i+1,0]= coeff - else: - A[0,i+1]= c0*coeff - A[i+1,0]= c0*coeff - - return A,absA - - -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)*(1./2)) - implMat.addValue(j*nbComp, j*nbComp,(A-absA)*(-1./2)) - elif ( j==nbCells-1) : - implMat.addValue(j*nbComp, j*nbComp,(A+absA)*(1./2)) - implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)*(-1./2)) - else : - implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)*(1./2)) - implMat.addValue(j*nbComp, j*nbComp,(A-absA)*(-1./2)) - - implMat.addValue(j*nbComp, j*nbComp,(A+absA)*(1./2)) - implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)*(-1./2)) - - return implMat - -def WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName,scaling): - dim=1 - nbCells = nx - - dt = 0. - time = 0. - it=0; - isStationary=False - - dx=(b-a)/nx - dt = cfl * dx / c0 - - nbVoisinsMax=2 - - #iteration vectors - Un =cdmath.Vector(nbCells*(dim+1)) - dUn=cdmath.Vector(nbCells*(dim+1)) - - Un_implicite =cdmath.Vector(nbCells*(dim+1)) - dUn_implicite=cdmath.Vector(nbCells*(dim+1)) - - # Initial conditions # - print("Construction of the initial condition …") - pressure_field, velocity_field = initial_conditions_Riemann_problem(a,b,nx) - pressure_field_implicite, velocity_field_implicite = initial_conditions_Riemann_problem(a,b,nx) - max_initial_p=max(pressure_field) - min_initial_p=min(pressure_field) - max_initial_v=max(velocity_field) - min_initial_v=min(velocity_field) - - for k in range(nbCells): - Un[k*(dim+1)+0] = pressure_field[k] - Un[k*(dim+1)+1] =rho0*velocity_field[k] - Un_implicite[k*(dim+1)+0] = pressure_field_implicite[k] - Un_implicite[k*(dim+1)+1] =rho0*velocity_field_implicite[k] - - # Video settings - FFMpegWriter = manimation.writers['ffmpeg'] - metadata = dict(title="Finite volumes schemes for the 2D Wave System", artist = "CEA Saclay", comment="Shock propagation") - writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264') - with writer.saving(plt.figure(), "2DWaveSystem_Upwind"+".mp4", ntmax): - #sauvegarde de la donnée initiale - plt.xlabel('x (m)') - plt.ylabel('Pressure -Pa)') - plt.xlim(a,b) - plt.ylim( min_initial_p - 0.1*(max_initial_p-min_initial_p), max_initial_p + 0.1*(max_initial_p-min_initial_p) ) - plt.title("Riemann problem for Wave system on " + str(nx) + " cells") - line1, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field, label='Explicit upwind scheme') #new picture for video # Returns a tuple of line objects, thus the comma - line3, = plt.plot([a+0.5*dx + i*dx for i in range(nx)], pressure_field_implicite, label='Implicit upwind scheme') #new picture for video # Returns a tuple of line objects, thus the comma - plt.legend() - writer.grab_frame() - np.savetxt( "WaveSystem"+str(dim)+"DUpwindExplicit"+meshName+"_pressure"+"_0"+".txt", pressure_field, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DUpwindExplicit"+meshName+"_velocity"+"_0"+".txt", velocity_field, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DUpwindImplicit"+meshName+"_pressure"+"_0"+".txt", pressure_field_implicite, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DUpwindImplicit"+meshName+"_velocity"+"_0"+".txt", velocity_field_implicite, delimiter="\n") - plt.savefig("WaveSystem"+str(dim)+"DUpwind" +meshName+"_pressure"+"_0"+".png") - - divMat=computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) - divMat_implicit=computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling) - - iterGMRESMax=50 - - divMat_implicit.diagonalShift(1)#only after filling all coefficients - if( scaling==0): - LS=cdmath.LinearSolver(divMat_implicit,Un,iterGMRESMax, precision, "GMRES","ILU") - else: - LS=cdmath.LinearSolver(divMat_implicit,Vn,iterGMRESMax, precision, "GMRES","ILU") - - print("Starting computation of the linear wave system with an upwind scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations" ) - - np.savetxt("WaveSystem" +str(dim)+"DUpwindExplicit"+meshName+"_pressure"+str(it)+".txt", pressure_field , delimiter="\n") - np.savetxt("WaveSystem" +str(dim)+"DUpwindExplicit"+meshName+"_velocity"+str(it)+".txt", velocity_field , delimiter="\n") - np.savetxt("WaveSystem" +str(dim)+"DUpwindImplicit"+meshName+"_pressure"+str(it)+".txt", pressure_field , delimiter="\n") - np.savetxt("WaveSystem" +str(dim)+"DUpwindImplicit"+meshName+"_velocity"+str(it)+".txt", velocity_field , delimiter="\n") - plt.savefig("WaveSystem"+str(dim)+"DUpwind" +meshName+"_pressure"+str(it)+".png") - - print() - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) - return - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) - print( "------------------------------------------------------------------------------------") - - np.savetxt( "WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat.txt", pressure_field, delimiter="\n") - np.savetxt( "WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat.txt", velocity_field, delimiter="\n") - plt.savefig("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat.png") - - return - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - return - - -def solve( a,b,nx, meshName, scaling, meshType, cfl): - - print( "Resolution of the Wave system in dimension 1 on "+str(nx)+ " cells, upwind scheme") - print( "Initial data : ", "Riemann problem") - print( "Boundary conditions : ", "Neumann") - print( "Mesh name : ",meshName , ", ", nx, " cells") - - # Problem data - tmax = 10000. - ntmax = 50 - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, a,b,nx, output_freq, meshName, scaling) - - return - - -if __name__ == """__main__""": - a=0. - b=1. - nx=100 - cfl=0.99 - scaling=0 - solve( a,b,nx,"SquareRegularSquares",scaling,"RegularSquares",cfl) diff --git a/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt deleted file mode 100755 index fdc4fc0..0000000 --- a/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ - -SET(MESH_MED - ../../ressources/squareWithTriangles.med - ../../ressources/squareWithSquares.med - ../../ressources/squareWithBrickWall.med - ../../ressources/squareWithCheckerboardSquares.med - ../../ressources/squareWithDeformedQuadrangles.med - ../../ressources/squareWithHexagons.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(IMPLICIT_SCHEME 0 ) - - SET(MESH_FILE ../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithBrickWall.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithCheckerboardSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithDeformedQuadrangles.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_deformedQuadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindExplicit_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(IMPLICIT_SCHEME 1 ) - - SET(MESH_FILE ../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithBrickWall.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_brickwall ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithCheckerboardSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_checkerboard ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithDeformedQuadrangles.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_deformedQuadrangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../ressources/squareWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DRiemannProblem_UpwindImplicit_SQUARE_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py deleted file mode 100755 index 9d3abde..0000000 --- a/CDMATH/tests/examples/WaveSystem2DUpwind_RiemannProblem/WaveSystemUpwind.py +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc droite -# Utilisation du schéma upwind explicite ou implicite sur un maillage général -# Initialisation par une discontinuité verticale -# Conditions aux limites de Neumann -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sin, cos, pi, sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_RiemannProblem(my_mesh): - print( "Initial data : Riemann problem" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - xcentre = 0 - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - if x < xcentre: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - -def jacobianMatrices(normal,coeff): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - absA[0,0]=c0*coeff - for i in range(dim): - A[i+1,0]= normal[i]*coeff - A[0,i+1]=c0*c0*normal[i]*coeff - for j in range(dim): - absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff - - return (A - absA)*(1./2) - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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 cell number") - - implMat.addValue(j*nbComp,cellAutre*nbComp,Am) - implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - - return implMat - -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) - - SumFluxes = cdmath.Field("Fluxes", cdmath.CELLS, my_mesh, dim+1) - - # Initial conditions # - print("Construction of the initial condition …") - pressure_field, velocity_field = initial_conditions_RiemannProblem(my_mesh) - - #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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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 explicit UPWIND scheme …") - - # Starting time loop - while (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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - - -def solve(my_mesh,filename,resolution, isImplicit): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : upwind") - print( "Initial data : single straight discontinuity (Riemann problem)") - print( "Neumann boundary conditions") - print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") - - # Problem data - tmax = 1. - ntmax = 50 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) - -def solve_file( filename,resolution, isImplicit): - my_mesh = cdmath.Mesh(filename+".med") - solve(my_mesh, filename,resolution, isImplicit) - -if __name__ == """__main__""": - if len(sys.argv) >2 : - filename=sys.argv[1] - isImplicit=bool(int(sys.argv[2])) - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100, isImplicit) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt deleted file mode 100755 index 1a18ab0..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemCentered) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_Centered_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_Centered_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshHexagonWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_Centered_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py deleted file mode 100755 index 95fa24f..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemCentered/WaveSystemCentered.py +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc sphérique -# Utilisation du schéma centré (implicite) sur un maillage général -# Initialisation par une surpression sphérique -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sqrt -from numpy import sign -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_shock(my_mesh, isCircle): - print( "Initial data : Spherical wave" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - rayon = 0.15 - if(not isCircle): - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - else: - xcentre = 0. - ycentre = 0. - zcentre = 0. - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - x = my_mesh.getCell(i).x() - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val = sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - -def jacobianMatrices(normal, coeff, signun): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - - for i in range(dim): - A[i+1,0]=normal[i]*coeff - A[0,i+1]=c0*c0*normal[i]*coeff - - return A*(1./2) - - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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) - - v0=cdmath.Vector(dim) - for i in range(dim) : - v0[i] = 1. - - 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 - - signun=sign(normal*v0) - Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); - - 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - meshName=my_mesh.getName() - - dt = 0. - time = 0. - it=0; - isStationary=False; - - 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(dim==1 or 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_shock(my_mesh,False) - elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): - pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) - else: - print( "Mesh name : ", filename ) - raise ValueError("Mesh name should contain substring square, cube, Hexagon or disk") - - for k in range(nbCells): - Un[k*(dim+1)+0] = pressure_field[k] - Un[k*(dim+1)+1] = rho0*velocity_field[k,0] - if(dim>=2): - Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face - if(dim==3): - Un[k + 3*nbCells] = rho0*velocity_field[k,2] - - #sauvegarde de la donnée initiale - pressure_field.setTime(time,it); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"); - #Postprocessing : save 2D picture - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_initial") - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_initial") - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / c0 - - divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) - - # 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 a centered scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) - - 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)+"DCentered"+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity",False); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print() - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" ) - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time ) - print( "------------------------------------------------------------------------------------" ) - - pressure_field.setTime(time,0); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"); - - #Postprocessing : save 2D picture - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat") - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint" ) - - -def solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : implicit centered") - print( "Initial data : spherical wave") - print( "Wall boundary conditions") - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells") - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - filename=sys.argv[1] - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt deleted file mode 100755 index 2f349fd..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemPStag) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_PStag_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_PStag_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshHexagonWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_PStag_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py deleted file mode 100755 index 1130af8..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemPStag/WaveSystemPStag.py +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc sphérique -# Utilisation du schéma MAC sur un maillage cartésien -# Initialisation par une surpression sphérique -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sqrt -from numpy import sign -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_shock(my_mesh, isCircle): - print( "Initial data : Spherical wave" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - rayon = 0.15 - if(not isCircle): - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - else: - xcentre = 0. - ycentre = 0. - zcentre = 0. - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - x = my_mesh.getCell(i).x() - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val = sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - -def jacobianMatrices(normal, coeff, signun): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - for i in range(dim): - A[i+1,0]=normal[i]*coeff - absA[i+1,0]=-signun*A[i+1,0] - A[0,i+1]=c0*c0*normal[i]*coeff - absA[0,i+1]=signun*A[0,i+1] - - return (A-absA)*(1./2) - - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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) - - v0=cdmath.Vector(dim) - for i in range(dim) : - v0[i] = 1. - - 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 - - signun=sign(normal*v0) - Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); - - 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - meshName=my_mesh.getName() - - dt = 0. - time = 0. - it=0; - isStationary=False; - - 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(dim==1 or 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_shock(my_mesh,False) - elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): - pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) - else: - print( "Mesh name : ", filename ) - raise ValueError("Mesh name should contain substring square, cube, Hexagon or disk") - - for k in range(nbCells): - Un[k*(dim+1)+0] = pressure_field[k] - Un[k*(dim+1)+1] = rho0*velocity_field[k,0] - if(dim>=2): - Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face - if(dim==3): - Un[k + 3*nbCells] = rho0*velocity_field[k,2] - - #sauvegarde de la donnée initiale - pressure_field.setTime(time,it); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity"); - #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+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_initial") - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / c0 - - divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) - - # 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 or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) - - 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)+"DPStag"+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity",False); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0) - print() - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print( "------------------------------------------------------------------------------------") - - pressure_field.setTime(time,0); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat"); - - #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+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint" ) - - -def solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : implicit pseudo staggered" ) - print( "Initial data : spherical wave" ) - print( "Wall boundary conditions" ) - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - filename=sys.argv[1] - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt deleted file mode 100755 index 5fc4636..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleWaveSystem_2DShock_Staggered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemStaggered.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py deleted file mode 100755 index 752c378..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemStaggered/WaveSystemStaggered.py +++ /dev/null @@ -1,367 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc sphérique -# Utilisation du schéma MAC sur un maillage cartésien -# Initialisation par une surpression sphérique -# Conditions aux limites périodiques -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_shock(my_mesh, isCircle): - print( "Initial data : Spherical wave") - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - rayon = 0.15 - if(not isCircle): - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - else: - xcentre = 0. - ycentre = 0. - zcentre = 0. - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - x = my_mesh.getCell(i).x() - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val = sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling): - nbCells = my_mesh.getNumberOfCells() - dim=my_mesh.getMeshDimension() - nbComp=dim+1 - - if(not my_mesh.isStructured()): - raise ValueError("WaveSystemStaggered: the mesh should be structured"); - - NxNyNz=my_mesh.getCellGridStructure() - DxDyDz=my_mesh.getDXYZ() - - implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) - - idMoinsJacCL=cdmath.Matrix(nbComp) - - if( dim == 1) : - nx=NxNyNz[0] - dx=DxDyDz[0] - - if( scaling==0 ): - for k in range(nbCells): - implMat.addValue(k,1*nbCells + k , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + (k+1)%nx, c0*c0*dt/dx) - - implMat.addValue( 1*nbCells + k ,k, dt/dx) - implMat.addValue( 1*nbCells + (k+1)%nx,k, -dt/dx) - else : # scaling >0 - for k in range(nbCells): - implMat.addValue(k,1*nbCells + k , -c0*dt/dx) - implMat.addValue(k,1*nbCells + (k+1)%nx, c0*dt/dx) - - implMat.addValue( 1*nbCells + k ,k, c0*dt/dx) - implMat.addValue( 1*nbCells + (k+1)%nx,k, -c0*dt/dx) - - elif( dim == 2) :# k = j*nx+i - nx=NxNyNz[0] - ny=NxNyNz[1] - dx=DxDyDz[0] - dy=DxDyDz[1] - - if( scaling==0 ): - for k in range(nbCells): - i = k % nx - j = k //nx - - implMat.addValue(k,1*nbCells + j*nx + i , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*c0*dt/dx) - - implMat.addValue(k,2*nbCells + j *nx + i, -c0*c0*dt/dy) - implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*c0*dt/dy) - - implMat.addValue( 1*nbCells + j*nx + i , k, dt/dx) - implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -dt/dx) - - implMat.addValue( 2*nbCells + j *nx + i,k, dt/dy) - implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -dt/dy) - - else :# scaling >0 - for k in range(nbCells): - i = k % nx - j = k //nx - - implMat.addValue(k,1*nbCells + j*nx + i , -c0*dt/dx) - implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*dt/dx) - - implMat.addValue(k,2*nbCells + j *nx + i, -c0*dt/dy) - implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*dt/dy) - - implMat.addValue( 1*nbCells + j*nx + i , k, c0*dt/dx) - implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -c0*dt/dx) - - implMat.addValue( 2*nbCells + j *nx + i,k, c0*dt/dy) - implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -c0*dt/dy) - - elif( dim == 3) :# k = l*nx*ny+j*nx+i - nx=NxNyNz[0] - ny=NxNyNz[1] - nz=NxNyNz[2] - dx=DxDyDz[0] - dy=DxDyDz[1] - dz=DxDyDz[2] - - if( scaling==0 ): - for k in range(nbCells): - i = k % nx - j = (k //nx)%ny - l = k //(nx*ny) - - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*c0*dt/dx) - - implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*c0*dt/dy) - implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*c0*dt/dy) - - implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*c0*dt/dz) - implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*c0*dt/dz) - - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, dt/dx) - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -dt/dx) - - implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, dt/dy) - implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -dt/dy) - - implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, dt/dz) - implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -dt/dz) - - else:# scaling >0 - for k in range(nbCells): - i = k % nx - j = (k //nx)%ny - l = k //(nx*ny) - - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*dt/dx) - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*dt/dx) - - implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*dt/dy) - implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*dt/dy) - - implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*dt/dz) - implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*dt/dz) - - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, c0*dt/dx) - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -c0*dt/dx) - - implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, c0*dt/dy) - implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -c0*dt/dy) - - implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, c0*dt/dz) - implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -c0*dt/dz) - - return implMat - -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 …") - if(dim==1 or 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_shock(my_mesh,False) - elif(meshName.find("disk")>-1 or meshName.find("Disk")>-1): - pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) - else: - print( "Mesh name : ", meshName ) - raise ValueError("Mesh name should contain substring square, cube or disk") - - 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 - if(dim>=2): - Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face - if(dim==3): - Un[k + 3*nbCells] = rho0*velocity_field[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 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 solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : staggered scheme" ) - print( "Initial data : Spherical wave" ) - print( "Periodic boundary conditions" ) - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - my_mesh = cdmath.Mesh(sys.argv[1]) - solve(my_mesh,my_mesh.getName(),100) - else : - nx=50 - my_mesh = cdmath.Mesh(0,1,nx,0,1,nx) - solve(my_mesh,"square",100) diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt deleted file mode 100755 index 5b36455..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(IMPLICIT_SCHEME 0 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshHexagonWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindExplicit_HEXAGON_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(IMPLICIT_SCHEME 1 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DShock_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DShock_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py deleted file mode 100755 index 10b55c9..0000000 --- a/CDMATH/tests/examples/WaveSystem_Shock/WaveSystemUpwind/WaveSystemUpwind.py +++ /dev/null @@ -1,290 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Propagation d'une onde de choc sphérique -# Utilisation du schéma upwind explicite ou implicite sur un maillage général -# Initialisation par une surpression sphérique -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_shock(my_mesh, isCircle): - print( "Initial data : Spherical wave" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - rayon = 0.15 - if(not isCircle):#Case of a square domain - xcentre = 0.5 - ycentre = 0.5 - zcentre = 0.5 - else:#Case of a disk or a hexagonal domain - xcentre = 0. - ycentre = 0. - zcentre = 0. - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - velocity_field[i,0] = 0 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - - x = my_mesh.getCell(i).x() - valX = (x - xcentre) * (x - xcentre) - - if(dim==1): - val = sqrt(valX) - if(dim==2): - y = my_mesh.getCell(i).y() - valY = (y - ycentre) * (y - ycentre) - val = sqrt(valX + valY) - if(dim==3): - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - valY = (y - ycentre) * (y - ycentre) - valZ = (z - zcentre) * (z - zcentre) - val = sqrt(valX + valY + valZ) - - if val < rayon: - pressure_field[i] = p0 - pass - else: - pressure_field[i] = p0/2 - pass - pass - - return pressure_field, velocity_field - -def jacobianMatrices(normal,coeff): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - absA[0,0]=c0*coeff - for i in range(dim): - A[i+1,0]= normal[i]*coeff - A[0,i+1]=c0*c0*normal[i]*coeff - for j in range(dim): - absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff - - return (A - absA)*(1./2) - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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 cell number") - - implMat.addValue(j*nbComp,cellAutre*nbComp,Am) - implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - else : - if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -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(dim==1 or 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_shock(my_mesh,False) - elif(filename.find("disk")>-1 or filename.find("Disk")>-1 or filename.find("Hexagon")>-1): - pressure_field, velocity_field = initial_conditions_shock(my_mesh,True) - else: - print( "Mesh name : ", filename ) - raise ValueError("Mesh name should contain substring square, cube, hexagon 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] - if(dim>=2): - Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face - if(dim==3): - Un[k + 3*nbCells] = rho0*velocity_field[k,2] - - #sauvegarde de la donnée initiale - pressure_field.setTime(time,it); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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 explicit UPWIND scheme …") - - # Starting time loop - while (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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+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"+"_isImplicit"+str(isImplicit)+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - - -def solve(my_mesh,filename,resolution, isImplicit): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : upwind" ) - print( "Initial data : spherical wave" ) - print( "Wall boundary conditions" ) - print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells" ) - - # Problem data - tmax = 1. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 1 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) - -def solve_file( filename,resolution, isImplicit): - my_mesh = cdmath.Mesh(filename+".med") - solve(my_mesh, filename,resolution, isImplicit) - -if __name__ == """__main__""": - if len(sys.argv) >2 : - filename=sys.argv[1] - isImplicit=bool(int(sys.argv[2])) - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100, isImplicit) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt deleted file mode 100755 index d54c556..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemCentered) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_Centered_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_Centered_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_Centered_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemCentered.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py deleted file mode 100755 index c6c6fa8..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemCentered/WaveSystemCentered.py +++ /dev/null @@ -1,300 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Test de préservation d'un état stationnaire -# Utilisation du schéma centré (implicite) sur un maillage général -# Initialisation par un vortex stationnaire -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sin, cos, pi, sqrt -from numpy import sign -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_disk_vortex(my_mesh): - print( "Disk vortex initial data") - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - if(dim!=2): - raise ValueError("Wave system on disk : mesh dimension should be 2") - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - - pressure_field[i] = p0 - - velocity_field[i,0] = -y - velocity_field[i,1] = x - velocity_field[i,2] = 0 - - return pressure_field, velocity_field - -def initial_conditions_square_vortex(my_mesh): - print( "Initial data : Square vortex (Constant pressure, divergence free velocity)") - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - - pressure_field[i] = p0 - if(dim==1): - velocity_field[i,0] = 1 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - elif(dim==2): - velocity_field[i,0] = sin(pi*x)*cos(pi*y) - velocity_field[i,1] = -sin(pi*y)*cos(pi*x) - velocity_field[i,2] = 0 - elif(dim==3): - velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) - velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) - velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) - - return pressure_field, velocity_field - -def jacobianMatrices(normal, coeff, signun): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - - for i in range(dim): - A[i+1,0]=normal[i]*coeff - A[0,i+1]=c0*c0*normal[i]*coeff - - return A*(1./2) - - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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) - - v0=cdmath.Vector(dim) - for i in range(dim) : - v0[i] = 1. - - 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 - - signun=sign(normal*v0) - Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); - - 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - meshName=my_mesh.getName() - - dt = 0. - time = 0. - it=0; - isStationary=False; - - 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(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 or filename.find("Hexagon")>-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, Hexagon or disk") - - 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)+"DCentered"+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"); - #Postprocessing : save 2D picture - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_initial") - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_initial") - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / c0 - - divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) - - # 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 a centered scheme …") - - # Starting time loop - while (it=ntmax or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print( "Linear system converged in ", iterGMRES, " GMRES iterations") - - 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)+"DCentered"+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity",False); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print() - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print( "------------------------------------------------------------------------------------") - - pressure_field.setTime(time,0); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"); - - #Postprocessing : save 2D picture - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_pressure_Stat") - PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DCentered"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - - -def solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() ) - print( "Numerical method : implicit centered" ) - print( "Initial data : stationary solution (constant pressure, divergence free velocity)" ) - print( "Wall boundary conditions" ) - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 100 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - filename=sys.argv[1] - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt deleted file mode 100755 index 3aa9d62..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemPStag) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_PStag_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_PStag_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_PStag_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemPStag.py ${MESH_FILE}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py deleted file mode 100755 index f73e2b4..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemPStag/WaveSystemPStag.py +++ /dev/null @@ -1,303 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Test de préservation d'un état stationnaire -# Utilisation du schéma pseudo décalé (implicite) sur un maillage général -# Initialisation par un vortex stationnaire -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sin, cos, pi, sqrt -from numpy import sign -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_disk_vortex(my_mesh): - print( "Disk vortex initial data" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - if(dim!=2): - raise ValueError("Wave system on disk : mesh dimension should be 2") - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - - pressure_field[i] = p0 - - velocity_field[i,0] = -y - velocity_field[i,1] = x - velocity_field[i,2] = 0 - - return pressure_field, velocity_field - -def initial_conditions_square_vortex(my_mesh): - print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - - pressure_field[i] = p0 - if(dim==1): - velocity_field[i,0] = 1 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - elif(dim==2): - velocity_field[i,0] = sin(pi*x)*cos(pi*y) - velocity_field[i,1] = -sin(pi*y)*cos(pi*x) - velocity_field[i,2] = 0 - elif(dim==3): - velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) - velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) - velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) - - return pressure_field, velocity_field - -def jacobianMatrices(normal, coeff, signun): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - for i in range(dim): - A[i+1,0]=normal[i]*coeff - absA[i+1,0]=-signun*A[i+1,0] - A[0,i+1]=c0*c0*normal[i]*coeff - absA[0,i+1]=signun*A[0,i+1] - - return (A-absA)*(1./2) - - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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) - - v0=cdmath.Vector(dim) - for i in range(dim) : - v0[i] = 1. - - 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 - - signun=sign(normal*v0) - Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure(),signun); - - 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( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution): - dim=my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - meshName=my_mesh.getName() - - dt = 0. - time = 0. - it=0; - isStationary=False; - - 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(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") - - 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)+"DPStag"+meshName+"_pressure"); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity"); - #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+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_initial") - - dx_min=my_mesh.minRatioVolSurf() - - dt = cfl * dx_min / c0 - - divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) - - # 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 or isStationary or time >=tmax): - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print( "Linear system converged in ", iterGMRES, " GMRES iterations" ) - - 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)+"DPStag"+meshName+"_pressure",False); - velocity_field.setTime(time,it); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity",False); - - print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) ) - print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 ) - print() - - if(it>=ntmax): - print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint") - elif(isStationary): - print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time) - print( "------------------------------------------------------------------------------------") - - pressure_field.setTime(time,0); - pressure_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_pressure_Stat"); - velocity_field.setTime(time,0); - velocity_field.writeVTK("WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat"); - - #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+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DPStag"+meshName+"_velocity_Stat") - - else: - print( "Temps maximum Tmax= ", tmax, " atteint") - - -def solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) - print( "Numerical method : implicit pseudo staggered") - print( "Initial data : stationary solution (constant pressure, divergence free velocity)") - print( "Wall boundary conditions") - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" ) - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 100 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, filename+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - filename=sys.argv[1] - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name") diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt deleted file mode 100755 index c30f344..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - ADD_TEST(ExampleWaveSystem_2DVortex_Staggered_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemStaggered.py ) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py deleted file mode 100755 index 092ab28..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemStaggered/WaveSystemStaggered.py +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Test de préservation d'un état stationnaire -# Utilisation du schéma MAC sur un maillage cartésien -# Initialisation par un vortex stationnaire -# Conditions aux limites périodiques -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sin, cos, pi, sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_square_vortex(my_mesh): - print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - - pressure_field[i] = p0 - if(dim==1): - velocity_field[i,0] = 1 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - elif(dim==2): - velocity_field[i,0] = sin(pi*x)*cos(pi*y) - velocity_field[i,1] = -sin(pi*y)*cos(pi*x) - velocity_field[i,2] = 0 - elif(dim==3): - velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) - velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) - velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) - - return pressure_field, velocity_field - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling): - nbCells = my_mesh.getNumberOfCells() - dim=my_mesh.getMeshDimension() - nbComp=dim+1 - - if(not my_mesh.isStructured()): - raise ValueError("WaveSystemStaggered: the mesh should be structured"); - - NxNyNz=my_mesh.getCellGridStructure() - DxDyDz=my_mesh.getDXYZ() - - implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp) - - idMoinsJacCL=cdmath.Matrix(nbComp) - - if( dim == 1) : - nx=NxNyNz[0] - dx=DxDyDz[0] - - if( scaling==0 ): - for k in range(nbCells): - implMat.addValue(k,1*nbCells + k , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + (k+1)%nx, c0*c0*dt/dx) - - implMat.addValue( 1*nbCells + k ,k, dt/dx) - implMat.addValue( 1*nbCells + (k+1)%nx,k, -dt/dx) - else : # scaling >0 - for k in range(nbCells): - implMat.addValue(k,1*nbCells + k , -c0*dt/dx) - implMat.addValue(k,1*nbCells + (k+1)%nx, c0*dt/dx) - - implMat.addValue( 1*nbCells + k ,k, c0*dt/dx) - implMat.addValue( 1*nbCells + (k+1)%nx,k, -c0*dt/dx) - - elif( dim == 2) :# k = j*nx+i - nx=NxNyNz[0] - ny=NxNyNz[1] - dx=DxDyDz[0] - dy=DxDyDz[1] - - if( scaling==0 ): - for k in range(nbCells): - i = k % nx - j = k //nx - - implMat.addValue(k,1*nbCells + j*nx + i , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*c0*dt/dx) - - implMat.addValue(k,2*nbCells + j *nx + i, -c0*c0*dt/dy) - implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*c0*dt/dy) - - implMat.addValue( 1*nbCells + j*nx + i , k, dt/dx) - implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -dt/dx) - - implMat.addValue( 2*nbCells + j *nx + i,k, dt/dy) - implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -dt/dy) - - else :# scaling >0 - for k in range(nbCells): - i = k % nx - j = k //nx - - implMat.addValue(k,1*nbCells + j*nx + i , -c0*dt/dx) - implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*dt/dx) - - implMat.addValue(k,2*nbCells + j *nx + i, -c0*dt/dy) - implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*dt/dy) - - implMat.addValue( 1*nbCells + j*nx + i , k, c0*dt/dx) - implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -c0*dt/dx) - - implMat.addValue( 2*nbCells + j *nx + i,k, c0*dt/dy) - implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -c0*dt/dy) - - elif( dim == 3) :# k = l*nx*ny+j*nx+i - nx=NxNyNz[0] - ny=NxNyNz[1] - nz=NxNyNz[2] - dx=DxDyDz[0] - dy=DxDyDz[1] - dz=DxDyDz[2] - - if( scaling==0 ): - for k in range(nbCells): - i = k % nx - j = (k //nx)%ny - l = k //(nx*ny) - - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*c0*dt/dx) - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*c0*dt/dx) - - implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*c0*dt/dy) - implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*c0*dt/dy) - - implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*c0*dt/dz) - implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*c0*dt/dz) - - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, dt/dx) - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -dt/dx) - - implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, dt/dy) - implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -dt/dy) - - implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, dt/dz) - implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -dt/dz) - - else:# scaling >0 - for k in range(nbCells): - i = k % nx - j = (k //nx)%ny - l = k //(nx*ny) - - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*dt/dx) - implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*dt/dx) - - implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*dt/dy) - implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*dt/dy) - - implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*dt/dz) - implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*dt/dz) - - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, c0*dt/dx) - implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -c0*dt/dx) - - implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, c0*dt/dy) - implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -c0*dt/dy) - - implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, c0*dt/dz) - implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -c0*dt/dz) - - return implMat - -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_square_vortex(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 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 solve(my_mesh,meshName,resolution): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) - print( "Numerical method : staggered scheme") - print( "Initial data : stationary solution (constant pressure, divergence free velocity)") - print( "Periodic boundary conditions") - print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells") - - # Problem data - tmax = 1000. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 100 - - WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution) - -def solve_file( filename,meshName, resolution): - my_mesh = cdmath.Mesh(filename+".med") - - return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution) - - -if __name__ == """__main__""": - if len(sys.argv) >1 : - my_mesh = cdmath.Mesh(sys.argv[1]) - solve(my_mesh,my_mesh.getName(),100) - else : - nx=50 - my_mesh = cdmath.Mesh(0,1,nx,0,1,nx) - solve(my_mesh,my_mesh.getName(),100) diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt deleted file mode 100755 index 376bb9d..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/CMakeLists.txt +++ /dev/null @@ -1,89 +0,0 @@ - -SET(MESH_MED - ../../../ressources/squareWithTriangles.med - ../../../ressources/meshCube.med - ../../../ressources/squareWithSquares.med - ../../../ressources/cubeWithCubes.med - ../../../ressources/diskWithTriangles.med - ../../../ressources/diskWithSquares.med - ../../../ressources/diskWithSpiderWeb.med - ../../../ressources/diskWithHexagons.med - ../../../ressources/ballWithTetrahedra.med - ) - -file(COPY ${MESH_MED} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(FILES ${MESH_MED} DESTINATION share/examples/WaveSystemUpwind) - -if (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - SET(IMPLICIT_SCHEME 0 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_UpwindExplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_UpwindExplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindExplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(IMPLICIT_SCHEME 0 ) - - SET(MESH_FILE ../../../ressources/meshSquare.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_SQUARE_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/squareWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_SQUARE_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/meshCube.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_UpwindImplicit_CUBE_tetrahedra ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/cubeWithCubes.med ) - - ADD_TEST(ExampleWaveSystem_3DVortex_UpwindImplicit_CUBE_cubes ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithTriangles.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_triangles ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSquares.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_squares ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithSpiderWeb.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_spiderWeb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - - SET(MESH_FILE ../../../ressources/diskWithHexagons.med ) - - ADD_TEST(ExampleWaveSystem_2DVortex_UpwindImplicit_DISK_hexagons ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/WaveSystemUpwind.py ${MESH_FILE} ${IMPLICIT_SCHEME}) - -endif (CDMATH_WITH_PYTHON AND CDMATH_WITH_PETSC AND CDMATH_WITH_POSTPRO) - - diff --git a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py b/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py deleted file mode 100755 index bb190e0..0000000 --- a/CDMATH/tests/examples/WaveSystem_Stationary/WaveSystemUpwind/WaveSystemUpwind.py +++ /dev/null @@ -1,292 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:utf-8 -* - -#=============================================================================================================================== -# Name : Résolution VF du système des ondes 2D sans terme source -# \partial_t p + c^2 \div q = 0 -# \partial_t q + \grad p = 0 -# Author : Michaël Ndjinga -# Copyright : CEA Saclay 2019 -# Description : Test de préservation d'un état stationnaire -# Utilisation du schéma upwind explicite ou implicite sur un maillage général -# Initialisation par une vortex stationnaire -# Conditions aux limites parois -# Création et sauvegarde du champ résultant et des figures -#================================================================================================================================ - - -from math import sin, cos, pi, sqrt -import cdmath -import PV_routines -import VTK_routines -import sys - -p0=155e5#reference pressure in a pressurised nuclear vessel -c0=700.#reference sound speed for water at 155 bars, 600K -rho0=p0/c0*c0#reference density -precision=1e-5 - -def initial_conditions_disk_vortex(my_mesh): - print( "Disk vortex initial data") - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - if(dim!=2): - raise ValueError("Wave system on disk : mesh dimension should be 2") - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - - pressure_field[i] = p0 - - velocity_field[i,0] = -y - velocity_field[i,1] = x - velocity_field[i,2] = 0 - - return pressure_field, velocity_field - -def initial_conditions_square_vortex(my_mesh): - print( "Initial data : Square vortex (Constant pressure, divergence free velocity)" ) - dim = my_mesh.getMeshDimension() - nbCells = my_mesh.getNumberOfCells() - - pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1) - velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3) - - for i in range(nbCells): - x = my_mesh.getCell(i).x() - y = my_mesh.getCell(i).y() - z = my_mesh.getCell(i).z() - - pressure_field[i] = p0 - if(dim==1): - velocity_field[i,0] = 1 - velocity_field[i,1] = 0 - velocity_field[i,2] = 0 - elif(dim==2): - velocity_field[i,0] = sin(pi*x)*cos(pi*y) - velocity_field[i,1] = -sin(pi*y)*cos(pi*x) - velocity_field[i,2] = 0 - elif(dim==3): - velocity_field[i,0] = sin(pi*x)*cos(pi*y)*cos(pi*z) - velocity_field[i,1] = sin(pi*y)*cos(pi*x)*cos(pi*z) - velocity_field[i,2] = -2*sin(pi*z)*cos(pi*x)*cos(pi*y) - - return pressure_field, velocity_field - -def jacobianMatrices(normal,coeff): - dim=normal.size() - A=cdmath.Matrix(dim+1,dim+1) - absA=cdmath.Matrix(dim+1,dim+1) - - absA[0,0]=c0*coeff - for i in range(dim): - A[i+1,0]= normal[i]*coeff - A[0,i+1]=c0*c0*normal[i]*coeff - for j in range(dim): - absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff - - return (A - absA)*(1./2) - -def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt): - 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 cell number") - - implMat.addValue(j*nbComp,cellAutre*nbComp,Am) - implMat.addValue(j*nbComp, j*nbComp,Am*(-1.)) - else : - if( Fk.getGroupName() != "Periodic" and Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Periodic/Neumann specified explicitly - 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( Fk.getGroupName() == "Periodic"):#Periodic boundary condition - 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(Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition - print( Fk.getGroupName() ) - raise ValueError("computeFluxes: Unknown boundary condition name"); - - return implMat - -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 …") - - # Starting time loop - while (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(my_mesh,filename,resolution, isImplicit): - print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension()) - print( "Numerical method : upwind") - print( "Initial data : stationary solution (constant pressure, divergence free velocity)") - print( "Wall boundary conditions") - print( "Mesh name : ",filename , my_mesh.getNumberOfCells(), " cells") - - # Problem data - tmax = 1. - ntmax = 100 - cfl = 1./my_mesh.getSpaceDimension() - output_freq = 100 - - WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit) - -def solve_file( filename,resolution): - my_mesh = cdmath.Mesh(filename+".med") - solve(my_mesh, filename,resolution, isImplicit) - -if __name__ == """__main__""": - if len(sys.argv) >2 : - filename=sys.argv[1] - isImplicit=bool(int(sys.argv[2])) - my_mesh = cdmath.Mesh(filename) - solve(my_mesh,filename,100, isImplicit) - else : - raise ValueError("WaveSystemUpwind.py expects a mesh file name and a boolean (isImplicit)") diff --git a/CDMATH/tests/examples/thermique1d/main.cxx b/CDMATH/tests/examples/thermique1d/main.cxx deleted file mode 100644 index b80f292..0000000 --- a/CDMATH/tests/examples/thermique1d/main.cxx +++ /dev/null @@ -1,335 +0,0 @@ -//============================================================================ -// Name : Thermique 1D Entrée sortie -// Author : M. Ndjinga -// Version : -// Copyright : CEA Saclay 2014 -// Description : Modélisation 1D d'un cœur de réacteur -//============================================================================ - -#include -#include -//#include - -//#include "Matrix.hxx" -#include "Vector.hxx" -#include "LinearSolver.hxx" -#include "Mesh.hxx" -#include "Field.hxx" -#include "Cell.hxx" -//#include "Face.hxx" -//#include "Node.hxx" -#include "CdmathException.hxx" - -using namespace std; - - -void champ_heaviside(Field& Temp, double milieu, double TempLeft, double TempRight) -{ - Mesh M=Temp.getMesh(); - int nbCells=M.getNumberOfCells(); - double x; - for (int j=0 ; jepsilon) - { - d= ScndMbre;//contiendra le second membre du système - /*cout<< " Debut itération d= "< e(n-1); - for(int i=0;i a(n-1,-1),b(n,2),c(n-1,-0.5); - Mesh M(0,1,n); - Field d("Test",CELLS,M,1); - int nbCells=M.getNumberOfCells(); - for(int i=0;i -#include - -#include "Cell.hxx" -#include "Mesh.hxx" -#include "Field.hxx" - -using namespace std; - - -int main( void ) -{ - double a=-5.0; - double b=5.0; - int nx=1000; - int ntmax=3; - double dx = (b-a)/nx; - double pi=3.1415927; - // Transport velocity - double cfl=0.5; - double u=3.; - double dt=cfl*dx/u; - - Mesh myMesh(a,b,nx); - - Field conc("Concentration",CELLS,myMesh,1); - - // Initial conditions - double sigma=sqrt(0.2); - for (int i=0 ; i -#include -#include - -#include "Mesh.hxx" -#include "Cell.hxx" -#include "Face.hxx" -#include "Field.hxx" - -using namespace std; - - -void conditions_initiales(Field& yField) -{ - double rayon=0.15; - double xcentre=0.25; - double ycentre=0.25; - Mesh myMesh=yField.getMesh(); - int nbCells=myMesh.getNumberOfCells(); - for (int j=0 ; j0 : rien a faire sinon inverser la gauche et la droite - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(cellAutre); - }else - { - /* conditions aux limites neumann homogene */ - if (Fk.getGroupName().compare("GAUCHE")==0 || Fk.getGroupName().compare("DROITE")==0) - { - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=0.0; - } - /* conditions aux limites periodiques */ - if (Fk.getGroupName().compare("BAS")==0 || Fk.getGroupName().compare("HAUT")==0) - { - int indexFP=indexFacesPerio[indexFace]; - /* une autre manière de recuperer l'index de la face periodique */ - //int indexFP=M.getIndexFacePeriodic(indexFace); - Face Fp=myMesh.getFace(indexFP); - int indexCp=Fp.getCellsId()[0]; - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(indexCp); - } - } - SumF=SumF+UN*LengthFk*conc; - } - dt=cfl*minlengthFk/normU; - SumFlux(j)=dt*SumF/Cj.getMeasure(); - } -} - -void EquationTransport2D(double tmax, double VitesseX, double VitesseY, double cfl, int freqSortie, const Mesh& myMesh, const string file) -{ - /* Initial conditions */ - cout << "Construction of the initial condition …" << endl; - Field yField("Y field",CELLS,myMesh,1) ; - conditions_initiales(yField); - - /* - * MED output of the initial condition at t=0 and iter = 0 - */ - int iter=0; - double time=0.; - cout << "Saving the solution at T=" << time << "…" << endl; - yField.setTime(time,iter); - yField.writeMED(file); - yField.writeVTK(file); - yField.writeCSV(file); - /* --------------------------------------------- */ - - /* Time loop */ - cout << "Resolution of the transport equation with an UPWIND scheme …" << endl; - int ntmax=3; - double dt; - IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); - while (iter0: nothing to do, else invert left and right - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = y_field[cellAutre] - pass - pass - else: - # homogeneous Neumann boundary conditions # - if (Fk.getGroupName() == "GAUCHE" or Fk.getGroupName() == "DROITE"): - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = 0.0 - pass - pass - # periodical boundary conditions # - if (Fk.getGroupName() == "BAS" or Fk.getGroupName() == "HAUT"): - indexFP = indexFacesPerio[indexFace] - # another way to get the index of the periodical face # - # int indexFP=my_mesh.getIndexFacePeriodic(indexFace); - Fp = my_mesh.getFace(indexFP) - indexCp = Fp.getCellsId()[0] - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = y_field[indexCp] - pass - pass - pass - SumF = SumF + UN * LengthFk * conc - pass - dt = cfl * minlengthFk / normU - SumFlux[j] = dt * SumF / Cj.getMeasure() - pass - return dt, SumFlux - - -def EquationTransport2D(tmax, VitesseX, VitesseY, cfl, freqSortie, my_mesh, output_filename): - - # Initial conditions # - print("Construction of the initial condition …") - y_field = initial_conditions(my_mesh) - # - # MED output of the initial condition at t=0 and iter = 0 - # - - it = 0 - time = 0. - print("Saving the solution at T=" + str(time) + "…") - y_field.setTime(time, it) - y_field.writeMED(output_filename) - y_field.writeVTK(output_filename) - y_field.writeCSV(output_filename) - - # Time loop # - print("Resolution of the transport equation with an UPWIND scheme…") - ntmax = 3 - indexFacesPerio = my_mesh.getIndexFacePeriodic() - dt = 0. - while (it < ntmax and time <= tmax): - dt, SumFlux = sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio) - print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) - - # Advancing one time step # - y_field -= SumFlux - time += dt - it += 1 - # Output every freq times - if (it % freqSortie == 0): - y_field.setTime(time, it) - y_field.writeMED(output_filename, False) - y_field.writeVTK(output_filename, False) - y_field.writeCSV(output_filename) - pass - pass - return - - -def main(): - print("Resolution of the 2D transport equation:") - print("- DOMAIN: SQUARE") - print("- MESH: TRIANGULAR, GENERATED WITH SALOME") - print("- PERIODICAL BC UP AND DOWN") - print("- HOMOGENEOUS NEUMANN BC LEFT AND RIGHT") - - # Problem data - cfl = 0.4 - VitesseX = 1.0 - VitesseY = 1.0 - tmax = 1. - freqSortie = 10 - - print("Loading triangular mesh …") - my_mesh = cdmath.Mesh("../../tests/ressources/meshSquare.med") - output_filename = "Exercice2PyTest" - EquationTransport2D(tmax, VitesseX, VitesseY, cfl, freqSortie, my_mesh, output_filename) - print("CDMATH calculation done.") - return - - -if __name__ == """__main__""": - main() diff --git a/CDMATH/tests/examples/transport2d_ns/main2.cxx b/CDMATH/tests/examples/transport2d_ns/main2.cxx deleted file mode 100644 index ff6845e..0000000 --- a/CDMATH/tests/examples/transport2d_ns/main2.cxx +++ /dev/null @@ -1,243 +0,0 @@ -//============================================================================ -// Author : Anouar MEKKAS -// Version : -// Description : Equation de transport lineaire 2D non structure -//============================================================================ - -#include -#include -#include - -#include "Mesh.hxx" -#include "Cell.hxx" -#include "Face.hxx" -#include "Field.hxx" - -using namespace std; - -struct parameters { - double cfl; - double VitesseX; - double VitesseY; - int freqSortie; - std::string outFile; -}; - -void conditions_initiales(Field& yField) -{ - double rayon=0.15; - double xcentre=0.25; - double ycentre=0.25; - Mesh myMesh=yField.getMesh(); - int nbCells=myMesh.getNumberOfCells(); - for (int j=0 ; j0 : rien a faire sinon inverser la gauche et la droite - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(cellAutre); - }else - { - /* conditions aux limites neumann homogene */ - if (Fk.getGroupName().compare("GAUCHE")==0 || Fk.getGroupName().compare("DROITE")==0) - { - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=0.0; - } - /* conditions aux limites periodiques */ - if (Fk.getGroupName().compare("BAS")==0 || Fk.getGroupName().compare("HAUT")==0) - { - int indexFP=indexFacesPerio[indexFace]; - /* une autre manière de recuperer l'index de la face periodique */ - //int indexFP=M.getIndexFacePeriodic(indexFace); - Face Fp=myMesh.getFace(indexFP); - int indexCp=Fp.getCellsId()[0]; - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(indexCp); - } - } - SumF=SumF+UN*LengthFk*conc; - } - dt=p.cfl*minlengthFk/normU; - SumFlux(j)=dt*SumF/Cj.getMeasure(); - } -} - -void EquationTransport2D(int &iter, double tmin, double & tmax, - const parameters & p, Field & yField) -{ - - /* - * MED output of the initial condition at t=0 and iter = 0 - */ - double time=tmin; - const Mesh& myMesh = yField.getMesh(); - - yField.setTime(time,iter); - yField.writeMED(p.outFile,true); - yField.writeVTK(p.outFile); - yField.writeCSV(p.outFile); - /* --------------------------------------------- */ - - /* Time loop */ - cout << "Resolution of the transport equation with an UPWIND scheme…" << endl; - int ntmax=3 + iter; - double dt; - IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); - while (iter -#include -#include - -#include "Mesh.hxx" -#include "Cell.hxx" -#include "Face.hxx" -#include "Field.hxx" - -using namespace std; - - -void initial_conditions(Field& yField) -{ - double rayon=0.15; - double xcentre=0.25; - double ycentre=0.25; - Mesh myMesh=yField.getMesh(); - int nbCells=myMesh.getNumberOfCells(); - for (int j=0 ; j0, then nothing to do, else invert left and right - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(cellAutre); - }else - { - /* Homogeneous Neumann boundary conditions */ - if (Fk.getGroupName().compare("LeftEdge")==0 || Fk.getGroupName().compare("RightEdge")==0) - { - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=0.0; - } - /* Periodic boundary conditions */ - if (Fk.getGroupName().compare("BottomEdge")==0 || Fk.getGroupName().compare("TopEdge")==0) - { - int indexFP=indexFacesPerio[indexFace]; - /* une autre manière de recuperer l'index de la face periodique */ - //int indexFP=myMesh.getIndexFacePeriodic(indexFace); - Face Fp=myMesh.getFace(indexFP); - int indexCp=Fp.getCellsId()[0]; - if (UN>1.E-15) - conc=yField(cellCourante); - else - conc=yField(indexCp); - } - } - SumF=SumF+UN*LengthFk*conc; - } - dt=cfl*minlengthFk/normU; - SumFlux(j)=dt*SumF/Cj.getMeasure(); - } -} - -void EquationTransport2D(double tmax, double VitesseX, double VitesseY, double cfl, int freqSortie, const Mesh& myMesh, const string file) -{ - /* Initial conditions */ - cout << "Construction of the initial condition …" << endl; - Field yField("Y field",CELLS,myMesh,1) ; - initial_conditions(yField); - - /* - * MED output of the initial condition at t=0 and iter = 0 - */ - int iter=0; - double time=0.; - cout << "Saving the solution at T=" << time << "…" << endl; - yField.setTime(time,iter); - yField.writeMED(file); - yField.writeVTK(file); - yField.writeCSV(file); - /* --------------------------------------------- */ - - /* Time loop */ - cout << "Resolution of the transport equation with an UPWIND scheme …" << endl; - int ntmax=3; - double dt; - IntTab indexFacesPerio=myMesh.getIndexFacePeriodic(); - while (iter0 : rien a faire sinon inverser la gauche et la droite - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = y_field[cellAutre] - pass - pass - else: - # conditions aux limites neumann homogene # - if (Fk.getGroupName() == "LeftEdge" or Fk.getGroupName() == "RightEdge"): - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = 0.0 - pass - pass - # conditions aux limites periodiques # - if (Fk.getGroupName() == "BottomEdge" or Fk.getGroupName() == "TopEdge"): - indexFP = indexFacesPerio[indexFace] - # une autre manière de recuperer l'index de la face periodique # - # int indexFP=my_mesh.getIndexFacePeriodic(indexFace); - Fp = my_mesh.getFace(indexFP) - indexCp = Fp.getCellsId()[0] - if (UN > 1.E-15): - conc = y_field[cellCourante] - pass - else: - conc = y_field[indexCp] - pass - pass - pass - SumF = SumF + UN * LengthFk * conc - pass - dt = cfl * minlengthFk / normU - SumFlux[j] = dt * SumF / Cj.getMeasure() - pass - return dt, SumFlux - - -def EquationTransport2D(tmax, VitesseX, VitesseY, cfl, output_freq, my_mesh, file): - - # Initial conditions # - print("Construction of the initial condition …") - y_field = initial_conditions(my_mesh) - # - # MED output of the initial conditions at t=0 and iteration = 0 - # - - iteration = 0 - time = 0. - print("Saving the solution at T=" + str(time) + "…") - y_field.setTime(time, iteration) - y_field.writeMED(file) - y_field.writeVTK(file) - y_field.writeCSV(file) - - # Time loop # - print("Resolution of the transport equation with an UPWIND scheme …") - ntmax = 3 - indexFacesPerio = my_mesh.getIndexFacePeriodic() - dt = 0. - while (iteration < ntmax and time <= tmax): - dt, SumFlux = sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio) - print("-- Iter: " + str(iteration) + ", Time: " + str(time) + ", dt: " + str(dt)) - - # Advancing time step # - y_field -= SumFlux - time += dt - iteration += 1 - # Output every output_freq iterations - if (iteration % output_freq == 0): - y_field.setTime(time, iteration) - y_field.writeMED(file, False) - y_field.writeVTK(file, False) - y_field.writeCSV(file) - pass - pass - return - - -def main(): - print("RESOLUTION OF THE 2D TRANSPORT EQUATION:") - print("- DOMAIN: SQUARE [0,1]x[0,1]") - print("- MESH: CARTESIAN, INTERNAL GENERATION WITH CDMATH") - print("- PERIODIC BC ON TOP AND BOTTOM") - print("- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT") - - # Problem data - cfl = 0.4 - VitesseX = 1.0 - VitesseY = 1.0 - tmax = 1. - output_freq = 10 - - print("Construction of a cartesian mesh …") - xinf = 0.0 - xsup = 1.0 - yinf = 0.0 - ysup = 1.0 - nx = 100 - ny = 100 - my_mesh = cdmath.Mesh(xinf, xsup, nx, yinf, ysup, ny) - eps = 1.E-10 - my_mesh.setGroupAtPlan(xsup, 0, eps, "RightEdge") - my_mesh.setGroupAtPlan(xinf, 0, eps, "LeftEdge") - my_mesh.setGroupAtPlan(yinf, 1, eps, "BottomEdge") - my_mesh.setGroupAtPlan(ysup, 1, eps, "TopEdge") - fileOutPutCart = "Exercice1PyTest" - EquationTransport2D(tmax, VitesseX, VitesseY, cfl, output_freq, my_mesh, fileOutPutCart) - print("CDMATH calculation done.") - return - - -if __name__ == """__main__""": - main() diff --git a/CDMATH/tests/examples/transport2d_s/makefile b/CDMATH/tests/examples/transport2d_s/makefile deleted file mode 100644 index 3ef2bc7..0000000 --- a/CDMATH/tests/examples/transport2d_s/makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Transport2D_S makefile - -CC = g++ -# Adapt the following line to your own system: -CDMATHDIR = ../../../../.. -IFLAG = -I$(CDMATHDIR)/include -I. -LFLAG = -L$(CDMATHDIR)/lib -LIBS =-linterpkernel -lmedC -lmedloader -lmedcoupling -lbase -lmesh -llinearsolver -OBJ = main.o - -all: $(OBJ) - $(CC) -o main $^ $(IFLAG) $(LFLAG) $(LIBS) - -%.o: %.cxx - $(CC) -c -o $@ $< $(CFLAGS) $(IFLAG) $(LFLAG) $(LIBS) - -.PHONY: clean - -clean: - rm -f *.o *~ core $(INCDIR)/*~ - -sweep: - rm -f *.vtu - rm -f *.pvd - rm -f *.csv - rm -f Exercie1*.med diff --git a/CDMATH/tests/ressources/CMakeLists.txt b/CDMATH/tests/ressources/CMakeLists.txt index acf794c..ad1b6cf 100755 --- a/CDMATH/tests/ressources/CMakeLists.txt +++ b/CDMATH/tests/ressources/CMakeLists.txt @@ -1,9 +1,6 @@ -SET(MESH_MED2 - ../ressources/ - ) -file(COPY ${MESH_MED2} DESTINATION ${CMAKE_BINARY_DIR}/CDMATH/tests/ressources) +file(COPY ${MED_MESHES} DESTINATION ${CMAKE_BINARY_DIR}/CDMATH/tests/ressources) -install(DIRECTORY ${MESH_MED2} DESTINATION share/meshes) +install(DIRECTORY ${MED_MESHES} DESTINATION share/meshes)