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
+file(GLOB BurgersEquation_EXAMPLES_TO_INSTALL
+ BurgersEquation1D # 1D Burgers' equation
+)
+
+install(DIRECTORY ${BurgersEquation_EXAMPLES_TO_INSTALL} DESTINATION share/examples/BurgersEquation)
if (CDMATH_WITH_PYTHON )
--- /dev/null
+
+ ADD_SUBDIRECTORY(IsentropicEulerSystem)
+ ADD_SUBDIRECTORY( FullEulerSystem)
--- /dev/null
+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)
+
+
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/usr/bin/env python3\r
+# -*-coding:utf-8 -*\r
+\r
+"""\r
+Created on Mon Aug 30 2021\r
+@author: Michael NDJINGA, Katia Ait Ameur, Coraline Mounier\r
+\r
+Euler system with heating source term (phi) in one dimension on regular domain [a,b]\r
+Riemann problemn with ghost cell boundary condition\r
+Left : Inlet boundary condition (velocity and temperature imposed)\r
+Right : Outlet boundary condition (pressure imposed)\r
+Roe scheme\r
+Regular square mesh\r
+\r
+State law Stiffened gaz : p = (gamma - 1) * rho * (e - q) - gamma * p0\r
+4 choices of parameters gamma and p0 are available : \r
+ - Lagrange interpolation (with q=0)\r
+ - Hermite interpolation with reference point at 575K (with q=0)\r
+ - Hermite interpolation with reference point at 590K (with q=0)\r
+ - Hermite interpolation with reference point at 617.94K (saturation at 155 bar) with q=0\r
+ \r
+Linearized enthalpy : h = h_sat + cp * (T - T_sat)\r
+Values for cp and T_sat parameters are taken at the reference point chosen for the state law\r
+\r
+To do correct the computation of the time step : lambda_max (maximum eigenvalue) should be computed first)\r
+"""\r
+\r
+import cdmath\r
+import numpy as np\r
+import matplotlib\r
+\r
+matplotlib.use("Agg")\r
+import matplotlib.pyplot as plt\r
+import matplotlib.animation as manimation\r
+import sys\r
+from math import sqrt, atan, pi\r
+from numpy import sign\r
+\r
+\r
+#### Initial and boundary condition (T in K, v in m/s, p in Pa)\r
+T_inlet = 565.\r
+v_inlet = 5.\r
+p_outlet = 155.0 * 10**5\r
+\r
+#initial parameters are determined from boundary conditions\r
+p_0 = p_outlet #initial pressure\r
+v_0 = v_inlet #initial velocity\r
+T_0 = T_inlet #initial temperature\r
+### Heating source term\r
+phi=1.e8\r
+\r
+## Numerical parameter\r
+precision = 1e-6\r
+\r
+#state law parameter : can be 'Lagrange', 'Hermite590K', 'Hermite617K', or 'FLICA'\r
+state_law = "Hermite575K"\r
+\r
+def state_law_parameters(state_law):\r
+ #state law Stiffened Gaz : p = (gamma - 1) * rho * e - gamma * p0\r
+ global gamma\r
+ global p0\r
+ global q\r
+ global c0\r
+ global cp\r
+ global h_sat\r
+ global T_sat\r
+ \r
+ if state_law == "Lagrange":\r
+ # reference values for Lagrange interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant \r
+ p1 = 153. * 10**5 # value of pressure at inlet of a 900 MWe PWR vessel\r
+ rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars\r
+ rho1 = 742.36 # value of density at inlet of a 900 MWe PWR vessel (T1 = 565K)\r
+ e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars\r
+ e1 = 1273.6 * 10**3 # value of internal energy at inlet of a 900 MWe PWR vessel\r
+ \r
+ gamma = (p1 - p_ref) / (rho1 * e1 - rho_ref *e_ref) + 1.\r
+ p0 = - 1. / gamma * ( - (gamma - 1) * rho_ref * e_ref + p_ref)\r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 8950.\r
+ h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars\r
+ T_sat = 617.94 \r
+\r
+ elif state_law == "Hermite617K":\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 617.94 #Reference temperature for interpolation at 617.94K\r
+ rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars\r
+ e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 621.43 #sound speed for water at 155 bars and 617.94K\r
+\r
+ gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 8950. # value at 155 bar and 617.94K\r
+ h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars\r
+ T_sat = 617.94 \r
+ \r
+ elif state_law == 'Hermite590K':\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 590. #Reference temperature for interpolation at 590K\r
+ rho_ref = 688.3 #density of water at 590K and 155 bars\r
+ e_ref = 1411.4 * 10**3 #internal energy of water at 590K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 866.29 #sound speed for water at 155 bars and 590K\r
+ \r
+ gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 5996.8 # value at 155 bar and 590K\r
+ h_sat = 1433.9 * 10 ** 3 # saturation enthalpy of water at 155 bars\r
+ T_sat = 590. \r
+\r
+ elif state_law == 'Hermite575K':\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155 * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 575 #Reference temperature at inlet in a REP 900 nuclear power plant\r
+ #Remaining values determined using iapws python package\r
+ rho_ref = 722.66 #density of water at 575K and 155 bars\r
+ e_ref = 1326552.66 #internal energy of water at 575K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 959.28 #sound speed for water at 155 bars and 575K\r
+ \r
+ gamma = 1 + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1 / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))#This is actually c_ref\r
+ \r
+ cp = 5504.05 # value at 155 bar and 590K\r
+ h_sat = h_ref # saturation enthalpy of water at 155 bars\r
+ T_sat = T_ref\r
+ else:\r
+ raise ValueError("Incorrect value for parameter state_law")\r
+ \r
+def initial_conditions_Riemann_problem(a, b, nx):\r
+ print("Initial data Riemann problem")\r
+ dx = (b - a) / nx # space step\r
+ x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh)\r
+\r
+ p_initial = np.array([ p_0 for xi in x])\r
+ v_initial = np.array([ v_0 for xi in x])\r
+ T_initial = np.array([ T_0 for xi in x])\r
+\r
+ rho_initial = p_to_rho_StiffenedGaz(p_initial, T_initial)\r
+ q_initial = rho_initial * v_initial\r
+ rho_E_initial = T_to_rhoE_StiffenedGaz(T_initial, rho_initial, q_initial)\r
+\r
+ return rho_initial, q_initial, rho_E_initial, p_initial, v_initial, T_initial\r
+\r
+def p_to_rho_StiffenedGaz(p_field, T_field):\r
+ rho_field = (p_field + p0) * gamma / (gamma - 1) * 1. / (h_sat + cp * (T_field - T_sat))\r
+ return rho_field\r
+ \r
+def T_to_rhoE_StiffenedGaz(T_field, rho_field, q_field):\r
+ rho_E_field = 1. / 2. * (q_field) ** 2 / rho_field + p0 + rho_field / gamma * (h_sat + cp * (T_field- T_sat))\r
+ return rho_E_field\r
+\r
+def rhoE_to_T_StiffenedGaz(rho_field, q_field, rho_E_field):\r
+ 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)\r
+ return T_field\r
+\r
+def rho_to_p_StiffenedGaz(rho_field, q_field, rho_E_field):\r
+ p_field = (gamma - 1) * (rho_E_field - 1. / 2 * q_field ** 2 / rho_field) - gamma * p0\r
+ return p_field\r
+\r
+def T_to_E_StiffenedGaz(p_field, T_field, v_field):\r
+ rho_field = p_to_rho_StiffenedGaz(p_field, T_field)\r
+ E_field = (p_field + gamma * p0) / ((gamma-1) * rho_field) + 0.5 * v_field **2\r
+ return E_field\r
+ \r
+def dp_drho_e_const_StiffenedGaz( e ):\r
+ return (gamma-1)*(e-q)\r
+\r
+def dp_de_rho_const_StiffenedGaz( rho ):\r
+ return (gamma-1)*rho\r
+\r
+def sound_speed_StiffenedGaz( h ):\r
+ return np.sqrt((gamma-1)*(h-q))\r
+\r
+def rho_h_to_p_StiffenedGaz( rho, h ):\r
+ return (gamma - 1) * rho * ( h - q ) / gamma - p0\r
+\r
+def MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ RoeMat = cdmath.Matrix(3, 3)\r
+\r
+ u_l = q_l / rho_l\r
+ u_r = q_r / rho_r\r
+ p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l)\r
+ p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r)\r
+ H_l = rho_E_l / rho_l + p_l / rho_l\r
+ H_r = rho_E_r / rho_r + p_r / rho_r\r
+\r
+ # Roe averages\r
+ rho = np.sqrt(rho_l * rho_r)\r
+ u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+ H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+\r
+ p = rho_h_to_p_StiffenedGaz( rho, H - u**2/2. )\r
+ e = H - p / rho - 1./2 * u**2\r
+ dp_drho = dp_drho_e_const_StiffenedGaz( e )\r
+ dp_de = dp_de_rho_const_StiffenedGaz( rho )\r
+\r
+ RoeMat[0, 0] = 0\r
+ RoeMat[0, 1] = 1\r
+ RoeMat[0, 2] = 0\r
+ RoeMat[1, 0] = dp_drho - u ** 2 + dp_de / rho * (u**2/2 - e)\r
+ RoeMat[1, 1] = 2 * u - u * dp_de / rho\r
+ RoeMat[1, 2] = dp_de / rho\r
+ RoeMat[2, 0] = -u * ( -dp_drho + H - dp_de / rho * (u**2/2 - e) )\r
+ RoeMat[2, 1] = H - dp_de / rho * u ** 2\r
+ RoeMat[2, 2] = (dp_de / rho +1) * u\r
+ \r
+ return(RoeMat)\r
+\r
+ \r
+def Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ Droe = cdmath.Matrix(3, 3)\r
+\r
+ u_l = q_l / rho_l\r
+ u_r = q_r / rho_r\r
+ p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l)\r
+ p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r)\r
+ H_l = rho_E_l / rho_l + p_l / rho_l\r
+ H_r = rho_E_r / rho_r + p_r / rho_r\r
+\r
+ # Roe averages\r
+ rho = np.sqrt(rho_l * rho_r)\r
+ u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+ H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+\r
+ c = sound_speed_StiffenedGaz( H - u**2/2. )\r
+ \r
+ lamb = cdmath.Vector(3)\r
+ lamb[0] = u-c\r
+ lamb[1] = u\r
+ lamb[2] = u+c \r
+\r
+ r = cdmath.Matrix(3, 3)\r
+ r[0,0] = 1.\r
+ r[1,0] = u-c\r
+ r[2,0] = H-u*c \r
+ r[0,1] = 1.\r
+ r[1,1] = u \r
+ r[2,1] = H-c**2/(gamma-1) \r
+ r[0,2] = 1.\r
+ r[1,2] = u+c\r
+ r[2,2] = H+u*c \r
+\r
+ l = cdmath.Matrix(3, 3)\r
+ l[0,0] = (1./(2*c**2))*(0.5*(gamma-1)*u**2+u*c)\r
+ l[1,0] = (1./(2*c**2))*(-u*(gamma-1)-c)\r
+ l[2,0] = (1./(2*c**2))*(gamma-1)\r
+ l[0,1] = ((gamma-1)/c**2)*(H-u**2)\r
+ l[1,1] = ((gamma-1)/c**2)*u \r
+ l[2,1] = -((gamma-1)/c**2) \r
+ l[0,2] = (1./(2*c**2))*(0.5*(gamma-1)*u**2-u*c)\r
+ l[1,2] = (1./(2*c**2))*(c-u*(gamma-1))\r
+ l[2,2] = (1./(2*c**2))*(gamma-1)\r
+\r
+ M1 = cdmath.Matrix(3, 3) #abs(lamb[0])*r[:,0].tensProduct(l[:,0])\r
+ M2 = cdmath.Matrix(3, 3) #abs(lamb[1])*r[:,1].tensProduct(l[:,1]) \r
+ M3 = cdmath.Matrix(3, 3) #abs(lamb[2])*r[:,2].tensProduct(l[:,2])\r
+ for i in range(3):\r
+ for j in range(3):\r
+ M1[i,j] = abs(lamb[0])*r[i,0]*l[j,0]\r
+ M2[i,j] = abs(lamb[1])*r[i,1]*l[j,1] \r
+ M3[i,j] = abs(lamb[2])*r[i,2]*l[j,2]\r
+ \r
+ Droe = M1+M2+M3 \r
+ \r
+ return(Droe) \r
+\r
+\r
+def jacobianMatricesm(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+\r
+ if rho_l < 0 or rho_r < 0:\r
+ print("rho_l=", rho_l, " rho_r= ", rho_r)\r
+ raise ValueError("Negative density")\r
+ if rho_E_l < 0 or rho_E_r < 0:\r
+ print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r)\r
+ raise ValueError("Negative total energy")\r
+\r
+ RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+ return (RoeMat - Droe) * coeff * 0.5\r
+\r
+\r
+def jacobianMatricesp(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ if rho_l < 0 or rho_r < 0:\r
+ print("rho_l=", rho_l, " rho_r= ", rho_r)\r
+ raise ValueError("Negative density")\r
+ if rho_E_l < 0 or rho_E_r < 0:\r
+ print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r)\r
+ raise ValueError("Negative total energy")\r
+\r
+ RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+\r
+ return (RoeMat + Droe) * coeff * 0.5\r
+\r
+\r
+def FillEdges(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit):\r
+ dUi1 = cdmath.Vector(3)\r
+ dUi2 = cdmath.Vector(3)\r
+ temp1 = cdmath.Vector(3)\r
+ temp2 = cdmath.Vector(3)\r
+\r
+ if (j == 0):\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2] \r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+\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\r
+ rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure\r
+ #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain\r
+ q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet\r
+ 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\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ \r
+ if(isImplicit):\r
+ dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp1 = Am * dUi1\r
+ \r
+ dUi2[0] = rho_l - Uk[(j ) * nbComp + 0]\r
+ dUi2[1] = q_l - Uk[(j ) * nbComp + 1]\r
+ dUi2[2] = rho_E_l - Uk[(j ) * nbComp + 2]\r
+ temp2 = Ap * dUi2\r
+ else:\r
+ dUi2[0] = rho_l \r
+ dUi2[1] = q_l \r
+ dUi2[2] = rho_E_l \r
+ temp2 = Ap * dUi2\r
+\r
+ elif (j == nx - 1):\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain\r
+ q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain\r
+ 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\r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+\r
+ if(isImplicit):\r
+ dUi1[0] = rho_r - Uk[j * nbComp + 0]\r
+ dUi1[1] = q_r - Uk[j * nbComp + 1]\r
+ dUi1[2] = rho_E_r - Uk[j * nbComp + 2]\r
+ temp1 = Am * dUi1\r
+\r
+ dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp2 = Ap * dUi2\r
+ else:\r
+ dUi1[0] = rho_r \r
+ dUi1[1] = q_r \r
+ dUi1[2] = rho_E_r \r
+ temp1 = Am * dUi1\r
+ \r
+ if(isImplicit):#implicit scheme, contribution from the Newton scheme residual\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+ else:#explicit scheme, contribution from the boundary data the right hand side\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] \r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] \r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] \r
+\r
+def FillInnerCell(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit):\r
+\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2]\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+\r
+ if(isImplicit):\r
+ dUi1 = cdmath.Vector(3)\r
+ dUi2 = cdmath.Vector(3)\r
+ \r
+ dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ \r
+ dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ \r
+ temp1 = Am * dUi1\r
+ temp2 = Ap * dUi2\r
+\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+ else:\r
+ Rhs[j * nbComp + 0] = 0\r
+ Rhs[j * nbComp + 1] = 0\r
+ Rhs[j * nbComp + 2] = 0\r
+\r
+def SetPicture(rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx):\r
+ max_initial_rho = max(rho_field_Roe)\r
+ min_initial_rho = min(rho_field_Roe)\r
+ max_initial_q = max(q_field_Roe)\r
+ min_initial_q = min(q_field_Roe)\r
+ min_initial_h = min(h_field_Roe)\r
+ max_initial_h = max(h_field_Roe)\r
+ max_initial_p = max(p_field_Roe)\r
+ min_initial_p = min(p_field_Roe)\r
+ max_initial_v = max(v_field_Roe)\r
+ min_initial_v = min(v_field_Roe)\r
+ max_initial_T = max(T_field_Roe)\r
+ min_initial_T = min(T_field_Roe)\r
+\r
+ fig, ([axDensity, axMomentum, axh],[axPressure, axVitesse, axTemperature]) = plt.subplots(2, 3,sharex=True, figsize=(14,10))\r
+ plt.gcf().subplots_adjust(wspace = 0.5)\r
+\r
+ lineDensity_Roe, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field_Roe, label='Roe')\r
+ axDensity.set(xlabel='x (m)', ylabel='Densité (kg/m3)')\r
+ axDensity.set_xlim(a,b)\r
+ axDensity.set_ylim(680, 800)\r
+ axDensity.legend()\r
+\r
+ lineMomentum_Roe, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field_Roe, label='Roe')\r
+ axMomentum.set(xlabel='x (m)', ylabel='Momentum (kg/(m2.s))')\r
+ axMomentum.set_xlim(a,b)\r
+ axMomentum.set_ylim(3500, 4000)\r
+ axMomentum.legend()\r
+\r
+ lineh_Roe, = axh.plot([a+0.5*dx + i*dx for i in range(nx)], h_field_Roe, label='Roe')\r
+ axh.set(xlabel='x (m)', ylabel='h (J/m3)')\r
+ axh.set_xlim(a,b)\r
+ axh.set_ylim(1.2 * 10**6, 1.5*10**6)\r
+ axh.legend()\r
+ \r
+ linePressure_Roe, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field_Roe, label='Roe')\r
+ axPressure.set(xlabel='x (m)', ylabel='Pression (bar)')\r
+ axPressure.set_xlim(a,b)\r
+ axPressure.set_ylim(155, 155.5)\r
+ axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axPressure.legend()\r
+\r
+ lineVitesse_Roe, = axVitesse.plot([a+0.5*dx + i*dx for i in range(nx)], v_field_Roe, label='Roe')\r
+ axVitesse.set(xlabel='x (m)', ylabel='Vitesse (m/s)')\r
+ axVitesse.set_xlim(a,b)\r
+ axVitesse.set_ylim(v_0-1, v_0+1)\r
+ axVitesse.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axVitesse.legend()\r
+\r
+ lineTemperature_Roe, = axTemperature.plot([a+0.5*dx + i*dx for i in range(nx)], T_field_Roe, label='Roe')\r
+ axTemperature.set(xlabel='x (m)', ylabel='Température (K)')\r
+ axTemperature.set_xlim(a,b)\r
+ axTemperature.set_ylim(T_0-10, T_0+30)\r
+ axTemperature.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axTemperature.legend()\r
+ \r
+ return(fig, lineDensity_Roe, lineMomentum_Roe, lineh_Roe, linePressure_Roe, lineVitesse_Roe, lineTemperature_Roe)\r
+\r
+\r
+def EulerSystemRoe(ntmax, tmax, cfl, a, b, nbCells, output_freq, meshName, state_law, isImplicit):\r
+ state_law_parameters(state_law)\r
+ dim = 1\r
+ nbComp = 3\r
+ dt = 0.\r
+ time = 0.\r
+ it = 0\r
+ isStationary = False\r
+ dx = (b - a) / nx\r
+ dt = cfl * dx / c0\r
+ #dt = 5*10**(-6)\r
+ nbVoisinsMax = 2\r
+\r
+ # iteration vectors\r
+ Un_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ dUn_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ dUk_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ Rhs_Roe = cdmath.Vector(nbCells * (nbComp))\r
+\r
+ # Initial conditions\r
+ print("Construction of the initial condition …")\r
+\r
+ 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)\r
+ h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2\r
+ p_field_Roe = p_field_Roe * 10 ** (-5)\r
+ \r
+\r
+ for k in range(nbCells):\r
+ Un_Roe[k * nbComp + 0] = rho_field_Roe[k]\r
+ Un_Roe[k * nbComp + 1] = q_field_Roe[k]\r
+ Un_Roe[k * nbComp + 2] = rho_E_field_Roe[k]\r
+\r
+ divMat_Roe = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp)\r
+ \r
+ # Picture settings\r
+ 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)\r
+\r
+ plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "0" + ".png")\r
+ iterGMRESMax = 50\r
+ newton_max = 100\r
+\r
+ print("Starting computation of the non linear Euler non isentropic system with Roe scheme …")\r
+ # STARTING TIME LOOP\r
+ while (it < ntmax and time <= tmax and not isStationary):\r
+ dUn_Roe = Un_Roe.deepCopy()\r
+ Uk_Roe = Un_Roe.deepCopy()\r
+ residu_Roe = 1.\r
+ \r
+ k_Roe = 0\r
+ while (k_Roe < newton_max and residu_Roe > precision):\r
+ # STARTING NEWTON LOOP\r
+ divMat_Roe.zeroEntries() #sets the matrix coefficients to zero\r
+ for j in range(nbCells):\r
+ \r
+ # traitements des bords\r
+ if (j == 0):\r
+ FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+ elif (j == nbCells - 1):\r
+ FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+\r
+ # traitement des cellules internes\r
+ else:\r
+ FillInnerCell(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+ \r
+ Rhs_Roe[j * nbComp + 2] += phi*dt\r
+ \r
+ if(isImplicit):\r
+ #solving the linear system divMat * dUk = Rhs\r
+ divMat_Roe.diagonalShift(1.)\r
+ LS_Roe = cdmath.LinearSolver(divMat_Roe, Rhs_Roe, iterGMRESMax, precision, "GMRES", "LU")\r
+ dUk_Roe = LS_Roe.solve()\r
+ vector_residu_Roe = dUk_Roe.maxVector(nbComp)\r
+ residu_Roe = max(abs(vector_residu_Roe[0])/rho0, abs(vector_residu_Roe[1])/(rho0*v_0), abs(vector_residu_Roe[2])/rhoE0 )\r
+ else:\r
+ dUk_Roe=Rhs_Roe - divMat_Roe*Un_Roe\r
+ residu_Roe = 0.#Convergence schéma Newton\r
+ \r
+ if (isImplicit and (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax)):\r
+ print("Residu Newton at iteration ",k_Roe, " : ", residu_Roe)\r
+ print("Linear system converged in ", LS_Roe.getNumberOfIter(), " GMRES iterations")\r
+\r
+ #updates for Newton loop\r
+ Uk_Roe += dUk_Roe\r
+ k_Roe = k_Roe + 1\r
+ if (isImplicit and not LS_Roe.getStatus()):\r
+ print("Linear system did not converge ", LS_Roe.getNumberOfIter(), " GMRES iterations")\r
+ raise ValueError("No convergence of the linear system")\r
+ \r
+ if k_Roe == newton_max:\r
+ raise ValueError("No convergence of Newton Roe Scheme")\r
+\r
+ #updating fields\r
+ Un_Roe = Uk_Roe.deepCopy()\r
+ dUn_Roe -= Un_Roe\r
+\r
+ #Testing stationarity\r
+ residu_stat = dUn_Roe.maxVector(nbComp)#On prend le max de chaque composante\r
+ if (it % output_freq == 0 ):\r
+ 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 ))\r
+\r
+ if ( it>1 and abs(residu_stat[0])/rho0<precision and abs(residu_stat[1])/(rho0*v_0)<precision and abs(residu_stat[2])/rhoE0<precision):\r
+ isStationary = True\r
+ \r
+ for k in range(nbCells):\r
+ rho_field_Roe[k] = Un_Roe[k * nbComp + 0]\r
+ q_field_Roe[k] = Un_Roe[k * nbComp + 1]\r
+ rho_E_field_Roe[k] = Un_Roe[k * nbComp + 2]\r
+\r
+ v_field_Roe = q_field_Roe / rho_field_Roe\r
+ p_field_Roe = rho_to_p_StiffenedGaz(rho_field_Roe, q_field_Roe, rho_E_field_Roe)\r
+ T_field_Roe = rhoE_to_T_StiffenedGaz(rho_field_Roe, q_field_Roe, rho_E_field_Roe)\r
+ h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2\r
+ p_field_Roe = p_field_Roe * 10 ** (-5)\r
+ \r
+ if( min(p_field_Roe)<0) :\r
+ raise ValueError("Negative pressure, stopping calculation")\r
+\r
+ #picture and video updates\r
+ lineDensity_Roe.set_ydata(rho_field_Roe)\r
+ lineMomentum_Roe.set_ydata(q_field_Roe)\r
+ lineRhoE_Roe.set_ydata(h_field_Roe)\r
+ linePressure_Roe.set_ydata(p_field_Roe)\r
+ lineVitesse_Roe.set_ydata(v_field_Roe)\r
+ lineTemperature_Roe.set_ydata(T_field_Roe)\r
+ \r
+ time = time + dt\r
+ it = it + 1\r
+\r
+ # Savings\r
+ if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax):\r
+ \r
+ print("-- Time step : " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))\r
+\r
+ print("Temperature gain between inlet and outlet is ", T_field_Roe[nbCells-1]-T_field_Roe[0],"\n")\r
+\r
+ plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "Implicit"+str(isImplicit)+ str(it) + '_time' + str(time) + ".png")\r
+\r
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)+"\n")\r
+ \r
+ if (it >= ntmax):\r
+ print("Maximum number of time steps ntmax= ", ntmax, " reached")\r
+ return\r
+\r
+ elif (isStationary):\r
+ print("Stationary regime reached at time step ", it, ", t= ", time)\r
+ print("------------------------------------------------------------------------------------")\r
+ np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_rho_Stat.txt", rho_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_q_Stat.txt", q_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_rhoE_Stat.txt", rho_E_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "_p_Stat.txt", p_field_Roe, delimiter="\n")\r
+ plt.savefig("EulerComplet_HeatedChannel_" + str(dim) + "D_Roe" + meshName + "Implicit"+str(isImplicit)+"_Stat.png")\r
+ return\r
+ else:\r
+ print("Maximum time Tmax= ", tmax, " reached")\r
+ return\r
+\r
+\r
+def solve(a, b, nx, meshName, meshType, cfl, state_law, isImplicit):\r
+ print("Simulation of a heated channel in dimension 1 on " + str(nx) + " cells")\r
+ print("State Law Stiffened Gaz, " + state_law)\r
+ print("Initial data : ", "constant fields")\r
+ print("Boundary conditions : ", "Inlet (Left), Outlet (Right)")\r
+ print("Mesh name : ", meshName, ", ", nx, " cells")\r
+ # Problem data\r
+ tmax = 10.\r
+ ntmax = 100000\r
+ output_freq = 1000\r
+ EulerSystemRoe(ntmax, tmax, cfl, a, b, nx, output_freq, meshName, state_law, isImplicit)\r
+ return\r
+\r
+def FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx):\r
+\r
+ if (j == 0):\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2] \r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+ \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\r
+ rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure\r
+ #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain\r
+ q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet\r
+ 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\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+\r
+ elif (j == nx - 1):\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain\r
+ q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain\r
+ 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\r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+ \r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+\r
+\r
+def FillMatrixFromInnerCell(j, Uk, nbComp, divMat, dt, dx):\r
+\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2]\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+ \r
+def FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit):\r
+ dUi1 = cdmath.Vector(3)\r
+ dUi2 = cdmath.Vector(3)\r
+ temp1 = cdmath.Vector(3)\r
+ temp2 = cdmath.Vector(3)\r
+\r
+ if (j == 0):\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2] \r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\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\r
+ rho_l=p_to_rho_StiffenedGaz(p_inlet, T_inlet) # rho is computed from the temperature BC and the inner pressure\r
+ #rho_l = Uk[j * nbComp + 0] # We take rho from inside the domain\r
+ q_l = rho_l * v_inlet # q is imposed by the boundary condition v_inlet\r
+ 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\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ if(isImplicit):\r
+ dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp1 = Am * dUi1\r
+ \r
+ dUi2[0] = rho_l - Uk[(j ) * nbComp + 0]\r
+ dUi2[1] = q_l - Uk[(j ) * nbComp + 1]\r
+ dUi2[2] = rho_E_l - Uk[(j ) * nbComp + 2]\r
+ temp2 = Ap * dUi2\r
+ else:\r
+ dUi2[0] = rho_l \r
+ dUi2[1] = q_l \r
+ dUi2[2] = rho_E_l \r
+ temp2 = Ap * dUi2\r
+\r
+ elif (j == nx - 1):\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j ) * nbComp + 0] # We take rho inside the domain\r
+ q_r = Uk[(j ) * nbComp + 1] # We take q from inside the domain\r
+ 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\r
+\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+\r
+ if(isImplicit):\r
+ dUi1[0] = rho_r - Uk[j * nbComp + 0]\r
+ dUi1[1] = q_r - Uk[j * nbComp + 1]\r
+ dUi1[2] = rho_E_r - Uk[j * nbComp + 2]\r
+ temp1 = Am * dUi1\r
+ \r
+ dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp2 = Ap * dUi2\r
+ else:\r
+ dUi1[0] = rho_r \r
+ dUi1[1] = q_r \r
+ dUi1[2] = rho_E_r \r
+ temp1 = Am * dUi1\r
+ \r
+ if(isImplicit):\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+ else:#explicit scheme, contribution from the boundary data the right hand side\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] \r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] \r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] \r
+\r
+def FillRHSFromInnerCell(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit):\r
+\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2]\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\r
+ if(isImplicit):#Contribution to the right hand side if te scheme is implicit\r
+ dUi1 = cdmath.Vector(3)\r
+ dUi2 = cdmath.Vector(3)\r
+ \r
+ dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ \r
+ dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+\r
+ temp1 = Am * dUi1\r
+ temp2 = Ap * dUi2\r
+\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+ else:\r
+ Rhs[j * nbComp + 0] = 0\r
+ Rhs[j * nbComp + 1] = 0\r
+ Rhs[j * nbComp + 2] = 0\r
+\r
+\r
+def computeSystemMatrix(a,b,nx, cfl, Uk, isImplicit):\r
+ dim = 1\r
+ nbComp = 3\r
+ dx = (b - a) / nx\r
+ dt = cfl * dx / c0\r
+ nbVoisinsMax = 2\r
+\r
+ nbCells = nx\r
+ divMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp)\r
+\r
+ divMat.zeroEntries() #sets the matrix coefficients to zero\r
+ for j in range(nbCells):\r
+ \r
+ # traitements des bords\r
+ if (j == 0):\r
+ FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx)\r
+ elif (j == nbCells - 1):\r
+ FillMatrixFromEdges(j, Uk, nbComp, divMat, dt, dx)\r
+ # traitement des cellules internes\r
+ else:\r
+ FillMatrixFromInnerCell(j, Uk, nbComp, divMat, dt, dx)\r
+ \r
+ if(isImplicit): \r
+ divMat.diagonalShift(1.) # add one on the diagonal\r
+ else:\r
+ divMat*=-1.\r
+ divMat.diagonalShift(1.) # add one on the diagonal\r
+\r
+ return divMat\r
+\r
+def computeRHSVector(a,b,nx, cfl, Uk, Un, isImplicit):\r
+ dim = 1\r
+ nbComp = 3\r
+ dx = (b - a) / nx\r
+ dt = cfl * dx / c0\r
+ nbVoisinsMax = 2\r
+\r
+ nbCells = nx\r
+ Rhs = cdmath.Vector(nbCells * (nbComp))\r
+\r
+ for j in range(nbCells):\r
+ \r
+ # traitements des bords\r
+ if (j == 0):\r
+ FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit)\r
+ elif (j == nbCells - 1):\r
+ FillRHSFromEdges(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit)\r
+ # traitement des cellules internes\r
+ else:\r
+ FillRHSFromInnerCell(j, Uk, nbComp, Rhs, Un, dt, dx, isImplicit)\r
+ \r
+ return Rhs\r
+\r
+\r
+if __name__ == """__main__""":\r
+ nbComp=3 # number of equations \r
+ a = 0.# domain is interval [a,b]\r
+ b = 4.2# domain is interval [a,b]\r
+ nx = 10# number of cells\r
+ dx = (b - a) / nx # space step\r
+ x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh)\r
+ state_law = "Hermite575K"\r
+ state_law_parameters(state_law)\r
+ rho0=p_to_rho_StiffenedGaz(p_0, T_0)\r
+ rhoE0=T_to_rhoE_StiffenedGaz(T_0, rho0, rho0*v_0)\r
+\r
+\r
+#### initial condition (T in K, v in m/s, p in Pa)\r
+ p_initial = np.array([ p_outlet for xi in x])\r
+ v_initial = np.array([ v_inlet for xi in x])\r
+ T_initial = np.array([ T_inlet for xi in x])\r
+ \r
+ rho_field = p_to_rho_StiffenedGaz(p_initial, T_initial)\r
+ q_field = rho_field * v_initial\r
+ rho_E_field = rho_field * T_to_E_StiffenedGaz(p_initial, T_initial, v_initial)\r
+\r
+ U = cdmath.Vector(nx * (nbComp))#Inutile à terme mais nécessaire pour le moment\r
+\r
+ for k in range(nx):\r
+ U[k * nbComp + 0] = rho_field[k]\r
+ U[k * nbComp + 1] = q_field[k]\r
+ U[k * nbComp + 2] = rho_E_field[k]\r
+ print("\n Testing function computeSystemMatrix \n")\r
+ cfl = 0.5\r
+ computeSystemMatrix(a, b, nx, cfl, U,True) #Implicit matrix\r
+ computeSystemMatrix(a, b, nx, cfl, U,False) #Explicit matrix\r
+\r
+ print("\n Testing function computeRHSVector \n")\r
+ cfl = 0.5\r
+ computeRHSVector(a, b, nx, cfl, U, U,True) #Implicit RHS\r
+ computeRHSVector(a, b, nx, cfl, U, U,False) #Explicit RHS\r
+\r
+ print("\n Testing function solve (Implicit scheme) \n")\r
+ isImplicit=True\r
+ cfl = 1000.\r
+ solve(a, b, nx, "RegularSquares", "", cfl, state_law, isImplicit)\r
+ \r
+ print("\n Testing function solve (Explicit scheme) \n")\r
+ isImplicit=False\r
+ cfl = 0.5\r
+ solve(a, b, nx, "RegularSquares", "", cfl, state_law, isImplicit)\r
+\r
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/usr/bin/env python3\r
+# -*-coding:utf-8 -*\r
+\r
+"""\r
+Created on Mon Aug 30 2021\r
+@author: Michael NDJINGA, Katia Ait Ameur, Coraline Mounier\r
+\r
+Euler system without source term in one dimension on regular domain [a,b]\r
+Riemann problemn with ghost cell boundary condition\r
+Left and right: Neumann boundary condition \r
+Roe scheme\r
+Regular square mesh\r
+\r
+State law Stiffened gaz : p = (gamma - 1) * rho * (e - q) - gamma * p0\r
+4 choices of parameters gamma and p0 are available : \r
+ - Lagrange interpolation (with q=0)\r
+ - Hermite interpolation with reference point at 575K (with q=0)\r
+ - Hermite interpolation with reference point at 590K (with q=0)\r
+ - Hermite interpolation with reference point at 617.94K (saturation at 155 bar) with q=0\r
+ \r
+Linearized enthalpy : h = h_sat + cp * (T - T_sat)\r
+Values for cp and T_sat parameters are taken at the reference point chosen for the state law\r
+\r
+To do correct the computation of the time step : lambda_max (maximum eigenvalue) should be computed first)\r
+"""\r
+\r
+import cdmath\r
+import numpy as np\r
+import matplotlib\r
+\r
+matplotlib.use("Agg")\r
+import matplotlib.pyplot as plt\r
+import matplotlib.animation as manimation\r
+import sys\r
+from math import sqrt, atan, pi\r
+from numpy import sign\r
+\r
+\r
+## Numerical parameter\r
+precision = 1e-5\r
+\r
+#state law parameter : can be 'Lagrange', 'Hermite590K', 'Hermite617K', or 'FLICA'\r
+state_law = "Hermite590K"\r
+\r
+#indicates with test case is simulated to compare with FLICA5 results\r
+#num_test = 0 means there are no FLICA5 results given here\r
+num_test = 0\r
+\r
+#def state_law_parameters(state_law):\r
+#state law Stiffened Gaz : p = (gamma - 1) * rho * e - gamma * p0\r
+global gamma\r
+global p0\r
+global q\r
+global c0\r
+global cp\r
+global h_sat\r
+global T_sat\r
+\r
+if state_law == "Lagrange":\r
+ # reference values for Lagrange interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant \r
+ p1 = 153. * 10**5 # value of pressure at inlet of a 900 MWe PWR vessel\r
+ rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars\r
+ rho1 = 742.36 # value of density at inlet of a 900 MWe PWR vessel (T1 = 565K)\r
+ e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars\r
+ e1 = 1273.6 * 10**3 # value of internal energy at inlet of a 900 MWe PWR vessel\r
+ \r
+ gamma = (p1 - p_ref) / (rho1 * e1 - rho_ref *e_ref) + 1.\r
+ p0 = - 1. / gamma * ( - (gamma - 1) * rho_ref * e_ref + p_ref)\r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 8950.\r
+ h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars\r
+ T_sat = 617.94 \r
+\r
+elif state_law == "Hermite617K":\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 617.94 #Reference temperature for interpolation at 617.94K\r
+ rho_ref = 594.38 #density of water at saturation temperature of 617.94K and 155 bars\r
+ e_ref = 1603.8 * 10**3 #internal energy of water at saturation temperature of 617.94K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 621.43 #sound speed for water at 155 bars and 617.94K\r
+\r
+ gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 8950. # value at 155 bar and 617.94K\r
+ h_sat = 1.63 * 10 ** 6 # saturation enthalpy of water at 155 bars\r
+ T_sat = 617.94 \r
+\r
+elif state_law == 'Hermite590K':\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155. * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 590. #Reference temperature for interpolation at 590K\r
+ rho_ref = 688.3 #density of water at 590K and 155 bars\r
+ e_ref = 1411.4 * 10**3 #internal energy of water at 590K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 866.29 #sound speed for water at 155 bars and 590K\r
+ \r
+ gamma = 1. + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1. / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))\r
+ \r
+ cp = 5996.8 # value at 155 bar and 590K\r
+ h_sat = 1433.9 * 10 ** 3 # saturation enthalpy of water at 155 bars\r
+ T_sat = 590. \r
+\r
+elif state_law == 'Hermite575K':\r
+ # reference values for Hermite interpolation\r
+ p_ref = 155 * 10**5 #Reference pressure in a REP 900 nuclear power plant\r
+ T_ref = 575 #Reference temperature at inlet in a REP 900 nuclear power plant\r
+ #Remaining values determined using iapws python package\r
+ rho_ref = 722.66 #density of water at 575K and 155 bars\r
+ e_ref = 1326552.66 #internal energy of water at 575K and 155 bars\r
+ h_ref = e_ref + p_ref / rho_ref\r
+ c_ref = 959.28 #sound speed for water at 155 bars and 575K\r
+ \r
+ gamma = 1 + c_ref * c_ref / (e_ref + p_ref / rho_ref) # From the sound speed formula\r
+ p0 = 1 / gamma * ( (gamma - 1) * rho_ref * e_ref - p_ref) \r
+ q=0.\r
+ c0 = sqrt((gamma - 1) * (e_ref + p_ref / rho_ref))#This is actually c_ref\r
+ \r
+ cp = 5504.05 # value at 155 bar and 590K\r
+ h_sat = h_ref # saturation enthalpy of water at 155 bars\r
+ T_sat = T_ref\r
+else:\r
+ raise ValueError("Incorrect value for parameter state_law")\r
+\r
+\r
+#initial parameters for Riemann problem (p in Pa, v in m/s, T in K)\r
+p_L = 155. * 10**5 \r
+p_R = 150. * 10**5\r
+v_L = 0.\r
+v_R = 0.\r
+h_L = 1.4963*10**6\r
+h_R = 1.4963*10**6\r
+\r
+T_L = (h_L - h_sat ) / cp + T_sat\r
+T_R = (h_R - h_sat ) / cp + T_sat\r
+\r
+def initial_conditions_Riemann_problem(a, b, nx):\r
+ print("Initial data Riemann problem")\r
+ dx = (b - a) / nx # space step\r
+ x = [a + 0.5 * dx + i * dx for i in range(nx)] # array of cell center (1D mesh) \r
+\r
+ p_initial = np.array([ (xi < (a + b) / 2) * p_L + (xi >= (a + b) / 2) * p_R for xi in x])\r
+ v_initial = np.array([ (xi < (a + b) / 2) * v_L + (xi >= (a + b) / 2) * v_R for xi in x])\r
+ T_initial = np.array([ (xi < (a + b) / 2) * T_L + (xi >= (a + b) / 2) * T_R for xi in x])\r
+\r
+ rho_initial = p_to_rho_StiffenedGaz(p_initial, T_initial)\r
+ q_initial = rho_initial * v_initial\r
+ rho_E_initial = T_to_rhoE_StiffenedGaz(T_initial, rho_initial, q_initial)\r
+\r
+ return rho_initial, q_initial, rho_E_initial, p_initial, v_initial, T_initial\r
+\r
+def rho_to_p_StiffenedGaz(rho_field, q_field, rho_E_field):\r
+ p_field = (gamma - 1) * ( rho_E_field - 1. / 2 * q_field ** 2 / rho_field - rho_field * q) - gamma * p0\r
+ return p_field\r
+ \r
+\r
+def p_to_rho_StiffenedGaz(p_field, T_field):\r
+ rho_field = (p_field + p0) * gamma / (gamma - 1) * 1 / (h_sat + cp * (T_field - T_sat) - q)\r
+ return rho_field\r
+ \r
+\r
+def T_to_rhoE_StiffenedGaz(T_field, rho_field, q_field):\r
+ rho_E_field = 1 / 2 * (q_field) ** 2 / rho_field + p0 + rho_field / gamma * (h_sat + cp * (T_field- T_sat) + (gamma - 1) * q)\r
+ return rho_E_field\r
+\r
+ \r
+def rhoE_to_T_StiffenedGaz(rho_field, q_field, rho_E_field):\r
+ 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)\r
+ return T_field\r
+\r
+def dp_drho_e_const_StiffenedGaz( e ):\r
+ return (gamma-1)*(e-q)\r
+\r
+def dp_de_rho_const_StiffenedGaz( rho ):\r
+ return (gamma-1)*rho\r
+\r
+def sound_speed_StiffenedGaz( h ):\r
+ return np.sqrt((gamma-1)*(h-q))\r
+\r
+def rho_h_to_p_StiffenedGaz( rho, h ):\r
+ return (gamma - 1) * rho * ( h - q ) / gamma - p0\r
+\r
+def MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ RoeMat = cdmath.Matrix(3, 3)\r
+\r
+ u_l = q_l / rho_l\r
+ u_r = q_r / rho_r\r
+ p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l)\r
+ p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r)\r
+ H_l = rho_E_l / rho_l + p_l / rho_l\r
+ H_r = rho_E_r / rho_r + p_r / rho_r\r
+\r
+ # Roe averages\r
+ rho = np.sqrt(rho_l * rho_r)\r
+ u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+ H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+\r
+ p = rho_h_to_p_StiffenedGaz( rho, H - u**2/2. )\r
+ e = H - p / rho - 1./2 * u**2\r
+ dp_drho = dp_drho_e_const_StiffenedGaz( e )\r
+ dp_de = dp_de_rho_const_StiffenedGaz( rho )\r
+\r
+ RoeMat[0, 0] = 0\r
+ RoeMat[0, 1] = 1\r
+ RoeMat[0, 2] = 0\r
+ RoeMat[1, 0] = dp_drho - u ** 2 + dp_de / rho * (u**2/2 - e)\r
+ RoeMat[1, 1] = 2 * u - u * dp_de / rho\r
+ RoeMat[1, 2] = dp_de / rho\r
+ RoeMat[2, 0] = -u * ( -dp_drho + H - dp_de / rho * (u**2/2 - e) )\r
+ RoeMat[2, 1] = H - dp_de / rho * u ** 2\r
+ RoeMat[2, 2] = (dp_de / rho +1) * u\r
+ \r
+ return(RoeMat)\r
+\r
+ \r
+def Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ Droe = cdmath.Matrix(3, 3)\r
+\r
+ u_l = q_l / rho_l\r
+ u_r = q_r / rho_r\r
+ p_l = rho_to_p_StiffenedGaz(rho_l, q_l, rho_E_l)\r
+ p_r = rho_to_p_StiffenedGaz(rho_r, q_r, rho_E_r)\r
+ H_l = rho_E_l / rho_l + p_l / rho_l\r
+ H_r = rho_E_r / rho_r + p_r / rho_r\r
+\r
+ # Roe averages\r
+ rho = np.sqrt(rho_l * rho_r)\r
+ u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+ H = (H_l * sqrt(rho_l) + H_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))\r
+\r
+ c = sound_speed_StiffenedGaz( H - u**2/2. )\r
+ \r
+ lamb = cdmath.Vector(3)\r
+ lamb[0] = u-c\r
+ lamb[1] = u\r
+ lamb[2] = u+c \r
+\r
+ r = cdmath.Matrix(3, 3)\r
+ r[0,0] = 1.\r
+ r[1,0] = u-c\r
+ r[2,0] = H-u*c \r
+ r[0,1] = 1.\r
+ r[1,1] = u \r
+ r[2,1] = H-c**2/(gamma-1) \r
+ r[0,2] = 1.\r
+ r[1,2] = u+c\r
+ r[2,2] = H+u*c \r
+\r
+ l = cdmath.Matrix(3, 3)\r
+ l[0,0] = (1./(2*c**2))*(0.5*(gamma-1)*u**2+u*c)\r
+ l[1,0] = (1./(2*c**2))*(-u*(gamma-1)-c)\r
+ l[2,0] = (1./(2*c**2))*(gamma-1)\r
+ l[0,1] = ((gamma-1)/c**2)*(H-u**2)\r
+ l[1,1] = ((gamma-1)/c**2)*u \r
+ l[2,1] = -((gamma-1)/c**2) \r
+ l[0,2] = (1./(2*c**2))*(0.5*(gamma-1)*u**2-u*c)\r
+ l[1,2] = (1./(2*c**2))*(c-u*(gamma-1))\r
+ l[2,2] = (1./(2*c**2))*(gamma-1)\r
+\r
+ M1 = cdmath.Matrix(3, 3) #abs(lamb[0])*r[:,0].tensProduct(l[:,0])\r
+ M2 = cdmath.Matrix(3, 3) #abs(lamb[1])*r[:,1].tensProduct(l[:,1]) \r
+ M3 = cdmath.Matrix(3, 3) #abs(lamb[2])*r[:,2].tensProduct(l[:,2])\r
+ for i in range(3):\r
+ for j in range(3):\r
+ M1[i,j] = abs(lamb[0])*r[i,0]*l[j,0]\r
+ M2[i,j] = abs(lamb[1])*r[i,1]*l[j,1] \r
+ M3[i,j] = abs(lamb[2])*r[i,2]*l[j,2]\r
+ \r
+ Droe = M1+M2+M3 \r
+ \r
+ return(Droe) \r
+\r
+\r
+def jacobianMatricesm(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+\r
+ if rho_l < 0 or rho_r < 0:\r
+ print("rho_l=", rho_l, " rho_r= ", rho_r)\r
+ raise ValueError("Negative density")\r
+ if rho_E_l < 0 or rho_E_r < 0:\r
+ print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r)\r
+ raise ValueError("Negative total energy")\r
+\r
+ RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+ return (RoeMat - Droe) * coeff * 0.5\r
+\r
+\r
+def jacobianMatricesp(coeff, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r):\r
+ if rho_l < 0 or rho_r < 0:\r
+ print("rho_l=", rho_l, " rho_r= ", rho_r)\r
+ raise ValueError("Negative density")\r
+ if rho_E_l < 0 or rho_E_r < 0:\r
+ print("rho_E_l=", rho_E_l, " rho_E_r= ", rho_E_r)\r
+ raise ValueError("Negative total energy")\r
+\r
+ RoeMat = MatRoe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ Droe = Droe_StiffenedGaz( rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r) \r
+\r
+ return (RoeMat + Droe) * coeff * 0.5\r
+\r
+\r
+def FillEdges(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit):\r
+ dUi = cdmath.Vector(3)\r
+\r
+ if (j == 0):\r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2]\r
+ \r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+\r
+ dUi[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp = Am * dUi\r
+\r
+ if(isImplicit):\r
+ Rhs[j * nbComp + 0] = -temp[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+\r
+ elif (j == nx - 1):\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+\r
+ dUi[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+\r
+ temp = Ap * dUi\r
+\r
+ if(isImplicit):\r
+ Rhs[j * nbComp + 0] = temp[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = temp[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = temp[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+\r
+def FillInnerCell(j, Uk, nbComp, divMat, Rhs, Un, dt, dx, isImplicit):\r
+\r
+ rho_l = Uk[(j - 1) * nbComp + 0]\r
+ q_l = Uk[(j - 1) * nbComp + 1]\r
+ rho_E_l = Uk[(j - 1) * nbComp + 2]\r
+ rho_r = Uk[j * nbComp + 0]\r
+ q_r = Uk[j * nbComp + 1]\r
+ rho_E_r = Uk[j * nbComp + 2]\r
+ Ap = jacobianMatricesp(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+ \r
+ rho_l = Uk[j * nbComp + 0]\r
+ q_l = Uk[j * nbComp + 1]\r
+ rho_E_l = Uk[j * nbComp + 2]\r
+ rho_r = Uk[(j + 1) * nbComp + 0]\r
+ q_r = Uk[(j + 1) * nbComp + 1]\r
+ rho_E_r = Uk[(j + 1) * nbComp + 2]\r
+ Am = jacobianMatricesm(dt / dx, rho_l, q_l, rho_E_l, rho_r, q_r, rho_E_r)\r
+\r
+ divMat.addValue(j * nbComp, (j + 1) * nbComp, Am)\r
+ divMat.addValue(j * nbComp, j * nbComp, Am * (-1.))\r
+ divMat.addValue(j * nbComp, j * nbComp, Ap)\r
+ divMat.addValue(j * nbComp, (j - 1) * nbComp, Ap * (-1.))\r
+ dUi1 = cdmath.Vector(3)\r
+ dUi2 = cdmath.Vector(3)\r
+ dUi1[0] = Uk[(j + 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi1[1] = Uk[(j + 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi1[2] = Uk[(j + 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+\r
+ dUi2[0] = Uk[(j - 1) * nbComp + 0] - Uk[j * nbComp + 0]\r
+ dUi2[1] = Uk[(j - 1) * nbComp + 1] - Uk[j * nbComp + 1]\r
+ dUi2[2] = Uk[(j - 1) * nbComp + 2] - Uk[j * nbComp + 2]\r
+ temp1 = Am * dUi1\r
+ temp2 = Ap * dUi2\r
+\r
+ if(isImplicit):\r
+ Rhs[j * nbComp + 0] = -temp1[0] + temp2[0] - (Uk[j * nbComp + 0] - Un[j * nbComp + 0])\r
+ Rhs[j * nbComp + 1] = -temp1[1] + temp2[1] - (Uk[j * nbComp + 1] - Un[j * nbComp + 1])\r
+ Rhs[j * nbComp + 2] = -temp1[2] + temp2[2] - (Uk[j * nbComp + 2] - Un[j * nbComp + 2])\r
+\r
+def SetPicture(rho_field_Roe, q_field_Roe, h_field_Roe, p_field_Roe, v_field_Roe, T_field_Roe, dx):\r
+ max_initial_rho = max(rho_field_Roe)\r
+ min_initial_rho = min(rho_field_Roe)\r
+ max_initial_q = max(q_field_Roe)\r
+ min_initial_q = min(q_field_Roe)\r
+ min_initial_h = min(h_field_Roe)\r
+ max_initial_h = max(h_field_Roe)\r
+ max_initial_p = max(p_field_Roe)\r
+ min_initial_p = min(p_field_Roe)\r
+ max_initial_v = max(v_field_Roe)\r
+ min_initial_v = min(v_field_Roe)\r
+ max_initial_T = max(T_field_Roe)\r
+ min_initial_T = min(T_field_Roe)\r
+\r
+ fig, ([axDensity, axMomentum, axRhoE],[axPressure, axVitesse, axTemperature]) = plt.subplots(2, 3,sharex=True, figsize=(14,10))\r
+ plt.gcf().subplots_adjust(wspace = 0.5)\r
+\r
+ lineDensity_Roe, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field_Roe, label='Roe')\r
+ axDensity.set(xlabel='x (m)', ylabel='Densité (kg/m3)')\r
+ axDensity.set_xlim(a,b)\r
+ #axDensity.set_ylim(min_initial_rho - 0.1 * (max_initial_rho - min_initial_rho), 700.)\r
+ axDensity.set_ylim(657, 660.5)\r
+ axDensity.legend()\r
+\r
+ lineMomentum_Roe, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field_Roe, label='Roe')\r
+ axMomentum.set(xlabel='x (m)', ylabel='Momentum (kg/(m2.s))')\r
+ axMomentum.set_xlim(a,b)\r
+ #axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q * 2.5)\r
+ axMomentum.set_ylim(-50, 500)\r
+ axMomentum.legend()\r
+ \r
+ lineRhoE_Roe, = axRhoE.plot([a+0.5*dx + i*dx for i in range(nx)], h_field_Roe, label='Roe')\r
+ axRhoE.set(xlabel='x (m)', ylabel='h (J/m3)')\r
+ axRhoE.set_xlim(a,b)\r
+ #axRhoE.set_ylim(min_initial_h - 0.05*abs(min_initial_h), max_initial_h + 0.5*(max_initial_h-min_initial_h))\r
+ axRhoE.set_ylim(1.495 * 10**6, 1.5*10**6)\r
+ axRhoE.legend()\r
+ \r
+ linePressure_Roe, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field_Roe, label='Roe')\r
+ axPressure.set(xlabel='x (m)', ylabel='Pression (bar)')\r
+ axPressure.set_xlim(a,b)\r
+ #axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.5*(max_initial_p-min_initial_p))\r
+ axPressure.set_ylim(149, 156)\r
+ axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axPressure.legend()\r
+\r
+ lineVitesse_Roe, = axVitesse.plot([a+0.5*dx + i*dx for i in range(nx)], v_field_Roe, label='Roe')\r
+ axVitesse.set(xlabel='x (m)', ylabel='Vitesse (m/s)')\r
+ axVitesse.set_xlim(a,b)\r
+ #axVitesse.set_ylim(min_initial_v - 0.05*abs(min_initial_v), 15)\r
+ axVitesse.set_ylim(-0.5, 1)\r
+ axVitesse.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axVitesse.legend()\r
+\r
+ lineTemperature_Roe, = axTemperature.plot([a+0.5*dx + i*dx for i in range(nx)], T_field_Roe, label='Roe')\r
+ axTemperature.set(xlabel='x (m)', ylabel='Température (K)')\r
+ axTemperature.set_xlim(a,b)\r
+ #axTemperature.set_ylim(min_initial_T - 0.005*abs(min_initial_T), 604)\r
+ axTemperature.set_ylim(600, 601)\r
+ axTemperature.ticklabel_format(axis='y', style='sci', scilimits=(0,0))\r
+ axTemperature.legend()\r
+ \r
+ 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)\r
+\r
+\r
+def EulerSystemRoe(ntmax, tmax, cfl, a, b, nbCells, output_freq, meshName, state_law):\r
+ #state_law_parameters(state_law)\r
+ dim = 1\r
+ nbComp = 3\r
+ dt = 0.\r
+ time = 0.\r
+ it = 0\r
+ isStationary = False\r
+ isImplicit = False\r
+ dx = (b - a) / nx\r
+ dt = cfl * dx / c0\r
+ #dt = 5*10**(-6)\r
+ nbVoisinsMax = 2\r
+\r
+ # iteration vectors\r
+ Un_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ dUn_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ dUk_Roe = cdmath.Vector(nbCells * (nbComp))\r
+ Rhs_Roe = cdmath.Vector(nbCells * (nbComp))\r
+\r
+ # Initial conditions\r
+ print("Construction of the initial condition …")\r
+\r
+ 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)\r
+ h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2\r
+ p_field_Roe = p_field_Roe * 10 ** (-5)\r
+ \r
+\r
+ for k in range(nbCells):\r
+ Un_Roe[k * nbComp + 0] = rho_field_Roe[k]\r
+ Un_Roe[k * nbComp + 1] = q_field_Roe[k]\r
+ Un_Roe[k * nbComp + 2] = rho_E_field_Roe[k]\r
+\r
+ divMat_Roe = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp, (nbVoisinsMax + 1) * nbComp)\r
+ \r
+ # Picture settings\r
+ 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)\r
+\r
+ # Video settings\r
+ FFMpegWriter = manimation.writers['ffmpeg']\r
+ metadata = dict(title="Roe scheme for the 1D Euler system", artist="CEA Saclay", comment="Shock tube")\r
+ writer = FFMpegWriter(fps=10, metadata=metadata, codec='h264')\r
+ with writer.saving(fig, "1DEuler_complet_RP_Roe" + ".mp4", ntmax):\r
+ writer.grab_frame()\r
+ plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "0" + ".png")\r
+ np.savetxt( "EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rho" + "0" + ".txt", rho_field_Roe, delimiter="\n")\r
+ np.savetxt( "EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_q" + "0" + ".txt", q_field_Roe, delimiter="\n")\r
+ iterGMRESMax = 50\r
+ newton_max = 100\r
+ \r
+ print("Starting computation of the non linear Euler non isentropic system with Roe scheme …")\r
+ # STARTING TIME LOOP\r
+ while (it < ntmax and time <= tmax and not isStationary):\r
+ dUn_Roe = Un_Roe.deepCopy()\r
+ Uk_Roe = Un_Roe.deepCopy()\r
+ residu_Roe = 1.\r
+ \r
+ k_Roe = 0\r
+ while (k_Roe < newton_max and residu_Roe > precision):\r
+ # STARTING NEWTON LOOP\r
+ divMat_Roe.zeroEntries() #sets the matrix coefficients to zero\r
+ for j in range(nbCells):\r
+ \r
+ # traitements des bords\r
+ if (j == 0):\r
+ FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+ elif (j == nbCells - 1):\r
+ FillEdges(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+ \r
+ # traitement des cellules internes\r
+ else:\r
+ FillInnerCell(j, Uk_Roe, nbComp, divMat_Roe, Rhs_Roe, Un_Roe, dt, dx, isImplicit)\r
+ \r
+ #solving the linear system divMat * dUk = Rhs\r
+ \r
+ if(isImplicit):\r
+ divMat_Roe.diagonalShift(1.)\r
+ LS_Roe = cdmath.LinearSolver(divMat_Roe, Rhs_Roe, iterGMRESMax, precision, "GMRES", "LU")\r
+ dUk_Roe = LS_Roe.solve()\r
+ residu_Roe = dUk_Roe.norm()\r
+ else:\r
+ dUk_Roe=Rhs_Roe - divMat_Roe*Un_Roe\r
+ residu_Roe = 0.#Convergence schéma Newton\r
+ \r
+ if (isImplicit and (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax)):\r
+ print("Residu Newton : ", residu_Roe)\r
+ print("Linear system converged in ", LS_Roe.getNumberOfIter(), " GMRES iterations")\r
+ \r
+ #updates for Newton loop\r
+ Uk_Roe += dUk_Roe\r
+ k_Roe = k_Roe + 1\r
+ if (isImplicit and not LS_Roe.getStatus()):\r
+ print("Linear system did not converge ", LS_Roe.getNumberOfIter(), " GMRES iterations")\r
+ raise ValueError("No convergence of the linear system")\r
+ \r
+ if k_Roe == newton_max:\r
+ raise ValueError("No convergence of Newton Roe Scheme")\r
+ \r
+ #updating fields\r
+ Un_Roe = Uk_Roe.deepCopy()\r
+ dUn_Roe -= Un_Roe\r
+ if (dUn_Roe.norm()<precision):\r
+ isStationary = True\r
+ \r
+ for k in range(nbCells):\r
+ rho_field_Roe[k] = Un_Roe[k * nbComp + 0]\r
+ q_field_Roe[k] = Un_Roe[k * nbComp + 1]\r
+ rho_E_field_Roe[k] = Un_Roe[k * nbComp + 2]\r
+ \r
+ v_field_Roe = q_field_Roe / rho_field_Roe\r
+ p_field_Roe = rho_to_p_StiffenedGaz(rho_field_Roe, q_field_Roe, rho_E_field_Roe)\r
+ T_field_Roe = rhoE_to_T_StiffenedGaz(rho_field_Roe, q_field_Roe, rho_E_field_Roe)\r
+ h_field_Roe = (rho_E_field_Roe + p_field_Roe) / rho_field_Roe - 0.5 * (q_field_Roe / rho_field_Roe) **2\r
+ p_field_Roe = p_field_Roe * 10 ** (-5)\r
+ \r
+ if( min(p_field_Roe)<0) :\r
+ raise ValueError("Negative pressure, stopping calculation")\r
+ \r
+ #picture and video updates\r
+ lineDensity_Roe.set_ydata(rho_field_Roe)\r
+ lineMomentum_Roe.set_ydata(q_field_Roe)\r
+ lineRhoE_Roe.set_ydata(h_field_Roe)\r
+ linePressure_Roe.set_ydata(p_field_Roe)\r
+ lineVitesse_Roe.set_ydata(v_field_Roe)\r
+ lineTemperature_Roe.set_ydata(T_field_Roe)\r
+ \r
+ writer.grab_frame()\r
+ \r
+ time = time + dt\r
+ it = it + 1\r
+ \r
+ # Savings\r
+ if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax):\r
+ \r
+ print("-- Time step : " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))\r
+ \r
+ plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + str(it) + '_time' + str(time) + ".png")\r
+\r
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))\r
+ if (it >= ntmax):\r
+ print("Maximum number of time steps ntmax= ", ntmax, " reached")\r
+ return\r
+\r
+ elif (isStationary):\r
+ print("Stationary regime reached at time step ", it, ", t= ", time)\r
+ print("------------------------------------------------------------------------------------")\r
+ np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rho_Stat.txt", rho_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_q_Stat.txt", q_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_rhoE_Stat.txt", rho_E_field_Roe, delimiter="\n")\r
+ np.savetxt("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_p_Stat.txt", p_field_Roe, delimiter="\n")\r
+ plt.savefig("EulerComplet_RP_" + str(dim) + "D_Roe" + meshName + "_Stat.png")\r
+ return\r
+ else:\r
+ print("Maximum time Tmax= ", tmax, " reached")\r
+ return\r
+\r
+\r
+def solve(a, b, nx, meshName, meshType, cfl, state_law):\r
+ print("Resolution of the Euler System in dimension 1 on " + str(nx) + " cells")\r
+ print("State Law Stiffened Gaz, " + state_law)\r
+ print("Initial data : ", "Riemann problem")\r
+ print("Boundary conditions : ", "Neumann")\r
+ print("Mesh name : ", meshName, ", ", nx, " cells")\r
+ # Problem data\r
+ tmax = 10.\r
+ ntmax = 25\r
+ output_freq = 1\r
+ EulerSystemRoe(ntmax, tmax, cfl, a, b, nx, output_freq, meshName, state_law)\r
+ return\r
+\r
+\r
+if __name__ == """__main__""":\r
+ a = 0.\r
+ b = 1.\r
+ nx = 50\r
+ cfl = 0.5\r
+ #state_law = "Hermite590K"\r
+ #state_law_parameters(state_law)\r
+ solve(a, b, nx, "RegularSquares", "", cfl, state_law)\r
--- /dev/null
+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)
+
+
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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<ntmax and time <= tmax and not isStationary):
+ dUn = Un.deepCopy()
+ Uk = Un.deepCopy()
+ residu = 1.
+ k=0
+ while (k<newton_max and residu > 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)
--- /dev/null
+
+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)
+
+
--- /dev/null
+# 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 and time <= tmax ):
+ # time step
+ dt=compTimeStep(UU,dx,CFL);
+ # Neumann boundary condition
+ UU_limL[0] = UU[0,0];
+ UU_limL[1] = UU[0,1];
+ UU_limR[0] = UU[M.getNumberOfCells()-1,0];
+ UU_limR[1] = UU[M.getNumberOfCells()-1,1];
+ flux_iminus = flux(UU_limL[0],UU_limL[1]);
+ #Main loop on cells
+ for i in range(0,M.getNumberOfCells()):
+ if (i<M.getNumberOfCells()-1):
+ Del_UU_RL[0]=UU[i+1,0]-UU[i,0];
+ Del_UU_RL[1]=UU[i+1,1]-UU[i,1];
+ AbsRoeMa = AbsRoeMatrix(UU[i,0],UU[i,1],UU[i+1,0],UU[i+1,1]);
+ flux_iplus = (flux(UU[i,0],UU[i,1])+flux(UU[i+1,0],UU[i+1,1]))-AbsRoeMa*Del_UU_RL;
+ flux_iplus[0]*=0.5;
+ flux_iplus[1]*=0.5;
+ else:
+ flux_iplus= flux(UU_limR[0],UU_limR[1]);
+ UU_new[i,0] = UU[i,0] - dt/dx*(flux_iplus[0]-flux_iminus[0]);
+ UU_new[i,1] = UU[i,1] - dt/dx*(flux_iplus[1]-flux_iminus[1]);
+ flux_iminus = flux_iplus;
+ pass
+ UU = UU_new;
+ time+=dt;
+ it+=1;
+
+ 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)]
+
+ lineDensity.set_ydata(rho_field)
+ lineMomentum.set_ydata(q_field)
+ lineVelocity.set_ydata(v_field)
+ linePressure.set_ydata(p_field)
+ writer.grab_frame()
+
+ if (it%freqSortie==0):
+ print( "-- Iter : ", it," Time : ",time," dt : ",dt)
+ plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_"+str(it)+".png")
+ pass
+
+ 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)+"UpwindExplicit"+meshName+"_Stat.png")
+ return
+ else:
+ print("Temps maximum Tmax= ", tmax, " atteint")
+
+ return
+
+if __name__ == '__main__':
+ main("SquareRegularSquares")
--- /dev/null
+
+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)
+
+
--- /dev/null
+# 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 and time <= tmax ):
+ # time step
+ dt=compTimeStep(UU,dx,CFL);
+ # Neumann boundary condition
+ UU_limL[0] = UU[0,0];
+ UU_limL[1] = UU[0,1];
+ UU_limR[0] = UU[M.getNumberOfCells()-1,0];
+ UU_limR[1] = UU[M.getNumberOfCells()-1,1];
+ flux_iminus = flux(UU_limL[0],UU_limL[1]);
+ #Main loop on cells
+ for i in range(0,M.getNumberOfCells()):
+ if (i<M.getNumberOfCells()-1):
+ Del_UU_RL[0]=UU[i+1,0]-UU[i,0];
+ Del_UU_RL[1]=UU[i+1,1]-UU[i,1];
+ AbsRoeMa = AbsRoeMatrix(UU[i,0],UU[i,1],UU[i+1,0],UU[i+1,1]);
+ flux_iplus = (flux(UU[i,0],UU[i,1])+flux(UU[i+1,0],UU[i+1,1]))-AbsRoeMa*Del_UU_RL - Del_UU_RL*abs(UU[i+1,1]/UU[i+1,0]-UU[i,1]/UU[i,0])#The last term is the entropic correction
+ flux_iplus[0]*=0.5;
+ flux_iplus[1]*=0.5;
+ else:
+ flux_iplus= flux(UU_limR[0],UU_limR[1]);
+ UU_new[i,0] = UU[i,0] - dt/dx*(flux_iplus[0]-flux_iminus[0]);
+ UU_new[i,1] = UU[i,1] - dt/dx*(flux_iplus[1]-flux_iminus[1]);
+ flux_iminus = flux_iplus;
+ pass
+ UU = UU_new;
+ time+=dt;
+ it+=1;
+
+ 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)]
+
+ lineDensity.set_ydata(rho_field)
+ lineMomentum.set_ydata(q_field)
+ lineVelocity.set_ydata(v_field)
+ linePressure.set_ydata(p_field)
+ writer.grab_frame()
+
+ if (it%freqSortie==0):
+ print( "-- Iter : ", it," Time : ",time," dt : ",dt)
+ plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_"+str(it)+".png")
+ pass
+
+ 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)+"UpwindExplicit"+meshName+"_Stat.png")
+ return
+ else:
+ print("Temps maximum Tmax= ", tmax, " atteint")
+
+ return
+
+if __name__ == '__main__':
+ main("SquareRegularSquares")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/usr/bin/env python3\r
+# -*-coding:utf-8 -*\r
+\r
+#===============================================================================================================================\r
+# Name : Résolution VF des équations d'Euler isotherme 2D sans terme source\r
+# \partial_t rho + \div q = 0\r
+# \partial_t q + \div q \otimes q/rho \grad p = 0\r
+# Author : Michaël Ndjinga, Coraline Mounier\r
+# Copyright : CEA Saclay 2020\r
+# Description : Propagation d'une onde de choc droite\r
+# Utilisation du schéma upwind explicite ou implicite sur un maillage général\r
+# Initialisation par une discontinuité verticale\r
+# Conditions aux limites de Neumann\r
+# Création et sauvegarde du champ résultant et des figures\r
+#================================================================================================================================\r
+\r
+\r
+import cdmath\r
+import numpy as np\r
+import matplotlib\r
+matplotlib.use("Agg")\r
+import matplotlib.pyplot as plt\r
+import matplotlib.animation as manimation\r
+from math import sqrt\r
+import sys\r
+import PV_routines\r
+\r
+p0=155.e5 #reference pressure in a pressurised nuclear vessel\r
+c0=700. #reference sound speed for water at 155 bars\r
+rho0=p0/(c0*c0) #reference density\r
+precision=1e-5\r
+\r
+def initial_conditions_Riemann_problem(my_mesh):\r
+ print( "Initial data : Riemann problem" )\r
+ dim = my_mesh.getMeshDimension()\r
+ nbCells = my_mesh.getNumberOfCells()\r
+\r
+ xcentre = 0.5\r
+\r
+ density_field = cdmath.Field("Density", cdmath.CELLS, my_mesh, 1)\r
+ q_x_field = cdmath.Field("Momentum x", cdmath.CELLS, my_mesh, 1)\r
+ q_y_field = cdmath.Field("Momentum y", cdmath.CELLS, my_mesh, 1)\r
+ #Velocity field with 3 components should be created for streamlines to be drawn\r
+ velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)\r
+\r
+ for i in range(nbCells):\r
+ x = my_mesh.getCell(i).x()\r
+\r
+ # Initial momentum is zero\r
+ q_x_field[i] = 0\r
+ q_y_field[i] = 0\r
+\r
+ # Initial velocity is zero\r
+ velocity_field[i,0] = 0\r
+ velocity_field[i,1] = 0\r
+ velocity_field[i,2] = 0\r
+\r
+ if x < xcentre:\r
+ density_field[i] = rho0\r
+ pass\r
+ else:\r
+ density_field[i] = rho0/2\r
+ pass\r
+ pass\r
+\r
+ return density_field, q_x_field, q_y_field, velocity_field\r
+\r
+\r
+def jacobianMatricesm_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
+ RoeMatx = cdmath.Matrix(3,3);\r
+ Dmacx = cdmath.Matrix(3,3);\r
+\r
+ u_lx=q_lx/rho_l\r
+ u_rx=q_rx/rho_r\r
+ u_ly=q_ly/rho_l\r
+ u_ry=q_ry/rho_r\r
+ if rho_l<0 or rho_r<0:\r
+ print("rho_l=",rho_l, " rho_r= ",rho_r)\r
+ raise ValueError("Negative density")\r
+ ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+ uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+\r
+ RoeMatx[0,0] = 0\r
+ RoeMatx[0,1] = 1\r
+ RoeMatx[0,2] = 0\r
+ RoeMatx[1,0] = c0*c0 - ux*ux\r
+ RoeMatx[1,1] = 2*ux\r
+ RoeMatx[1,2] = 0\r
+ RoeMatx[2,0] = -ux*uy\r
+ RoeMatx[2,1] = uy\r
+ RoeMatx[2,2] = ux\r
+\r
+ Dmacx[0,0] = abs(ux)-ux\r
+ Dmacx[0,1] = 1\r
+ Dmacx[0,2] = 0\r
+ Dmacx[1,0] = -c0*c0-ux*ux\r
+ Dmacx[1,1] = abs(ux)+ux\r
+ Dmacx[1,2] = 0\r
+ Dmacx[2,0] = -ux*uy\r
+ Dmacx[2,1] = uy\r
+ Dmacx[2,2] = abs(ux)\r
+\r
+ return (RoeMatx-Dmacx)*coeff*0.5\r
+\r
+def jacobianMatricesp_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
+ RoeMatx = cdmath.Matrix(3,3)\r
+ Dmacx = cdmath.Matrix(3,3)\r
+\r
+ u_lx=q_lx/rho_l\r
+ u_rx=q_rx/rho_r\r
+ u_ly=q_ly/rho_l\r
+ u_ry=q_ry/rho_r\r
+ if rho_l<0 or rho_r<0:\r
+ print("rho_l=",rho_l, " rho_r= ",rho_r)\r
+ raise ValueError("Negative density")\r
+ ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+ uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+\r
+ RoeMatx[0,0] = 0\r
+ RoeMatx[0,1] = 1\r
+ RoeMatx[0,2] = 0\r
+ RoeMatx[1,0] = c0*c0 - ux*ux\r
+ RoeMatx[1,1] = 2*ux\r
+ RoeMatx[1,2] = 0\r
+ RoeMatx[2,0] = -ux*uy\r
+ RoeMatx[2,1] = uy\r
+ RoeMatx[2,2] = ux\r
+\r
+ Dmacx[0,0] = abs(ux)-ux\r
+ Dmacx[0,1] = 1\r
+ Dmacx[0,2] = 0\r
+ Dmacx[1,0] = -c0*c0-ux*ux\r
+ Dmacx[1,1] = abs(ux)+ux\r
+ Dmacx[1,2] = 0\r
+ Dmacx[2,0] = -ux*uy\r
+ Dmacx[2,1] = uy\r
+ Dmacx[2,2] = abs(ux)\r
+\r
+ return (RoeMatx+Dmacx)*coeff*0.5\r
+\r
+def jacobianMatricesm_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
+ RoeMaty = cdmath.Matrix(3,3);\r
+ Dmacy = cdmath.Matrix(3,3);\r
+\r
+ u_lx=q_lx/rho_l\r
+ u_rx=q_rx/rho_r\r
+ u_ly=q_ly/rho_l\r
+ u_ry=q_ry/rho_r\r
+ if rho_l<0 or rho_r<0:\r
+ print("rho_l=",rho_l, " rho_r= ",rho_r)\r
+ raise ValueError("Negative density")\r
+ ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+ uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+\r
+ RoeMaty[0,0] = 0\r
+ RoeMaty[0,1] = 0\r
+ RoeMaty[0,2] = 1\r
+ RoeMaty[1,0] = -ux*uy\r
+ RoeMaty[1,1] = uy\r
+ RoeMaty[1,2] = ux\r
+ RoeMaty[2,0] = c0*c0-uy*uy\r
+ RoeMaty[2,1] = 0\r
+ RoeMaty[2,2] = 2*uy\r
+\r
+ Dmacy[0,0] = abs(uy)-uy\r
+ Dmacy[0,1] = 0\r
+ Dmacy[0,2] = 1\r
+ Dmacy[1,0] = -ux*uy\r
+ Dmacy[1,1] = abs(uy)\r
+ Dmacy[1,2] = ux\r
+ Dmacy[2,0] = -c0*c0-uy*uy\r
+ Dmacy[2,1] = 0\r
+ Dmacy[2,2] = abs(uy)+uy\r
+\r
+ return (RoeMaty-Dmacy)*coeff*0.5\r
+\r
+def jacobianMatricesp_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
+ RoeMaty = cdmath.Matrix(3,3);\r
+ Dmacy = cdmath.Matrix(3,3);\r
+\r
+ u_lx=q_lx/rho_l\r
+ u_rx=q_rx/rho_r\r
+ u_ly=q_ly/rho_l\r
+ u_ry=q_ry/rho_r\r
+ if rho_l<0 or rho_r<0:\r
+ print("rho_l=",rho_l, " rho_r= ",rho_r)\r
+ raise ValueError("Negative density")\r
+ ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+ uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
+\r
+ RoeMaty[0,0] = 0\r
+ RoeMaty[0,1] = 0\r
+ RoeMaty[0,2] = 1\r
+ RoeMaty[1,0] = -ux*uy\r
+ RoeMaty[1,1] = uy\r
+ RoeMaty[1,2] = ux\r
+ RoeMaty[2,0] = c0*c0-uy*uy\r
+ RoeMaty[2,1] = 0\r
+ RoeMaty[2,2] = 2*uy\r
+\r
+ Dmacy[0,0] = abs(uy)-uy\r
+ Dmacy[0,1] = 0\r
+ Dmacy[0,2] = 1\r
+ Dmacy[1,0] = -ux*uy\r
+ Dmacy[1,1] = abs(uy)\r
+ Dmacy[1,2] = ux\r
+ Dmacy[2,0] = -c0*c0-uy*uy\r
+ Dmacy[2,1] = 0\r
+ Dmacy[2,2] = abs(uy)+uy\r
+\r
+ return (RoeMaty+Dmacy)*coeff*0.5\r
+\r
+def EulerSystemStaggered(ntmax, tmax, cfl,output_freq, my_mesh, meshName):\r
+\r
+ if not my_mesh.isStructured() :\r
+ raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a structured mesh")\r
+\r
+ dim=my_mesh.getMeshDimension()\r
+ if dim != 2 :\r
+ raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a 2D mesh")\r
+\r
+ nbComp=dim+1\r
+ # Mesh parameters\r
+ nbCells = my_mesh.getNumberOfCells()\r
+ nbCells_x = my_mesh.getNx()\r
+ nbCells_y = my_mesh.getNy()\r
+ dx,dy = my_mesh.getDXYZ()\r
+ nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)\r
+ dx_min=my_mesh.minRatioVolSurf()\r
+ \r
+ # Time evolution parameters\r
+ time = 0.\r
+ it=0;\r
+ isStationary=False\r
+ iterGMRESMax = 50\r
+ newton_max = 50\r
+\r
+ #iteration vectors\r
+ Un =cdmath.Vector(nbCells*nbComp)\r
+ dUn=cdmath.Vector(nbCells*nbComp)\r
+ dUk=cdmath.Vector(nbCells*nbComp)\r
+ Rhs=cdmath.Vector(nbCells*nbComp)\r
+\r
+ dUi_x=cdmath.Vector(nbComp)\r
+ dUi_y=cdmath.Vector(nbComp)\r
+ dUi1_x=cdmath.Vector(nbComp)\r
+ dUi2_x=cdmath.Vector(nbComp)\r
+ dUi1_y=cdmath.Vector(nbComp)\r
+ dUi2_y=cdmath.Vector(nbComp)\r
+\r
+ # Initial conditions #\r
+ print("Construction of the initial condition …")\r
+ rho_field, q_x_field, q_y_field, velocity_field= initial_conditions_Riemann_problem(my_mesh)\r
+\r
+ for i in range(nbCells):\r
+ Un[nbComp*i] = rho_field[i]\r
+ Un[nbComp*i+1] = q_x_field[i]\r
+ Un[nbComp*i+2] = q_y_field[i]\r
+\r
+ #Sauvegarde de la donnée initiale\r
+ rho_field.setTime(time,it);\r
+ rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density");\r
+ q_x_field.setTime(time,it);\r
+ q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX");\r
+ q_y_field.setTime(time,it);\r
+ q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY");\r
+ velocity_field.setTime(time,it);\r
+ velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity");\r
+\r
+ print("Starting computation of the isothermal Euler system with a conservative staggered scheme …")\r
+ divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)\r
+\r
+ # Starting time loop\r
+ while (it<ntmax and time <= tmax and not isStationary):\r
+ dUn = Un.deepCopy()\r
+ Uk = Un.deepCopy()\r
+ residu = 1e10\r
+ k=0\r
+ while (k<newton_max and residu > 1/precision ):\r
+\r
+ 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\r
+ #DEBUT BOUCLE NEWTON\r
+ for j in range(nbCells_y):\r
+ for i in range(nbCells_x):\r
+ #Traitement des coins\r
+ if ( j==0 and i==0) :\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)-Am_y)\r
+\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+\r
+ temp_x = Am_x*dUi_x\r
+ temp_y = Am_y*dUi_y\r
+ #print("Bloc 0 matrix : ", Am)\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif(i==0 and j==nbCells_y-1):\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)+Ap_y)\r
+\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp_x = Am_x*dUi_x\r
+ temp_y = Ap_y*dUi_y\r
+ #print("Bloc 0 matrix : ", Am)\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif(i==nbCells_x-1 and j==0):\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_y)\r
+\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+\r
+ temp_x = Ap_x*dUi_x\r
+ temp_y= Am_y*dUi_y\r
+ #print("Bloc 0 matrix : ", Am)\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif ( j==nbCells_y-1 and i==nbCells_x-1) :\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y)\r
+\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp_x = Ap_x*dUi_x\r
+ temp_y = Ap_y*dUi_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ #Traitement des bords restants\r
+ elif i==0 :\r
+\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #remplissage de la divMat\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y-Am_x-Am_y)\r
+\r
+ #remplissage du membre de droite\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp_x = Am_x*dUi_x\r
+ temp1_y = Am_y*dUi1_y\r
+ temp2_y = Ap_y*dUi2_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif i==nbCells_x-1:\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #remplissage de la divMat\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y+Ap_x-Am_y)\r
+\r
+ #remplissage du membre de droite\r
+ dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp_x = Ap_x*dUi_x\r
+ temp1_y = Am_y*dUi1_y\r
+ temp2_y = Ap_y*dUi2_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif j==0:\r
+\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #remplissage de la divMat\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_x-Am_y)\r
+\r
+ #remplissage du membre de droite\r
+ dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+\r
+ temp1_x = Am_x*dUi1_x\r
+ temp2_x = Ap_x*dUi2_x\r
+ temp_y = Am_y*dUi_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ elif j==nbCells_y-1:\r
+\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #remplissage de la divMat\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x)\r
+\r
+ #remplissage du membre de droite\r
+ dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+ dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp1_x = Am_x*dUi1_x\r
+ temp2_x = Ap_x*dUi2_x\r
+ temp_y = Ap_y*dUi_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ #Traitement des autres cellules\r
+ else:\r
+\r
+ #Calcul de Am_x\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
+ qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
+ Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #Calcul de Ap_x\r
+ rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
+ qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Am_y\r
+ rho_l=Uk[3*nbCells_x*j+3*i]\r
+ qx_l =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*j+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
+ qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
+ Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #calcul de Ap_y\r
+ rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
+ qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
+ rho_r=Uk[3*nbCells_x*j+3*i]\r
+ qx_r =Uk[3*nbCells_x*j+3*i+1]\r
+ qy_r =Uk[3*nbCells_x*j+3*i+2]\r
+ Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
+\r
+ #remplissage de la divMat\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
+ divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x-Am_y)\r
+\r
+ #remplissage du membre de droite\r
+\r
+ dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
+\r
+ dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
+ dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
+ dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
+\r
+ dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
+ dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
+ dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
+\r
+ dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
+ dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
+ dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
+\r
+ temp1_x = Am_x*dUi1_x\r
+ temp2_x = Ap_x*dUi2_x\r
+ temp1_y = Am_y*dUi1_y\r
+ temp2_y = Ap_y*dUi2_y\r
+ 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])\r
+ 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])\r
+ 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])\r
+\r
+ divMat.diagonalShift(1) #only after filling all coefficients\r
+ LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU")\r
+ dUk=LS.solve();\r
+ residu = dUk.norm()\r
+ Uk+=dUk\r
+ #print("Newton iteration number ",k, "residu = ",residu)\r
+ if(not LS.getStatus()):\r
+ print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")\r
+ raise ValueError("Pas de convergence du système linéaire");\r
+ k=k+1\r
+ Un = Uk.deepCopy()\r
+ dUn-=Un\r
+ isStationary = dUn.norm()<precision\r
+ \r
+ for i in range(nbCells):\r
+ rho_field[i] = Un[nbComp*i]\r
+ q_x_field[i] = Un[nbComp*i+1]\r
+ q_y_field[i] = Un[nbComp*i+2]\r
+\r
+ time=time+dt;\r
+ it=it+1;\r
+ #Sauvegardes\r
+ if(it==1 or it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):\r
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) + ", Newton iterations: "+str(k)+", ||dUn|| = "+str(dUn.norm()))\r
+ print("Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations, résidu = ", residu)\r
+ for k in range(nbCells):\r
+ rho =rho_field[k]\r
+ velocity_field[k,0]=q_x_field[i]/rho\r
+ if(dim>1):\r
+ velocity_field[k,1]=q_y_field[k]/rho\r
+ print\r
+ rho_field.setTime(time,it);\r
+ rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density",False);\r
+ q_x_field.setTime(time,it);\r
+ q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX",False);\r
+ q_y_field.setTime(time,it);\r
+ q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY",False);\r
+ velocity_field.setTime(time,it);\r
+ velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity",False);\r
+ #Postprocessing : save 2D picture\r
+ 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))\r
+ 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))\r
+ 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))\r
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))\r
+ if(it>=ntmax):\r
+ print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")\r
+ return\r
+ elif(isStationary):\r
+ print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time)\r
+ print("------------------------------------------------------------------------------------")\r
+ return\r
+ else:\r
+ print("Temps maximum Tmax= ", tmax, " atteint")\r
+ return\r
+\r
+def solve( my_mesh,filename, resolution):\r
+ print("Resolution of the Isothermal Euler system in dimension 2 on "+str(my_mesh.getNumberOfCells())+ " cells")\r
+ print("Initial data : ", "Riemann problem")\r
+ print("Boundary conditions : ", "Neumann")\r
+ print("Mesh name : ",filename )\r
+ # Problem data\r
+ tmax = 10.\r
+ ntmax = 10\r
+ cfl=1\r
+ output_freq = 1\r
+ EulerSystemStaggered(ntmax, tmax, cfl, output_freq, my_mesh, filename)\r
+ return\r
+\r
+if __name__ == """__main__""":\r
+ if len(sys.argv) >1 :\r
+ filename=sys.argv[1]\r
+ my_mesh = cdmath.Mesh(filename)\r
+ else :\r
+ filename = "CartesianGrid"\r
+ ax=0;bx=1;nx=20;\r
+ ay=0;by=1;ny=10; \r
+ my_mesh = cdmath.Mesh(ax,bx,nx,ay,by,ny)\r
+\r
+ solve(my_mesh,filename,100)\r
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ divMat.zeroEntries()#sets the matrix coefficients to zero
+ vp_max=computeDivergenceMatrix(my_mesh,divMat,Un)#To update at each time step
+ dt = cfl * dx_min / vp_max#To update at each time step
+
+ if(isImplicit):
+ #Adding the identity matrix on the diagonal
+ divMat.diagonalShift(1)#only after filling all coefficients
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ else:
+ dUn=divMat*Un
+# print(Un)
+ Un-=dUn
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+
+ for k in range(nbCells):
+ pressure_field[k] =Un[k*(dim+1)+0]*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)")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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<ntmax and time <= tmax and not isStationary):
- dUn = Un.deepCopy()
- Uk = Un.deepCopy()
- residu = 1.
- k=0
- while (k<newton_max and residu > 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)
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# 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 and time <= tmax ):
- # time step
- dt=compTimeStep(UU,dx,CFL);
- # Neumann boundary condition
- UU_limL[0] = UU[0,0];
- UU_limL[1] = UU[0,1];
- UU_limR[0] = UU[M.getNumberOfCells()-1,0];
- UU_limR[1] = UU[M.getNumberOfCells()-1,1];
- flux_iminus = flux(UU_limL[0],UU_limL[1]);
- #Main loop on cells
- for i in range(0,M.getNumberOfCells()):
- if (i<M.getNumberOfCells()-1):
- Del_UU_RL[0]=UU[i+1,0]-UU[i,0];
- Del_UU_RL[1]=UU[i+1,1]-UU[i,1];
- AbsRoeMa = AbsRoeMatrix(UU[i,0],UU[i,1],UU[i+1,0],UU[i+1,1]);
- flux_iplus = (flux(UU[i,0],UU[i,1])+flux(UU[i+1,0],UU[i+1,1]))-AbsRoeMa*Del_UU_RL;
- flux_iplus[0]*=0.5;
- flux_iplus[1]*=0.5;
- else:
- flux_iplus= flux(UU_limR[0],UU_limR[1]);
- UU_new[i,0] = UU[i,0] - dt/dx*(flux_iplus[0]-flux_iminus[0]);
- UU_new[i,1] = UU[i,1] - dt/dx*(flux_iplus[1]-flux_iminus[1]);
- flux_iminus = flux_iplus;
- pass
- UU = UU_new;
- time+=dt;
- it+=1;
-
- 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)]
-
- lineDensity.set_ydata(rho_field)
- lineMomentum.set_ydata(q_field)
- lineVelocity.set_ydata(v_field)
- linePressure.set_ydata(p_field)
- writer.grab_frame()
-
- if (it%freqSortie==0):
- print( "-- Iter : ", it," Time : ",time," dt : ",dt)
- plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_"+str(it)+".png")
- pass
-
- 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)+"UpwindExplicit"+meshName+"_Stat.png")
- return
- else:
- print("Temps maximum Tmax= ", tmax, " atteint")
-
- return
-
-if __name__ == '__main__':
- main("SquareRegularSquares")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# 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 and time <= tmax ):
- # time step
- dt=compTimeStep(UU,dx,CFL);
- # Neumann boundary condition
- UU_limL[0] = UU[0,0];
- UU_limL[1] = UU[0,1];
- UU_limR[0] = UU[M.getNumberOfCells()-1,0];
- UU_limR[1] = UU[M.getNumberOfCells()-1,1];
- flux_iminus = flux(UU_limL[0],UU_limL[1]);
- #Main loop on cells
- for i in range(0,M.getNumberOfCells()):
- if (i<M.getNumberOfCells()-1):
- Del_UU_RL[0]=UU[i+1,0]-UU[i,0];
- Del_UU_RL[1]=UU[i+1,1]-UU[i,1];
- AbsRoeMa = AbsRoeMatrix(UU[i,0],UU[i,1],UU[i+1,0],UU[i+1,1]);
- flux_iplus = (flux(UU[i,0],UU[i,1])+flux(UU[i+1,0],UU[i+1,1]))-AbsRoeMa*Del_UU_RL - Del_UU_RL*abs(UU[i+1,1]/UU[i+1,0]-UU[i,1]/UU[i,0])#The last term is the entropic correction
- flux_iplus[0]*=0.5;
- flux_iplus[1]*=0.5;
- else:
- flux_iplus= flux(UU_limR[0],UU_limR[1]);
- UU_new[i,0] = UU[i,0] - dt/dx*(flux_iplus[0]-flux_iminus[0]);
- UU_new[i,1] = UU[i,1] - dt/dx*(flux_iplus[1]-flux_iminus[1]);
- flux_iminus = flux_iplus;
- pass
- UU = UU_new;
- time+=dt;
- it+=1;
-
- 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)]
-
- lineDensity.set_ydata(rho_field)
- lineMomentum.set_ydata(q_field)
- lineVelocity.set_ydata(v_field)
- linePressure.set_ydata(p_field)
- writer.grab_frame()
-
- if (it%freqSortie==0):
- print( "-- Iter : ", it," Time : ",time," dt : ",dt)
- plt.savefig("EulerSystem"+str(dim)+"UpwindExplicit"+meshName+"_"+str(it)+".png")
- pass
-
- 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)+"UpwindExplicit"+meshName+"_Stat.png")
- return
- else:
- print("Temps maximum Tmax= ", tmax, " atteint")
-
- return
-
-if __name__ == '__main__':
- main("SquareRegularSquares")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/usr/bin/env python3\r
-# -*-coding:utf-8 -*\r
-\r
-#===============================================================================================================================\r
-# Name : Résolution VF des équations d'Euler isotherme 2D sans terme source\r
-# \partial_t rho + \div q = 0\r
-# \partial_t q + \div q \otimes q/rho \grad p = 0\r
-# Author : Michaël Ndjinga, Coraline Mounier\r
-# Copyright : CEA Saclay 2020\r
-# Description : Propagation d'une onde de choc droite\r
-# Utilisation du schéma upwind explicite ou implicite sur un maillage général\r
-# Initialisation par une discontinuité verticale\r
-# Conditions aux limites de Neumann\r
-# Création et sauvegarde du champ résultant et des figures\r
-#================================================================================================================================\r
-\r
-\r
-import cdmath\r
-import numpy as np\r
-import matplotlib\r
-matplotlib.use("Agg")\r
-import matplotlib.pyplot as plt\r
-import matplotlib.animation as manimation\r
-from math import sqrt\r
-import sys\r
-import PV_routines\r
-\r
-p0=155.e5 #reference pressure in a pressurised nuclear vessel\r
-c0=700. #reference sound speed for water at 155 bars\r
-rho0=p0/(c0*c0) #reference density\r
-precision=1e-5\r
-\r
-def initial_conditions_Riemann_problem(my_mesh):\r
- print( "Initial data : Riemann problem" )\r
- dim = my_mesh.getMeshDimension()\r
- nbCells = my_mesh.getNumberOfCells()\r
-\r
- xcentre = 0.5\r
-\r
- density_field = cdmath.Field("Density", cdmath.CELLS, my_mesh, 1)\r
- q_x_field = cdmath.Field("Momentum x", cdmath.CELLS, my_mesh, 1)\r
- q_y_field = cdmath.Field("Momentum y", cdmath.CELLS, my_mesh, 1)\r
- #Velocity field with 3 components should be created for streamlines to be drawn\r
- velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)\r
-\r
- for i in range(nbCells):\r
- x = my_mesh.getCell(i).x()\r
-\r
- # Initial momentum is zero\r
- q_x_field[i] = 0\r
- q_y_field[i] = 0\r
-\r
- # Initial velocity is zero\r
- velocity_field[i,0] = 0\r
- velocity_field[i,1] = 0\r
- velocity_field[i,2] = 0\r
-\r
- if x < xcentre:\r
- density_field[i] = rho0\r
- pass\r
- else:\r
- density_field[i] = rho0/2\r
- pass\r
- pass\r
-\r
- return density_field, q_x_field, q_y_field, velocity_field\r
-\r
-\r
-def jacobianMatricesm_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
- RoeMatx = cdmath.Matrix(3,3);\r
- Dmacx = cdmath.Matrix(3,3);\r
-\r
- u_lx=q_lx/rho_l\r
- u_rx=q_rx/rho_r\r
- u_ly=q_ly/rho_l\r
- u_ry=q_ry/rho_r\r
- if rho_l<0 or rho_r<0:\r
- print("rho_l=",rho_l, " rho_r= ",rho_r)\r
- raise ValueError("Negative density")\r
- ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
- uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
-\r
- RoeMatx[0,0] = 0\r
- RoeMatx[0,1] = 1\r
- RoeMatx[0,2] = 0\r
- RoeMatx[1,0] = c0*c0 - ux*ux\r
- RoeMatx[1,1] = 2*ux\r
- RoeMatx[1,2] = 0\r
- RoeMatx[2,0] = -ux*uy\r
- RoeMatx[2,1] = uy\r
- RoeMatx[2,2] = ux\r
-\r
- Dmacx[0,0] = abs(ux)-ux\r
- Dmacx[0,1] = 1\r
- Dmacx[0,2] = 0\r
- Dmacx[1,0] = -c0*c0-ux*ux\r
- Dmacx[1,1] = abs(ux)+ux\r
- Dmacx[1,2] = 0\r
- Dmacx[2,0] = -ux*uy\r
- Dmacx[2,1] = uy\r
- Dmacx[2,2] = abs(ux)\r
-\r
- return (RoeMatx-Dmacx)*coeff*0.5\r
-\r
-def jacobianMatricesp_x(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
- RoeMatx = cdmath.Matrix(3,3)\r
- Dmacx = cdmath.Matrix(3,3)\r
-\r
- u_lx=q_lx/rho_l\r
- u_rx=q_rx/rho_r\r
- u_ly=q_ly/rho_l\r
- u_ry=q_ry/rho_r\r
- if rho_l<0 or rho_r<0:\r
- print("rho_l=",rho_l, " rho_r= ",rho_r)\r
- raise ValueError("Negative density")\r
- ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
- uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
-\r
- RoeMatx[0,0] = 0\r
- RoeMatx[0,1] = 1\r
- RoeMatx[0,2] = 0\r
- RoeMatx[1,0] = c0*c0 - ux*ux\r
- RoeMatx[1,1] = 2*ux\r
- RoeMatx[1,2] = 0\r
- RoeMatx[2,0] = -ux*uy\r
- RoeMatx[2,1] = uy\r
- RoeMatx[2,2] = ux\r
-\r
- Dmacx[0,0] = abs(ux)-ux\r
- Dmacx[0,1] = 1\r
- Dmacx[0,2] = 0\r
- Dmacx[1,0] = -c0*c0-ux*ux\r
- Dmacx[1,1] = abs(ux)+ux\r
- Dmacx[1,2] = 0\r
- Dmacx[2,0] = -ux*uy\r
- Dmacx[2,1] = uy\r
- Dmacx[2,2] = abs(ux)\r
-\r
- return (RoeMatx+Dmacx)*coeff*0.5\r
-\r
-def jacobianMatricesm_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
- RoeMaty = cdmath.Matrix(3,3);\r
- Dmacy = cdmath.Matrix(3,3);\r
-\r
- u_lx=q_lx/rho_l\r
- u_rx=q_rx/rho_r\r
- u_ly=q_ly/rho_l\r
- u_ry=q_ry/rho_r\r
- if rho_l<0 or rho_r<0:\r
- print("rho_l=",rho_l, " rho_r= ",rho_r)\r
- raise ValueError("Negative density")\r
- ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
- uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
-\r
- RoeMaty[0,0] = 0\r
- RoeMaty[0,1] = 0\r
- RoeMaty[0,2] = 1\r
- RoeMaty[1,0] = -ux*uy\r
- RoeMaty[1,1] = uy\r
- RoeMaty[1,2] = ux\r
- RoeMaty[2,0] = c0*c0-uy*uy\r
- RoeMaty[2,1] = 0\r
- RoeMaty[2,2] = 2*uy\r
-\r
- Dmacy[0,0] = abs(uy)-uy\r
- Dmacy[0,1] = 0\r
- Dmacy[0,2] = 1\r
- Dmacy[1,0] = -ux*uy\r
- Dmacy[1,1] = abs(uy)\r
- Dmacy[1,2] = ux\r
- Dmacy[2,0] = -c0*c0-uy*uy\r
- Dmacy[2,1] = 0\r
- Dmacy[2,2] = abs(uy)+uy\r
-\r
- return (RoeMaty-Dmacy)*coeff*0.5\r
-\r
-def jacobianMatricesp_y(coeff,rho_l,q_lx,q_ly,rho_r,q_rx,q_ry):\r
- RoeMaty = cdmath.Matrix(3,3);\r
- Dmacy = cdmath.Matrix(3,3);\r
-\r
- u_lx=q_lx/rho_l\r
- u_rx=q_rx/rho_r\r
- u_ly=q_ly/rho_l\r
- u_ry=q_ry/rho_r\r
- if rho_l<0 or rho_r<0:\r
- print("rho_l=",rho_l, " rho_r= ",rho_r)\r
- raise ValueError("Negative density")\r
- ux = (u_lx*sqrt(rho_l)+u_rx*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
- uy = (u_ly*sqrt(rho_l)+u_ry*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));\r
-\r
- RoeMaty[0,0] = 0\r
- RoeMaty[0,1] = 0\r
- RoeMaty[0,2] = 1\r
- RoeMaty[1,0] = -ux*uy\r
- RoeMaty[1,1] = uy\r
- RoeMaty[1,2] = ux\r
- RoeMaty[2,0] = c0*c0-uy*uy\r
- RoeMaty[2,1] = 0\r
- RoeMaty[2,2] = 2*uy\r
-\r
- Dmacy[0,0] = abs(uy)-uy\r
- Dmacy[0,1] = 0\r
- Dmacy[0,2] = 1\r
- Dmacy[1,0] = -ux*uy\r
- Dmacy[1,1] = abs(uy)\r
- Dmacy[1,2] = ux\r
- Dmacy[2,0] = -c0*c0-uy*uy\r
- Dmacy[2,1] = 0\r
- Dmacy[2,2] = abs(uy)+uy\r
-\r
- return (RoeMaty+Dmacy)*coeff*0.5\r
-\r
-def EulerSystemStaggered(ntmax, tmax, cfl,output_freq, my_mesh, meshName):\r
-\r
- if not my_mesh.isStructured() :\r
- raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a structured mesh")\r
-\r
- dim=my_mesh.getMeshDimension()\r
- if dim != 2 :\r
- raise ValueError("Euler_ConservativeStaggered2D_RiemannProblem.py expects a 2D mesh")\r
-\r
- nbComp=dim+1\r
- # Mesh parameters\r
- nbCells = my_mesh.getNumberOfCells()\r
- nbCells_x = my_mesh.getNx()\r
- nbCells_y = my_mesh.getNy()\r
- dx,dy = my_mesh.getDXYZ()\r
- nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)\r
- dx_min=my_mesh.minRatioVolSurf()\r
- \r
- # Time evolution parameters\r
- time = 0.\r
- it=0;\r
- isStationary=False\r
- iterGMRESMax = 50\r
- newton_max = 50\r
-\r
- #iteration vectors\r
- Un =cdmath.Vector(nbCells*nbComp)\r
- dUn=cdmath.Vector(nbCells*nbComp)\r
- dUk=cdmath.Vector(nbCells*nbComp)\r
- Rhs=cdmath.Vector(nbCells*nbComp)\r
-\r
- dUi_x=cdmath.Vector(nbComp)\r
- dUi_y=cdmath.Vector(nbComp)\r
- dUi1_x=cdmath.Vector(nbComp)\r
- dUi2_x=cdmath.Vector(nbComp)\r
- dUi1_y=cdmath.Vector(nbComp)\r
- dUi2_y=cdmath.Vector(nbComp)\r
-\r
- # Initial conditions #\r
- print("Construction of the initial condition …")\r
- rho_field, q_x_field, q_y_field, velocity_field= initial_conditions_Riemann_problem(my_mesh)\r
-\r
- for i in range(nbCells):\r
- Un[nbComp*i] = rho_field[i]\r
- Un[nbComp*i+1] = q_x_field[i]\r
- Un[nbComp*i+2] = q_y_field[i]\r
-\r
- #Sauvegarde de la donnée initiale\r
- rho_field.setTime(time,it);\r
- rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density");\r
- q_x_field.setTime(time,it);\r
- q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX");\r
- q_y_field.setTime(time,it);\r
- q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY");\r
- velocity_field.setTime(time,it);\r
- velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity");\r
-\r
- print("Starting computation of the isothermal Euler system with a conservative staggered scheme …")\r
- divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)\r
-\r
- # Starting time loop\r
- while (it<ntmax and time <= tmax and not isStationary):\r
- dUn = Un.deepCopy()\r
- Uk = Un.deepCopy()\r
- residu = 1e10\r
- k=0\r
- while (k<newton_max and residu > 1/precision ):\r
-\r
- 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\r
- #DEBUT BOUCLE NEWTON\r
- for j in range(nbCells_y):\r
- for i in range(nbCells_x):\r
- #Traitement des coins\r
- if ( j==0 and i==0) :\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)-Am_y)\r
-\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
-\r
- temp_x = Am_x*dUi_x\r
- temp_y = Am_y*dUi_y\r
- #print("Bloc 0 matrix : ", Am)\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif(i==0 and j==nbCells_y-1):\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Am_x*(-1.)+Ap_y)\r
-\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp_x = Am_x*dUi_x\r
- temp_y = Ap_y*dUi_y\r
- #print("Bloc 0 matrix : ", Am)\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif(i==nbCells_x-1 and j==0):\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_y)\r
-\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
- dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
-\r
- temp_x = Ap_x*dUi_x\r
- temp_y= Am_y*dUi_y\r
- #print("Bloc 0 matrix : ", Am)\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif ( j==nbCells_y-1 and i==nbCells_x-1) :\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y)\r
-\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
- dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp_x = Ap_x*dUi_x\r
- temp_y = Ap_y*dUi_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- #Traitement des bords restants\r
- elif i==0 :\r
-\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #remplissage de la divMat\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y-Am_x-Am_y)\r
-\r
- #remplissage du membre de droite\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp_x = Am_x*dUi_x\r
- temp1_y = Am_y*dUi1_y\r
- temp2_y = Ap_y*dUi2_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif i==nbCells_x-1:\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #remplissage de la divMat\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_y+Ap_x-Am_y)\r
-\r
- #remplissage du membre de droite\r
- dUi_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
- dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp_x = Ap_x*dUi_x\r
- temp1_y = Am_y*dUi1_y\r
- temp2_y = Ap_y*dUi2_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif j==0:\r
-\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #remplissage de la divMat\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x-Am_x-Am_y)\r
-\r
- #remplissage du membre de droite\r
- dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
- dUi_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
-\r
- temp1_x = Am_x*dUi1_x\r
- temp2_x = Ap_x*dUi2_x\r
- temp_y = Am_y*dUi_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- elif j==nbCells_y-1:\r
-\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #remplissage de la divMat\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x)\r
-\r
- #remplissage du membre de droite\r
- dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
- dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
- dUi_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp1_x = Am_x*dUi1_x\r
- temp2_x = Ap_x*dUi2_x\r
- temp_y = Ap_y*dUi_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- #Traitement des autres cellules\r
- else:\r
-\r
- #Calcul de Am_x\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*(i+1)]\r
- qx_r =Uk[3*nbCells_x*j+3*(i+1)+1]\r
- qy_r =Uk[3*nbCells_x*j+3*(i+1)+2]\r
- Am_x= jacobianMatricesm_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #Calcul de Ap_x\r
- rho_l=Uk[3*nbCells_x*j+3*(i-1)]\r
- qx_l =Uk[3*nbCells_x*j+3*(i-1)+1]\r
- qy_l =Uk[3*nbCells_x*j+3*(i-1)+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_x= jacobianMatricesp_x(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Am_y\r
- rho_l=Uk[3*nbCells_x*j+3*i]\r
- qx_l =Uk[3*nbCells_x*j+3*i+1]\r
- qy_l =Uk[3*nbCells_x*j+3*i+2]\r
- rho_r=Uk[3*nbCells_x*(j+1)+3*i]\r
- qx_r =Uk[3*nbCells_x*(j+1)+3*i+1]\r
- qy_r =Uk[3*nbCells_x*(j+1)+3*i+2]\r
- Am_y= jacobianMatricesm_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #calcul de Ap_y\r
- rho_l=Uk[3*nbCells_x*(j-1)+3*i]\r
- qx_l =Uk[3*nbCells_x*(j-1)+3*i+1]\r
- qy_l =Uk[3*nbCells_x*(j-1)+3*i+2]\r
- rho_r=Uk[3*nbCells_x*j+3*i]\r
- qx_r =Uk[3*nbCells_x*j+3*i+1]\r
- qy_r =Uk[3*nbCells_x*j+3*i+2]\r
- Ap_y= jacobianMatricesp_y(dt/dx,rho_l,qx_l,qy_l,rho_r,qx_r,qy_r)\r
-\r
- #remplissage de la divMat\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i-1),Ap_x*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j-1)+3*i,Ap_y*(-1.))\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*(i+1),Am_x)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*(j+1)+3*i,Am_y)\r
- divMat.addValue(3*nbCells_x*j+3*i,3*nbCells_x*j+3*i,Ap_x+Ap_y-Am_x-Am_y)\r
-\r
- #remplissage du membre de droite\r
-\r
- dUi1_x[0] = Uk[3*nbCells_x*j+3*(i+1)]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_x[1] = Uk[3*nbCells_x*j+3*(i+1)+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_x[2] = Uk[3*nbCells_x*j+3*(i+1)+2]-Uk[3*nbCells_x*j+3*i+2]\r
-\r
- dUi2_x[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*j+3*(i-1)]\r
- dUi2_x[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*j+3*(i-1)+1]\r
- dUi2_x[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*j+3*(i-1)+2]\r
-\r
- dUi1_y[0] = Uk[3*nbCells_x*(j+1)+3*i]-Uk[3*nbCells_x*j+3*i]\r
- dUi1_y[1] = Uk[3*nbCells_x*(j+1)+3*i+1]-Uk[3*nbCells_x*j+3*i+1]\r
- dUi1_y[2] = Uk[3*nbCells_x*(j+1)+3*i+2]-Uk[3*nbCells_x*j+3*i+2]\r
-\r
- dUi2_y[0] = Uk[3*nbCells_x*j+3*i]-Uk[3*nbCells_x*(j-1)+3*i]\r
- dUi2_y[1] = Uk[3*nbCells_x*j+3*i+1]-Uk[3*nbCells_x*(j-1)+3*i+1]\r
- dUi2_y[2] = Uk[3*nbCells_x*j+3*i+2]-Uk[3*nbCells_x*(j-1)+3*i+2]\r
-\r
- temp1_x = Am_x*dUi1_x\r
- temp2_x = Ap_x*dUi2_x\r
- temp1_y = Am_y*dUi1_y\r
- temp2_y = Ap_y*dUi2_y\r
- 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])\r
- 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])\r
- 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])\r
-\r
- divMat.diagonalShift(1) #only after filling all coefficients\r
- LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU")\r
- dUk=LS.solve();\r
- residu = dUk.norm()\r
- Uk+=dUk\r
- #print("Newton iteration number ",k, "residu = ",residu)\r
- if(not LS.getStatus()):\r
- print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")\r
- raise ValueError("Pas de convergence du système linéaire");\r
- k=k+1\r
- Un = Uk.deepCopy()\r
- dUn-=Un\r
- isStationary = dUn.norm()<precision\r
- \r
- for i in range(nbCells):\r
- rho_field[i] = Un[nbComp*i]\r
- q_x_field[i] = Un[nbComp*i+1]\r
- q_y_field[i] = Un[nbComp*i+2]\r
-\r
- time=time+dt;\r
- it=it+1;\r
- #Sauvegardes\r
- if(it==1 or it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):\r
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) + ", Newton iterations: "+str(k)+", ||dUn|| = "+str(dUn.norm()))\r
- print("Linear system converged in ", LS.getNumberOfIter(), " GMRES iterations, résidu = ", residu)\r
- for k in range(nbCells):\r
- rho =rho_field[k]\r
- velocity_field[k,0]=q_x_field[i]/rho\r
- if(dim>1):\r
- velocity_field[k,1]=q_y_field[k]/rho\r
- print\r
- rho_field.setTime(time,it);\r
- rho_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_density",False);\r
- q_x_field.setTime(time,it);\r
- q_x_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumX",False);\r
- q_y_field.setTime(time,it);\r
- q_y_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_momentumY",False);\r
- velocity_field.setTime(time,it);\r
- velocity_field.writeVTK("EulerIsothermal_"+str(dim)+"DConservativeStaggered_"+meshName+"_velocity",False);\r
- #Postprocessing : save 2D picture\r
- 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))\r
- 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))\r
- 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))\r
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))\r
- if(it>=ntmax):\r
- print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")\r
- return\r
- elif(isStationary):\r
- print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time)\r
- print("------------------------------------------------------------------------------------")\r
- return\r
- else:\r
- print("Temps maximum Tmax= ", tmax, " atteint")\r
- return\r
-\r
-def solve( my_mesh,filename, resolution):\r
- print("Resolution of the Isothermal Euler system in dimension 2 on "+str(my_mesh.getNumberOfCells())+ " cells")\r
- print("Initial data : ", "Riemann problem")\r
- print("Boundary conditions : ", "Neumann")\r
- print("Mesh name : ",filename )\r
- # Problem data\r
- tmax = 10.\r
- ntmax = 10\r
- cfl=1\r
- output_freq = 1\r
- EulerSystemStaggered(ntmax, tmax, cfl, output_freq, my_mesh, filename)\r
- return\r
-\r
-if __name__ == """__main__""":\r
- if len(sys.argv) >1 :\r
- filename=sys.argv[1]\r
- my_mesh = cdmath.Mesh(filename)\r
- else :\r
- filename = "CartesianGrid"\r
- ax=0;bx=1;nx=20;\r
- ay=0;by=1;ny=10; \r
- my_mesh = cdmath.Mesh(ax,bx,nx,ay,by,ny)\r
-\r
- solve(my_mesh,filename,100)\r
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- divMat.zeroEntries()#sets the matrix coefficients to zero
- vp_max=computeDivergenceMatrix(my_mesh,divMat,Un)#To update at each time step
- dt = cfl * dx_min / vp_max#To update at each time step
-
- if(isImplicit):
- #Adding the identity matrix on the diagonal
- divMat.diagonalShift(1)#only after filling all coefficients
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- if(not LS.getStatus()):
- print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- else:
- dUn=divMat*Un
- Un-=dUn
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
-
- for k in range(nbCells):
- pressure_field[k] =Un[k*(dim+1)+0]*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)")
--- /dev/null
+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)
+
+
--- /dev/null
+
+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 )
+
+
--- /dev/null
+#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+ u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+ total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
+
+ time = 0.
+ it = 0
+ output_freq = 10
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Explicit scheme for heat equation", artist = "CEA Saclay", comment="CFL="+str(cfl)+", Stable if CFL<1")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
+ plt.title("Explicit scheme for the heat equation, CFL="+str(cfl))
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ un=deepcopy(u)
+ for i in range(nx):
+ u[i] = un[i] + d * dt / (dx*dx) * (un[(i+1)%nx] -2*un[i] + un[(i-1)%nx])/2
+
+ time += dt
+ it += 1
+
+ if cfl<1 :
+ assert max(u) <= max_initial
+ assert min(u) >= 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)
+
--- /dev/null
+
+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 )
+
+
--- /dev/null
+#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+ u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+ total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
+
+ time = 0.
+ it = 0
+ output_freq = 10
+
+ #Initialisation of the linear system
+ systemMat=implicitSchemeMatrix(nx,cfl)
+ iterGMRESMax=50
+ precision=1.e-5
+ Un =cdmath.Vector(nx)
+ for i in range(nx):
+ Un[i]=u[i]
+ LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
+ LS.setComputeConditionNumber()
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Implicit scheme for heat equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL number")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
+ plt.title("Implicit scheme for heat equation, "+"CFL="+str(cfl))
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ # Solve linear system
+ for i in range(nx):
+ Un[i]=u[i]
+ LS.setSndMember(Un)
+ Un=LS.solve()
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ for i in range(nx):
+ u[i]=Un[i]
+
+ assert max(u) <= max_initial
+ assert min(u) >= 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)
+
+++ /dev/null
-
-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 )
-
-
+++ /dev/null
-#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
- u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
- total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
-
- time = 0.
- it = 0
- output_freq = 10
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Explicit scheme for heat equation", artist = "CEA Saclay", comment="CFL="+str(cfl)+", Stable if CFL<1")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
- plt.title("Explicit scheme for the heat equation, CFL="+str(cfl))
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("HeatEquation1D_Explicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- un=deepcopy(u)
- for i in range(nx):
- u[i] = un[i] + d * dt / (dx*dx) * (un[(i+1)%nx] -2*un[i] + un[(i-1)%nx])/2
-
- time += dt
- it += 1
-
- if cfl<1 :
- assert max(u) <= max_initial
- assert min(u) >= 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)
-
+++ /dev/null
-
-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 )
-
-
+++ /dev/null
-#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
- u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
- total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
-
- time = 0.
- it = 0
- output_freq = 10
-
- #Initialisation of the linear system
- systemMat=implicitSchemeMatrix(nx,cfl)
- iterGMRESMax=50
- precision=1.e-5
- Un =cdmath.Vector(nx)
- for i in range(nx):
- Un[i]=u[i]
- LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
- LS.setComputeConditionNumber()
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Implicit scheme for heat equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL number")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
- plt.title("Implicit scheme for heat equation, "+"CFL="+str(cfl))
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- # Solve linear system
- for i in range(nx):
- Un[i]=u[i]
- LS.setSndMember(Un)
- Un=LS.solve()
- if(not LS.getStatus()):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- for i in range(nx):
- u[i]=Un[i]
-
- assert max(u) <= max_initial
- assert min(u) >= 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)
-
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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" )
-
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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.
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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.
+++ /dev/null
-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)
-
-
+++ /dev/null
-#!/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.
--- /dev/null
+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)
+
+
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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" )
+
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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.
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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.
--- /dev/null
+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)
+
+
--- /dev/null
+#!/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.
--- /dev/null
+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)
+
+
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+# -*-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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-# -*-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")
+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)
--- /dev/null
+
+if (CDMATH_WITH_PYTHON )
+
+ ADD_TEST(ExampleTransportEquation_2DUpwind_Explicit ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/TransportEquationUpwind.py)
+
+endif (CDMATH_WITH_PYTHON )
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ if(isImplicit):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un+S*dt)
+ Un=LS.solve();
+ if(not LS.getStatus()):
+ print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ else:
+ dUn=divMat*Un-S*dt
+ Un-=dUn
+
+ maxVector=dUn.maxVector(1)
+ isStationary= maxVector[0]<precision
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : ", 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()<precision
+ print( "------------------------------------------------------------------------------------")
+
+ unknown_field.setTime(time,0);
+ unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat");
+
+ #Postprocessing : Extraction of the diagonal data
+ if(dim==2):
+ diag_data_u=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,1,0],[1,0,0], resolution)
+ elif(dim==3):
+ diag_data_u=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,0,0],[1,1,1], resolution)
+ #Postprocessing : save 2D picture
+ PV_routines.Save_PV_data_to_picture_file("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat"+'_0.vtu',"unknown",'CELLS',"TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat")
+
+ return nbCells, time, it, unknown_field.getNormEuclidean().max(), diag_data_u
+ else:
+ print( "Temps maximum Tmax= ", tmax, " atteint" )
+ raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")
+
+
+def solve(my_mesh, meshName, resolution, meshType, cfl, test_bc):
+ print( "Resolution of the Transport Equation in dimension ", my_mesh.getMeshDimension() )
+ print( "Numerical method : ", "Upwind" )
+ print( "Initial data : ", "Spherical shock" )
+ print( "Mesh name : ",meshName , ", ", my_mesh.getNumberOfCells(), " cells" )
+
+ # Problem data
+ tmax = 10000.
+ ntmax = 30000
+ output_freq = 1000
+
+ isImplicit=True
+
+ dim=my_mesh.getMeshDimension()
+ velocity=cdmath.Vector(dim)
+ for i in range(dim) :
+ velocity[i] = 1
+
+ nbCells, t_final, ndt_final, max_unknown, diag_data_u = TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, test_bc, velocity,isImplicit)
+
+ return nbCells, t_final, ndt_final, max_unknown, diag_data_u
+
+def solve_file( filename,meshName, resolution,meshType, cfl, test_bc):
+ my_mesh = cdmath.Mesh(filename+".med")
+
+ return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution, meshType, cfl, test_bc)
+
+
+if __name__ == """__main__""":
+ M1=cdmath.Mesh(0.,1.,20,0.,1.,20,0)
+ cfl=0.5
+ solve(M1,"SquareRegularTriangles",100,"Regular triangles",cfl,"Periodic")
+
--- /dev/null
+#!/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./3<xi)*int(xi<2./3) for xi in x];# to be used with a=0, b=1
+ tmax = (b-a)/c # runs the simulation for 0 <= t <= tMax
+ ntmax = ceil(tmax/dt)
+
+ u = deepcopy(u_initial)
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+
+ time = 0.
+ it = 0
+ output_freq = int(10/cfl)
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Centered explicit scheme for transport equation", artist = "CEA Saclay", comment="CFL="+str(cfl)+", Stable if CFL<1")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "1DTransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.5*(max_initial-min_initial), max_initial + 0.5*(max_initial-min_initial) )
+ plt.title('Centered explicit scheme for transport equation')
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ un=deepcopy(u)
+ for i in range(nx):
+ u[i] = un[i] - c * dt / dx * (un[(i+1)%nx] - un[(i-1)%nx])/2
+
+ 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_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n")
+ plt.savefig("TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_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 1D transport equation with explicit centered scheme done" )
+
+ 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) >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)
+
--- /dev/null
+
+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 )
+
+
--- /dev/null
+#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+ u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+ total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
+
+ time = 0.
+ it = 0
+ output_freq = 10
+
+ #Linear system initialisation
+ systemMat=centeredSchemeMatrix(nx,cfl)
+ iterGMRESMax=50
+ precision=1.e-5
+ Un =cdmath.Vector(nx)
+ for i in range(nx):
+ Un[i]=u[i]
+ LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
+ LS.setComputeConditionNumber()
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Centered implicit scheme for transport equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL>0")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "1DTransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
+ plt.title("Centered implicit scheme for transport equation, "+"CFL="+str(cfl))
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ # Solve linear system
+ for i in range(nx):
+ Un[i]=u[i]
+ LS.setSndMember(Un)
+ Un=LS.solve()
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ for i in range(nx):
+ u[i]=Un[i]
+
+ if ( max(u) > max_initial ):
+ print( "-- Iter: " + str(it) + " max principle violated : max(t) > max(0) : max(t)= ",max(u), " max(0)= ", max_initial )
+ if ( min(u) < min_initial ):
+ print( "-- Iter: " + str(it) + " min principle violated : min(t) < min(0) : min(t)= ",min(u), " min(0)= ", min_initial )
+ if ( np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) > total_var_initial ):
+ print( "-- Iter: " + str(it) + " total variation increased : var(t) > var(0) : var(t)= ", np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), " var(0)= ", total_var_initial )
+
+ time += dt
+ it += 1
+
+ # Postprocessing
+ line1.set_ydata(u)
+ 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)
+
--- /dev/null
+
+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 )
+
+
--- /dev/null
+#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+ u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+ total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
+
+ time = 0.
+ it = 0
+ output_freq = 10
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Upwind explicit scheme for transport equation, CFL="+str(cfl), artist = "CEA Saclay", comment="Stable if CFL<1")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "1DTransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
+ plt.title("Upwind explicit scheme for transport equation, CFL="+str(cfl))
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ un=deepcopy(u)
+ for i in range(nx):
+ u[i] = un[i] - c * dt / dx * (un[i] - un[(i-1)%nx])
+
+ time += dt
+ it += 1
+
+ if cfl<1 :
+ assert max(u) <= max_initial
+ assert min(u) >= 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)
+
--- /dev/null
+
+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 )
+
+
--- /dev/null
+#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+ u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
+
+ max_initial=max(u_initial)
+ min_initial=min(u_initial)
+ total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
+
+ time = 0.
+ it = 0
+ output_freq = 10
+
+ #Linear system initialisation
+ systemMat=upwindSchemeMatrix(nx,cfl)
+ iterGMRESMax=50
+ Un =cdmath.Vector(nx)
+ for i in range(nx):
+ Un[i]=u[i]
+ LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
+
+ # Video settings
+ FFMpegWriter = manimation.writers['ffmpeg']
+ metadata = dict(title="Upwind implicit scheme for transport equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL>0")
+ writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
+ with writer.saving(plt.figure(), "1DTransportEquation_UpwindImplicit_"+str(nx)+"CELLS_CFL"+str(cfl)+".mp4", ntmax):
+ ########################### Postprocessing initialisation
+ # Picture frame
+ plt.legend()
+ plt.xlabel('x')
+ plt.ylabel('u')
+ plt.xlim(a,b)
+ plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
+ plt.title("Upwind implicit scheme for transport equation, "+"CFL="+str(cfl))
+ line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
+
+ print("Starting time loop")
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ np.savetxt( "TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
+ writer.grab_frame()
+ plt.savefig("TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
+
+ ############################# Time loop
+ while (it < ntmax and time <= tmax):
+ # Solve linear system
+ for i in range(nx):
+ Un[i]=u[i]
+ LS.setSndMember(Un)
+ Un=LS.solve()
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ for i in range(nx):
+ u[i]=Un[i]
+
+ time += dt
+ it += 1
+
+ assert max(u) <= max_initial
+ assert min(u) >= 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)
+
--- /dev/null
+
+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 )
+
+
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- if(isImplicit):
- dUn=Un.deepCopy()
- LS.setSndMember(Un+S*dt)
- Un=LS.solve();
- if(not LS.getStatus()):
- print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- else:
- dUn=divMat*Un-S*dt
- Un-=dUn
-
- maxVector=dUn.maxVector(1)
- isStationary= maxVector[0]<precision
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : ", 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()<precision
- print( "------------------------------------------------------------------------------------")
-
- unknown_field.setTime(time,0);
- unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat");
-
- #Postprocessing : Extraction of the diagonal data
- if(dim==2):
- diag_data_u=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,1,0],[1,0,0], resolution)
- elif(dim==3):
- diag_data_u=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,0,0],[1,1,1], resolution)
- #Postprocessing : save 2D picture
- PV_routines.Save_PV_data_to_picture_file("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat"+'_0.vtu',"unknown",'CELLS',"TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat")
-
- return nbCells, time, it, unknown_field.getNormEuclidean().max(), diag_data_u
- else:
- print( "Temps maximum Tmax= ", tmax, " atteint" )
- raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")
-
-
-def solve(my_mesh, meshName, resolution, meshType, cfl, test_bc):
- print( "Resolution of the Transport Equation in dimension ", my_mesh.getMeshDimension() )
- print( "Numerical method : ", "Upwind" )
- print( "Initial data : ", "Spherical shock" )
- print( "Mesh name : ",meshName , ", ", my_mesh.getNumberOfCells(), " cells" )
-
- # Problem data
- tmax = 10000.
- ntmax = 30000
- output_freq = 1000
-
- isImplicit=True
-
- dim=my_mesh.getMeshDimension()
- velocity=cdmath.Vector(dim)
- for i in range(dim) :
- velocity[i] = 1
-
- nbCells, t_final, ndt_final, max_unknown, diag_data_u = TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, test_bc, velocity,isImplicit)
-
- return nbCells, t_final, ndt_final, max_unknown, diag_data_u
-
-def solve_file( filename,meshName, resolution,meshType, cfl, test_bc):
- my_mesh = cdmath.Mesh(filename+".med")
-
- return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution, meshType, cfl, test_bc)
-
-
-if __name__ == """__main__""":
- M1=cdmath.Mesh(0.,1.,20,0.,1.,20,0)
- cfl=0.5
- solve(M1,"SquareRegularTriangles",100,"Regular triangles",cfl,"Periodic")
-
--- /dev/null
+//============================================================================
+// 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 <iostream>
+#include <cmath>
+//#include<complex>
+
+//#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 ; j<nbCells ; j++)
+ {
+ x = M.getCell(j).x() ;
+ //cout<<"cellule "<< j<<" x= "<< x<<" milieu= "<< milieu <<endl;
+ if (x<milieu)
+ Temp(j) = TempLeft;
+ else
+ Temp(j) = TempRight;
+ }
+}
+
+
+double sign(double x)
+{
+ if(x>0)
+ return 1.;
+ else if(x<0)
+ return -1.;
+ else
+ return 0.;
+}
+
+
+double theta_upwind(double Tim1, double Ti, double Tip1, double Tip2, double VitesseX, double dt, double Tin, double Tip1n)
+{
+ if(abs(Tip1-Ti)<1.e-5)
+ return 1.;
+
+ double denominateur = abs(VitesseX)*(2.-sign(Tip1-Ti)*(sign(Tip2-Tip1)+sign(Ti-Tim1)));
+
+ if( abs(denominateur) <=1.e-5 )
+ return 0.5;
+ else
+ {
+ double result = (1-sign(Tip1-Ti)*sign(Ti-Tim1))/denominateur;
+ if(result <0.5)
+ return 0.5;
+ else
+ return result;
+ }
+}
+
+
+void solveTriDiag(vector<double>& a,vector<double>& b,vector<double>& c,Field &d, int nbCells)
+{
+ int n= nbCells;
+
+ if(a.size()!=c.size() || a.size()+1 != b.size() || n != (int) b.size() || n != (int) (d.getMesh()).getNumberOfCells())
+ throw CdmathException("solveTriDiag(): vectors with inapropriate size");
+
+/* cout<<"avant solveTri"<<endl;
+ for(int i=0;i<nbCells-2;i++)
+ cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
+
+ /* Algorithme de résolution d'un Système Tridiagonal*/
+ n--; // since we start from x0 (not x1)
+ c[0] /= b[0];
+ d[0] /= b[0];
+ for (int i = 1; i < n; i++) {
+ c[i] /= b[i] - a[i-1]*c[i-1];
+ d[i] = (d[i] - a[i-1]*d[i-1]) / (b[i] - a[i-1]*c[i-1]);
+ }
+
+ d[n] = (d[n] - a[n-1]*d[n-1]) / (b[n] - a[n-1]*c[n-1]);
+
+ for (int i = n; i-- > 0;) {
+ d[i] -= c[i]*d[i+1];
+ }
+
+ /*cout<<"apres solveTri"<<endl;
+ for(int i=0;i<nbCells-2;i++)
+ cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
+}
+
+
+void solveEntreeImplicit(Field& phi, Field& Temp, int nbCells, double VitesseX, double cfl, double Tentree, double dt) {
+
+ /* Coefficients de la matrice tridiagonalee liee au systeme*/
+ /*b=coeff diag, c= coeff au dessus diag, a= coeff sous diag */
+ vector<double> a(nbCells-1),b(nbCells),c(nbCells-1);
+ double theta, epsilon=1.e-2, erreur=1/epsilon;
+ int iterMax=100, k=0;
+ Field d, ScndMbre=phi, Tempn=Temp;
+ ScndMbre*=dt;
+ ScndMbre+=Tempn;//On obtient Tn+dt*phi
+ //On décentre le terme source
+ for (int i = 1; i < nbCells-1; i++)
+ {
+ ScndMbre[i]-=cfl*(phi[i]-phi[i-1])*dt/2;
+ }
+ ScndMbre[0]-=cfl*(phi[0])*dt/2;
+ //d[0]-=cfl*(phi[n-1]-phi[n-2]);
+
+ if(nbCells<3)
+ throw CdmathException("solveEntreeImplicit(): mesh should have at least three cells");
+
+ while( k<iterMax && erreur>epsilon)
+ {
+ d= ScndMbre;//contiendra le second membre du système
+ /*cout<< " Debut itération d= "<<endl;
+ for(int i=0;i<nbCells-1;i++)
+ cout<< " , "<< d(i);
+ cout<<endl;*/
+ cout<<"theta="<<endl;
+ /* On traite la première face (entrée) */
+ theta=theta_upwind(Tentree,Tentree,Temp(0),Temp(1),VitesseX, dt, Tentree, Tempn(0));
+ b[0]=1+ cfl*(2*theta-1);
+ c[0]=(1-theta)*cfl;
+ d(0)+=theta*cfl*Tentree;
+
+ cout<< theta << " , ";
+
+ /* On traite la deuxième face interne */
+ theta=theta_upwind(Tentree,Temp(0),Temp(1),Temp(2),VitesseX, dt, Tempn(0), Tempn(1));
+ b[1]=1+ cfl*(2*theta-1);
+ c[1]=(1-theta)*cfl;
+ a[0]=-theta*cfl;
+
+ cout<< theta << " , ";
+
+ //On traite les faces internes
+ for(int i=2; i<nbCells-2; i++)
+ {
+ theta=theta_upwind(Temp(i-2),Temp(i-1),Temp(i),Temp(i+1),VitesseX, dt, Tempn(i-1), Tempn(i));
+ b[i]=1+ cfl*(2*theta-1);
+ c[i]=(1-theta)*cfl;
+ a[i-1]=-theta*cfl;
+ cout<< theta << " , ";
+ }
+
+ /* On traite l'avant dernière face interne */
+ theta=theta_upwind(Temp(nbCells-3),Temp(nbCells-2),Temp(nbCells-1),Temp(nbCells-1),VitesseX, dt, Tempn(nbCells-2), Tempn(nbCells-1));
+ b[nbCells-2]=1+ cfl*(2*theta-1);
+ c[nbCells-2]=(1-theta)*cfl;
+ a[nbCells-3]=-theta*cfl;
+
+ cout<< theta << " , ";
+
+ /* On traite la dernière face (sortie) */
+ theta=theta_upwind(Temp(nbCells-2),Temp(nbCells-1),Temp(nbCells-1),Temp(nbCells-1),VitesseX, dt, Tempn(nbCells-1), Tempn(nbCells));
+ b[nbCells-1]=1+ cfl*theta;
+ a[nbCells-2]=-theta*cfl;
+ //d(nbCells-1)+=-(1-theta_sortie)*cfl*Tempn(nbCells-1);
+
+ cout<< theta << endl;
+
+ cout<<" k= " << k<<endl;
+ /*cout<<"avant solveTri"<<endl;
+ for(int i=0;i<nbCells-2;i++)
+ cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
+ solveTriDiag(a,b,c,d,nbCells);
+ /*cout<<"après solveTri"<<endl;
+ for(int i=0;i<nbCells-2;i++)
+ cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
+ k++;
+ erreur = 0;
+ for(int i=0;i<nbCells; i++)
+ erreur=max(erreur, abs(Temp(i)-d[i])/300);
+ cout<< " erreur= "<<erreur<<endl;
+ /*cout<< " Fin itération d= "<<endl;
+ for(int i=0;i<nbCells-1;i++)
+ cout<< " , "<< d(i);
+ cout<<endl;*/
+ Temp=d;
+// for(int i=0;i<nbCells-1;i++)
+// cout<< " Temp= "<< Temp(i)<<endl;
+ }
+
+ if(k>=iterMax)
+ throw CdmathException("solveEntreeImplicit: Newton scheme not convergent");
+}
+
+
+void EquationTransport1D_entree(double tmax, double VitesseX, int ntmax, double dt, double cfl,int freqSortie, const Mesh& M, const string file, double milieu, double TempLeft, double TempRight)
+{
+ /* --------------------------------------------- */
+ /* Condition initiale */
+ cout << "Construction de la condition initiale ... " << endl;
+ Field Temp("Temperature",CELLS,M,1) ;
+ champ_heaviside(Temp,milieu,TempLeft, TempRight);
+
+ /*terme source */
+ cout << "Construction du terme source ... " << endl;
+ Field phi("Flux thermique",CELLS,M,1) ;
+ champ_heaviside(phi,milieu,-10, 10);
+ /*
+ * Sortie MED de la condition initiale et du flux thermique à t=0 et iter = 0
+ */
+ int iter=0;
+ double time=0.;
+ int nbCells=M.getNumberOfCells();
+ cout << "Post-traitement MED du flux thermique constant en temps"<< " ..." << endl;
+ //phi.setTime(time,iter);
+ //phi.writeCSV(file);
+ cout << "Post-traitement MED de la solution à t=" << time << " ..." << endl;
+ Temp.setTime(time,iter);
+ //Temp.writeCSV(file);
+ Temp.writeVTK(file);
+ /* boucle de temps */
+ cout << " Resolution de l'equation de transport 1D avec entree par un schema Implicite TVD" << endl;
+
+ while (iter<ntmax && time <= tmax )
+ {
+ cout << "-- Iter : " << iter << " Time : " << time << " dt : " << dt << endl;
+
+ /* Avancement en temps */
+ solveEntreeImplicit(phi, Temp,nbCells, VitesseX, cfl, TempLeft, dt);
+ time+=dt;
+ iter+=1;
+ // sortie visu tous les freq iterations
+ if (iter%freqSortie==0)
+ {
+ Temp.setTime(time,iter);
+ Temp.writeVTK(file,false);
+ //Temp.writeCSV(file);
+ }
+ }
+}
+
+
+int Equation_Transport()
+{
+ cout << "RESOLUTION EQUATION DE TRANSPORT 1D :" << endl;
+ cout << "- DOMAINE : Segment 0,10" << endl;
+ cout << "- MAILLAGE CARTESIEN : GENERATION INTERNE CDMATH " << endl;
+
+ // Problem data
+ double VitesseX=1.0;
+ double tmax=100.;
+ int freqSortie=1;
+ int ntmax=3;
+ int nx=50;
+ double xinf=0.0;
+ double xsup=10.;
+ double dx=(xsup-xinf)/nx;
+ double cfl=1;
+ double dt=cfl*dx/abs(VitesseX);
+
+ double TempLeft=300;//285.;
+ double TempRight=300;//315.;
+
+ cout << "Début Construction du maillage Cartesien…" << endl;
+ Mesh M(xinf,xsup,nx);
+ cout << "Fin Construction du maillage Cartesien…" << endl;
+
+ // theta=1;
+ EquationTransport1D_entree(tmax, VitesseX, ntmax, dt, cfl, freqSortie, M, "TemperatureEntreeImplicitTVD50CellsSourceUpwind", (xsup+xinf)/2, TempLeft, TempRight);
+ //EquationTransport1D_entree(tmax, VitesseX, ntmax, dt, cfl, freqSortie, M, "TemperatureEntreeImplicitUpwindCreneau50Cells", (xsup+xinf)/4, TempLeft, TempRight);
+
+ cout << "CDMATH calculation done." << endl;
+ return 0;
+}
+
+
+int main() {
+/* Test solveur tridiagonal
+ int n=6;
+ Matrix A2(n,n,n+2*(n-1));
+
+ A2(0,0)=2.;
+ vector<double> e(n-1);
+ for(int i=0;i<n-1;i++)
+ {
+ e[i]=-1/(i+1);
+ A2(i,i+1)=-1/(i+1);
+ A2(i+1,i)=-1.;
+ A2(i+1,i+1)=2.;
+ }
+ Vector Xana2(n);
+ for(int i=0;i<n;i++)
+ Xana2(i)=i;
+
+ Vector B2=A2*Xana2;
+
+ LinearSolver LS11(A2,B2,500,1.E-10,"GMRES","ILU");
+ Vector X11=LS11.solve();
+ bool correct=true;
+ for (int i=0;i<X11.getNumberOfRows();i++)
+ correct=correct && (abs(X11(i)-Xana2(i))<1.E-10);
+
+ if(correct)
+ cout<<"OK"<<endl;
+ else
+ cout<<"KO"<<endl;
+ vector<double> 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<nbCells;i++)
+ d[i]=B2(i);
+ solveTriDiag(a,b,e,d,nbCells);
+ correct=true;
+ for (int i=0;i<X11.getNumberOfRows();i++)
+ correct=correct && (abs(d(i)-Xana2(i))<1.E-10);
+
+ if(correct)
+ cout<<"OK"<<endl;
+ else
+ cout<<"KO"<<endl;
+
+ Fin Test solveur tridiagonal */
+
+ int ret=Equation_Transport();
+ return ret;
+}
--- /dev/null
+# thermique1d makefile
+
+CC = g++
+
+# Adapt the following lines to your own system:
+PETSCDIR = /usr/lib/petscdir/3.4.5
+MPIDIR = /usr/lib/openmpi
+CDMATHDIR = ../../../../..
+
+IFLAG = -I$(PETSCDIR)/include -I$(MPIDIR)/include -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
--- /dev/null
+//============================================================================
+// Author : Anouar MEKKAS
+// Version :
+// Description : 1D linear transport equation
+//============================================================================
+
+#include <iostream>
+#include <cmath>
+
+#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<myMesh.getNumberOfCells() ; i++)
+ {
+ double x=myMesh.getCell(i).x();
+ conc(i) = 0.5/(sigma*sqrt(2*pi))*exp(-0.5*pow((x/sigma),2));
+ }
+
+ double time=0.;
+ double tmax=3.0;
+ int iter=0;
+
+ cout << "MED post-treatment of the solution at T=" << time << "…" << endl;
+ string fileOutPut="EqTr1D";
+ conc.setTime(time,iter);
+ conc.writeMED(fileOutPut);
+ conc.writeVTK(fileOutPut);
+ conc.writeCSV(fileOutPut);
+ int outputFreq=10;
+
+ // Time loop
+ while (iter<ntmax && time <= tmax )
+ {
+ cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
+ conc(0) = conc(0) -u*dt/dx*(conc(0)-conc(myMesh.getNumberOfCells()-1));
+ for (int j=1 ; j<myMesh.getNumberOfCells() ; j++)
+ {
+ conc(j) = conc(j) -u*dt/dx*(conc(j)-conc(j-1));
+ }
+ time+=dt;
+ iter+=1;
+ if (iter%outputFreq==0)
+ {
+ conc.setTime(time,iter);
+ conc.writeMED(fileOutPut,false);
+ conc.writeVTK(fileOutPut,false);
+ conc.writeCSV(fileOutPut);
+ }
+ }
+ cout << "CDMATH calculation done." << endl;
+ return 0;
+}
+
+
--- /dev/null
+#!/usr/bin/env python
+# -*-coding:utf-8 -*
+
+import math
+
+import cdmath
+
+
+def main():
+ a = -5.0
+ b = 5.0
+ nx = 1000
+ ntmax = 1000
+ dx = (b - a) / nx
+ pi = 3.1415927
+ # Transport velocity
+ cfl = 0.5
+ u = 3.
+ dt = cfl * dx / u
+
+ my_mesh = cdmath.Mesh(a, b, nx)
+ conc = cdmath.Field("Concentration", cdmath.CELLS, my_mesh, 1)
+
+ # Initial conditions
+ sigma = math.sqrt(0.2)
+ for i in range(my_mesh.getNumberOfCells()):
+ x = my_mesh.getCell(i).x()
+ conc[i] = 0.5 / (sigma * math.sqrt(2 * pi)) * math.exp(-0.5 * math.pow((x / sigma), 2))
+ pass
+
+ time = 0.
+ tmax = 3.0
+ it = 0
+
+ print("MED post-treatment of the solution at T=" + str(time) + "…")
+ output_filename = "EqTr1D"
+ conc.setTime(time, it)
+ conc.writeMED(output_filename)
+ conc.writeVTK(output_filename)
+ conc.writeCSV(output_filename)
+ output_freq = 10
+
+ # Time loop
+ while (it < ntmax and time <= tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ conc[0] = conc[0] - u * dt / dx * (conc[0] - conc[my_mesh.getNumberOfCells() - 1])
+ for j in range(1, my_mesh.getNumberOfCells()):
+ conc[j] = conc[j] - u * dt / dx * (conc[j] - conc[j - 1])
+ pass
+ time += dt
+ it += 1
+ if (it % output_freq == 0):
+ conc.setTime(time, it)
+ conc.writeMED(output_filename, False)
+ conc.writeVTK(output_filename, False)
+ conc.writeCSV(output_filename)
+ pass
+ pass
+ print("CDMATH calculation done.")
+ return
+
+
+if __name__ == """__main__""":
+ main()
--- /dev/null
+# Transport1d 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 *.med
--- /dev/null
+//============================================================================
+// Author : Anouar MEKKAS
+// Version :
+// Description : Equation de transport lineaire 2D non structure
+//============================================================================
+
+#include <iostream>
+#include <string>
+#include <cmath>
+
+#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 ; j<nbCells ; j++)
+ {
+ double x = myMesh.getCell(j).x() ;
+ double y = myMesh.getCell(j).y() ;
+ double valX=(x-xcentre)*(x-xcentre);
+ double valY=(y-ycentre)*(y-ycentre);
+ double val=sqrt(valX+valY);
+ if (val<rayon)
+ yField(j) = 1.0;
+ else
+ yField(j) = 0.0;
+ }
+}
+
+void sigma_flux(double VitesseX, double VitesseY, double cfl, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
+{
+ // Calculation of fluxes
+ Mesh myMesh=yField.getMesh();
+ int nbCells=myMesh.getNumberOfCells();
+ double normU=sqrt(VitesseX*VitesseX+VitesseY*VitesseY);
+ for (int j=0 ; j<nbCells ; j++)
+ {
+ Cell Cj=myMesh.getCell(j);
+ int nbFace=Cj.getNumberOfFaces();
+ double SumF=0.0;
+ double minlengthFk=1.E30;
+
+ int cellCourante,cellAutre;
+ for (int k=0 ; k<nbFace ; k++)
+ {
+ int indexFace=Cj.getFacesId()[k];
+ Face Fk=myMesh.getFace(indexFace);
+ double NormalX=Cj.getNormalVector(k,0);
+ double NormalY=Cj.getNormalVector(k,1);
+ double LengthFk = Fk.getMeasure();
+ double UN=VitesseX*NormalX+VitesseY*NormalY;
+
+ minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseX));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseY));
+
+ double conc=0.0;
+ cellCourante=j;
+ cellAutre=-1;
+
+ if (!Fk.isBorder())
+ {
+ int indexC1=Fk.getCellsId()[0];
+ int indexC2=Fk.getCellsId()[1];
+ /* hypothese: La cellule d'index indexC1 est la cellule courante index j */
+ if ( indexC1 == j )
+ {
+ /* hypothese verifie */
+ cellCourante=indexC1;
+ cellAutre=indexC2;
+ } else if ( indexC2 == j )
+ {
+ /* hypothese non verifie */
+ cellCourante=indexC2;
+ cellAutre=indexC1;
+ }
+ // definir la cellule gauche et droite par le prduit vitesse * normale sortante
+ // si u*n>0 : rien a faire sinon inverser la gauche et la droite
+ if (UN>1.E-15)
+ conc=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 (iter<ntmax && time <= tmax )
+ {
+ Field SumFlux("Fluxes sum",CELLS,myMesh,1) ;
+ sigma_flux(VitesseX,VitesseY,cfl,yField,indexFacesPerio,dt,SumFlux);
+ cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
+
+ /* Advancing time step */
+ yField-=SumFlux;
+
+ time+=dt;
+ iter+=1;
+ // Output every freq iterations
+ if (iter%freqSortie==0)
+ {
+ yField.setTime(time,iter);
+ yField.writeMED(file,false);
+ yField.writeVTK(file,false);
+ yField.writeCSV(file);
+ }
+ }
+}
+
+int main()
+{
+ cout << "Resolution of the 2D transport equation:" << endl;
+ cout << "- DOMAIN: SQUARE" << endl;
+ cout << "- MESH: TRIANGULAR, GENERATED WITH SALOME" << endl;
+ cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
+ cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
+
+ // Problem data
+ double cfl=0.4;
+ double VitesseX=1.0;
+ double VitesseY=1.0;
+ double tmax=1.;
+ int freqSortie=10;
+
+ cout << "Construction of Cartesian mesh…" << endl;
+ Mesh myMesh("../../tests/ressources/meshSquare.med");
+ string fileOutPut="Exercice2";
+ EquationTransport2D(tmax,VitesseX,VitesseY,cfl,freqSortie,myMesh,fileOutPut);
+ cout << "CDMATH calculation done." << endl;
+
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env python
+# -*-coding:utf-8 -*
+
+import math
+
+import cdmath
+
+
+def initial_conditions(my_mesh):
+ rayon = 0.15
+ xcentre = 0.25
+ ycentre = 0.25
+ y_field = cdmath.Field("Y field", cdmath.CELLS, my_mesh, 1)
+ nbCells = my_mesh.getNumberOfCells()
+ for j in range(nbCells):
+ x = my_mesh.getCell(j).x()
+ y = my_mesh.getCell(j).y()
+ valX = (x - xcentre) * (x - xcentre)
+ valY = (y - ycentre) * (y - ycentre)
+ val = math.sqrt(valX + valY)
+ if val < rayon:
+ y_field[j] = 1.0
+ pass
+ else:
+ y_field[j] = 0.0
+ pass
+ pass
+ return y_field
+
+
+def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
+ # Calculation of fluxes #
+ SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
+ my_mesh = y_field.getMesh()
+ nbCells = my_mesh.getNumberOfCells()
+ normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
+ for j in range(nbCells):
+ Cj = my_mesh.getCell(j)
+ nbFace = Cj.getNumberOfFaces()
+ SumF = 0.0
+ minlengthFk = 1.E30
+ for k in range(nbFace):
+ indexFace = Cj.getFacesId()[k]
+ Fk = my_mesh.getFace(indexFace)
+ NormalX = Cj.getNormalVector(k, 0)
+ NormalY = Cj.getNormalVector(k, 1)
+ LengthFk = Fk.getMeasure()
+ UN = VitesseX * NormalX + VitesseY * NormalY
+ minlengthFk = min(minlengthFk, LengthFk / abs(UN))
+ minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
+ minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
+ conc = 0.0
+ cellCourante = j
+ cellAutre = -1
+ if (not Fk.isBorder()):
+ indexC1 = Fk.getCellsId()[0]
+ indexC2 = Fk.getCellsId()[1]
+ # hypothesis: the cell of index indexC1 is the current cell of index j #
+ if (indexC1 == j):
+ # hypothese is verified #
+ cellCourante = indexC1
+ cellAutre = indexC2
+ pass
+ elif (indexC2 == j):
+ # hypothesis is not verified #
+ cellCourante = indexC2
+ cellAutre = indexC1
+ pass
+ # define left and right cell with the product of velocity * outward normal vector
+ # if u*n>0: nothing to do, else invert left and right
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = y_field[cellAutre]
+ pass
+ pass
+ else:
+ # homogeneous Neumann boundary conditions #
+ if (Fk.getGroupName() == "GAUCHE" or Fk.getGroupName() == "DROITE"):
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = 0.0
+ pass
+ pass
+ # periodical boundary conditions #
+ if (Fk.getGroupName() == "BAS" or Fk.getGroupName() == "HAUT"):
+ indexFP = indexFacesPerio[indexFace]
+ # another way to get the index of the periodical face #
+ # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
+ Fp = my_mesh.getFace(indexFP)
+ indexCp = Fp.getCellsId()[0]
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = y_field[indexCp]
+ pass
+ pass
+ pass
+ SumF = SumF + UN * LengthFk * conc
+ pass
+ dt = cfl * minlengthFk / normU
+ SumFlux[j] = dt * SumF / Cj.getMeasure()
+ pass
+ return dt, SumFlux
+
+
+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()
--- /dev/null
+//============================================================================
+// Author : Anouar MEKKAS
+// Version :
+// Description : Equation de transport lineaire 2D non structure
+//============================================================================
+
+#include <iostream>
+#include <string>
+#include <cmath>
+
+#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 ; j<nbCells ; j++)
+ {
+ double x = myMesh.getCell(j).x() ;
+ double y = myMesh.getCell(j).y() ;
+ double valX=(x-xcentre)*(x-xcentre);
+ double valY=(y-ycentre)*(y-ycentre);
+ double val=sqrt(valX+valY);
+ if (val<rayon)
+ yField(j) = 1.0;
+ else
+ yField(j) = 0.0;
+ }
+}
+
+void sigma_flux(const parameters & p, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
+{
+ /* Calcul des flux */
+ Mesh myMesh=yField.getMesh();
+ int nbCells=myMesh.getNumberOfCells();
+ double normU=sqrt(p.VitesseX*p.VitesseX+p.VitesseY*p.VitesseY);
+ for (int j=0 ; j<nbCells ; j++)
+ {
+ Cell Cj=myMesh.getCell(j);
+ int nbFace=Cj.getNumberOfFaces();
+ double SumF=0.0;
+ double minlengthFk=1.E30;
+
+ int cellCourante,cellAutre;
+ for (int k=0 ; k<nbFace ; k++)
+ {
+ int indexFace=Cj.getFacesId()[k];
+ Face Fk=myMesh.getFace(indexFace);
+ double NormalX=Cj.getNormalVector(k,0);
+ double NormalY=Cj.getNormalVector(k,1);
+ double LengthFk = Fk.getMeasure();
+ double UN=p.VitesseX*NormalX+p.VitesseY*NormalY;
+
+ minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(p.VitesseX));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(p.VitesseY));
+
+ double conc=0.0;
+ cellCourante=j;
+ cellAutre=-1;
+
+ if (!Fk.isBorder())
+ {
+ int indexC1=Fk.getCellsId()[0];
+ int indexC2=Fk.getCellsId()[1];
+ /* hypothese: La cellule d'index indexC1 est la cellule courante index j */
+ if ( indexC1 == j )
+ {
+ /* hypothese verifie */
+ cellCourante=indexC1;
+ cellAutre=indexC2;
+ } else if ( indexC2 == j )
+ {
+ /* hypothese non verifie */
+ cellCourante=indexC2;
+ cellAutre=indexC1;
+ }
+ // definir la cellule gauche et droite par le prduit vitesse * normale sortante
+ // si u*n>0 : rien a faire sinon inverser la gauche et la droite
+ if (UN>1.E-15)
+ conc=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<ntmax && time <= tmax )
+ {
+ Field SumFlux("Fluxes sum",CELLS,myMesh,1) ;
+ sigma_flux(p,yField,indexFacesPerio,dt,SumFlux);
+ cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
+
+ /* Advancing time step */
+ yField-=SumFlux;
+
+ time+=dt;
+ iter+=1;
+ // Output every freq iterations
+ if (iter % p.freqSortie==0)
+ {
+ yField.setTime(time,iter);
+ yField.writeVTK(p.outFile,false);
+ yField.writeCSV(p.outFile);
+ }
+ }
+
+ cout << "MED post-treatment of the solution at T=" << time << endl;
+ yField.setTime(time,iter);
+ yField.writeMED(p.outFile,false);
+ yField.writeCSV(p.outFile);
+
+ tmax = time;
+ cout << "End of EquationTransport2D." << endl;
+}
+
+void compute_onepass(double tmin, double tmax, const Mesh & M, const parameters & p)
+{
+ int iter = 0;
+
+ /* Initial conditions */
+ cout << "Construction of initial condition…" << endl;
+ Field f("Y field",CELLS,M,1) ;
+ conditions_initiales(f);
+
+ EquationTransport2D(iter, tmin, tmax, p, f);
+}
+
+void compute_twopass(double tmin, double tmax, const Mesh & M, const parameters & p)
+{
+ int iter = 0;
+ parameters q(p);
+ double tstep = 0.5 * (tmin + tmax);
+
+ /* Initial conditions */
+ cout << "Construction of initial condition…" << endl;
+ Field f("Y field",CELLS,M,1) ;
+ conditions_initiales(f);
+
+ q.outFile = p.outFile + "_A";
+ EquationTransport2D(iter, tmin, tstep, q, f);
+
+ Field f2(q.outFile, CELLS, "Y field", iter, 0);
+
+ q.outFile = p.outFile + "_B";
+ EquationTransport2D(iter, tstep, tmax, q, f2);
+
+}
+
+int main()
+{
+ cout << "Resolution of the 2D transport equation:" << endl;
+ cout << "- DOMAIN: SQUARE" << endl;
+ cout << "- MESH: TRIANGULAR, GENERATED WITH SALOME" << endl;
+ cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
+ cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
+
+ // donnees du probleme
+ parameters p;
+ int iter;
+
+ p.cfl=0.4;
+ p.VitesseX=1.0;
+ p.VitesseY=1.0;
+ p.freqSortie=50;
+ p.outFile="res2D";
+
+ cout << "Construction of Cartesian mesh…" << endl;
+ Mesh M("../../tests/ressources/meshSquare.med");
+
+ double tmin = 0;
+ double tmax = 0.1;
+
+ compute_onepass(tmin, tmax, M, p);
+ compute_twopass(tmin, tmax, M, p);
+ cout << "CDMATH calculation done." << endl;
+
+ return 0;
+}
--- /dev/null
+# Transport2D_NS makefile
+
+CC = g++
+# Adapt the following line to your own system:
+CDMATHDIR = ../../../../..
+IFLAG = -I$(CDMATHDIR)/include -I.
+LFLAG = -L$(CDMATHDIR)/lib -L$(PETSC_DIR)/$(PETSC_ARCH)/lib
+LIBS = -linterpkernel -lmedC -lmedloader -lmedcoupling -lbase -lmesh -llinearsolver -lpetsc
+
+all: main main2
+
+main: main.cxx
+ $(CC) -g -o $@ $^ $(IFLAG) $(LFLAG) $(LIBS)
+
+main2: main2.cxx
+ $(CC) -g -o $@ $^ $(IFLAG) $(LFLAG) $(LIBS)
+
+%.o: %.cxx
+ $(CC) -c -g -o $@ $< $(CFLAGS) $(IFLAG) $(LFLAG) $(LIBS)
+
+.PHONY: clean
+
+clean:
+ rm -f main main2 *.o *~ core $(INCDIR)/*~
+
+sweep:
+ rm -f *.vtu
+ rm -f *.pvd
+ rm -f *.csv
+ rm -f Exercie2*.med
--- /dev/null
+//============================================================================
+// Author : Anouar MEKKAS
+// Version :
+// Description : 2D linear transport equation on cartesian grid
+//============================================================================
+
+#include <iostream>
+#include <string>
+#include <cmath>
+
+#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 ; j<nbCells ; j++)
+ {
+ double x = myMesh.getCell(j).x() ;
+ double y = myMesh.getCell(j).y() ;
+ double valX=(x-xcentre)*(x-xcentre);
+ double valY=(y-ycentre)*(y-ycentre);
+ double val=sqrt(valX+valY);
+ if (val<rayon)
+ yField(j) = 1.0;
+ else
+ yField(j) = 0.0;
+ }
+}
+
+void sigma_flux(double VitesseX, double VitesseY, double cfl, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
+{
+ /* Fluxes calculation */
+ Mesh myMesh=yField.getMesh();
+ int nbCells=myMesh.getNumberOfCells();
+ double normU=sqrt(VitesseX*VitesseX+VitesseY*VitesseY);
+ for (int j=0 ; j<nbCells ; j++)
+ {
+ Cell Cj=myMesh.getCell(j);
+ int nbFace=Cj.getNumberOfFaces();
+ double SumF=0.0;
+ double minlengthFk=1.E30;
+
+ int cellCourante,cellAutre;
+ for (int k=0 ; k<nbFace ; k++)
+ {
+ int indexFace=Cj.getFacesId()[k];
+ Face Fk=myMesh.getFace(indexFace);
+ double NormalX=Cj.getNormalVector(k,0);
+ double NormalY=Cj.getNormalVector(k,1);
+ double LengthFk = Fk.getMeasure();
+ double UN=VitesseX*NormalX+VitesseY*NormalY;
+
+ minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseX));
+ minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseY));
+
+ double conc=0.0;
+ cellCourante=j;
+ cellAutre=-1;
+
+ if (!Fk.isBorder())
+ {
+ int indexC1=Fk.getCellsId()[0];
+ int indexC2=Fk.getCellsId()[1];
+ /* Hypothesis: the cell of index indexC1 is the current cell index j */
+ if ( indexC1 == j )
+ {
+ /* Hypothesis verified */
+ cellCourante=indexC1;
+ cellAutre=indexC2;
+ } else if ( indexC2 == j )
+ {
+ /* Hypothesis not verified */
+ cellCourante=indexC2;
+ cellAutre=indexC1;
+ }
+ // Define left and right cells with the product velocity * outward normal
+ // If u*n>0, 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 (iter<ntmax && time <= tmax )
+ {
+ Field SumFlux("Sum Flux",CELLS,myMesh,1) ;
+ sigma_flux(VitesseX,VitesseY,cfl,yField,indexFacesPerio,dt,SumFlux);
+ cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
+
+ /* Advancing time step */
+ yField-=SumFlux;
+
+ time+=dt;
+ iter+=1;
+ // Ouput every freq iterations
+ if (iter%freqSortie==0)
+ {
+ yField.setTime(time,iter);
+ yField.writeMED(file,false);
+ yField.writeVTK(file,false);
+ yField.writeCSV(file);
+ }
+ }
+}
+
+int main()
+{
+ cout << "RESOLUTION OF 2D TRANSPORT EQUATION:" << endl;
+ cout << "- DOMAIN: SQUARE" << endl;
+ cout << "- MESH: CARTESIAN, GENERATED INTERNALLY WITH CDMATH" << endl;
+ cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
+ cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
+
+ // Problem data
+ double cfl=0.4;
+ double VitesseX=1.0;
+ double VitesseY=1.0;
+ double tmax=1.;
+ int freqSortie=10;
+
+ cout << "Construction of a cartesian mesh …" << endl;
+ double xinf=0.0;
+ double xsup=1.0;
+ double yinf=0.0;
+ double ysup=1.0;
+ int nx=100;
+ int ny=100;
+ Mesh myMesh(xinf,xsup,nx,yinf,ysup,ny);
+ double eps=1.E-10;
+ myMesh.setGroupAtPlan(xsup,0,eps,"RightEdge");
+ myMesh.setGroupAtPlan(xinf,0,eps,"LeftEdge");
+ myMesh.setGroupAtPlan(yinf,1,eps,"BottomEdge");
+ myMesh.setGroupAtPlan(ysup,1,eps,"TopEdge");
+ string fileOutPutCart="Exercice1";
+ EquationTransport2D(tmax,VitesseX,VitesseY,cfl,freqSortie,myMesh,fileOutPutCart);
+ cout << "CDMATH calculation done." << endl;
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env python
+# -*-coding:utf-8 -*
+
+import math
+
+import cdmath
+
+
+def initial_conditions(my_mesh):
+ rayon = 0.15
+ xcentre = 0.25
+ ycentre = 0.25
+ y_field = cdmath.Field("Y field", cdmath.CELLS, my_mesh, 1)
+ nbCells = my_mesh.getNumberOfCells()
+ for j in range(nbCells):
+ x = my_mesh.getCell(j).x()
+ y = my_mesh.getCell(j).y()
+ valX = (x - xcentre) * (x - xcentre)
+ valY = (y - ycentre) * (y - ycentre)
+ val = math.sqrt(valX + valY)
+ if val < rayon:
+ y_field[j] = 1.0
+ pass
+ else:
+ y_field[j] = 0.0
+ pass
+ pass
+ return y_field
+
+
+def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
+ # Fluxes calculation #
+ SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
+ my_mesh = y_field.getMesh()
+ nbCells = my_mesh.getNumberOfCells()
+ normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
+ for j in range(nbCells):
+ Cj = my_mesh.getCell(j)
+ nbFace = Cj.getNumberOfFaces()
+ SumF = 0.0
+ minlengthFk = 1.E30
+ for k in range(nbFace):
+ indexFace = Cj.getFacesId()[k]
+ Fk = my_mesh.getFace(indexFace)
+ NormalX = Cj.getNormalVector(k, 0)
+ NormalY = Cj.getNormalVector(k, 1)
+ LengthFk = Fk.getMeasure()
+ UN = VitesseX * NormalX + VitesseY * NormalY
+ minlengthFk = min(minlengthFk, LengthFk / abs(UN))
+ minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
+ minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
+ conc = 0.0
+ cellCourante = j
+ cellAutre = -1
+ if (not Fk.isBorder()):
+ indexC1 = Fk.getCellsId()[0]
+ indexC2 = Fk.getCellsId()[1]
+ # hypothese: La cellule d'index indexC1 est la cellule courante index j #
+ if (indexC1 == j):
+ # hypothese verifie #
+ cellCourante = indexC1
+ cellAutre = indexC2
+ pass
+ elif (indexC2 == j):
+ # hypothese non verifie #
+ cellCourante = indexC2
+ cellAutre = indexC1
+ pass
+ # definir la cellule gauche et droite par le prduit vitesse * normale sortante
+ # si u*n>0 : rien a faire sinon inverser la gauche et la droite
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = y_field[cellAutre]
+ pass
+ pass
+ else:
+ # conditions aux limites neumann homogene #
+ if (Fk.getGroupName() == "LeftEdge" or Fk.getGroupName() == "RightEdge"):
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = 0.0
+ pass
+ pass
+ # conditions aux limites periodiques #
+ if (Fk.getGroupName() == "BottomEdge" or Fk.getGroupName() == "TopEdge"):
+ indexFP = indexFacesPerio[indexFace]
+ # une autre manière de recuperer l'index de la face periodique #
+ # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
+ Fp = my_mesh.getFace(indexFP)
+ indexCp = Fp.getCellsId()[0]
+ if (UN > 1.E-15):
+ conc = y_field[cellCourante]
+ pass
+ else:
+ conc = y_field[indexCp]
+ pass
+ pass
+ pass
+ SumF = SumF + UN * LengthFk * conc
+ pass
+ dt = cfl * minlengthFk / normU
+ SumFlux[j] = dt * SumF / Cj.getMeasure()
+ pass
+ return dt, SumFlux
+
+
+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()
--- /dev/null
+# 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
+++ /dev/null
-#!/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./3<xi)*int(xi<2./3) for xi in x];# to be used with a=0, b=1
- tmax = (b-a)/c # runs the simulation for 0 <= t <= tMax
- ntmax = ceil(tmax/dt)
-
- u = deepcopy(u_initial)
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
-
- time = 0.
- it = 0
- output_freq = int(10/cfl)
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Centered explicit scheme for transport equation", artist = "CEA Saclay", comment="CFL="+str(cfl)+", Stable if CFL<1")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "1DTransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.5*(max_initial-min_initial), max_initial + 0.5*(max_initial-min_initial) )
- plt.title('Centered explicit scheme for transport equation')
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- un=deepcopy(u)
- for i in range(nx):
- u[i] = un[i] - c * dt / dx * (un[(i+1)%nx] - un[(i-1)%nx])/2
-
- 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_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n")
- plt.savefig("TransportEquation_CenteredExplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_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 1D transport equation with explicit centered scheme done" )
-
- 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) >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)
-
+++ /dev/null
-
-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 )
-
-
+++ /dev/null
-#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
- u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
- total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
-
- time = 0.
- it = 0
- output_freq = 10
-
- #Linear system initialisation
- systemMat=centeredSchemeMatrix(nx,cfl)
- iterGMRESMax=50
- precision=1.e-5
- Un =cdmath.Vector(nx)
- for i in range(nx):
- Un[i]=u[i]
- LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
- LS.setComputeConditionNumber()
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Centered implicit scheme for transport equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL>0")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "1DTransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
- plt.title("Centered implicit scheme for transport equation, "+"CFL="+str(cfl))
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- # Solve linear system
- for i in range(nx):
- Un[i]=u[i]
- LS.setSndMember(Un)
- Un=LS.solve()
- if(not LS.getStatus()):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- for i in range(nx):
- u[i]=Un[i]
-
- if ( max(u) > max_initial ):
- print( "-- Iter: " + str(it) + " max principle violated : max(t) > max(0) : max(t)= ",max(u), " max(0)= ", max_initial )
- if ( min(u) < min_initial ):
- print( "-- Iter: " + str(it) + " min principle violated : min(t) < min(0) : min(t)= ",min(u), " min(0)= ", min_initial )
- if ( np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) > total_var_initial ):
- print( "-- Iter: " + str(it) + " total variation increased : var(t) > var(0) : var(t)= ", np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), " var(0)= ", total_var_initial )
-
- time += dt
- it += 1
-
- # Postprocessing
- line1.set_ydata(u)
- 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)
-
+++ /dev/null
-
-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 )
-
-
+++ /dev/null
-#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
- u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
- total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
-
- time = 0.
- it = 0
- output_freq = 10
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Upwind explicit scheme for transport equation, CFL="+str(cfl), artist = "CEA Saclay", comment="Stable if CFL<1")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "1DTransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
- plt.title("Upwind explicit scheme for transport equation, CFL="+str(cfl))
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("TransportEquation_UpwindExplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- un=deepcopy(u)
- for i in range(nx):
- u[i] = un[i] - c * dt / dx * (un[i] - un[(i-1)%nx])
-
- time += dt
- it += 1
-
- if cfl<1 :
- assert max(u) <= max_initial
- assert min(u) >= 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)
-
+++ /dev/null
-
-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 )
-
-
+++ /dev/null
-#!/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<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
- u = [ 0.5*(1+sin(4*pi*xi-pi*.5))*int(xi<0.5)*int(0<xi) + int(0.6<xi)*int(xi<0.85) for xi in x];# to be used with a=0, b=1
-
- max_initial=max(u_initial)
- min_initial=min(u_initial)
- total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
-
- time = 0.
- it = 0
- output_freq = 10
-
- #Linear system initialisation
- systemMat=upwindSchemeMatrix(nx,cfl)
- iterGMRESMax=50
- Un =cdmath.Vector(nx)
- for i in range(nx):
- Un[i]=u[i]
- LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
-
- # Video settings
- FFMpegWriter = manimation.writers['ffmpeg']
- metadata = dict(title="Upwind implicit scheme for transport equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL>0")
- writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
- with writer.saving(plt.figure(), "1DTransportEquation_UpwindImplicit_"+str(nx)+"CELLS_CFL"+str(cfl)+".mp4", ntmax):
- ########################### Postprocessing initialisation
- # Picture frame
- plt.legend()
- plt.xlabel('x')
- plt.ylabel('u')
- plt.xlim(a,b)
- plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
- plt.title("Upwind implicit scheme for transport equation, "+"CFL="+str(cfl))
- line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
-
- print("Starting time loop")
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- np.savetxt( "TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
- writer.grab_frame()
- plt.savefig("TransportEquation_UpwindImplicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
-
- ############################# Time loop
- while (it < ntmax and time <= tmax):
- # Solve linear system
- for i in range(nx):
- Un[i]=u[i]
- LS.setSndMember(Un)
- Un=LS.solve()
- if(not LS.getStatus()):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- for i in range(nx):
- u[i]=Un[i]
-
- time += dt
- it += 1
-
- assert max(u) <= max_initial
- assert min(u) >= 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)
-
+++ /dev/null
-
-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 )
-
-
--- /dev/null
+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)
+
+
--- /dev/null
+
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn_staggered=Un_staggered.deepCopy()
+ LS_staggered.setSndMember(Un_staggered)
+ Un_staggered=LS_staggered.solve();
+ if(not LS_staggered.getStatus()):
+ print( "Linear system did not converge for staggered scheme ", LS.getNumberOfIter(), " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn_staggered-=Un_staggered
+
+ for k in range(nbCells):
+ pressure_field_staggered[k] = Un_staggered[k*(dim+1)+0]
+ velocity_field_staggered[k] = Un_staggered[k*(dim+1)+1] / rho0
+
+ line2.set_ydata(pressure_field_staggered)
+ 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( "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)
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ computeFluxes(U,SumFluxes);
+
+ SumFluxes*=dt;
+ maxVector=SumFluxes.normMax()
+ isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision
+ U-=SumFluxes;
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 )
+ print()
+
+ for k in range(nbCells):
+ pressure_field[k]=U[k,0]
+ velocity_field[k,0]=U[k,1]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeCSV("WaveSystem1DUpwind_pressure");
+ velocity_field.setTime(time,it);
+ velocity_field.writeCSV("WaveSystem1DUpwind_velocity");
+
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "|| Un+1 - Un || : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 )
+ print()
+
+ if(it>=ntmax):
+ print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" )
+ raise ValueError("Maximum number of time steps reached : Stationary state not found !!!!!!!")
+ elif(isStationary):
+ print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time )
+ for k in range(nbCells):
+ pressure_field[k]=U[k,0]
+ velocity_field[k,0]=U[k,1]/rho0
+
+ pressure_field.setTime(time,0);
+ pressure_field.writeCSV("WaveSystem1DUpwind_pressure_Stat");
+ velocity_field.setTime(time,0);
+ velocity_field.writeCSV("WaveSystem1DUpwind_velocity_Stat");
+
+ else:
+ print( "Temps maximum Tmax= ", tmax, " atteint" )
+ raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")
+
+
+def solve(my_mesh,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)
--- /dev/null
+
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=divMat*Un
+ Un-=dUn
+
+ dUn_implicite=Un_implicite.deepCopy()
+ LS.setSndMember(Un_implicite)
+ Un_implicite=LS.solve();
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn_implicite-=Un_implicite
+
+ for k in range(nbCells):
+ pressure_field[k] = Un[k*(dim+1)+0]
+ velocity_field[k] = Un[k*(dim+1)+1] / rho0
+ pressure_field_implicite[k] = Un_implicite[k*(dim+1)+0]
+ velocity_field_implicite[k] = Un_implicite[k*(dim+1)+1] / rho0
+
+ line1.set_ydata(pressure_field)
+ line3.set_ydata(pressure_field_implicite)
+ 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( "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)
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ if(isImplicit):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ else:
+ dUn=divMat*Un
+ Un-=dUn
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+
+ for k in range(nbCells):
+ pressure_field[k] =Un[k*(dim+1)+0]
+ velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
+ if(dim>1):
+ velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
+ if(dim>2):
+ velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_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)")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ maxVector=dUn.maxVector(dim+1)
+ isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
+ if(dim==3):
+ isStationary=isStationary and maxVector[3]/rho0<precision
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
+ 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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ maxVector=dUn.maxVector(dim+1)
+ isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
+ if(dim==3):
+ isStationary=isStationary and maxVector[3]/rho0<precision
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
+ 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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ max_dp=0 ; max_dq=0
+ for k in range(nbCells):
+ max_dp = max(max_dp,abs(dUn[k]))
+ for i in range(dim):
+ max_dq=max(max_dq,abs(dUn[k+(1+i)*nbCells]))
+
+ isStationary= max_dp/p0<precision and max_dq/rho0<precision
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
+ print( "Linear system converged in ", iterGMRES, " GMRES iterations" )
+
+ for k in range(nbCells):
+ pressure_field[k]=Un[k]
+ velocity_field[k,0]=Un[k+1*nbCells]/rho0
+ if(dim>1):
+ velocity_field[k,1]=Un[k+2*nbCells]/rho0
+ if(dim>2):
+ velocity_field[k,2]=Un[k+3*nbCells]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure",False);
+ velocity_field.setTime(time,it);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity",False);
+
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
+ print()
+
+ if(it>=ntmax):
+ print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
+ elif(isStationary):
+ print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
+ print( "------------------------------------------------------------------------------------")
+
+ pressure_field.setTime(time,0);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat");
+ velocity_field.setTime(time,0);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat");
+
+ #Postprocessing : save 2D picture
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat")
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat")
+
+ else:
+ print( "Temps maximum Tmax= ", tmax, " atteint")
+
+
+def 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)
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ if(isImplicit):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ else:
+ dUn=divMat*Un
+ Un-=dUn
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+
+ for k in range(nbCells):
+ pressure_field[k] =Un[k*(dim+1)+0]
+ velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
+ if(dim>1):
+ velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
+ if(dim>2):
+ velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_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)")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ maxVector=dUn.maxVector(dim+1)
+ isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
+ if(dim==3):
+ isStationary=isStationary and maxVector[3]/rho0<precision
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
+ 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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ maxVector=dUn.maxVector(dim+1)
+ isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
+ if(dim==3):
+ isStationary=isStationary and maxVector[3]/rho0<precision
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
+ 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")
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ cvgceLS=LS.getStatus();
+ iterGMRES=LS.getNumberOfIter();
+ if(not cvgceLS):
+ print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ max_dp=0 ; max_dq=0
+ for k in range(nbCells):
+ max_dp = max(max_dp,abs(dUn[k]))
+ for i in range(dim):
+ max_dq=max(max_dq,abs(dUn[k+(1+i)*nbCells]))
+
+ isStationary= max_dp/p0<precision and max_dq/rho0<precision
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0)
+ print( "Linear system converged in ", iterGMRES, " GMRES iterations")
+
+ for k in range(nbCells):
+ pressure_field[k]=Un[k]
+ velocity_field[k,0]=Un[k+1*nbCells]/rho0
+ if(dim>1):
+ velocity_field[k,1]=Un[k+2*nbCells]/rho0
+ if(dim>2):
+ velocity_field[k,2]=Un[k+3*nbCells]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure",False);
+ velocity_field.setTime(time,it);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity",False);
+
+ print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
+ print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
+ print()
+
+ if(it>=ntmax):
+ print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
+ elif(isStationary):
+ print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
+ print( "------------------------------------------------------------------------------------")
+
+ pressure_field.setTime(time,0);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat");
+ velocity_field.setTime(time,0);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat");
+
+ #Postprocessing : save 2D picture
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat")
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat")
+
+ else:
+ print( "Temps maximum Tmax= ", tmax, " atteint" )
+
+
+def 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)
--- /dev/null
+
+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)
+
+
--- /dev/null
+#!/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 and time <= tmax and not isStationary):
+ if(isImplicit):
+ dUn=Un.deepCopy()
+ LS.setSndMember(Un)
+ Un=LS.solve();
+ if(not LS.getStatus()):
+ print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
+ raise ValueError("Pas de convergence du système linéaire");
+ dUn-=Un
+
+ else:
+ dUn=divMat*Un
+ Un-=dUn
+
+ time=time+dt;
+ it=it+1;
+
+ #Sauvegardes
+ if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+
+ for k in range(nbCells):
+ pressure_field[k] =Un[k*(dim+1)+0]
+ velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
+ if(dim>1):
+ velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
+ if(dim>2):
+ velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
+
+ pressure_field.setTime(time,it);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False);
+ velocity_field.setTime(time,it);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False);
+
+ print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
+ print()
+
+ if(it>=ntmax):
+ print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
+ elif(isStationary):
+ print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
+
+ pressure_field.setTime(time,0);
+ pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat");
+ velocity_field.setTime(time,0);
+ velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat");
+
+ #Postprocessing : Extraction of the diagonal data
+ diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)
+ diag_data_vel =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)
+ #Postprocessing : save 2D picture
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
+ PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
+
+ else:
+ print( "Temps maximum Tmax= ", tmax, " atteint")
+
+
+def solve(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)")
+++ /dev/null
-
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn_staggered=Un_staggered.deepCopy()
- LS_staggered.setSndMember(Un_staggered)
- Un_staggered=LS_staggered.solve();
- if(not LS_staggered.getStatus()):
- print( "Linear system did not converge for staggered scheme ", LS.getNumberOfIter(), " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn_staggered-=Un_staggered
-
- for k in range(nbCells):
- pressure_field_staggered[k] = Un_staggered[k*(dim+1)+0]
- velocity_field_staggered[k] = Un_staggered[k*(dim+1)+1] / rho0
-
- line2.set_ydata(pressure_field_staggered)
- 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( "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)
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- computeFluxes(U,SumFluxes);
-
- SumFluxes*=dt;
- maxVector=SumFluxes.normMax()
- isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision
- U-=SumFluxes;
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 )
- print()
-
- for k in range(nbCells):
- pressure_field[k]=U[k,0]
- velocity_field[k,0]=U[k,1]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeCSV("WaveSystem1DUpwind_pressure");
- velocity_field.setTime(time,it);
- velocity_field.writeCSV("WaveSystem1DUpwind_velocity");
-
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "|| Un+1 - Un || : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 )
- print()
-
- if(it>=ntmax):
- print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" )
- raise ValueError("Maximum number of time steps reached : Stationary state not found !!!!!!!")
- elif(isStationary):
- print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time )
- for k in range(nbCells):
- pressure_field[k]=U[k,0]
- velocity_field[k,0]=U[k,1]/rho0
-
- pressure_field.setTime(time,0);
- pressure_field.writeCSV("WaveSystem1DUpwind_pressure_Stat");
- velocity_field.setTime(time,0);
- velocity_field.writeCSV("WaveSystem1DUpwind_velocity_Stat");
-
- else:
- print( "Temps maximum Tmax= ", tmax, " atteint" )
- raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")
-
-
-def solve(my_mesh,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)
+++ /dev/null
-
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=divMat*Un
- Un-=dUn
-
- dUn_implicite=Un_implicite.deepCopy()
- LS.setSndMember(Un_implicite)
- Un_implicite=LS.solve();
- if(not LS.getStatus()):
- print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn_implicite-=Un_implicite
-
- for k in range(nbCells):
- pressure_field[k] = Un[k*(dim+1)+0]
- velocity_field[k] = Un[k*(dim+1)+1] / rho0
- pressure_field_implicite[k] = Un_implicite[k*(dim+1)+0]
- velocity_field_implicite[k] = Un_implicite[k*(dim+1)+1] / rho0
-
- line1.set_ydata(pressure_field)
- line3.set_ydata(pressure_field_implicite)
- 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( "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)
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- if(isImplicit):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- if(not LS.getStatus()):
- print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- else:
- dUn=divMat*Un
- Un-=dUn
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
-
- for k in range(nbCells):
- pressure_field[k] =Un[k*(dim+1)+0]
- velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
- if(dim>1):
- velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
- if(dim>2):
- velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_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)")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- maxVector=dUn.maxVector(dim+1)
- isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
- if(dim==3):
- isStationary=isStationary and maxVector[3]/rho0<precision
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
- 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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- maxVector=dUn.maxVector(dim+1)
- isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
- if(dim==3):
- isStationary=isStationary and maxVector[3]/rho0<precision
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
- 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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- max_dp=0 ; max_dq=0
- for k in range(nbCells):
- max_dp = max(max_dp,abs(dUn[k]))
- for i in range(dim):
- max_dq=max(max_dq,abs(dUn[k+(1+i)*nbCells]))
-
- isStationary= max_dp/p0<precision and max_dq/rho0<precision
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
- print( "Linear system converged in ", iterGMRES, " GMRES iterations" )
-
- for k in range(nbCells):
- pressure_field[k]=Un[k]
- velocity_field[k,0]=Un[k+1*nbCells]/rho0
- if(dim>1):
- velocity_field[k,1]=Un[k+2*nbCells]/rho0
- if(dim>2):
- velocity_field[k,2]=Un[k+3*nbCells]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure",False);
- velocity_field.setTime(time,it);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity",False);
-
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
- print()
-
- if(it>=ntmax):
- print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
- elif(isStationary):
- print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
- print( "------------------------------------------------------------------------------------")
-
- pressure_field.setTime(time,0);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat");
- velocity_field.setTime(time,0);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat");
-
- #Postprocessing : save 2D picture
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat")
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat")
-
- else:
- print( "Temps maximum Tmax= ", tmax, " atteint")
-
-
-def 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)
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- if(isImplicit):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- if(not LS.getStatus()):
- print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" )
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- else:
- dUn=divMat*Un
- Un-=dUn
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
-
- for k in range(nbCells):
- pressure_field[k] =Un[k*(dim+1)+0]
- velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
- if(dim>1):
- velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
- if(dim>2):
- velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+"_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)")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- maxVector=dUn.maxVector(dim+1)
- isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
- if(dim==3):
- isStationary=isStationary and maxVector[3]/rho0<precision
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
- 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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- maxVector=dUn.maxVector(dim+1)
- isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
- if(dim==3):
- isStationary=isStationary and maxVector[3]/rho0<precision
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0 )
- 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")
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- cvgceLS=LS.getStatus();
- iterGMRES=LS.getNumberOfIter();
- if(not cvgceLS):
- print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- max_dp=0 ; max_dq=0
- for k in range(nbCells):
- max_dp = max(max_dp,abs(dUn[k]))
- for i in range(dim):
- max_dq=max(max_dq,abs(dUn[k+(1+i)*nbCells]))
-
- isStationary= max_dp/p0<precision and max_dq/rho0<precision
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0)
- print( "Linear system converged in ", iterGMRES, " GMRES iterations")
-
- for k in range(nbCells):
- pressure_field[k]=Un[k]
- velocity_field[k,0]=Un[k+1*nbCells]/rho0
- if(dim>1):
- velocity_field[k,1]=Un[k+2*nbCells]/rho0
- if(dim>2):
- velocity_field[k,2]=Un[k+3*nbCells]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure",False);
- velocity_field.setTime(time,it);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity",False);
-
- print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
- print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
- print()
-
- if(it>=ntmax):
- print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
- elif(isStationary):
- print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
- print( "------------------------------------------------------------------------------------")
-
- pressure_field.setTime(time,0);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat");
- velocity_field.setTime(time,0);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat");
-
- #Postprocessing : save 2D picture
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat")
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat")
-
- else:
- print( "Temps maximum Tmax= ", tmax, " atteint" )
-
-
-def 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)
+++ /dev/null
-
-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)
-
-
+++ /dev/null
-#!/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 and time <= tmax and not isStationary):
- if(isImplicit):
- dUn=Un.deepCopy()
- LS.setSndMember(Un)
- Un=LS.solve();
- if(not LS.getStatus()):
- print( "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
- raise ValueError("Pas de convergence du système linéaire");
- dUn-=Un
-
- else:
- dUn=divMat*Un
- Un-=dUn
-
- time=time+dt;
- it=it+1;
-
- #Sauvegardes
- if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
-
- for k in range(nbCells):
- pressure_field[k] =Un[k*(dim+1)+0]
- velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
- if(dim>1):
- velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
- if(dim>2):
- velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
-
- pressure_field.setTime(time,it);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False);
- velocity_field.setTime(time,it);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False);
-
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- print()
-
- if(it>=ntmax):
- print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
- elif(isStationary):
- print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
-
- pressure_field.setTime(time,0);
- pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat");
- velocity_field.setTime(time,0);
- velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat");
-
- #Postprocessing : Extraction of the diagonal data
- diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)
- diag_data_vel =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)
- #Postprocessing : save 2D picture
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
- PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
-
- else:
- print( "Temps maximum Tmax= ", tmax, " atteint")
-
-
-def solve(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)")
+++ /dev/null
-//============================================================================
-// 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 <iostream>
-#include <cmath>
-//#include<complex>
-
-//#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 ; j<nbCells ; j++)
- {
- x = M.getCell(j).x() ;
- //cout<<"cellule "<< j<<" x= "<< x<<" milieu= "<< milieu <<endl;
- if (x<milieu)
- Temp(j) = TempLeft;
- else
- Temp(j) = TempRight;
- }
-}
-
-
-double sign(double x)
-{
- if(x>0)
- return 1.;
- else if(x<0)
- return -1.;
- else
- return 0.;
-}
-
-
-double theta_upwind(double Tim1, double Ti, double Tip1, double Tip2, double VitesseX, double dt, double Tin, double Tip1n)
-{
- if(abs(Tip1-Ti)<1.e-5)
- return 1.;
-
- double denominateur = abs(VitesseX)*(2.-sign(Tip1-Ti)*(sign(Tip2-Tip1)+sign(Ti-Tim1)));
-
- if( abs(denominateur) <=1.e-5 )
- return 0.5;
- else
- {
- double result = (1-sign(Tip1-Ti)*sign(Ti-Tim1))/denominateur;
- if(result <0.5)
- return 0.5;
- else
- return result;
- }
-}
-
-
-void solveTriDiag(vector<double>& a,vector<double>& b,vector<double>& c,Field &d, int nbCells)
-{
- int n= nbCells;
-
- if(a.size()!=c.size() || a.size()+1 != b.size() || n != (int) b.size() || n != (int) (d.getMesh()).getNumberOfCells())
- throw CdmathException("solveTriDiag(): vectors with inapropriate size");
-
-/* cout<<"avant solveTri"<<endl;
- for(int i=0;i<nbCells-2;i++)
- cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
-
- /* Algorithme de résolution d'un Système Tridiagonal*/
- n--; // since we start from x0 (not x1)
- c[0] /= b[0];
- d[0] /= b[0];
- for (int i = 1; i < n; i++) {
- c[i] /= b[i] - a[i-1]*c[i-1];
- d[i] = (d[i] - a[i-1]*d[i-1]) / (b[i] - a[i-1]*c[i-1]);
- }
-
- d[n] = (d[n] - a[n-1]*d[n-1]) / (b[n] - a[n-1]*c[n-1]);
-
- for (int i = n; i-- > 0;) {
- d[i] -= c[i]*d[i+1];
- }
-
- /*cout<<"apres solveTri"<<endl;
- for(int i=0;i<nbCells-2;i++)
- cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
-}
-
-
-void solveEntreeImplicit(Field& phi, Field& Temp, int nbCells, double VitesseX, double cfl, double Tentree, double dt) {
-
- /* Coefficients de la matrice tridiagonalee liee au systeme*/
- /*b=coeff diag, c= coeff au dessus diag, a= coeff sous diag */
- vector<double> a(nbCells-1),b(nbCells),c(nbCells-1);
- double theta, epsilon=1.e-2, erreur=1/epsilon;
- int iterMax=100, k=0;
- Field d, ScndMbre=phi, Tempn=Temp;
- ScndMbre*=dt;
- ScndMbre+=Tempn;//On obtient Tn+dt*phi
- //On décentre le terme source
- for (int i = 1; i < nbCells-1; i++)
- {
- ScndMbre[i]-=cfl*(phi[i]-phi[i-1])*dt/2;
- }
- ScndMbre[0]-=cfl*(phi[0])*dt/2;
- //d[0]-=cfl*(phi[n-1]-phi[n-2]);
-
- if(nbCells<3)
- throw CdmathException("solveEntreeImplicit(): mesh should have at least three cells");
-
- while( k<iterMax && erreur>epsilon)
- {
- d= ScndMbre;//contiendra le second membre du système
- /*cout<< " Debut itération d= "<<endl;
- for(int i=0;i<nbCells-1;i++)
- cout<< " , "<< d(i);
- cout<<endl;*/
- cout<<"theta="<<endl;
- /* On traite la première face (entrée) */
- theta=theta_upwind(Tentree,Tentree,Temp(0),Temp(1),VitesseX, dt, Tentree, Tempn(0));
- b[0]=1+ cfl*(2*theta-1);
- c[0]=(1-theta)*cfl;
- d(0)+=theta*cfl*Tentree;
-
- cout<< theta << " , ";
-
- /* On traite la deuxième face interne */
- theta=theta_upwind(Tentree,Temp(0),Temp(1),Temp(2),VitesseX, dt, Tempn(0), Tempn(1));
- b[1]=1+ cfl*(2*theta-1);
- c[1]=(1-theta)*cfl;
- a[0]=-theta*cfl;
-
- cout<< theta << " , ";
-
- //On traite les faces internes
- for(int i=2; i<nbCells-2; i++)
- {
- theta=theta_upwind(Temp(i-2),Temp(i-1),Temp(i),Temp(i+1),VitesseX, dt, Tempn(i-1), Tempn(i));
- b[i]=1+ cfl*(2*theta-1);
- c[i]=(1-theta)*cfl;
- a[i-1]=-theta*cfl;
- cout<< theta << " , ";
- }
-
- /* On traite l'avant dernière face interne */
- theta=theta_upwind(Temp(nbCells-3),Temp(nbCells-2),Temp(nbCells-1),Temp(nbCells-1),VitesseX, dt, Tempn(nbCells-2), Tempn(nbCells-1));
- b[nbCells-2]=1+ cfl*(2*theta-1);
- c[nbCells-2]=(1-theta)*cfl;
- a[nbCells-3]=-theta*cfl;
-
- cout<< theta << " , ";
-
- /* On traite la dernière face (sortie) */
- theta=theta_upwind(Temp(nbCells-2),Temp(nbCells-1),Temp(nbCells-1),Temp(nbCells-1),VitesseX, dt, Tempn(nbCells-1), Tempn(nbCells));
- b[nbCells-1]=1+ cfl*theta;
- a[nbCells-2]=-theta*cfl;
- //d(nbCells-1)+=-(1-theta_sortie)*cfl*Tempn(nbCells-1);
-
- cout<< theta << endl;
-
- cout<<" k= " << k<<endl;
- /*cout<<"avant solveTri"<<endl;
- for(int i=0;i<nbCells-2;i++)
- cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
- solveTriDiag(a,b,c,d,nbCells);
- /*cout<<"après solveTri"<<endl;
- for(int i=0;i<nbCells-2;i++)
- cout<< " a= "<< a[i]<<" b= "<< b[i]<<" c= "<< c[i]<< " d= "<< d[i]<<endl;*/
- k++;
- erreur = 0;
- for(int i=0;i<nbCells; i++)
- erreur=max(erreur, abs(Temp(i)-d[i])/300);
- cout<< " erreur= "<<erreur<<endl;
- /*cout<< " Fin itération d= "<<endl;
- for(int i=0;i<nbCells-1;i++)
- cout<< " , "<< d(i);
- cout<<endl;*/
- Temp=d;
-// for(int i=0;i<nbCells-1;i++)
-// cout<< " Temp= "<< Temp(i)<<endl;
- }
-
- if(k>=iterMax)
- throw CdmathException("solveEntreeImplicit: Newton scheme not convergent");
-}
-
-
-void EquationTransport1D_entree(double tmax, double VitesseX, int ntmax, double dt, double cfl,int freqSortie, const Mesh& M, const string file, double milieu, double TempLeft, double TempRight)
-{
- /* --------------------------------------------- */
- /* Condition initiale */
- cout << "Construction de la condition initiale ... " << endl;
- Field Temp("Temperature",CELLS,M,1) ;
- champ_heaviside(Temp,milieu,TempLeft, TempRight);
-
- /*terme source */
- cout << "Construction du terme source ... " << endl;
- Field phi("Flux thermique",CELLS,M,1) ;
- champ_heaviside(phi,milieu,-10, 10);
- /*
- * Sortie MED de la condition initiale et du flux thermique à t=0 et iter = 0
- */
- int iter=0;
- double time=0.;
- int nbCells=M.getNumberOfCells();
- cout << "Post-traitement MED du flux thermique constant en temps"<< " ..." << endl;
- //phi.setTime(time,iter);
- //phi.writeCSV(file);
- cout << "Post-traitement MED de la solution à t=" << time << " ..." << endl;
- Temp.setTime(time,iter);
- //Temp.writeCSV(file);
- Temp.writeVTK(file);
- /* boucle de temps */
- cout << " Resolution de l'equation de transport 1D avec entree par un schema Implicite TVD" << endl;
-
- while (iter<ntmax && time <= tmax )
- {
- cout << "-- Iter : " << iter << " Time : " << time << " dt : " << dt << endl;
-
- /* Avancement en temps */
- solveEntreeImplicit(phi, Temp,nbCells, VitesseX, cfl, TempLeft, dt);
- time+=dt;
- iter+=1;
- // sortie visu tous les freq iterations
- if (iter%freqSortie==0)
- {
- Temp.setTime(time,iter);
- Temp.writeVTK(file,false);
- //Temp.writeCSV(file);
- }
- }
-}
-
-
-int Equation_Transport()
-{
- cout << "RESOLUTION EQUATION DE TRANSPORT 1D :" << endl;
- cout << "- DOMAINE : Segment 0,10" << endl;
- cout << "- MAILLAGE CARTESIEN : GENERATION INTERNE CDMATH " << endl;
-
- // Problem data
- double VitesseX=1.0;
- double tmax=100.;
- int freqSortie=1;
- int ntmax=3;
- int nx=50;
- double xinf=0.0;
- double xsup=10.;
- double dx=(xsup-xinf)/nx;
- double cfl=1;
- double dt=cfl*dx/abs(VitesseX);
-
- double TempLeft=300;//285.;
- double TempRight=300;//315.;
-
- cout << "Début Construction du maillage Cartesien…" << endl;
- Mesh M(xinf,xsup,nx);
- cout << "Fin Construction du maillage Cartesien…" << endl;
-
- // theta=1;
- EquationTransport1D_entree(tmax, VitesseX, ntmax, dt, cfl, freqSortie, M, "TemperatureEntreeImplicitTVD50CellsSourceUpwind", (xsup+xinf)/2, TempLeft, TempRight);
- //EquationTransport1D_entree(tmax, VitesseX, ntmax, dt, cfl, freqSortie, M, "TemperatureEntreeImplicitUpwindCreneau50Cells", (xsup+xinf)/4, TempLeft, TempRight);
-
- cout << "CDMATH calculation done." << endl;
- return 0;
-}
-
-
-int main() {
-/* Test solveur tridiagonal
- int n=6;
- Matrix A2(n,n,n+2*(n-1));
-
- A2(0,0)=2.;
- vector<double> e(n-1);
- for(int i=0;i<n-1;i++)
- {
- e[i]=-1/(i+1);
- A2(i,i+1)=-1/(i+1);
- A2(i+1,i)=-1.;
- A2(i+1,i+1)=2.;
- }
- Vector Xana2(n);
- for(int i=0;i<n;i++)
- Xana2(i)=i;
-
- Vector B2=A2*Xana2;
-
- LinearSolver LS11(A2,B2,500,1.E-10,"GMRES","ILU");
- Vector X11=LS11.solve();
- bool correct=true;
- for (int i=0;i<X11.getNumberOfRows();i++)
- correct=correct && (abs(X11(i)-Xana2(i))<1.E-10);
-
- if(correct)
- cout<<"OK"<<endl;
- else
- cout<<"KO"<<endl;
- vector<double> 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<nbCells;i++)
- d[i]=B2(i);
- solveTriDiag(a,b,e,d,nbCells);
- correct=true;
- for (int i=0;i<X11.getNumberOfRows();i++)
- correct=correct && (abs(d(i)-Xana2(i))<1.E-10);
-
- if(correct)
- cout<<"OK"<<endl;
- else
- cout<<"KO"<<endl;
-
- Fin Test solveur tridiagonal */
-
- int ret=Equation_Transport();
- return ret;
-}
+++ /dev/null
-# thermique1d makefile
-
-CC = g++
-
-# Adapt the following lines to your own system:
-PETSCDIR = /usr/lib/petscdir/3.4.5
-MPIDIR = /usr/lib/openmpi
-CDMATHDIR = ../../../../..
-
-IFLAG = -I$(PETSCDIR)/include -I$(MPIDIR)/include -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
+++ /dev/null
-//============================================================================
-// Author : Anouar MEKKAS
-// Version :
-// Description : 1D linear transport equation
-//============================================================================
-
-#include <iostream>
-#include <cmath>
-
-#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<myMesh.getNumberOfCells() ; i++)
- {
- double x=myMesh.getCell(i).x();
- conc(i) = 0.5/(sigma*sqrt(2*pi))*exp(-0.5*pow((x/sigma),2));
- }
-
- double time=0.;
- double tmax=3.0;
- int iter=0;
-
- cout << "MED post-treatment of the solution at T=" << time << "…" << endl;
- string fileOutPut="EqTr1D";
- conc.setTime(time,iter);
- conc.writeMED(fileOutPut);
- conc.writeVTK(fileOutPut);
- conc.writeCSV(fileOutPut);
- int outputFreq=10;
-
- // Time loop
- while (iter<ntmax && time <= tmax )
- {
- cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
- conc(0) = conc(0) -u*dt/dx*(conc(0)-conc(myMesh.getNumberOfCells()-1));
- for (int j=1 ; j<myMesh.getNumberOfCells() ; j++)
- {
- conc(j) = conc(j) -u*dt/dx*(conc(j)-conc(j-1));
- }
- time+=dt;
- iter+=1;
- if (iter%outputFreq==0)
- {
- conc.setTime(time,iter);
- conc.writeMED(fileOutPut,false);
- conc.writeVTK(fileOutPut,false);
- conc.writeCSV(fileOutPut);
- }
- }
- cout << "CDMATH calculation done." << endl;
- return 0;
-}
-
-
+++ /dev/null
-#!/usr/bin/env python
-# -*-coding:utf-8 -*
-
-import math
-
-import cdmath
-
-
-def main():
- a = -5.0
- b = 5.0
- nx = 1000
- ntmax = 1000
- dx = (b - a) / nx
- pi = 3.1415927
- # Transport velocity
- cfl = 0.5
- u = 3.
- dt = cfl * dx / u
-
- my_mesh = cdmath.Mesh(a, b, nx)
- conc = cdmath.Field("Concentration", cdmath.CELLS, my_mesh, 1)
-
- # Initial conditions
- sigma = math.sqrt(0.2)
- for i in range(my_mesh.getNumberOfCells()):
- x = my_mesh.getCell(i).x()
- conc[i] = 0.5 / (sigma * math.sqrt(2 * pi)) * math.exp(-0.5 * math.pow((x / sigma), 2))
- pass
-
- time = 0.
- tmax = 3.0
- it = 0
-
- print("MED post-treatment of the solution at T=" + str(time) + "…")
- output_filename = "EqTr1D"
- conc.setTime(time, it)
- conc.writeMED(output_filename)
- conc.writeVTK(output_filename)
- conc.writeCSV(output_filename)
- output_freq = 10
-
- # Time loop
- while (it < ntmax and time <= tmax):
- print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
- conc[0] = conc[0] - u * dt / dx * (conc[0] - conc[my_mesh.getNumberOfCells() - 1])
- for j in range(1, my_mesh.getNumberOfCells()):
- conc[j] = conc[j] - u * dt / dx * (conc[j] - conc[j - 1])
- pass
- time += dt
- it += 1
- if (it % output_freq == 0):
- conc.setTime(time, it)
- conc.writeMED(output_filename, False)
- conc.writeVTK(output_filename, False)
- conc.writeCSV(output_filename)
- pass
- pass
- print("CDMATH calculation done.")
- return
-
-
-if __name__ == """__main__""":
- main()
+++ /dev/null
-# Transport1d 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 *.med
+++ /dev/null
-//============================================================================
-// Author : Anouar MEKKAS
-// Version :
-// Description : Equation de transport lineaire 2D non structure
-//============================================================================
-
-#include <iostream>
-#include <string>
-#include <cmath>
-
-#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 ; j<nbCells ; j++)
- {
- double x = myMesh.getCell(j).x() ;
- double y = myMesh.getCell(j).y() ;
- double valX=(x-xcentre)*(x-xcentre);
- double valY=(y-ycentre)*(y-ycentre);
- double val=sqrt(valX+valY);
- if (val<rayon)
- yField(j) = 1.0;
- else
- yField(j) = 0.0;
- }
-}
-
-void sigma_flux(double VitesseX, double VitesseY, double cfl, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
-{
- // Calculation of fluxes
- Mesh myMesh=yField.getMesh();
- int nbCells=myMesh.getNumberOfCells();
- double normU=sqrt(VitesseX*VitesseX+VitesseY*VitesseY);
- for (int j=0 ; j<nbCells ; j++)
- {
- Cell Cj=myMesh.getCell(j);
- int nbFace=Cj.getNumberOfFaces();
- double SumF=0.0;
- double minlengthFk=1.E30;
-
- int cellCourante,cellAutre;
- for (int k=0 ; k<nbFace ; k++)
- {
- int indexFace=Cj.getFacesId()[k];
- Face Fk=myMesh.getFace(indexFace);
- double NormalX=Cj.getNormalVector(k,0);
- double NormalY=Cj.getNormalVector(k,1);
- double LengthFk = Fk.getMeasure();
- double UN=VitesseX*NormalX+VitesseY*NormalY;
-
- minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
- minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseX));
- minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseY));
-
- double conc=0.0;
- cellCourante=j;
- cellAutre=-1;
-
- if (!Fk.isBorder())
- {
- int indexC1=Fk.getCellsId()[0];
- int indexC2=Fk.getCellsId()[1];
- /* hypothese: La cellule d'index indexC1 est la cellule courante index j */
- if ( indexC1 == j )
- {
- /* hypothese verifie */
- cellCourante=indexC1;
- cellAutre=indexC2;
- } else if ( indexC2 == j )
- {
- /* hypothese non verifie */
- cellCourante=indexC2;
- cellAutre=indexC1;
- }
- // definir la cellule gauche et droite par le prduit vitesse * normale sortante
- // si u*n>0 : rien a faire sinon inverser la gauche et la droite
- if (UN>1.E-15)
- conc=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 (iter<ntmax && time <= tmax )
- {
- Field SumFlux("Fluxes sum",CELLS,myMesh,1) ;
- sigma_flux(VitesseX,VitesseY,cfl,yField,indexFacesPerio,dt,SumFlux);
- cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
-
- /* Advancing time step */
- yField-=SumFlux;
-
- time+=dt;
- iter+=1;
- // Output every freq iterations
- if (iter%freqSortie==0)
- {
- yField.setTime(time,iter);
- yField.writeMED(file,false);
- yField.writeVTK(file,false);
- yField.writeCSV(file);
- }
- }
-}
-
-int main()
-{
- cout << "Resolution of the 2D transport equation:" << endl;
- cout << "- DOMAIN: SQUARE" << endl;
- cout << "- MESH: TRIANGULAR, GENERATED WITH SALOME" << endl;
- cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
- cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
-
- // Problem data
- double cfl=0.4;
- double VitesseX=1.0;
- double VitesseY=1.0;
- double tmax=1.;
- int freqSortie=10;
-
- cout << "Construction of Cartesian mesh…" << endl;
- Mesh myMesh("../../tests/ressources/meshSquare.med");
- string fileOutPut="Exercice2";
- EquationTransport2D(tmax,VitesseX,VitesseY,cfl,freqSortie,myMesh,fileOutPut);
- cout << "CDMATH calculation done." << endl;
-
- return 0;
-}
+++ /dev/null
-#!/usr/bin/env python
-# -*-coding:utf-8 -*
-
-import math
-
-import cdmath
-
-
-def initial_conditions(my_mesh):
- rayon = 0.15
- xcentre = 0.25
- ycentre = 0.25
- y_field = cdmath.Field("Y field", cdmath.CELLS, my_mesh, 1)
- nbCells = my_mesh.getNumberOfCells()
- for j in range(nbCells):
- x = my_mesh.getCell(j).x()
- y = my_mesh.getCell(j).y()
- valX = (x - xcentre) * (x - xcentre)
- valY = (y - ycentre) * (y - ycentre)
- val = math.sqrt(valX + valY)
- if val < rayon:
- y_field[j] = 1.0
- pass
- else:
- y_field[j] = 0.0
- pass
- pass
- return y_field
-
-
-def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
- # Calculation of fluxes #
- SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
- my_mesh = y_field.getMesh()
- nbCells = my_mesh.getNumberOfCells()
- normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
- for j in range(nbCells):
- Cj = my_mesh.getCell(j)
- nbFace = Cj.getNumberOfFaces()
- SumF = 0.0
- minlengthFk = 1.E30
- for k in range(nbFace):
- indexFace = Cj.getFacesId()[k]
- Fk = my_mesh.getFace(indexFace)
- NormalX = Cj.getNormalVector(k, 0)
- NormalY = Cj.getNormalVector(k, 1)
- LengthFk = Fk.getMeasure()
- UN = VitesseX * NormalX + VitesseY * NormalY
- minlengthFk = min(minlengthFk, LengthFk / abs(UN))
- minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
- minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
- conc = 0.0
- cellCourante = j
- cellAutre = -1
- if (not Fk.isBorder()):
- indexC1 = Fk.getCellsId()[0]
- indexC2 = Fk.getCellsId()[1]
- # hypothesis: the cell of index indexC1 is the current cell of index j #
- if (indexC1 == j):
- # hypothese is verified #
- cellCourante = indexC1
- cellAutre = indexC2
- pass
- elif (indexC2 == j):
- # hypothesis is not verified #
- cellCourante = indexC2
- cellAutre = indexC1
- pass
- # define left and right cell with the product of velocity * outward normal vector
- # if u*n>0: nothing to do, else invert left and right
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = y_field[cellAutre]
- pass
- pass
- else:
- # homogeneous Neumann boundary conditions #
- if (Fk.getGroupName() == "GAUCHE" or Fk.getGroupName() == "DROITE"):
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = 0.0
- pass
- pass
- # periodical boundary conditions #
- if (Fk.getGroupName() == "BAS" or Fk.getGroupName() == "HAUT"):
- indexFP = indexFacesPerio[indexFace]
- # another way to get the index of the periodical face #
- # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
- Fp = my_mesh.getFace(indexFP)
- indexCp = Fp.getCellsId()[0]
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = y_field[indexCp]
- pass
- pass
- pass
- SumF = SumF + UN * LengthFk * conc
- pass
- dt = cfl * minlengthFk / normU
- SumFlux[j] = dt * SumF / Cj.getMeasure()
- pass
- return dt, SumFlux
-
-
-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()
+++ /dev/null
-//============================================================================
-// Author : Anouar MEKKAS
-// Version :
-// Description : Equation de transport lineaire 2D non structure
-//============================================================================
-
-#include <iostream>
-#include <string>
-#include <cmath>
-
-#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 ; j<nbCells ; j++)
- {
- double x = myMesh.getCell(j).x() ;
- double y = myMesh.getCell(j).y() ;
- double valX=(x-xcentre)*(x-xcentre);
- double valY=(y-ycentre)*(y-ycentre);
- double val=sqrt(valX+valY);
- if (val<rayon)
- yField(j) = 1.0;
- else
- yField(j) = 0.0;
- }
-}
-
-void sigma_flux(const parameters & p, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
-{
- /* Calcul des flux */
- Mesh myMesh=yField.getMesh();
- int nbCells=myMesh.getNumberOfCells();
- double normU=sqrt(p.VitesseX*p.VitesseX+p.VitesseY*p.VitesseY);
- for (int j=0 ; j<nbCells ; j++)
- {
- Cell Cj=myMesh.getCell(j);
- int nbFace=Cj.getNumberOfFaces();
- double SumF=0.0;
- double minlengthFk=1.E30;
-
- int cellCourante,cellAutre;
- for (int k=0 ; k<nbFace ; k++)
- {
- int indexFace=Cj.getFacesId()[k];
- Face Fk=myMesh.getFace(indexFace);
- double NormalX=Cj.getNormalVector(k,0);
- double NormalY=Cj.getNormalVector(k,1);
- double LengthFk = Fk.getMeasure();
- double UN=p.VitesseX*NormalX+p.VitesseY*NormalY;
-
- minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
- minlengthFk=min(minlengthFk,LengthFk/fabs(p.VitesseX));
- minlengthFk=min(minlengthFk,LengthFk/fabs(p.VitesseY));
-
- double conc=0.0;
- cellCourante=j;
- cellAutre=-1;
-
- if (!Fk.isBorder())
- {
- int indexC1=Fk.getCellsId()[0];
- int indexC2=Fk.getCellsId()[1];
- /* hypothese: La cellule d'index indexC1 est la cellule courante index j */
- if ( indexC1 == j )
- {
- /* hypothese verifie */
- cellCourante=indexC1;
- cellAutre=indexC2;
- } else if ( indexC2 == j )
- {
- /* hypothese non verifie */
- cellCourante=indexC2;
- cellAutre=indexC1;
- }
- // definir la cellule gauche et droite par le prduit vitesse * normale sortante
- // si u*n>0 : rien a faire sinon inverser la gauche et la droite
- if (UN>1.E-15)
- conc=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<ntmax && time <= tmax )
- {
- Field SumFlux("Fluxes sum",CELLS,myMesh,1) ;
- sigma_flux(p,yField,indexFacesPerio,dt,SumFlux);
- cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
-
- /* Advancing time step */
- yField-=SumFlux;
-
- time+=dt;
- iter+=1;
- // Output every freq iterations
- if (iter % p.freqSortie==0)
- {
- yField.setTime(time,iter);
- yField.writeVTK(p.outFile,false);
- yField.writeCSV(p.outFile);
- }
- }
-
- cout << "MED post-treatment of the solution at T=" << time << endl;
- yField.setTime(time,iter);
- yField.writeMED(p.outFile,false);
- yField.writeCSV(p.outFile);
-
- tmax = time;
- cout << "End of EquationTransport2D." << endl;
-}
-
-void compute_onepass(double tmin, double tmax, const Mesh & M, const parameters & p)
-{
- int iter = 0;
-
- /* Initial conditions */
- cout << "Construction of initial condition…" << endl;
- Field f("Y field",CELLS,M,1) ;
- conditions_initiales(f);
-
- EquationTransport2D(iter, tmin, tmax, p, f);
-}
-
-void compute_twopass(double tmin, double tmax, const Mesh & M, const parameters & p)
-{
- int iter = 0;
- parameters q(p);
- double tstep = 0.5 * (tmin + tmax);
-
- /* Initial conditions */
- cout << "Construction of initial condition…" << endl;
- Field f("Y field",CELLS,M,1) ;
- conditions_initiales(f);
-
- q.outFile = p.outFile + "_A";
- EquationTransport2D(iter, tmin, tstep, q, f);
-
- Field f2(q.outFile, CELLS, "Y field", iter, 0);
-
- q.outFile = p.outFile + "_B";
- EquationTransport2D(iter, tstep, tmax, q, f2);
-
-}
-
-int main()
-{
- cout << "Resolution of the 2D transport equation:" << endl;
- cout << "- DOMAIN: SQUARE" << endl;
- cout << "- MESH: TRIANGULAR, GENERATED WITH SALOME" << endl;
- cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
- cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
-
- // donnees du probleme
- parameters p;
- int iter;
-
- p.cfl=0.4;
- p.VitesseX=1.0;
- p.VitesseY=1.0;
- p.freqSortie=50;
- p.outFile="res2D";
-
- cout << "Construction of Cartesian mesh…" << endl;
- Mesh M("../../tests/ressources/meshSquare.med");
-
- double tmin = 0;
- double tmax = 0.1;
-
- compute_onepass(tmin, tmax, M, p);
- compute_twopass(tmin, tmax, M, p);
- cout << "CDMATH calculation done." << endl;
-
- return 0;
-}
+++ /dev/null
-# Transport2D_NS makefile
-
-CC = g++
-# Adapt the following line to your own system:
-CDMATHDIR = ../../../../..
-IFLAG = -I$(CDMATHDIR)/include -I.
-LFLAG = -L$(CDMATHDIR)/lib -L$(PETSC_DIR)/$(PETSC_ARCH)/lib
-LIBS = -linterpkernel -lmedC -lmedloader -lmedcoupling -lbase -lmesh -llinearsolver -lpetsc
-
-all: main main2
-
-main: main.cxx
- $(CC) -g -o $@ $^ $(IFLAG) $(LFLAG) $(LIBS)
-
-main2: main2.cxx
- $(CC) -g -o $@ $^ $(IFLAG) $(LFLAG) $(LIBS)
-
-%.o: %.cxx
- $(CC) -c -g -o $@ $< $(CFLAGS) $(IFLAG) $(LFLAG) $(LIBS)
-
-.PHONY: clean
-
-clean:
- rm -f main main2 *.o *~ core $(INCDIR)/*~
-
-sweep:
- rm -f *.vtu
- rm -f *.pvd
- rm -f *.csv
- rm -f Exercie2*.med
+++ /dev/null
-//============================================================================
-// Author : Anouar MEKKAS
-// Version :
-// Description : 2D linear transport equation on cartesian grid
-//============================================================================
-
-#include <iostream>
-#include <string>
-#include <cmath>
-
-#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 ; j<nbCells ; j++)
- {
- double x = myMesh.getCell(j).x() ;
- double y = myMesh.getCell(j).y() ;
- double valX=(x-xcentre)*(x-xcentre);
- double valY=(y-ycentre)*(y-ycentre);
- double val=sqrt(valX+valY);
- if (val<rayon)
- yField(j) = 1.0;
- else
- yField(j) = 0.0;
- }
-}
-
-void sigma_flux(double VitesseX, double VitesseY, double cfl, const Field& yField, const IntTab indexFacesPerio, double& dt, Field& SumFlux)
-{
- /* Fluxes calculation */
- Mesh myMesh=yField.getMesh();
- int nbCells=myMesh.getNumberOfCells();
- double normU=sqrt(VitesseX*VitesseX+VitesseY*VitesseY);
- for (int j=0 ; j<nbCells ; j++)
- {
- Cell Cj=myMesh.getCell(j);
- int nbFace=Cj.getNumberOfFaces();
- double SumF=0.0;
- double minlengthFk=1.E30;
-
- int cellCourante,cellAutre;
- for (int k=0 ; k<nbFace ; k++)
- {
- int indexFace=Cj.getFacesId()[k];
- Face Fk=myMesh.getFace(indexFace);
- double NormalX=Cj.getNormalVector(k,0);
- double NormalY=Cj.getNormalVector(k,1);
- double LengthFk = Fk.getMeasure();
- double UN=VitesseX*NormalX+VitesseY*NormalY;
-
- minlengthFk=min(minlengthFk,LengthFk/fabs(UN));
- minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseX));
- minlengthFk=min(minlengthFk,LengthFk/fabs(VitesseY));
-
- double conc=0.0;
- cellCourante=j;
- cellAutre=-1;
-
- if (!Fk.isBorder())
- {
- int indexC1=Fk.getCellsId()[0];
- int indexC2=Fk.getCellsId()[1];
- /* Hypothesis: the cell of index indexC1 is the current cell index j */
- if ( indexC1 == j )
- {
- /* Hypothesis verified */
- cellCourante=indexC1;
- cellAutre=indexC2;
- } else if ( indexC2 == j )
- {
- /* Hypothesis not verified */
- cellCourante=indexC2;
- cellAutre=indexC1;
- }
- // Define left and right cells with the product velocity * outward normal
- // If u*n>0, 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 (iter<ntmax && time <= tmax )
- {
- Field SumFlux("Sum Flux",CELLS,myMesh,1) ;
- sigma_flux(VitesseX,VitesseY,cfl,yField,indexFacesPerio,dt,SumFlux);
- cout << "-- Iter: " << iter << ", Time: " << time << ", dt: " << dt << endl;
-
- /* Advancing time step */
- yField-=SumFlux;
-
- time+=dt;
- iter+=1;
- // Ouput every freq iterations
- if (iter%freqSortie==0)
- {
- yField.setTime(time,iter);
- yField.writeMED(file,false);
- yField.writeVTK(file,false);
- yField.writeCSV(file);
- }
- }
-}
-
-int main()
-{
- cout << "RESOLUTION OF 2D TRANSPORT EQUATION:" << endl;
- cout << "- DOMAIN: SQUARE" << endl;
- cout << "- MESH: CARTESIAN, GENERATED INTERNALLY WITH CDMATH" << endl;
- cout << "- PERIODIC BC ON TOP AND BOTTOM" << endl;
- cout << "- HOMOGENEOUS NEUMANN BC ON LEFT AND RIGHT" << endl;
-
- // Problem data
- double cfl=0.4;
- double VitesseX=1.0;
- double VitesseY=1.0;
- double tmax=1.;
- int freqSortie=10;
-
- cout << "Construction of a cartesian mesh …" << endl;
- double xinf=0.0;
- double xsup=1.0;
- double yinf=0.0;
- double ysup=1.0;
- int nx=100;
- int ny=100;
- Mesh myMesh(xinf,xsup,nx,yinf,ysup,ny);
- double eps=1.E-10;
- myMesh.setGroupAtPlan(xsup,0,eps,"RightEdge");
- myMesh.setGroupAtPlan(xinf,0,eps,"LeftEdge");
- myMesh.setGroupAtPlan(yinf,1,eps,"BottomEdge");
- myMesh.setGroupAtPlan(ysup,1,eps,"TopEdge");
- string fileOutPutCart="Exercice1";
- EquationTransport2D(tmax,VitesseX,VitesseY,cfl,freqSortie,myMesh,fileOutPutCart);
- cout << "CDMATH calculation done." << endl;
- return 0;
-}
+++ /dev/null
-#!/usr/bin/env python
-# -*-coding:utf-8 -*
-
-import math
-
-import cdmath
-
-
-def initial_conditions(my_mesh):
- rayon = 0.15
- xcentre = 0.25
- ycentre = 0.25
- y_field = cdmath.Field("Y field", cdmath.CELLS, my_mesh, 1)
- nbCells = my_mesh.getNumberOfCells()
- for j in range(nbCells):
- x = my_mesh.getCell(j).x()
- y = my_mesh.getCell(j).y()
- valX = (x - xcentre) * (x - xcentre)
- valY = (y - ycentre) * (y - ycentre)
- val = math.sqrt(valX + valY)
- if val < rayon:
- y_field[j] = 1.0
- pass
- else:
- y_field[j] = 0.0
- pass
- pass
- return y_field
-
-
-def sigma_flux(VitesseX, VitesseY, cfl, y_field, indexFacesPerio):
- # Fluxes calculation #
- SumFlux = cdmath.Field("Fluxes", cdmath.CELLS, y_field.getMesh(), 1)
- my_mesh = y_field.getMesh()
- nbCells = my_mesh.getNumberOfCells()
- normU = math.sqrt(VitesseX * VitesseX + VitesseY * VitesseY)
- for j in range(nbCells):
- Cj = my_mesh.getCell(j)
- nbFace = Cj.getNumberOfFaces()
- SumF = 0.0
- minlengthFk = 1.E30
- for k in range(nbFace):
- indexFace = Cj.getFacesId()[k]
- Fk = my_mesh.getFace(indexFace)
- NormalX = Cj.getNormalVector(k, 0)
- NormalY = Cj.getNormalVector(k, 1)
- LengthFk = Fk.getMeasure()
- UN = VitesseX * NormalX + VitesseY * NormalY
- minlengthFk = min(minlengthFk, LengthFk / abs(UN))
- minlengthFk = min(minlengthFk, LengthFk / abs(VitesseX))
- minlengthFk = min(minlengthFk, LengthFk / abs(VitesseY))
- conc = 0.0
- cellCourante = j
- cellAutre = -1
- if (not Fk.isBorder()):
- indexC1 = Fk.getCellsId()[0]
- indexC2 = Fk.getCellsId()[1]
- # hypothese: La cellule d'index indexC1 est la cellule courante index j #
- if (indexC1 == j):
- # hypothese verifie #
- cellCourante = indexC1
- cellAutre = indexC2
- pass
- elif (indexC2 == j):
- # hypothese non verifie #
- cellCourante = indexC2
- cellAutre = indexC1
- pass
- # definir la cellule gauche et droite par le prduit vitesse * normale sortante
- # si u*n>0 : rien a faire sinon inverser la gauche et la droite
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = y_field[cellAutre]
- pass
- pass
- else:
- # conditions aux limites neumann homogene #
- if (Fk.getGroupName() == "LeftEdge" or Fk.getGroupName() == "RightEdge"):
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = 0.0
- pass
- pass
- # conditions aux limites periodiques #
- if (Fk.getGroupName() == "BottomEdge" or Fk.getGroupName() == "TopEdge"):
- indexFP = indexFacesPerio[indexFace]
- # une autre manière de recuperer l'index de la face periodique #
- # int indexFP=my_mesh.getIndexFacePeriodic(indexFace);
- Fp = my_mesh.getFace(indexFP)
- indexCp = Fp.getCellsId()[0]
- if (UN > 1.E-15):
- conc = y_field[cellCourante]
- pass
- else:
- conc = y_field[indexCp]
- pass
- pass
- pass
- SumF = SumF + UN * LengthFk * conc
- pass
- dt = cfl * minlengthFk / normU
- SumFlux[j] = dt * SumF / Cj.getMeasure()
- pass
- return dt, SumFlux
-
-
-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()
+++ /dev/null
-# 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
-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)