commit
43af600d31
@ -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.
Loading…
Reference in new issue