Subida inicial del proyecto
This commit is contained in:
commit
43af600d31
16 files changed
+1182
No files matched your search
@@ -0,0 +1,40 @@
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.optimize import curve_fit
|
||||
|
||||
kb = 1.380649e-23 # Constante de Boltzmann
|
||||
T = 300 # Temperatura en Kelvin
|
||||
kbT = kb * T # Factor kb * T
|
||||
|
||||
def helfrich_model(x, bend, stretch):
|
||||
|
||||
bend = abs(bend)
|
||||
stretch = abs(stretch)
|
||||
|
||||
term = stretch / bend + x**2
|
||||
|
||||
result = kbT * (0.5 / stretch) * ((1 / x) - term ** -0.5)
|
||||
return result
|
||||
|
||||
def aproxHelfrich(x, y):
|
||||
x = np.array(x)
|
||||
y = np.array(y)
|
||||
|
||||
try:
|
||||
|
||||
popt, _ = curve_fit(helfrich_model, x, y, p0=[1.4e-19, 1e-7]) # valores referencia
|
||||
bend, stretch = popt
|
||||
|
||||
# Aseguramos que bend y stretch sean siempre positivos
|
||||
bend = abs(bend)
|
||||
stretch = abs(stretch)
|
||||
|
||||
# # Establecemos un límite inferior para el valor de 'bend'
|
||||
# bend = max(bend, 1e-20)
|
||||
return bend, stretch
|
||||
except RuntimeError:
|
||||
print("Error: La optimización no convergió")
|
||||
return None, None
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
'''
|
||||
Version: 12/03/25
|
||||
--> Version definitiva del analisis por integracion numerica
|
||||
'''
|
||||
|
||||
# %% LIBRERIAS
|
||||
|
||||
from tqdm import tqdm
|
||||
import numpy as np
|
||||
import scipy.integrate as spi
|
||||
import scipy.interpolate as interp
|
||||
|
||||
# %% METODOS DE INGRACION NUMERICAS (TRAPZ,CUADRATURA CADA N PUNTOS)
|
||||
|
||||
def gauss_quad_discrete_complex(x, y, n=2):
|
||||
|
||||
integral = 0.0 + 0.0j # Iniciar como número complejo
|
||||
|
||||
for i in range(len(x) - 1):
|
||||
x_local = x[i:i+n+1]
|
||||
y_local = y[i:i+n+1]
|
||||
|
||||
# Ajustar un polinomio de Lagrange
|
||||
poly = interp.BarycentricInterpolator(x_local, y_local)
|
||||
|
||||
# Integrar usando quad_vec, que maneja números complejos
|
||||
result = spi.quad_vec(poly, x[i], x[i+1])[0]
|
||||
|
||||
integral += result
|
||||
|
||||
return integral
|
||||
|
||||
def trapecios_complejo(x, y):
|
||||
|
||||
h = np.diff(x) # Diferencias entre los puntos
|
||||
integral = np.sum(h * (y[:-1] + y[1:]) / 2) # Aplicamos la fórmula del trapecio
|
||||
return integral
|
||||
|
||||
# %% CALCULO (NO SE CUENTA EL MODO M = 0)
|
||||
|
||||
def f2(MatrizSph,limitemodos,positive="Yes"):
|
||||
|
||||
# DEFINICION DE PARAMETROS
|
||||
|
||||
time = MatrizSph.shape[0]
|
||||
R = MatrizSph[:,:,0] # MATRIZ TIEMPO X PARTICULAS
|
||||
PHI = MatrizSph[0,:,2] # Vector angular
|
||||
|
||||
# CAMBIO DE COORDENADAS
|
||||
|
||||
VMR = np.mean(R)
|
||||
U = R - VMR # matriz
|
||||
Z = PHI*VMR # vector
|
||||
dz = abs(Z[1]-Z[0]) # util para trapz (dx)
|
||||
|
||||
# DATOS
|
||||
|
||||
N = int(limitemodos) # digamos 51
|
||||
n = np.linspace(1,N,N) # nunca se incluye el modo 0
|
||||
modes = n
|
||||
cn = np.zeros((time, N), dtype=complex) # coeficientes
|
||||
|
||||
for i in tqdm(range(time), desc="Calculando coeficientes"):
|
||||
for j in range(N):
|
||||
cn[i,j] = np.trapz(U[i, :] * np.exp(-1j * (n[j] / VMR) * Z),dx = dz)
|
||||
|
||||
#cn[i, j] = trapecios_complejo(U[i, :] * np.exp(-1j * (n[j] / VMR) * Z), Z) # método de trapecios complejos
|
||||
|
||||
F1 = (abs(cn))**2 # módulo de cn elevado al cuadrado
|
||||
VMF1 = np.mean(F1, axis=0) # valor medio del módulo de cn al cuadrado
|
||||
|
||||
F2 = abs(cn) # módulo de cn
|
||||
VMF2 = np.mean(F2, axis=0) # valor medio de los coeficientes
|
||||
VMF3 = VMF2**2 # valor medio del módulo de coeficientes --> todo elevado al cuadrado
|
||||
|
||||
diference = VMF1 - VMF3
|
||||
|
||||
VM_MODUCUA = (1/(2*np.pi*VMR)) * diference # Con esto compararemos qx tal como dice la fórmula
|
||||
qx = modes / VMR
|
||||
|
||||
return qx,VM_MODUCUA
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
'''
|
||||
- Codigos para filtrar datos simulados en un intervalo de -z a z (valor)
|
||||
- Graficas para matrices con ceros y cambio de coordenadas en estas matrices
|
||||
- Interpolacion de puntos
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import orthopoly
|
||||
import numpy as np
|
||||
import time as timeglobal
|
||||
from scipy.spatial import KDTree
|
||||
from tqdm import tqdm
|
||||
from colorama import Fore, Style
|
||||
from scipy.interpolate import splprep, splev
|
||||
import matplotlib.pyplot as plt
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
# from Codigo1 import mcart_msph
|
||||
|
||||
def public_c2s(posicionescart):
|
||||
'''
|
||||
De cartesianas a esfericas (c2s) de forma publica
|
||||
'''
|
||||
x,y,z = posicionescart.T
|
||||
r,theta,phi = orthopoly.spherical_harmonic.cart2sph(-x,-y,z) #Bug in library
|
||||
return np.asarray([r,theta,phi]).T
|
||||
|
||||
def public_s2c(posicionesesf):
|
||||
'''
|
||||
De esfericas a cartesianas (s2c) de forma publica
|
||||
'''
|
||||
r,theta,phi = posicionesesf.T
|
||||
x,y,z = orthopoly.spherical_harmonic.sph2cart(r,theta,phi)
|
||||
return np.asarray([x,y,z]).T
|
||||
|
||||
def mcart_msph(matrizcart):
|
||||
tiempo = matrizcart.shape[0]
|
||||
matrizsph = (public_c2s(matrizcart.reshape(-1, 3))).reshape(tiempo, -1, 3)
|
||||
return matrizsph
|
||||
|
||||
def msph_mcart_filtrado(matrizsph):
|
||||
"""
|
||||
Transforma las filas de una matriz de coordenadas cartesianas a esféricas,
|
||||
ignorando las filas con valores [0, 0, 0].
|
||||
|
||||
Parameters:
|
||||
matrizcart (numpy.ndarray): Matriz de coordenadas cartesianas [tiempo, n, 3].
|
||||
|
||||
Returns:
|
||||
numpy.ndarray: Matriz transformada a coordenadas esféricas,
|
||||
manteniendo las filas [0, 0, 0] sin cambiar.
|
||||
"""
|
||||
tiempo = matrizsph.shape[0]
|
||||
matrizcart = np.zeros_like(matrizsph)
|
||||
|
||||
for t in range(tiempo):
|
||||
frame = matrizsph[t]
|
||||
|
||||
mask = ~np.all(frame == 0, axis=1) # solo seleccionamos filas que sean distintas de 0 (sino sale error en arcos)
|
||||
|
||||
matrizcart[t, mask] = public_s2c(frame[mask])
|
||||
|
||||
return matrizcart
|
||||
|
||||
def mcart_msph_filtrado(matrizcart):
|
||||
"""
|
||||
Transforma las filas de una matriz de coordenadas cartesianas a esféricas,
|
||||
ignorando las filas con valores [0, 0, 0].
|
||||
|
||||
Parameters:
|
||||
matrizcart (numpy.ndarray): Matriz de coordenadas cartesianas [tiempo, n, 3].
|
||||
|
||||
Returns:
|
||||
numpy.ndarray: Matriz transformada a coordenadas esféricas,
|
||||
manteniendo las filas [0, 0, 0] sin cambiar.
|
||||
"""
|
||||
tiempo = matrizcart.shape[0]
|
||||
matrizsph = np.zeros_like(matrizcart)
|
||||
|
||||
for t in range(tiempo):
|
||||
frame = matrizcart[t]
|
||||
|
||||
mask = ~np.all(frame == 0, axis=1) # solo seleccionamos filas que sean distintas de 0 (sino sale error en arcos)
|
||||
|
||||
matrizsph[t, mask] = public_c2s(frame[mask])
|
||||
|
||||
return matrizsph
|
||||
|
||||
def contarpuntos(valor,matrix):
|
||||
|
||||
|
||||
tiempo, particulas, _ = matrix.shape
|
||||
|
||||
contador = np.zeros(tiempo, dtype=int)
|
||||
|
||||
for t in range(tiempo):
|
||||
|
||||
z_coords = matrix[t, :, 2]
|
||||
contador[t] = np.sum((-valor <= z_coords) & (z_coords <= valor))
|
||||
|
||||
return contador
|
||||
|
||||
def datosfiltrados(valor,matrix):
|
||||
|
||||
contador = contarpuntos(valor,matrix)
|
||||
|
||||
fecha_actual = timeglobal.strftime("%d-%b-%Y %H:%M:%S")
|
||||
print(f"{fecha_actual} - Análisis3 - Contando datos con Z ∈ [-{valor}, {valor}] ...")
|
||||
print("El numero de puntos esta entre ",np.min(contador)," y ",np.max(contador))
|
||||
print(f"{fecha_actual} - Análisis3 - Filtrando datos de las simulaciones...")
|
||||
|
||||
tiempo = matrix.shape[0]
|
||||
max_contador = np.max(contador)
|
||||
matriz_homogenea = np.zeros((tiempo, max_contador, 3), dtype=float)
|
||||
|
||||
for t in range(tiempo):
|
||||
puntos = matrix[t, :, :]
|
||||
puntos_en_rango = puntos[(-valor <= puntos[:, 2]) & (puntos[:, 2] <= valor)]
|
||||
matriz_homogenea[t, :len(puntos_en_rango), :] = puntos_en_rango
|
||||
|
||||
return matriz_homogenea
|
||||
|
||||
def distribuirtraj_sobregrid(traj_sph, grid_sph):
|
||||
|
||||
'''
|
||||
Funcion analoga a la de distribucion de Codigo1
|
||||
'''
|
||||
fecha_actual = timeglobal.strftime("%d-%b-%Y %H:%M:%S")
|
||||
n_traj = traj_sph.shape[1]
|
||||
n_grid_points = grid_sph.shape[0]
|
||||
|
||||
print("------------------------------")
|
||||
print(f"{fecha_actual} - Análisis3 - Distribuyendo {Style.BRIGHT + Fore.GREEN}{n_traj}{Style.RESET_ALL} puntos de trayectoria en {Style.BRIGHT + Fore.BLUE}{n_grid_points}{Style.RESET_ALL} puntos del grid.")
|
||||
|
||||
print(f"Se está usando {Style.BRIGHT + Fore.GREEN}{traj_sph.shape[0]}{Style.RESET_ALL} valores de tiempo")
|
||||
|
||||
|
||||
theta_grid = grid_sph[:, 1]
|
||||
phi_grid = grid_sph[:, 2]
|
||||
|
||||
time = traj_sph.shape[0]
|
||||
# n_grid_points = grid_sph.shape[0]
|
||||
|
||||
grid_kdtree = KDTree(grid_sph)
|
||||
|
||||
traj_grid_sph = np.empty((time, n_grid_points, 3))
|
||||
|
||||
for t, frame_pos in enumerate(tqdm(traj_sph, total=time, desc="Procesando")): # Para cada instante de tiempo
|
||||
|
||||
frame_pos = frame_pos[~np.all(frame_pos == 0, axis=1)] # Filtrar valores distintos de cero
|
||||
|
||||
if frame_pos.size == 0:
|
||||
raise Exception(f"Ningun punto encontrado para el tiempo {t}. Revisar los datos de trayectoria.")
|
||||
|
||||
r, theta, phi = frame_pos.T
|
||||
|
||||
r = np.ones_like(r) # radio 1
|
||||
traj_over_sphere = np.vstack([r, theta, phi]).T
|
||||
|
||||
frame_grid_positions = grid_kdtree.query(traj_over_sphere)[1]
|
||||
|
||||
for i in range(n_grid_points):
|
||||
mask = (frame_grid_positions == i)
|
||||
|
||||
if not np.any(mask):
|
||||
raise Exception(f"Punto del grid {i} sin datos. Pruebe a reducir el numero de puntos del grid.")
|
||||
|
||||
r_vals, theta_vals, phi_vals = frame_pos[mask].T
|
||||
|
||||
traj_grid_sph[t, i] = np.array([np.mean(r_vals), theta_grid[i], phi_grid[i]])
|
||||
|
||||
return traj_grid_sph # devuelve en esfericas
|
||||
|
||||
# %% GRAFICAS
|
||||
|
||||
def graficapuntual(matriz_homogenea, t, rangoz,title):
|
||||
"""
|
||||
Grafica los puntos almacenados en la matriz homogénea en 3D para un instante de tiempo específico,
|
||||
ignorando los valores cero.
|
||||
|
||||
Parameters:
|
||||
matriz_homogenea (numpy.ndarray): Matriz de dimensiones [tiempo, max_contador, 3].
|
||||
t (int): Instante de tiempo para el cual se desea graficar los puntos.
|
||||
"""
|
||||
if t < 0 or t >= matriz_homogenea.shape[0]:
|
||||
raise ValueError("El tiempo especificado está fuera del rango válido.")
|
||||
|
||||
puntos = matriz_homogenea[t]
|
||||
|
||||
puntos_filtrados = puntos[~np.all(puntos == 0, axis=1)]
|
||||
|
||||
if len(puntos_filtrados) > 0:
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111, projection='3d')
|
||||
|
||||
x = puntos_filtrados[:, 0]
|
||||
y = puntos_filtrados[:, 1]
|
||||
z = puntos_filtrados[:, 2]
|
||||
|
||||
ax.scatter(x, y, z, color = "blue", linestyle='None')
|
||||
ax.set_xlabel('X')
|
||||
ax.set_ylabel('Y')
|
||||
ax.set_zlabel('Z')
|
||||
ax.set_zlim(-rangoz, rangoz)
|
||||
ax.set_title(f"{title} en t = {t}", fontweight="bold")
|
||||
|
||||
plt.show()
|
||||
else:
|
||||
print(f"No hay puntos válidos para el tiempo {t}.")
|
||||
|
||||
def gengraficav2(matrix, t, title, valor):
|
||||
'''
|
||||
Funcion identica a gengrafica solo que ahora tiene un input para los limites en z
|
||||
--> Util para comprobar que la funcion de filtrado actue adecuadamente
|
||||
'''
|
||||
|
||||
a3 = matrix[t][:, 0]
|
||||
b3 = matrix[t][:, 1]
|
||||
c3 = matrix[t][:, 2]
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111, projection='3d')
|
||||
ax.scatter(a3, b3, c3, marker='o', color="blue")
|
||||
|
||||
ax.set_xlabel('X')
|
||||
ax.set_ylabel('Y')
|
||||
ax.set_zlabel('Z')
|
||||
ax.set_title(f"{title} en t = {t}", fontweight="bold")
|
||||
|
||||
ax.set_zlim(-valor, valor)
|
||||
|
||||
plt.show()
|
||||
|
||||
# %% CONTINUO
|
||||
|
||||
# from Codigo1 import coefs,gencircunferencia
|
||||
|
||||
# def expandir(MSph,npoints,Lmax):
|
||||
# '''
|
||||
# # Es como interpolar mediante armonicos esfericos (no funciona!)
|
||||
# '''
|
||||
# _,coe = coefs(MSph,Lmax)
|
||||
# Matrizcart,Matrizsph = gencircunferencia(coe,npoints) # selecciono las esfericas en concreto
|
||||
# return Matrizcart,Matrizsph # cartesianas
|
||||
|
||||
# def interpolarpuntos(matrizcart, n):
|
||||
# '''
|
||||
# Interpola los puntos en coordenadas cartesianas para cada instante de tiempo.
|
||||
# ver: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.splprep.html
|
||||
# '''
|
||||
|
||||
# print("------------------")
|
||||
# fecha_actual = timeglobal.strftime("%d-%b-%Y %H:%M:%S")
|
||||
# print(f"{fecha_actual} - Análisis3 - Interpolando {matrizcart.shape[1]} .")
|
||||
# print(f"Se han obtenido {n} puntos tras la interpolación.")
|
||||
|
||||
|
||||
# tiempo = matrizcart.shape[0]
|
||||
# M1 = np.empty((tiempo, n+1, 3)) # cerrada con termino repetido
|
||||
# minterpolada_cart = np.empty((tiempo,n,3)) # lo que buscamos
|
||||
# u_new = np.linspace(0, 1, n+1) # siempre es cte, creamos un punto mas de lo normal (para forzar cierre)
|
||||
# znew = np.zeros((n+1)) # vector nulo (ya que se supone que el input es este mismo)
|
||||
|
||||
# for t in range(tiempo):
|
||||
|
||||
# frame = matrizcart[t]
|
||||
|
||||
# mask = ~np.all(frame == 0, axis=1)
|
||||
# frame = frame[mask]
|
||||
|
||||
# if frame.shape[0] < 2:
|
||||
# raise ValueError(f"No hay suficientes puntos para interpolar en el tiempo {t}.")
|
||||
|
||||
# # Datos sin cerrar
|
||||
# x = frame[:,0]
|
||||
# y = frame[:,1]
|
||||
|
||||
# # Forzamos cierre
|
||||
# x_closed = np.append(x, x[0])
|
||||
# y_closed = np.append(y, y[0])
|
||||
|
||||
# tck,_ = splprep([x_closed, y_closed], s=0) # tck generado a partir de los valores cerrados
|
||||
|
||||
# newpoints = splev(u_new, tck) # generamos puntos de dimension n+1, pero el ultimo termino es el primero
|
||||
|
||||
# M1[t] = np.vstack([newpoints[0], newpoints[1], znew]).T
|
||||
|
||||
# minterpolada_cart[t][:,:] = M1[t][0:-1,:] # no contamos el ultimo termino (repetido)
|
||||
|
||||
# if np.mean(abs(minterpolada_cart[t, :, 2])) <= 0.00001: # para que la grafica salga exactamente en 0
|
||||
# minterpolada_cart[t,:,2] = 0
|
||||
|
||||
# minterpolada_sph = mcart_msph(minterpolada_cart)
|
||||
# return minterpolada_cart,minterpolada_sph
|
||||
@@ -0,0 +1,51 @@
|
||||
'''
|
||||
Calculo de bending y stretching sobre datos en una circunferencia (se asume equiespaciamiento angular)
|
||||
Ultima Fecha Modificacion: 30/03/25
|
||||
'''
|
||||
|
||||
# %% LIBRERIAS
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import Codigo2D_Base as c7
|
||||
import Codigo2D_AjusteHelfrich as c8
|
||||
|
||||
# %% FUNCION TEORICA
|
||||
|
||||
kb = 1.380649*10**-23
|
||||
T = 300
|
||||
kbT = kb*T
|
||||
|
||||
valor = 10*kbT # este es el valor que deberia tener el bending
|
||||
|
||||
def fx(x,stretch,bend):
|
||||
y = kbT*(0.5/stretch)*((1/x) - (stretch/bend + x**2)**(-0.5))
|
||||
return y
|
||||
|
||||
# %% CODIGO
|
||||
|
||||
def calculatecoefs(MSph, nmin, nmax):
|
||||
|
||||
'''
|
||||
Se utiliza el metodo de trapecios
|
||||
'''
|
||||
|
||||
qx,u = c7.f2(MSph,21,positive = "Yes") # TODOS LOS COEFICIENTES (U) del 1 al 20
|
||||
|
||||
'''
|
||||
El bending solo se calcula para ciertos modos
|
||||
'''
|
||||
|
||||
qxnew = qx[nmin:nmax]
|
||||
unew = u[nmin:nmax]
|
||||
|
||||
bend,stretch = c8.aproxHelfrich(qxnew,unew)
|
||||
qxcont = np.linspace(qxnew[0],qxnew[-1],100) # limites coinciden con qx, pero Y no tiene porque es un ajuste no hay restriccion
|
||||
Ycont = fx(qxcont,stretch,bend) # Al representar sera en el eje x: qxnew y en el y: Y
|
||||
|
||||
print("----------------")
|
||||
print(f"Para modos entre {nmin+1} y {nmax+1} se obtiene:")
|
||||
print("Bending (en uds kbT): ",bend/kbT)
|
||||
print("Stretching [N/m]: ",stretch)
|
||||
|
||||
return qx,u,qxcont,Ycont,bend,stretch
|
||||
@@ -0,0 +1,70 @@
|
||||
'''
|
||||
Ejemplo de implementacion del Ánalisis en el plano ecuatorial
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
# from Codigo1 import mcart_msph,msph_mcart,gengraficasph
|
||||
import Codigo2D_FiltroZ as c1
|
||||
import Codigo2D_Interpolacion as c2
|
||||
import Codigo2D_Coefs as c3 # Este incluye a ajuste de Helfrich y a Base
|
||||
|
||||
time = 50 # tiempo para graficar
|
||||
|
||||
# %% PROGRAMA ARIN
|
||||
|
||||
normalizacion = 7*10**5 # No es necesaria son uds de los datos
|
||||
MATRIZ = np.load('matrizcartesianas.npy') # DATOS PROGRAMA ARIN
|
||||
|
||||
MATRIZESF = c1.mcart_msph(MATRIZ)
|
||||
MATRIZESF[:,:,0] = MATRIZESF[:,:,0] / normalizacion # cambiamos el radio / normalizamos (Ver luego que tambien intorud)
|
||||
MATRIZCART = c1.msph_mcart(MATRIZESF)
|
||||
|
||||
# %% FILTRO EN Z
|
||||
|
||||
RMatrix = MATRIZESF[:,:,0] # radios
|
||||
VMR = np.mean(RMatrix) # Valor medio del radio
|
||||
|
||||
Z1 = (VMR/10)*0.1 # Una centesima del radio medio
|
||||
FiltroCart,FiltroEsf = c1.filtroz(MATRIZ,Z1,normalizacion) # Filtramos
|
||||
|
||||
# %% INTERPOLACION
|
||||
|
||||
MSph = c2.newinterpolate2(FiltroEsf,2001) # Interpolamos
|
||||
MCart = c1.msph_mcart(MSph)
|
||||
MCart[:,:,2] = 0
|
||||
|
||||
# %% CALCULO DE BENDING Y STRETCH
|
||||
nmax = 19
|
||||
nmin = 4 # NOTA nmin = 0, es el modo 1
|
||||
qx,u,qxnew,unew,bend,stretch = c3.calculatecoefs(MSph,nmin,nmax)
|
||||
|
||||
# %% GRAFICA
|
||||
|
||||
# plt.figure()
|
||||
# plt.loglog(qx,u,marker = "o", color = "blue",linestyle = "none")
|
||||
# plt.loglog(qxnew,unew,color="red", linestyle="-.")
|
||||
|
||||
plt.figure()
|
||||
plt.plot(qx[nmin:nmax],u[nmin:nmax],marker = "o",color = "blue")
|
||||
plt.plot(qxnew,unew,color="red", linestyle="-.")
|
||||
|
||||
# GRAFICA FILTRO (Simplemente para ver forma)
|
||||
|
||||
mask = FiltroEsf[time,:,0] != 0
|
||||
FiltroEsfmask = FiltroEsf[time,mask] # Eliminar 0's para ver mejor la grafica
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(MSph[time, :, 2], MSph[time, :, 0], marker=".", linestyle="--", color="blue", label=r"Interpolación datos filtro ($\Delta z_1$)")
|
||||
|
||||
z1_label = f"$\Delta z_1$ = {np.format_float_scientific(Z1, precision=2)}"
|
||||
|
||||
plt.plot(FiltroEsfmask[:,2], FiltroEsfmask[:,0], marker="h", linestyle="none", color="red", label=z1_label)
|
||||
|
||||
plt.title("Datos simulaciones filtro", fontweight="bold")
|
||||
plt.xlabel("qx", fontweight="bold")
|
||||
plt.ylabel(r"$\langle \mathbf{|u|^2} \rangle$", fontsize=14)
|
||||
|
||||
plt.legend()
|
||||
plt.show()
|
||||
@@ -0,0 +1,70 @@
|
||||
'''
|
||||
Codigo para seleccionar en un rango de +-z
|
||||
Los datos de filtro estan en el plano z = 0
|
||||
'''
|
||||
import orthopoly
|
||||
import numpy as np
|
||||
import Codigo2D_CodigoBaseFiltro as c4
|
||||
# from Codigo1 import msph_mcart,mcart_msph
|
||||
|
||||
def public_c2s(posicionescart):
|
||||
'''
|
||||
De cartesianas a esfericas (c2s) de forma publica
|
||||
'''
|
||||
x,y,z = posicionescart.T
|
||||
r,theta,phi = orthopoly.spherical_harmonic.cart2sph(-x,-y,z) #Bug in library
|
||||
return np.asarray([r,theta,phi]).T
|
||||
|
||||
def public_s2c(posicionesesf):
|
||||
'''
|
||||
De esfericas a cartesianas (s2c) de forma publica
|
||||
'''
|
||||
r,theta,phi = posicionesesf.T
|
||||
x,y,z = orthopoly.spherical_harmonic.sph2cart(r,theta,phi)
|
||||
return np.asarray([x,y,z]).T
|
||||
|
||||
def msph_mcart(matrizsph):
|
||||
tiempo = matrizsph.shape[0]
|
||||
matrizcart = (public_s2c(matrizsph.reshape(-1, 3))).reshape(tiempo, -1, 3)
|
||||
return matrizcart
|
||||
|
||||
def mcart_msph(matrizcart):
|
||||
tiempo = matrizcart.shape[0]
|
||||
matrizsph = (public_c2s(matrizcart.reshape(-1, 3))).reshape(tiempo, -1, 3)
|
||||
return matrizsph
|
||||
|
||||
def funciondefiltro(Datoscart,selectz,cte):
|
||||
|
||||
'''
|
||||
# cte es para ajustar las unidades, el codigo da del orden de 10**1
|
||||
'''
|
||||
|
||||
Datosesf = mcart_msph(Datoscart)
|
||||
|
||||
Datosesf[:,:,0] = Datosesf[:,:,0]/(cte) # Normalizamos
|
||||
Datoscart = msph_mcart(Datosesf)
|
||||
|
||||
contador = c4.contarpuntos(selectz,Datoscart) # Contamos el numero de puntos que cumplen la condicion en cada tiempo
|
||||
filtro1 = c4.datosfiltrados(selectz,Datoscart) # Filtramos los puntos (nota: la matriz contiene filas de ceros, el numero de filas de ceros varian en el tiempo)
|
||||
filtroesf1 = c4.mcart_msph_filtrado(filtro1)
|
||||
|
||||
return filtro1,filtroesf1
|
||||
|
||||
def filtroz(Datoscart,selectz,cte):
|
||||
'''
|
||||
Codigo para hacer la proyeccion (sigue manteniendo 0's pero interpolar ignora los 0's)
|
||||
'''
|
||||
f1,esf1 = funciondefiltro(Datoscart,selectz,cte)
|
||||
|
||||
FiltroCart = np.zeros_like(f1)
|
||||
FiltroEsf = np.zeros_like(f1)
|
||||
|
||||
FiltroEsf[:,:,0] = np.sqrt(f1[:,:,0]**2 + f1[:,:,1]**2)
|
||||
FiltroEsf[:,:,1][esf1[:,:,1] != 0] = np.pi/2 # da igual poner el esf1[1]
|
||||
FiltroEsf[:,:,2] = esf1[:,:,2]
|
||||
|
||||
FiltroCart = c4.msph_mcart_filtrado(FiltroEsf)
|
||||
FiltroCart[:,:,2] = 0
|
||||
|
||||
return FiltroCart,FiltroEsf
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
'''
|
||||
Fecha: 15/03/25
|
||||
Codigo definitivo para la interpolacion de datos en coordenadas esfericas (polares)
|
||||
|
||||
--> El metodo de ajuste devuelve datos equiespaciados (por tanto no hay que proyectar constantemente)
|
||||
|
||||
--> Se añade un punto al final y principio, esto siempre mejora la precision del metodo porque es una condicion necesaria (alpha = 2pi + alpha)
|
||||
|
||||
NOTA: Este codigo ignora los 0's por tanto es compatible con filtroz, porque ademas se encarga de ordenar ascendentemente phi
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
from scipy.interpolate import PchipInterpolator
|
||||
|
||||
def newinterpolate2(matrizsph,n):
|
||||
|
||||
tiempo = matrizsph.shape[0]
|
||||
MSph = np.empty((tiempo,n,3)) # OBJETIVO
|
||||
|
||||
theta = np.zeros(n) + np.pi/2
|
||||
MSph[:,:,1] = theta
|
||||
|
||||
for t in range(tiempo):
|
||||
|
||||
frame = matrizsph[t]
|
||||
mask = ~np.all(frame == 0, axis=1) # seleccionamos valores distintos de 0
|
||||
frame = frame[mask]
|
||||
|
||||
if frame.shape[0] < 2:
|
||||
raise ValueError(f"No hay suficientes puntos para interpolar en el tiempo {t}.")
|
||||
|
||||
x = frame[:,2] # esto es phi
|
||||
y = frame[:,0] # esto es r
|
||||
|
||||
indices_ordenados = np.argsort(x)
|
||||
|
||||
x = x[indices_ordenados] # ordenados ascendentemente
|
||||
y = y[indices_ordenados]
|
||||
|
||||
x = np.concatenate(([x[-1] - 2*np.pi], x, [x[0] + 2*np.pi]))
|
||||
y = np.concatenate(([y[-1]], y, [y[0]]))
|
||||
|
||||
interp = PchipInterpolator(x, y)
|
||||
|
||||
#x_new = np.linspace(0, 2*np.pi, n) # 500 puntos en el intervalo de x EQUIESPACIADO
|
||||
x_new = np.linspace(0, 2*np.pi, n,endpoint = False) # 500 puntos en el intervalo de x EQUIESPACIADO
|
||||
y_new = interp(x_new)
|
||||
|
||||
MSph[t,:,2] = x_new # phi
|
||||
MSph[t,:,0] = y_new # r(phi)
|
||||
|
||||
return MSph
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.optimize import curve_fit
|
||||
|
||||
# %% AJUSTE
|
||||
|
||||
kb = 1.380649e-23 # Constante de Boltzmann
|
||||
T = 300 # Temperatura en Kelvin
|
||||
kbT = kb * T # Factor kb * T
|
||||
|
||||
def helfrich_model(x, kappa, b):
|
||||
|
||||
# b = abs(b)
|
||||
kappa = abs(kappa)
|
||||
b = abs(b)
|
||||
|
||||
result = kbT / (8*b + kappa*x)
|
||||
return result
|
||||
|
||||
def aproxHelfrich(x, y):
|
||||
x = np.array(x)
|
||||
y = np.array(y)
|
||||
|
||||
try:
|
||||
|
||||
popt, _ = curve_fit(helfrich_model, x, y, p0=[1.4e-19, 1e-7]) # valores referencia
|
||||
kappa, b = popt
|
||||
|
||||
# Aseguramos que bend y stretch sean siempre positivos
|
||||
b = abs(b)
|
||||
kappa = abs(kappa)
|
||||
|
||||
# # Establecemos un límite inferior para el valor de 'bend'
|
||||
# bend = max(bend, 1e-20)
|
||||
return kappa, b
|
||||
except RuntimeError:
|
||||
print("Error: La optimización no convergió")
|
||||
return None, None
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
'''
|
||||
Version del codigo completa para obtener los coeficientes
|
||||
PASOS:
|
||||
1. Creamos un grid icosahedrico, y proyectamos sobre el
|
||||
2. Sobre esta proyeccion que "conserva" el radio de los datos de simulaciones se realiza expansion por arm.es
|
||||
3. De alm se convierte a al
|
||||
FALTA. Se eligen los modos del l = 2 a l = 6, y se realiza ajuste por la funcion (ecuacion 7)
|
||||
|
||||
NOTA: No es necesario especifiar Lmin, parte del 0 el programa
|
||||
|
||||
'''
|
||||
|
||||
# %% LIBRERIAS
|
||||
|
||||
import sys,os
|
||||
|
||||
from itertools import combinations
|
||||
from tqdm import tqdm
|
||||
|
||||
import logging
|
||||
|
||||
import numpy as np
|
||||
|
||||
import orthopoly
|
||||
|
||||
import MDAnalysis as mda
|
||||
from MDAnalysis.analysis import align
|
||||
|
||||
from scipy import spatial
|
||||
from scipy.optimize import least_squares
|
||||
from scipy.optimize import lsq_linear
|
||||
|
||||
|
||||
# %% FUNCIONES PREVIAS
|
||||
|
||||
def public_c2s(posicionescart):
|
||||
'''
|
||||
De cartesianas a esfericas (c2s) de forma publica
|
||||
'''
|
||||
x,y,z = posicionescart.T
|
||||
r,theta,phi = orthopoly.spherical_harmonic.cart2sph(-x,-y,z) #Bug in library
|
||||
return np.asarray([r,theta,phi]).T
|
||||
|
||||
def public_s2c(posicionesesf):
|
||||
'''
|
||||
De esfericas a cartesianas (s2c) de forma publica
|
||||
'''
|
||||
r,theta,phi = posicionesesf.T
|
||||
x,y,z = orthopoly.spherical_harmonic.sph2cart(r,theta,phi)
|
||||
return np.asarray([x,y,z]).T
|
||||
|
||||
def msph_mcart(matrizsph):
|
||||
tiempo = matrizsph.shape[0]
|
||||
matrizcart = (public_s2c(matrizsph.reshape(-1, 3))).reshape(tiempo, -1, 3)
|
||||
return matrizcart
|
||||
|
||||
def mcart_msph(matrizcart):
|
||||
tiempo = matrizcart.shape[0]
|
||||
matrizsph = (public_c2s(matrizcart.reshape(-1, 3))).reshape(tiempo, -1, 3)
|
||||
return matrizsph
|
||||
|
||||
# %% DEFINICION DE LA CLASE
|
||||
|
||||
'''
|
||||
NOTA: phi [0,2pi]
|
||||
theta [0,pi]
|
||||
'''
|
||||
|
||||
class SHD:
|
||||
|
||||
def __cart2sph(self,cartPositions):
|
||||
x,y,z = cartPositions.T
|
||||
r,theta,phi = orthopoly.spherical_harmonic.cart2sph(-x,-y,z) #Bug in library
|
||||
return np.asarray([r,theta,phi]).T
|
||||
|
||||
def __sph2cart(self,sphPositions):
|
||||
|
||||
r,theta,phi = sphPositions.T
|
||||
x,y,z = orthopoly.spherical_harmonic.sph2cart(r,theta,phi)
|
||||
return np.asarray([x,y,z]).T
|
||||
|
||||
def __degreeOfTruncationToLM(self,n):
|
||||
A = orthopoly.spherical_harmonic.Tnm(self.__Lmax)
|
||||
l,m = A[0][n],A[1][n]
|
||||
return l,m
|
||||
|
||||
def __init__(self,name="SHD",Lmin=2,Lmax=10,debug=False,
|
||||
radiusMode = "geometric",
|
||||
expansionMode = "abs"):
|
||||
|
||||
self.__availableRadiusModes = ["expansion","geometric"]
|
||||
self.__availableExpansionModes = ["fluct","abs"]
|
||||
|
||||
self.__DEBUG = debug
|
||||
|
||||
self.__Lmin = Lmin
|
||||
self.__Lmax = Lmax
|
||||
self.__name = name
|
||||
|
||||
self.logger = logging.getLogger("sphAnalysis")
|
||||
#Clean up the logger
|
||||
for handler in self.logger.handlers[:]:
|
||||
self.logger.removeHandler(handler)
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
#Formatter, ascii time to day, month, year, hour, minute, second
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',"%d-%b-%Y %H:%M:%S")
|
||||
|
||||
#Set logger to console, with level INFO
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.INFO)
|
||||
ch.setFormatter(formatter)
|
||||
|
||||
#Create other logger. Log to file, with level DEBUG
|
||||
fh = logging.FileHandler(f'{self.__name}.log')
|
||||
fh.setLevel(logging.DEBUG)
|
||||
fh.setFormatter(formatter)
|
||||
|
||||
self.logger.addHandler(ch)
|
||||
self.logger.addHandler(fh)
|
||||
|
||||
######################################################
|
||||
|
||||
if radiusMode not in self.__availableRadiusModes:
|
||||
self.logger.error("Radius mode {} not available. Available modes are: {}".format(radiusMode,self.__availableRadiusModes))
|
||||
raise ValueError
|
||||
else:
|
||||
self.__radiusMode = radiusMode
|
||||
|
||||
if expansionMode not in self.__availableExpansionModes:
|
||||
self.logger.error("Traj mode {} not available. Available modes are: {}".format(expansionMode,self.__availableExpansionModes))
|
||||
raise ValueError
|
||||
else:
|
||||
self.__expansionMode = expansionMode
|
||||
|
||||
if self.__radiusMode == "expansion" and self.__expansionMode == "fluct":
|
||||
#Not compatible
|
||||
self.logger.error("Radius mode {} and traj mode {} not compatible".format(self.__radiusMode,self.__expansionMode))
|
||||
raise ValueError
|
||||
|
||||
|
||||
def __setGrid(self):
|
||||
self.gridSize = self.thetaGrid.shape[0]
|
||||
self.grid = np.asarray([self.thetaGrid,self.phiGrid]).T
|
||||
|
||||
r=[1.0]*self.gridSize
|
||||
self.gridVectors = self.__sph2cart(np.asarray([r,self.thetaGrid,self.phiGrid]).T)
|
||||
self.gridVectorssph = self.__cart2sph(self.gridVectors)
|
||||
|
||||
self.gridKDtree = spatial.KDTree(self.gridVectors)
|
||||
|
||||
def generateIcosahedralGrid(self,n):
|
||||
|
||||
print("----------")
|
||||
self.logger.info("Generating icosahedral grid with {} subdivisions ...".format(n))
|
||||
|
||||
self.thetaGrid,self.phiGrid=orthopoly.spherical_harmonic.grid_icosahedral(n)
|
||||
self.__setGrid()
|
||||
|
||||
|
||||
def distributeTrajPointsAlongGrid(self):
|
||||
"""
|
||||
Distribute the trajectory points along the grid.
|
||||
"""
|
||||
self.traj = self.traj2 # --> self.traj se deberia obtener desde loadsimulation
|
||||
|
||||
self.time = int(self.traj.shape[0]) # Numero de "tiempos"
|
||||
|
||||
self.trajSph = self.__cart2sph(self.traj.reshape(-1,3)).reshape(self.time,-1,3)
|
||||
|
||||
#Check if the trajectory has been loaded
|
||||
if self.traj is None:
|
||||
self.logger.error("Trying to distribute trajectory points along grid, but no trajectory has been loaded.")
|
||||
raise RuntimeError("No trajectory loaded.")
|
||||
|
||||
#Check if the grid has been generated
|
||||
if self.grid is None:
|
||||
self.logger.error("Trying to distribute trajectory points along grid, but no grid has been generated.")
|
||||
raise RuntimeError("No grid generated.")
|
||||
|
||||
self.logger.info("Distributing trajectory points along grid ...")
|
||||
|
||||
r,theta,phi = self.__cart2sph(self.traj.reshape(-1,3)).T
|
||||
|
||||
#Projects points over sphere
|
||||
r=np.asarray([1.0]*r.shape[0])
|
||||
trajOverSphere = self.__sph2cart(np.asarray([r,theta,phi]).T)
|
||||
|
||||
self.trajBeadsGridPosition = self.gridKDtree.query(trajOverSphere)[1].reshape(self.time,-1)
|
||||
|
||||
self.trajGridSph = np.empty((self.time,self.gridSize,3))
|
||||
for f,[framePos,frameGrid] in enumerate(tqdm(zip(self.trajSph,self.trajBeadsGridPosition),total=self.time)):
|
||||
for i in range(self.gridSize):
|
||||
mask = (frameGrid == i)
|
||||
|
||||
if not np.any(mask):
|
||||
self.logger.error("Grid point with no data. Try to decrease the number of grid points.")
|
||||
raise Exception("Grid point with no data")
|
||||
|
||||
r,theta,phi = framePos[mask].T
|
||||
|
||||
# f es cada tiempo, i es cada fila del grid que se calcula con el valor medio de los particulas
|
||||
# mas cercanas al grid
|
||||
|
||||
self.trajGridSph[f,i] = np.asarray([np.mean(r),self.thetaGrid[i],self.phiGrid[i]])
|
||||
|
||||
self.trajGrid = self.__sph2cart(self.trajGridSph)
|
||||
|
||||
if self.__DEBUG:
|
||||
|
||||
self.logger.debug("Distributed trajectory points along grid. Writing to file ...")
|
||||
|
||||
with open("gridPos.sp","w") as f:
|
||||
for framePos,frameGrid in zip(self.traj,self.trajBeadsGridPosition):
|
||||
f.write("#\n")
|
||||
for p,g in zip(framePos,frameGrid):
|
||||
f.write("{} {} {} 1.0 {}\n".format(p[0],p[1],p[2],g))
|
||||
|
||||
with open("gridTraj.sp","w") as f:
|
||||
for frame in self.trajGridSph:
|
||||
f.write("#\n")
|
||||
for p in frame:
|
||||
x,y,z = self.__sph2cart(np.asarray([p[0],p[1],p[2]]).T).T
|
||||
f.write("{} {} {} 1.0 0\n".format(x,y,z))
|
||||
|
||||
def sphericalHarmonicExpansion(self,TGS):
|
||||
|
||||
'''
|
||||
TGS (esf): Son los datos que queremos desarrollar, entonces deberian ser los datos que nos de onlytheta_mitdpi matriz 3D
|
||||
Objetivo --> Calcular los coeficientes
|
||||
'''
|
||||
|
||||
if self.trajGridSph is None:
|
||||
self.logger.error("Trying to compute spherical harmonic expansion, but trajectory has not been distributed along grid.")
|
||||
raise RuntimeError("No trajectory distributed along grid.")
|
||||
|
||||
self.logger.info("Performing spherical harmonic expansion ...")
|
||||
|
||||
v1 = TGS.shape[1]
|
||||
v2 = int((self.__Lmax+1)**2)
|
||||
|
||||
MATRIXY = np.empty((self.time,v1,v2))
|
||||
|
||||
self.aCoeffComputed = []
|
||||
|
||||
# THETA Y PHI NO CAMBIAN EN EL TIEMPO (cambia solo r)
|
||||
|
||||
th1 = TGS[0,:,1]
|
||||
ph1 = TGS[0,:,2]
|
||||
|
||||
infoY = orthopoly.spherical_harmonic.sph_har_T_matrix(th1,ph1,self.__Lmax)
|
||||
Y = infoY[0] # Matriz Ylm, como le conocemos theta y phi conocemos esta matriz
|
||||
|
||||
for i in range(self.time):
|
||||
|
||||
f,theta,phi = TGS[i].T
|
||||
|
||||
aFluct = lsq_linear(Y,f,max_iter=1000,tol=0.000001,lsq_solver='lsmr') # Sistema de ecuaciones R = Ylm*A donde conocemos R e Ylm
|
||||
self.aCoeffComputed.append(aFluct.x)
|
||||
|
||||
self.aCoeffComputed = np.asarray(self.aCoeffComputed)
|
||||
self.MatrizY = Y;
|
||||
|
||||
def valoresmedios(self,M1):
|
||||
|
||||
# Mensaje de advertencia
|
||||
|
||||
if self.aCoeffComputed is None:
|
||||
self.logger.error("No se puede calcular valores medios porque no esta definido self.aCoeffComputed")
|
||||
self.logger.error("--> Comprobar función: sphericalHarmonicExpansion")
|
||||
raise RuntimeError("No se hizo nada")
|
||||
self.logger.info("Realizando el calculo de valores medios...")
|
||||
|
||||
'''
|
||||
Tenemos los armonicos esfericos en formato de matriz de dimensiones (tiempo x (lmax+1)**2)
|
||||
En esta función calculamos:
|
||||
1) <alm**2> : Elevamos la matriz al cuadrado, despues promediamos temporalmente
|
||||
2) <alm> : Promediamos temporalmente (por columnas) # dimensiones de Lmax+1
|
||||
|
||||
Calcularemos el radio promedio tambien (espacial y temporal)
|
||||
--> M1 es la matriz (en esfericas) de dimensiones tiempoxnumero de particulas o numero puntos grid x3
|
||||
matriz proyectada para calcular R0
|
||||
'''
|
||||
# CALCULO DE VALORES MEDIOS
|
||||
|
||||
Vini = self.aCoeffComputed;
|
||||
|
||||
self.VM_CoefsCuadrado = np.mean(Vini**2,axis = 0) # Valor medio a lo largo de las filas (tiempo)
|
||||
self.VM_Coefs = np.mean(Vini,axis = 0)
|
||||
self.VMCuadrado_Coefs = self.VM_Coefs**2
|
||||
|
||||
# CALCULO DE LA LIBRERIA (nos permite conocer l y m a partir de n)
|
||||
|
||||
N = orthopoly.spherical_harmonic.T2nharm(self.__Lmax)
|
||||
|
||||
lm2n = {}
|
||||
|
||||
for n in range(N):
|
||||
l,m = self.__degreeOfTruncationToLM(n)
|
||||
lm2n[(l,m)] = n
|
||||
|
||||
# CALCULO DE <al**2> (ya no depende de m porque sumamos)
|
||||
|
||||
L = []
|
||||
a2l = []
|
||||
|
||||
for l in range(self.__Lmax+1):
|
||||
|
||||
L.append(l)
|
||||
|
||||
a2 = 0
|
||||
for m in range(-l,l+1):
|
||||
|
||||
a2 += self.VM_CoefsCuadrado[lm2n[(l,m)]]/(2*l+1)
|
||||
|
||||
a2l.append(a2)
|
||||
|
||||
va2l = np.asarray(a2l)
|
||||
self.VM_AlCuadrado = va2l # ESTO ES LO QUE NOS INTERESA
|
||||
|
||||
radial = M1[:,:,0] # dimensiones de tiempo x particulas
|
||||
self.R0 = np.mean(radial)
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# %% LIBRERIAS
|
||||
|
||||
import numpy as np
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from Codigo3D_FuncionGeneral import calculate_al
|
||||
|
||||
import Codigo3D_AjusteHelfrich as c3
|
||||
|
||||
# %% FUNCION DE AJUSTE (Para generar continuo de interpolacion)
|
||||
|
||||
kb = 1.380649e-23 # Constante de Boltzmann
|
||||
T = 300 # Temperatura en Kelvin
|
||||
kbT = kb * T # Factor kb * T
|
||||
|
||||
def fx(x,kappa,b):
|
||||
y = kbT/(8*b + kappa*x) # NOTA x incluye r0 y el termino de l
|
||||
return y
|
||||
|
||||
# %% ANALISIS
|
||||
|
||||
Datos_simul_cart = np.load('matrizcartesianas.npy')
|
||||
|
||||
Grid,ProyecGrid,terminol,a2l,r0 = calculate_al(Datos_simul_cart,20)
|
||||
|
||||
# %% DATOS PARA GRAFICAS
|
||||
|
||||
minimo = 2 # corresponde a l = 2
|
||||
maximo = 6 # corresponde a l = 5, pero luego sumamos 1 y es l = 6
|
||||
|
||||
coefs = a2l[minimo:maximo+1] # coeficientes entre l = 2, l = 6
|
||||
valorx = terminol[minimo:maximo+1]/(r0*r0) # x de la funcion
|
||||
|
||||
kappa,b = c3.aproxHelfrich(valorx,coefs)
|
||||
|
||||
bending = kappa/kbT
|
||||
stretching = b
|
||||
|
||||
print("-------------------")
|
||||
print(f"Para modos entre l = {minimo} y l = {maximo} se obtiene:")
|
||||
print("Bending (en uds kbT): ",bending)
|
||||
print(" (Aprox) Stretching [N/m]: ",stretching)
|
||||
|
||||
# %% AJUSTE PAPER
|
||||
|
||||
lvector = np.linspace(0,20,21) # vector de l
|
||||
lfiltro = np.linspace(2,6,100) # vector de l entre l = 2, l = 6
|
||||
|
||||
terminolfiltro = lfiltro*(lfiltro+1)*(lfiltro-1)*(lfiltro+2) # termino en l filtrado
|
||||
valorxfiltro = terminolfiltro/(r0*r0) # x filtrado
|
||||
|
||||
Y = fx(valorxfiltro,kappa,b) # se genera el continuo de lo que nos da el ajuste (generado con lfiltro!)
|
||||
|
||||
# %% GRAFICAS
|
||||
|
||||
#### GRAFICA 1: Representacion de los coeficientes en funcion del termino en l
|
||||
|
||||
plt.figure()
|
||||
plt.plot(valorxfiltro*r0**2,Y,linestyle="-.",color = "red") # misma dim
|
||||
plt.plot(valorx*r0**2,coefs,linestyle = "none", color = "blue",marker = "o") # misma dim
|
||||
plt.xlabel("l*(l+1)*(l-1)*(l+2)",fontweight = "bold")
|
||||
plt.ylabel(r'$\langle |a_\ell|^2 \rangle$',fontweight = "bold")
|
||||
plt.title("Coeficientes en funcion de l*(l+1)*(l-1)*(l+2)",fontsize = 14,fontweight = "bold")
|
||||
|
||||
#### GRAFICA 2: Representacion de los coeficientes en funcion de l (todos)
|
||||
|
||||
plt.figure()
|
||||
plt.plot(lfiltro,Y,linestyle="-.",color = "red")
|
||||
plt.plot(lvector,a2l,linestyle = "none", color = "blue",marker = "o")
|
||||
plt.yscale('log')
|
||||
plt.xlabel("l",fontweight = "bold")
|
||||
plt.ylabel(r'$\langle |a_\ell|^2 \rangle$',fontweight = "bold")
|
||||
plt.xticks(np.arange(0, 22, 2))
|
||||
plt.title("Coeficientes en funcion de l",fontsize = 14,fontweight = "bold")
|
||||
plt.show()
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import numpy as np
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from Codigo3D_Coefs import SHD,mcart_msph,msph_mcart
|
||||
from colorama import Fore, Style
|
||||
|
||||
import orthopoly
|
||||
import Codigo3D_AjusteHelfrich as c3
|
||||
|
||||
def calculate_al(Datos,Lmaximo):
|
||||
|
||||
cdata = SHD(name="SPH",Lmin=0,Lmax=Lmaximo,expansionMode="abs",radiusMode="expansion") # def clase
|
||||
|
||||
### CARGAMOS DATOS A LA CLASE
|
||||
|
||||
factor = 7*10**5
|
||||
d1 = mcart_msph(Datos) # datos en esfericas
|
||||
d1[:,:,0] = d1[:,:,0]/factor # normalizamos el radio al orden de 10**-5 como los datos experimentales
|
||||
d1cart = msph_mcart(d1) # convertimos de nuevo a cartesianas pero con el cambio
|
||||
|
||||
cdata.traj2 = d1cart # asignamos la trayectoria de la clase
|
||||
|
||||
print(f"Tenemos: {Style.BRIGHT + Fore.GREEN}{Datos.shape[1]}{Style.RESET_ALL} partículas")
|
||||
print(f"En {Style.BRIGHT + Fore.GREEN}{Datos.shape[0]}{Style.RESET_ALL} instantes temporales")
|
||||
|
||||
### GENERAMOS UN GRID
|
||||
|
||||
cdata.generateIcosahedralGrid(3)
|
||||
|
||||
G2esf = cdata.gridVectorssph # Puntos del grid en esfericas
|
||||
G2cart = cdata.gridVectors # Puntos del grid en cartesianas (sera exportado)
|
||||
|
||||
print(f"Nuestro grid tiene: {Style.BRIGHT + Fore.GREEN}{G2cart.shape[0]}{Style.RESET_ALL} puntos")
|
||||
|
||||
#### DISTRIBUIMOS TRAYECTORIA SOBRE GRID
|
||||
|
||||
print("------")
|
||||
cdata.distributeTrajPointsAlongGrid()
|
||||
|
||||
ProyeccionGrid = cdata.trajGrid # en cartesianas (sera exportado)
|
||||
|
||||
#### CALCULAMOS LA VARIACION CON RESPECTO A LA SUPERFICIE PROMEDIO
|
||||
|
||||
Superficie = np.mean(cdata.trajGridSph[:,:,0],axis = 0)
|
||||
|
||||
VariacionSuper = cdata.trajGridSph
|
||||
VariacionSuper[:,:,0] = VariacionSuper[:,:,0] - Superficie # Por defecto resta en cada fila
|
||||
|
||||
#### DESARROLLO EN ARMONICOS ESFERICOS
|
||||
|
||||
'''
|
||||
NOTA: los armonicos esfericos se hacen a partir de la variacion no directamente de la proyeccion del grid
|
||||
'''
|
||||
|
||||
cdata.sphericalHarmonicExpansion(VariacionSuper)
|
||||
|
||||
cdata.trajGridSph = mcart_msph(ProyeccionGrid) # Solucion a un bug, que asigna a la proyeccion variacion super
|
||||
|
||||
#### CALCULO DE LOS VALORES MEDIOS Y DETERMINACION DE AL
|
||||
|
||||
cdata.valoresmedios(cdata.trajGridSph) # solo tiene el input para calcular R0. Se calcula R0 del general no de la variacion
|
||||
|
||||
coefs_al2 = cdata.VM_AlCuadrado
|
||||
r0 = cdata.R0
|
||||
|
||||
lmain = np.linspace(0,Lmaximo,Lmaximo+1)
|
||||
terminol = lmain*(lmain+1)*(lmain-1)*(lmain+2)
|
||||
|
||||
return G2cart,ProyeccionGrid,terminol,coefs_al2,r0
|
||||
@@ -0,0 +1,8 @@
|
||||
09-Apr-2025 01:30:39 - sphAnalysis - INFO - Generating icosahedral grid with 3 subdivisions ...
|
||||
09-Apr-2025 01:30:39 - sphAnalysis - INFO - Distributing trajectory points along grid ...
|
||||
09-Apr-2025 01:31:47 - sphAnalysis - INFO - Performing spherical harmonic expansion ...
|
||||
09-Apr-2025 01:31:51 - sphAnalysis - INFO - Realizando el calculo de valores medios...
|
||||
09-Apr-2025 01:32:35 - sphAnalysis - INFO - Generating icosahedral grid with 3 subdivisions ...
|
||||
09-Apr-2025 01:32:36 - sphAnalysis - INFO - Distributing trajectory points along grid ...
|
||||
09-Apr-2025 01:33:45 - sphAnalysis - INFO - Performing spherical harmonic expansion ...
|
||||
09-Apr-2025 01:33:50 - sphAnalysis - INFO - Realizando el calculo de valores medios...
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user