Análisis Dinámico en PLAXIS 2D ES-EN
Análisis Dinámico en PLAXIS 2D ES-EN
Análisis Dinámico en PLAXIS 2D ES-EN
Resumen
El presente documento contiene un set de rutinas implementadas en los lenguajes de progra-
mación Python y MATLAB que permiten generar modelos numéricos en el software PLAXIS 2D
para análisis dinámicos, obtener resultados específicos y posteriormente procesar los resultados.
Manipular grandes volúmenes de información de forma manual puede conllevar errores, por lo
que automatización de la obtención de resultado en estos casos es necesaria.
Versión 3
Se modifica la lectura de las coordenadas de los polígonos desde el código principal a archivos
de texto para evitar modificar el código principal.
Pendientes
Índice de Contenidos
2. Output 19
2.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2. Obtención de Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.3. Obtención de puntos de monitoreo . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3. Post-Procesamiento 24
3.1. MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Índice de Figuras
1. Acceder a rutinas de Python desde PLAXIS 2D . . . . . . . . . . . . . . . . . . . . . . 1
2. Creación servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
3. Geometría . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
4. Creación del modelo - Asignación de materiales a los polígonos . . . . . . . . . . . . . 7
5. Malla de elementos finitos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
6. Archivos anidados Ejemplo 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Comparación desplazamientos en PLAXIS 2D (izquierda) y DEEPSOIL (derecha) para
el mismo registro de aceleraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
8. Fases secuenciales y en paralelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
9. Acceder a rutinas de Python desde PLAXIS 2D - Output . . . . . . . . . . . . . . . . 19
10. Step guardados en fase dinámica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
11. Archivos anidados en el ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12. Resultado rutina animacion.m en un instante de tiempo . . . . . . . . . . . . . . . . 27
Índice de Códigos
1. Ejemplo creación objetos g_i.polygon() . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Ejemplo creación objetos g_i.neginterface() g_i.linedispl() . . . . . . . . . . . . 3
3. Ejemplo parametros del suelo soil_params . . . . . . . . . . . . . . . . . . . . . . . 5
1.1. Introducción
La presente sección contiene las rutinas escritas en Python para generar el modelo numérico en
el software PLAXIS 2D.
Para acceder a las rutinas es posible hacerlo a través del software PLAXIS 2D, en la barra de
herramientas Expert menu > Run Python script > Open... (Figura 1).
Para vincular PLAXIS 2D con Python se crea un servidor interno (Figura 2), aparece de forma
automática un mensaje y basta en dar click en Star server. En caso de que el puerto (port) no
este disponible es posible modificar el número por defecto (10000).
1.2. Geometría
En PLAXIS 2D la geometría puede ser definida por medio de objetos g_i.borehole() (colum-
nas estatigraficas de suelo) o g_i.polygon() (poligonos).
En el caso de presas de relaves se opto por definir 3 polígonos representativos de las estructuras
principales: muro, fundación y relaves Figura 3.
Figura 3: Geometría
La definición del polígono se hace a través de sus vértices, estos se pueden asignar entregando
directamente un vector/tupla con todas las coordenadas. En el Código 1 se muestra un ejemplo
de una sección de deposito de relave utilizando como variables algunas medidas representativas:
Alturas del muro y de la fundación, pendientes aguas abajo y arriba, ancho del coronamiento y
revancha. El ancho de la fundación es función de la altura del muro y satisface que las distancias
entre el pie del talud aguas abajo y el borde de la fundación sin relaves, y el borde del coronamiento
aguas abajo y el borde de la fundación con relaves, es 10 veces la distancia horizontal entre el pie
del talud aguas abajo y el borde del coronamiento aguas abajo.
Usando las coordenadas de los polígonos representativos se define el lugar geométrico donde
se asignaran las condiciones de borde (g_i.neginterface()) y desde donde se propaga el registro
sísmico (g_i.linedispl()). En el Código 2 se muestra que el registro se propaga en ondas de
compresionales desde la base de la fundación (−L − 1), en la dirección Y y fijo en la dirección X y
escalado por 1. En ondas de corte desde la base de la fundación (−L), en la dirección X y libre en
la dirección Y y escalado por 1. Posteriormente cuando se creen las fases dinámicas se asignara un
valor especifico a los desplazamientos en Y (compresionales) y X (corte).
27 borehole_g = g_i.borehole(0)
28 borehole_g.Head = -L # NIVEL FREATICO
29 toppolygon1, topsoil1 = g_i.polygon([x_toe, 0],[x_muro, 0],[w_crest, H],[x_crest, H])
30 toppolygon2, topsoil2 = g_i.polygon([x_muro, 0],[x_right, 0],[ x_right, H-rev ],[ x_relave, H-rev
,→ ])
31 bottompolygon, bottomsoil = g_i.polygon([x_left, -L],[x_right, -L ],[ x_right, 0],[ x_left , 0])
1
2 line_g = g_i.line ((0, -L), (0, 0)) [-1]
3 interfaces_g = g_i.neginterface(line_g)
4
18
19 line_p = g_i.line((x_right, -L-1), (0, -L-1)) [-1]
20 linedisplacement_p = g_i.linedispl(line_p, "Displacement_x", "fixed", "Displacement_y", "
,→ Prescribed", "uy_start", 1.0)
21 interfaces_s = g_i.neginterface(line_p)
22
1.3. Materiales
La asignación de los materiales a los polígonos se hace por medio del objeto g_i.soilmat(),
La definición de parámetros se hace completando el valor de cada llaves/clave del diccionario
(soil_params), es importante respetar la numeración del modelo de suelo y el nombre de las variables
(llaves). En el Código 3 se tienen 4 modelos de suelo:
1: Lineal Elástico
2: Mohr-Coulomb
4: HS small
Es posible apreciar en el Código 3 que a medida que el modelo se complejiza, requiere completar
una mayor cantidad de parámetros.
3 if soilinfo [ "soilmodel"] == 1:
4 soil_params = [("MaterialName", soilinfo["name"]),
5 ("SoilModel", soilinfo [ "soilmodel" ]) ,
6 ("DrainageType", soilinfo [ "drainagetype"]) ,
7 ("gammaUnsat", soilinfo["gammaUnsat"]),
8 ("gammaSat", soilinfo["gammaSat"]),
9 ("Gref", soilinfo [ "E"]/(2*(1+soilinfo [ "nu"]))) ,
10 ("nu", soilinfo [ "nu"]) ,
11 (" cref " , soilinfo [ "cu"]) ,
12 ("RayleighAlpha", soilinfo [ "RayleighAlpha"]),
13 ("RayleighBeta", soilinfo [ "RayleighBeta"])]
14
15 if soilinfo [ "soilmodel"] == 2:
16 soil_params = [("MaterialName", soilinfo["name"]),
17 ("SoilModel", soilinfo [ "soilmodel" ]) ,
18 ("DrainageType", soilinfo [ "drainagetype"]) ,
19 ("gammaUnsat", soilinfo["gammaUnsat"]),
20 ("gammaSat", soilinfo["gammaSat"]),
21 ("Gref", soilinfo [ "E"]/(2*(1+soilinfo [ "nu"]))) ,
22 ("nu", soilinfo [ "nu"]) ,
23 (" cref " , soilinfo [ "cu"]) ,
24 ("cinc" , soilinfo [ "cinc" ]) ,
25 (" verticalRef " , soilinfo [ " verticalRef " ]) ,
26 ("RayleighAlpha", soilinfo [ "RayleighAlpha"]),
27 ("RayleighBeta", soilinfo [ "RayleighBeta"])]
28
29 if soilinfo [ "soilmodel"] == 4:
30 soil_params = [("MaterialName", soilinfo["name"]),
31 ("SoilModel", soilinfo [ "soilmodel" ]) ,
32 ("DrainageType", soilinfo [ "drainagetype"]) ,
33 ("gammaUnsat", soilinfo["gammaUnsat"]),
34 ("gammaSat", soilinfo["gammaSat"]),
35 ("E50ref", soilinfo [ "E50ref"]) ,
36 ("EoedRef", soilinfo [ "EoedRef"]),
37 ("EurRef", soilinfo [ "EurRef"]),
38 ("powerm", soilinfo [ "powerm"]),
39 ("G0ref", soilinfo [ "G0ref"]) ,
40 ("gamma07", soilinfo["gamma07"]),
41 ("K0nc", soilinfo [ "K0nc"]),
42 ("DefaultValuesAdvanced", soilinfo [ "DefaultValuesAdvanced"]),
43 ("nu", soilinfo [ "nu"]) ,
44 (" cref " , soilinfo [ "cu"]) ,
45 ("phi", soilinfo [ "phi" ]) ,
46 ("RayleighAlpha", soilinfo [ "RayleighAlpha"]),
47 ("RayleighBeta", soilinfo [ "RayleighBeta"])]
48
74 soil_material = g_i.soilmat(*soil_params)
75
76 return soil_material
1.4. Modelo
Definidos los polígonos representativos y los materiales es posible vincularlos para definir el
modelo numérico. En el Código 4 se muestra como vincularlos y en la Figura 4 es posible ver
visualmente en el software PLAXIS 2D esta asignación.
12 topmaterial2 = make_soilmaterial(toplayer2)
13 top_pg2.Soil.Material = topmaterial2
14
15 return topmaterial1, topmaterial2
1.5. Malla
Las opciones disponibles para generar un malla/grilla de elementos finitos son definir un razón
máxima de área de acuerdo con el área total del polígono (g_i.mesh()) o especificar el área
máxima de la malla (g_i.meshd()). Adicionalmente es posible pre-definir un refinamiento de un
polígono (g_i.refine()). En el Código se muestra como ejemplo el refinamiento de los polígonos 1
y 4 9 veces y el tamaño máximo de los elementos de la malla base es 100, de esta forma se obtienen
elementos de aproximadamente 3 metros de lado en el coronamiento (Figura 5), lugar con menor
velocidad de onda de corte y por tanto menor resolución de acuerdo con la expresión:
f = Vs /λ (1)
Considerando elementos finitos triangulares de 15 nodos media longitud de onda (λ/2) queda
bien caracterizada entre los nodos extremos del mismo lado (la linea tiene 5 nodos, otros criterios
usan 8 a 10 nodos por la longitud de onda completa). De esta forma considerando los elementos de
3 metros se tiene:
f = Vs /6
Para valores de Vs = 100m/s se tiene una resolución en frecuencia de 16Hz.
El motivo de refinar es por que para valores muy pequeños el proceso de creación de malla con-
sume mucho tiempo computacional y en ocasiones no logra generar una malla tan fina.
Este proceso no se ha logrado resolver sin un numero arbitrario de refinamientos en los polígo-
nos.
5 for i in range(1,9) :
6 g_i. refine (g_i.Polygon_4)
7 g_i. refine (g_i.Polygon_1)
8
9 g_i.meshd(100)
10
11 output_port = g_i.viewmesh()
12 s , g = new_server(’localhost’, port=output_port, password=s_i.connection._password)
21 # calculate
22 g_i. calculate ()
23
24 return s , g
8 # Materiales
9 with open(’HSS.txt’) as f :
10 data1 = f.read()
11 toplayer1 = json.loads(data1) # Muro HSS
12 with open(’PM4SAND.txt’) as f:
13 data2 = f.read()
14 toplayerPM4 = json.loads(data2) # Muro PM4SAND
15 with open(’MC.txt’) as f :
16 data3 = f.read()
17 toplayer2 = json.loads(data3) # Relaves Mohr-Coulomb
18 with open(’Elastico . txt ’ ) as f :
19 data4 = f.read()
20 bottomlayer = json.loads(data4) # Fundacion Lineal Elastico
21
La rutina primero lee un archivo de texto que contiene los nombres de los registros seleccionados
(registros_seleccionados.txt). En el ejemplo 1 se leen los registros 1, 9 y 23. En el ejemplo 2 se leen
los registros Maule 2010 Mw8.8 en santiago centro e Illapel 2015 Mw8.4 en la estación V05.
Los archivos de texto con los registros deben estar en la misma carpeta que el archivo antes
descrito.
Los registros deben estar en un formato por columnas, el primer elemento del encabezado con-
tiene el numero de muestras del registro, el segundo termino del encabezado muestra la tasa de
muestreo del registro. La primera columna después del encabezado corresponde al tiempo y la se-
gunda columna después del encabezado corresponde a desplazamiento, velocidad o aceleración en
el tiempo. El ejemplo corresponde a un registros de aceleración de 37616 muestras con una tasa
de muestreo de 0.005 segundos. Se eligió este formato porque es el mismo utilizado en el software
DEEPSOIL.
Dada la limitación de 10000 muestras se corta el registro en ventanas de 10000 muestras y cada
ventana se guarda en un objeto g_i.displmultiplier(), este objeto se asigna posteriormente al lu-
gar geométrico desde donde se propaga la onda sísmica. Para cada registro se guarda el numero de
ventanas para posteriormente en la creación de fases, crear análisis dinámicos en serie o secuenciales.
Posteriormente es posible crear fases en paralelo para cada set de análisis secuenciales de forma
de optimizar el usos de procesadores (se ha visto que los menores tiempos de calculo se obtienen al
asignar un procesador a un registro). En el ejemplo se leen los registros de aceleración y se escalan
por 9.8*3 (los registros se ingresan en unidades de m/s2 ).
6 # Regisros Sismicos
7 filename = []
8 with open(parent_dir) as f:
9 filename = f. readlines ()
10
11 cont_fases = 0
12
13 for fn in filename:
14 data = np.loadtxt(fn.replace( ’\n’, ’ ’ ))
15 cont_fases = cont_fases + int(data [0][0]) # largo del registro
16
17 max_step_plaxis = 10000 # Numero maximo de muestras de un registro temporal por fase
18
19 cont_fases = math.ceil(cont_fases/max_step_plaxis) # numero de fases
20 #print(cont_phases)
21
22 aux = 0
23 disp = [0]*cont_fases
24 lr = [0]*len(filename)
25 dt2 = [0]*len(filename)
26 MOD = [0]*len(filename)
27
28 for fn in filename:
29 data = np.loadtxt(fn.replace( ’\n’, ’ ’ ))
30 ifn = filename.index(fn)
31 lr [ ifn ] = int(data [0][0]) # largo del registro
32 dt2[ ifn ] = data [0][1] # dt del registro
33 mod = math.ceil(lr[ifn ]/max_step_plaxis) # numero de ventanas
34 MOD[ifn] = mod
35 for k2 in range(0, mod):
36 #for k2 in range(0, 1): PARA CORRER SOLO LA PRIMERA VENTANA
37 a = (*data[1],*data [2])
38
39 # borrar
40 #print(a)
41 #print(*data[0])
42 #print(*data[1])
43 #print(*data[2])
44 #
45
46 for j in range(3, min(max_step_plaxis+1,lr[ifn]-k2*max_step_plaxis)):
47 a = (*a,*data[j ])
48
56 aux = aux+1
57 data = data[9999:]
58
59 return disp, filename, lr , dt2, MOD
60
61 disp, filename, lr , dt2, MOD = read_records(parent_dir=’DB_REGISTROS.txt’, DataType="
,→ Displacements", Scale=9.8*3)
18 g_i.LineDisplacements.activate(phase2_s)
19 g_i.DynLineDisplacement_1_1.activate(phase2_s)
20 g_i.DynLineDisplacement_1_1.Multiplierx.set(phase2_s, disp[aux3])
21
22
23 g_i.Dynamics.BoundaryYMin.set(phase2_s,"Compliant base")
24 g_i.Dynamics.BoundaryXMin.set(phase2_s,"Free-field")
25
30 phase3_s = g_i.phase(phase2_s)
31 phase3_s.DeformCalcType = phase3_s.DeformCalcType.dynamic
32 phase3_s.Deform.TimeIntervalSeconds = dt2[k]*min(max_step_plaxis,lr[k]-max_step_plaxis
,→ *k2)
33 phase3_s.Deform.ResetDisplacementsToZero = False
34 phase3_s.Deform.UseDefaultIterationParams = False
35 phase3_s.Deform.MaxSteps = min(max_step_plaxis,lr[k]-max_step_plaxis*k2)
36 phase3_s.Deform.TimeStepDetermType = "Manual"
37 phase3_s.Deform.SubSteps = 1
38 phase3_s.Deform.ToleratedError = 0.001
39 #phase3_s.MaxStepsStored = min(max_step_plaxis,lr[k]-max_step_plaxis*k2)
40 phase3_s.MaxStepsStored = 1
41 phase3_s.MaxCores = 16
42
43
44 g_i.LineDisplacements.activate(phase3_s)
45 g_i.DynLineDisplacement_1_1.activate(phase3_s)
46 g_i.DynLineDisplacement_1_1.Multiplierx.set(phase3_s, disp[aux3])
47
48 g_i.Dynamics.BoundaryYMin.set(phase3_s,"Compliant base")
49 g_i.Dynamics.BoundaryXMin.set(phase3_s,"Free-field")
50
51 #g_i.Dynamics.BoundaryYMin.set(phase3_s,"None")
52 #g_i.Dynamics.BoundaryXMin.set(phase2_s,"Viscous")
53 #g_i.Dynamics.BoundaryYMin.set(phase2_s,"Compliant base")
54
55 aux3=aux3+1
56
57 g_i. calculate ()
2. Output
2.1. Introducción
La presente sección contiene las rutinas escritas en Python para generar el modelo numérico en
el software PLAXIS 2D.
Para acceder a las rutinas es posible hacerlo a través del software PLAXIS 2D, en la barra de
herramientas Expert menu > Run Python script > Open...
19 # CUARTO PASO: TIPO DE RESULTADO (VER CELDA INFERIOR CON TODOS LOS
,→ TIPOS DE RESULTADO)
20 #EDP = ’PlasticPointHistoryMohrCoulomb’
21 resulttypes = getattr(g_o.ResultTypes.Soil, EDP)
22
23 import os
24 newpath = os.path.join(parent_dir, ’{0}\ {1}\ {2}’.format(phase_name,p_type,EDP))
25 if not os.path. exists (newpath):
26 os.makedirs(newpath)
27
28 #print(g_o.Phases[-1].Steps.echo())
29 # 9/-4881. Step named "Step_41"
30 for i in range(9, 4000, 10):
31 #for i in range(3999, 4000, 10):
32 step = phaseorder.Steps[i]
33 #st = int(phaseorder.Steps [-1]. Name.value.replace("Step_", ""))
34 st = int(step.Name.value.replace("Step_", ""))
35 getframe(filename= os.path.join(newpath, ’{0}.txt’ .format(st)) ,
36 phaseorder = step, p_type = p_type, resulttypes = resulttypes)
31 import os
32 newpath = os.path.join(parent_dir, ’{0}\ {1}’.format(phase_name,EDP))
33 if not os.path. exists (newpath):
34 os.makedirs(newpath)
35
36 for node in pointtype:
37 print(node.Name.value)
38 st = node.Name.value.replace(pre, "")
39 gettable_time_vs_EDP(filename= os.path.join(newpath, ’{0}.txt’.format(st)),
40 phaseorder = phaseorder, node = node, resulttypes = resulttypes)
Para ejecutar los funciones antes descritas basta llamarlas de la siguiente forma:
En el ejemplo, primero se muestra como obtener en los puntos de monitoreo (del tipo puntos
de integración) la deformación γxy y la tensión τxy . Además se muestra como obtener los despla-
zamientos Uy y Ux para todos los nodos del modelo en todos los pasos guardados y definidos en
saveframe.
3. Post-Procesamiento
3.1. MATLAB
Se presentan las rutinas que permiten leer la información de las carpetas generadas en la sección
output.
La función curvedata.m lee toda la información en una carpeta. En el caso de Frame desde
Python se crea una carpeta con el nombre del tipo de resultado y dentro un archivo de texto para
cada step con su respectivo nombre, dentro del archivo se encuentra la informacion de cada tipo de
punto del modelo completo. En el caso de EDP desde Python se crea una carpeta con el nombre
del tipo de resultado y dentro un archivo de texto para cada punto de monitoreo con su respectivo
nombre, dentro del archivo se encuentra la información para todo el intervalo de tiempo.
Frame guarda una foto del modelo completo para un determinado instante de tiempo y tipo
de resultado. EDP guarda una serie de tiempo para un tipo de resultado en los puntos de monitoreo.
Para manipular los archivos generados tanto para Frame como EDP se crearon las rutinas read-
frame.m y readEDP.m que usan la rutina curvedata.m pero mantienen el formato usado en
Python para crear las carpetas.
13 Np=zeros(l_p,l_edp,Nstep);
14
15 for i = 1:Nstep
16 step( i ) = str2double( listing ( i+1).name(1:end-4));
17 Np (:,:, i )=importdata([MainFolder ’/’ listing( i+1).name]);
18 end
19
20 end
19 end
En la rutina animaciones.m se utilizan las rutinas antes mencionadas para crear una animación
de las deformaciones totales producidas en una presa de relaves. Los archivos utilizados en el ejemplo
se encuentran anidados de la siguiente forma (Figura 11):
28 open(v);
29 set(gcf , ’ position ’ ,get (0, ’ScreenSize’)) ;
30
31 for k= 1:length(step)
32
33 %figure(’ visible ’,’ off ’)
34 scatter (x2(dominio2)+Ux_(dominio2,k)*1,...
35 y2(dominio2)+Ux_(dominio2,k)*1,...
36 30,Utot_(dominio2,k),’ filled ’ )
37 % Configuración del plot
38 axis equal
39 colormap(jet)
40 hcb=colorbar;
41 hcb.Label.String= ’U_{total} [m]’;
42 caxis ([0 0.2])
43 xlabel( ’Seccion Transversal [m]’, ’FontSize’ , 14)
44 ylabel( ’ Elevación [m]’, ’FontSize’ , 14)
45 title ([ ’ t= ’ num2str((step(k)-31)*0.001) ’ [ s ] ’ ], ’FontSize’ , 14)
46 set(gca, ’FontSize’ ,14, ’Color’ ,[0.8 0.8 0.8])
47 frame = getframe(gcf);
48 set(gca, ’nextplot’ , ’ replacechildren ’ ) ;
49 writeVideo(v,frame)
50
51 end
52 close (v);
53 toc
Resumen
This document contains a set of routines implemented in Python and MATLAB programming
languages that allow for the generate numerical models in PLAXIS 2D software for dynamic analy-
sis, obtaining specific results, and processing the results.
Obtaining parameter records over time for different monitoring points is cumbersome.
The maximum number of samples is limiting when analyzing seismic records of events in the
subduction zone of Chile, with duration over 100 seconds. For a sampling rate of 200 samples per
second, sequential dynamic analysis is required.
Manipulating large volumes of information manually can lead to errors, so automation of result
retrieval in these cases is necessary.
The framework of this document has been successfully used in different geo-structures such as
tailings deposits and basins.
Version 3
The reading of parameters of the constitutive models from the main code to text files is modifies
to avoid modifying the main code.
Constitutive models from User-defined are inclued, in particular the PM4SAND model (thanks
to Nicolás Villanueva MSc(c)).
Seismic inputs are included in two directions respecting shear and compresional wave propaga-
tion (thanks to José Bustos PhD(c)).
The reading of polygon coordinates from the main code to text file is modified to avoid modifyng
the main code.
Pending tasks
Índice de Contenidos
2. Output 19
2.1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2. Obtaining Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.3. Obtaining monitoring points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3. Post-Processing 24
3.1. MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Índice de Figuras
1. Accessing Python routines from PLAXIS 2D . . . . . . . . . . . . . . . . . . . . . . . 1
2. Server creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
3. Geometría . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
4. Creating the model - Assigning materials to polygons . . . . . . . . . . . . . . . . . . . 7
5. Finite element mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
6. Nested files Example 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Comparison of displacements in PLAXIS 2D (left) and DEEPSOIL (right) for the
same acceleration record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
8. Sequential and parallel phases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
9. Accessing Python routines from PLAXIS 2D - Output . . . . . . . . . . . . . . . . . . 19
10. Step saved in dynamic phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
11. Nested files in the example (Code 20 ) . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12. Results animation.m routine at a time instant . . . . . . . . . . . . . . . . . . . . . . 27
Índice de Códigos
1. Example objet g_i.polygon() creation . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Example objets g_i.neginterface() g_i.linedispl() creation . . . . . . . . . . . . . 3
3. Example soil parameters soil_params . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1. Introduction
This section contains the routines written in Python to generate the numerical model in PLA-
XIS 2D software.
To access the routines it is possible to do it through the PLAXIS 2D software, in the toolbar
Expert menu > Run Python script > Open... (Figura 1).
To link PLAXIS 2D with Python an internal server is created (Figura 2), a message appears
automatically and just click on Star server. In case the port is not available it is possible to change
the default number (10000).
1.2. Geometry
In PLAXIS 2D the geometry can be defined by mens of objects g_i.borehole() (statigraphic
ground columns) or g_i.polygon() (polygons).
In the case of tailing storage facilities, we chose to define 3 polygons representative of the main
structures: dam, foundation and tailings Figure 3.
Figura 3: Geometría
The definition of the polygon is done through its vertices, these can be assigned by directly
providing a vector/tuple with all the coordinates. Code 1 shows an example of a tailing storage
facility cross section using as variables some representative measures: dam and foundation heights,
downstream and upstream slopes, crest width, and freeboard. The width of the foundation is a
function of the dam height and satisfies that the distances between the downstream slope toe and
the edge of the foundation without tailings, and the downstream crest edge and the edge of the
foundation with tailings, is 10 times the horizontal distance between the downstream slope toe and
the downstream crest edge.
Using the coordinates of the representative polygons, we define the geometrical place where
the boundary condition will be assigned (g_i.neginterface()) and from here the seismic record
propagates (g_i.linedispl()). In Code 2, it is shown that the record propagates in compressional
waves from the base of the foundation (−L − 1), in the Y direction, and fixed in the X direction
and scaled by 1. In shear waves from the base of the foundation (−L), in the X direction, and free
in the Y direction and scaled by 1. Later, when the dynamic phases are created, a specific value
will be assigned to the displacements in Y (compressional) and X (shear).
13 # Model edge/origin
14 x_left = 0
15
16 # distance from the edge/origin to the slope toe - function of the horizontal slope distance W
,→ =H*slope1
17
18
19 line_p = g_i.line((x_right, -L-1), (0, -L-1)) [-1]
20 linedisplacement_p = g_i.linedispl(line_p, "Displacement_x", "fixed", "Displacement_y", "
,→ Prescribed", "uy_start", 1.0)
21 interfaces_s = g_i.neginterface(line_p)
22
1.3. Materials
The assignment of materials to the polygons is done using the g_i.soilmat() object. Parameter
definitions are accomplished by assigning a value to each key in the (soil_params) dictionary. In
Code 3 there are 4 soil models:
1: Linear Elastic
2: Mohr-Coulomb
4: HS small
It is possible to appreciate in Code 3 that as the model becomes more complex, it requires the
completion of a greater number of parameters.
15 if soilinfo [ "soilmodel"] == 2:
16 soil_params = [("MaterialName", soilinfo["name"]),
17 ("SoilModel", soilinfo [ "soilmodel" ]) ,
18 ("DrainageType", soilinfo [ "drainagetype"]) ,
19 ("gammaUnsat", soilinfo["gammaUnsat"]),
20 ("gammaSat", soilinfo["gammaSat"]),
21 ("Gref", soilinfo [ "E"]/(2*(1+soilinfo [ "nu"]))) ,
22 ("nu", soilinfo [ "nu"]) ,
23 (" cref " , soilinfo [ "cu"]) ,
24 ("cinc" , soilinfo [ "cinc" ]) ,
25 (" verticalRef " , soilinfo [ " verticalRef " ]) ,
26 ("RayleighAlpha", soilinfo [ "RayleighAlpha"]),
27 ("RayleighBeta", soilinfo [ "RayleighBeta"])]
28
29 if soilinfo [ "soilmodel"] == 4:
30 soil_params = [("MaterialName", soilinfo["name"]),
31 ("SoilModel", soilinfo [ "soilmodel" ]) ,
32 ("DrainageType", soilinfo [ "drainagetype"]) ,
33 ("gammaUnsat", soilinfo["gammaUnsat"]),
34 ("gammaSat", soilinfo["gammaSat"]),
74 soil_material = g_i.soilmat(*soil_params)
75
76 return soil_material
1.4. Model
Once the representative polygons and materials have been defined, it is possible to link them to
define the numerical model. In Code 4 it is shown how to link them and in Figure 4 it is possible
to see visually in the PLAXIS 2D software this assignment.
12 topmaterial2 = make_soilmaterial(toplayer2)
13 top_pg2.Soil.Material = topmaterial2
14
15 return topmaterial1, topmaterial2
1.5. Mesh
The options available to generate a finite element mesh/grid are to define a maximum area
ratio according to the total area of the polygon (g_i.mesh()) or to specify the maximum area
of the mesh (g_i.meshd()). Additionally it is possible to pre-define a refinement of a polygon
(g_i.refine()). The Code shows as an example the refinement of polygons 1 and 4, 9 times, and
the maximum size of the base mesh elements is 100, thus obtaining elements of approximately 3
meters side at the crest (Figure 5), a place with lower shear wave velocity and therefore lower
resolution according to the expression:
f = Vs /λ (1)
Considering triangular finite elements of 15 nodes half wavelength (λ/2) is well characterized
between nodes of the same side (the line has 5 nodes, other criteria use 8 to 10 nodes for the full
wavelength). Thus, considering the elements of 3 meters we have:
f = Vs /6
For values of Vs = 100m/s there is a frequency resolution of 16Hz.
The reason for refining is that for very small values the mesh creation process takes a lot of
computational time and sometimes fails to generate such a fine mesh.
This process has not been solved without an arbitrary number of refinements in the polygons
5 for i in range(1,9) :
6 g_i. refine (g_i.Polygon_4)
7 g_i. refine (g_i.Polygon_1)
8
9 g_i.meshd(100)
10
11 output_port = g_i.viewmesh()
12 s , g = new_server(’localhost’, port=output_port, password=s_i.connection._password)
21 # calculate
22 g_i. calculate ()
23
24 return s , g
8 # Materials
9 with open(’HSS.txt’) as f :
10 data1 = f.read()
11 toplayer1 = json.loads(data1) # HSS Dam
12 with open(’PM4SAND.txt’) as f:
13 data2 = f.read()
14 toplayerPM4 = json.loads(data2) # PM4SAND Dam
15 with open(’MC.txt’) as f :
16 data3 = f.read()
17 toplayer2 = json.loads(data3) # Mohr-Coulomb Tailings
18 with open(’Elastico . txt ’ ) as f :
19 data4 = f.read()
20 bottomlayer = json.loads(data4) # Linear Elastic Foundation
21
The routine first reads a text file containing the names of the selected records (registros_seleccionados.txt).
In example 1 (Code 9), records 1, 9 and 23 are read. In example 2 (Code 10), records Maule 2010
Mw 8.8 in Santiago Centro and Illapel 2015 Mw 8.4 in station V05 are read.
The text files with the records must be in the same folder as the file described above, Figure 6.
The records should be in a columnar format, the first element of the header has the number
of samples in the record, the second term of the header shows the sampling rate of the record.
The first column afeter the header corresponds to time and the seconrd column after the header
corresponds to displacement, velocity or acceleration over time. The example (Code 11)corresponds
to an acceleration record of 37616 samples with a sampling rate of 0.005 seconds, This format was
chosen because it is the same format used in the DEEPSOIL software
Given the limitation of 10000 samples, the record is cut into windows of 10000 samples, and each
window is saved in an object g_i.displmultiplier(). This object is then assigned to the geometric
location from where the seismic wave propagates. For each record, the number of windows is saved
for later in the creation of phases, to create dynamic analysis in series.
Subsequently, it is possible to create parallel phases for each set of sequential analyses in order to
optimize the use of processors (it has been shown that the shortest computation times are obtained
by assigning a processor to a record). In the example (Code 12) the acceleration records are read
and scaled by 9.8*3 (the records are entered in units of m/s2 ).
6 # Seismic Records
7 filename = []
8 with open(parent_dir) as f:
9 filename = f. readlines ()
10
11 cont_fases = 0
12
13 for fn in filename:
14 data = np.loadtxt(fn.replace( ’\n’, ’ ’ ))
15 cont_fases = cont_fases + int(data [0][0]) # Record length
16
17 max_step_plaxis = 10000 # Maximum number of samples of a time record per phase
18
19 cont_fases = math.ceil(cont_fases/max_step_plaxis) # number of phases
20
21 aux = 0
22 disp = [0]*cont_fases
23 lr = [0]*len(filename)
24 dt2 = [0]*len(filename)
25 MOD = [0]*len(filename)
26
27 for fn in filename:
28 data = np.loadtxt(fn.replace( ’\n’, ’ ’ ))
29 ifn = filename.index(fn)
30 lr [ ifn ] = int(data [0][0]) # record length
31 dt2[ ifn ] = data [0][1] # time sample
32 mod = math.ceil(lr[ifn ]/max_step_plaxis) # number of windows
33 MOD[ifn] = mod
34 for k2 in range(0, mod):
35 a = (*data[1],*data [2])
36
47 aux = aux+1
48 data = data[10000:]
49
50 return disp, filename, lr , dt2, MOD
51
Considering the above, it is recommended to enter the seismic input in displacements to avoid
the shifts generated by the PLAXIS 2D software. However, when subsequently reviewing the ac-
celeration at the free surface, sometimes some punctual numerical instabilities appear where the
acceleration value is triggered.
22 g_i.Dynamics.BoundaryYMin.set(phase2_s,"Compliant base")
23 g_i.Dynamics.BoundaryXMin.set(phase2_s,"Free-field")
24
25 for k2 in range(1, 1):
26 aux3=aux3+1
27 phase2_s = g_i.Phases[-1]
28 phase3_s = g_i.phase(phase2_s)
29 phase3_s.DeformCalcType = phase3_s.DeformCalcType.dynamic
30 phase3_s.Deform.TimeIntervalSeconds = dt2[k]*min(max_step_plaxis,lr[k]-max_step_plaxis
,→ *k2)
31 phase3_s.Deform.ResetDisplacementsToZero = False
32 phase3_s.Deform.UseDefaultIterationParams = False
33 phase3_s.Deform.MaxSteps = min(max_step_plaxis,lr[k]-max_step_plaxis*k2)
34 phase3_s.Deform.TimeStepDetermType = "Manual"
35 phase3_s.Deform.SubSteps = 1
36 phase3_s.Deform.ToleratedError = 0.001
37 phase3_s.MaxStepsStored = 1
38 phase3_s.MaxCores = 16
39
40 g_i.LineDisplacements.activate(phase3_s)
41 g_i.DynLineDisplacement_1_1.activate(phase3_s)
42 g_i.DynLineDisplacement_1_1.Multiplierx.set(phase3_s, disp[aux3])
43
44 g_i.Dynamics.BoundaryYMin.set(phase3_s,"Compliant base")
45 g_i.Dynamics.BoundaryXMin.set(phase3_s,"Free-field")
46
47 aux3=aux3+1
48
49 g_i. calculate ()
2. Output
2.1. Introduction
This section contains the routines written in Python to generate the numerical model in PLA-
XIS 2D software.
The routines can be accessed through the PLAXIS 2D software, in the toolbar Expert menu >
Run Python script > Open... (Figura 9).
22 import os
23 newpath = os.path.join(parent_dir, ’{0}\ {1}\ {2}’.format(phase_name,p_type,EDP))
24 if not os.path. exists (newpath):
25 os.makedirs(newpath)
26
27 #print(g_o.Phases[-1].Steps.echo())
28 # 9/-4881. Step named "Step_41"
29 for i in range(9, 4000, 10):
30 step = phaseorder.Steps[i]
31 st = int(step.Name.value.replace("Step_", ""))
32 getframe(filename= os.path.join(newpath, ’{0}.txt’ .format(st)) ,
33 phaseorder = step, p_type = p_type, resulttypes = resulttypes)
30 import os
31 newpath = os.path.join(parent_dir, ’{0}\ {1}’.format(phase_name,EDP))
32 if not os.path. exists (newpath):
33 os.makedirs(newpath)
34
35 for node in pointtype:
36 print(node.Name.value)
37 st = node.Name.value.replace(pre, "")
38 gettable_time_vs_EDP(filename= os.path.join(newpath, ’{0}.txt’.format(st)),
39 phaseorder = phaseorder, node = node, resulttypes = resulttypes)
In the example, first it is shown how to obtain the shear strain γxy and the shear stress τxy
at the monitoring points (of the integration point type). Additionally, it is shown how to obtain
the displacements Uy and Ux for all the nodes of the model in all the steps saved and defined in
saveframe.
3. Post-Processing
3.1. MATLAB
The routines that allow reading the information of folders generated in the output section are
presented.
The curvedata.m function reads all the information in a folder. In the case of Frame from
Python, a folder is created with the name of the type of result, and inside, a text file is created for
each step with its respective name. Inside the file is the information of each type of point of the
complete model. In the case of EDP from Python, a folder is created with the name of the type of
result, and inside, a text file is created for each monitoring point with its respective name. Inside
the file is the information for the entire time interval.
Frame stores a snapshot of the entire model for a given time instant and result type. EDP
saves a time series for a result type at the monitoring points.
To manipulate the files generated for both Frame and EDP, readframe.m and readEDP.m
routines were created. These routines use the curvedata.m routine but maintain the format used
in Python to create the folders.
13 Np=zeros(l_p,l_edp,Nstep);
14
15 for i = 1:Nstep
16 step( i ) = str2double( listing ( i+1).name(1:end-4));
17 Np (:,:, i )=importdata([MainFolder ’/’ listing( i+1).name]);
18 end
19
20 end
19 end
In the animation.m routine (Code 20), the above routines are used to create an animation
of the total deformation produced in a tailings dam. The files used in the example are nested as
follows (Figure 11):
28 open(v);
29 set(gcf , ’ position ’ ,get (0, ’ScreenSize’)) ;
30
31 for k= 1:length(step)
32
33 %figure(’ visible ’,’ off ’)
34 scatter (x2(dominio2)+Ux_(dominio2,k)*1,...
35 y2(dominio2)+Ux_(dominio2,k)*1,...
36 30,Utot_(dominio2,k),’ filled ’ )
37
38 axis equal
39 colormap(jet)
40 hcb=colorbar;
41 hcb.Label.String= ’U_{total} [m]’;
42 caxis ([0 0.2])
43 xlabel( ’Seccion Transversal [m]’, ’FontSize’ , 14)
44 ylabel( ’ Elevación [m]’, ’FontSize’ , 14)
45 title ([ ’ t= ’ num2str((step(k)-31)*0.001) ’ [ s ] ’ ], ’FontSize’ , 14)
46 set(gca, ’FontSize’ ,14, ’Color’ ,[0.8 0.8 0.8])
47 frame = getframe(gcf);
48 set(gca, ’nextplot’ , ’ replacechildren ’ ) ;
49 writeVideo(v,frame)
50
51 end
52 close (v);
53 toc
Figure 12 shows the result of the animation.m routine for an instant of time.