Предыдущие части:
«Геометрическая головоломка на выходные»,
«Электродинамика виртуальной Вселенной»,
«Механика виртуальной Вселенной»,
«Квантовая механика виртуальной Вселенной (Часть I)»,
«Квантовая механика виртуальной Вселенной (Часть II)»
«Релятивизм виртуальной Вселенной»
«Космология виртуальной Вселенной (Часть I)»
«Космология виртуальной Вселенной (Часть II)»
«Электричество, проводимость и сверхпроводимость в виртуальной Вселенной»
«Атом в Виртуальной Вселенной (Часть I)»
«Атом в Виртуальной Вселенной (Часть II)»
«Атом в Виртуальной Вселенной (Часть III) [Химия]»
Здравствуйте, мои уважаемые читатели.
Следующим шагом я хотел приступить к описанию ядра атома в рамках описанной ранее теории. Но по комментариям и при личном обсуждении, пришёл к выводу, что теория хоть и является минималистичной, но всё-же, интуитивному её пониманию сильно мешает то, что всё обсуждение строится в 3+1 геометрических измерениях. С одной стороны — их не 11, как в теории суперструн, но и 4 — это сложно для понимания для неподготовленного человека. Да и, кого я обманываю — даже подготовленному проще оперировать формулами, чем образами в пространствах, размерностью выше трёх. Но в этой модели очень важно понимать её онтологию, суть процесса. Формулы являются лишь языком, позволяющим (вот тут будет тавтология) описать формализм системы и дать возможность оценить её качественно и количественно.
Эти размышления привели меня к мысли о необходимости дать расширенное визуальное описание системы. Я не придумал ничего лучше, чем понизить размерность. Исходно, у нас система представляет собой трёхмерную сферу S3. А давайте рассмотрим такую же модель, но на сфере S2. Да, удастся показать не всё — например, спин 1/2 здесь показать не выйдет. Но кое что должно проявиться и дать интуицию.
Я не хочу прибегать к банальным ассоциациям навроде той, где мы представляем двумерную плоскость, через которую проходит трёхмерный шар и что мы можем видеть, как двумерные жители этой плоскости. Аналогия, конечно, очень полезная, но она слишком простая для нашего случая. Вместо этого, я предлагаю построить полноценный лагранжиан для S2 мира и посмотреть, как он будет выглядеть.
Сразу исповедаюсь — я не специалист в python, он мне едва знаком (хотя, Монти Пайтон, в своё время — доставил :)) — мне ближе и роднее C/C++, PHP, Java. И, разумеется, я не знаком с его библиотеками для математики и визуализации. Мой грех в том, что я воспользовался ИИ для написания скриптов (и это было нелегко, вопреки содержимому бравурных статей о «Вайб Кодинге», но стоит отметить, что в итоге ИИ справился неплохо, судя по картинке). Скриптов с более-менее честными вычислениями и чтобы любопытные исследователи могли залезть в код, чтобы покрутить и «пощупать» модель. Просто, разумной альтернативы python я не нашёл. Возможно, я что-то упустил — не судите строго. Я действительно попытался донести идею максимально образно. Исходники буду вставлять в неизменном виде (возможно, с моими минорными правками, но оригинальные строки оставлю закомментированными; и я просил ИИ оставлять содержательные комментарии к коду).
Я буду искренне благодарен тем, кто сможет сделать визуализацию лучше, буде кто-то проявит к этому интерес — ИИ предлагал выходные данные обработать в Blender’е, но знакомство с ним на необходимом уровне подняло бы сроки подготовки статьи до Плеяд.
Итак, засучим рукава и приступим.
И, сразу, хочу прояснить ещё один момент — я заперт между двух огней, есть подготовленные читатели, которые вдумчиво смотрят на формулы и читатели, которые не погружены в тему достаточно глубоко. Мне придётся писать формулы для первых, но прошу вторых не пугаться — я постараюсь объяснить их суть и показать то, как они работают интуитивно.
Давайте, для начала выведем нашу двумерную систему.
Фазовый лагранжиан в 2+1D
Пусть в каждой точке мира определён фазовый вектор
,
где , а сама фаза является отображением
.
Геометрически это означает, что в каждой точке двумерного мира задан вектор единичной длины, указывающий ориентацию фазы в пространстве состояний.
Интуитивно — у нас есть сфера, как глобус. Это замкнутая двумерная поверхность, в трёхмерном пространстве. В каждой точке этой поверхности существует фаза U(1) — окружность, которая вращается. Эту вращающуюся окружность мы можем выразить неким виртуальным вектором, перпендикулярным плоскости её вращения. Кстати, если Вы знаете Геометрическую Алгебру и Вам что-то показалось знакомым — Вам не показалось. Лучше всего эта модель описывается на языке Геометрической Алгебры. Но это уже лирика. Итак, эта стрелочка своим концом может описывать точно такую же сферу S2, как и ту, на которой она находится, только меньшего масштаба.
Естественный лагранжиан для такого поля имеет вид нелинейной сигма-модели:
Здесь: — фазовая жёсткость,
, обычная сигма-модель, отвечает за распространение, волны, фотоны — без него нет вообще динамики.
-член — скрученная энергия — это член Скирма, делает вихри устойчивыми, без него электрон “схлопывается”, а так же задаёт вклад в энергию конфигурации. Далее мы будем трактовать этот вклад как источник инертной массы и гравитационного потенциала.
-член — потенциал вакуума
, фиксирует направление фазы в вакууме, задаёт масштаб энергий, делает возможным “спокойное состояние”.
при сигнатуре (+,−,−).
Пояснение: Деление на 2 и 4 не несёт самостоятельного физического смысла. Эти коэффициенты являются стандартной нормировкой, обеспечивающей корректный учёт симметрий при вариации действия. В частности, множитель 1/2 компенсирует двойной счёт квадратичных производных, а множитель 1/4 — комбинаторную кратность членов, содержащих антисимметричные произведения производных. То-есть, эти коэффициенты не вводят новой физики и не несут дополнительного смысла. Они лишь фиксируют удобную систему отсчёта для измерения энергии фазовой деформации.
Этот лагранжиан описывает чистую геометрию фазового поля без каких-либо внешних потенциалов или источников.
Опять же, интуитивно — в отсутствии каких-либо возбуждений и полей, первые два члена равны нулю, остаётся третий, который и задаёт предпочтительное направление фазы, как перпендикулярное нашей Мировой поверхности сферы S2 и она выглядит, как ёж (помните про вектор, которым мы описываем фазу?).
Ток Маурера–Картана
В полной 3+1D теории используется левый ток Маурера-Картана. В SU(2)-формализме ток — , в редукции на единичный вектор n удобно использовать эквивалентный so(3)-объект
.
Это вводится как удобная замена, то-есть — вместо самого поля n (этих самых окружностей или стрелочек) удобно ввести so(3)-ток:
Этот объект всегда ортогонален n (существует, как проекция на нашу Мировую поверхность и вообще, существует в касательном пространстве; но, прошу заметить — это только ради удобства и не вводит новых степеней свободы).
Пояснение: Проекция фазового вектора на мировую плоскость естественным образом приводит к току Маурера–Картана . Стоит отметить, что в полной SU(2)-версии модели используется именно левая форма этого тока, а не правая. Это связано с тем, что левая форма описывает изменение фазы относительно фиксированной системы отсчёта мира, то есть отражает реальное пространственно-временное перераспределение фазовой структуры. Правая форма, напротив, соответствует внутреннему «переопределению» фазы и не связана с физическим переносом или деформацией структуры в пространстве.
Замечание: Для поля тождественно сохраняется топологический ток:
интеграл от которого даёт целое топологическое число конфигурации. Этот ток не связан с динамическим переносом и отражает устойчивость вихревых решений.
Через этот ток лагранжиан переписывается в эквивалентной форме:
Таким образом, вся динамика системы выражается не через «потенциалы» или «поля», а через геометрию фазового тока.
Давайте теперь опишем фотон с помощью того, что у нас получилось.
Глобальная фаза и электромагнитное возбуждение
Как я уже говорил выше, в нашей модели вакуум — это не пустое пространство, а глобально эволюционирующая фазовая структура. В каждой точке физического пространства существует внутренняя фазовая степень свободы, глобальная эволюция которой определяет физическое время. Вакуум соответствует однородному вращению фазы вокруг выделенной («световой») оси, выбираемой потенциальным членом V(U) — тот самый третий член уравнения в Лагранжиане.
Электромагнитная волна не является материальным объектом, а представляет собой локальное возмущение этой глобальной фазовой динамики. То-есть, фотон соответствует временному избытку или дефициту фазовой скорости вращения по сравнению с вакуумным фоном. Если совсем грубо — фаза крутится с определённой , мы её немного «пинаем», чтобы она крутилась чуть быстрее (или медленнее), добавляем некоторую
. Поскольку функция фазы на всей поверхности старается сохранять гладкость — это возбуждение передаётся соседям и соседям соседей и далее.
Чтобы наглядно представить этот механизм, давайте рассмотрим локальный участок вакуумного фазового поля (локально поверхность нашей огромной Мировой S2 можно рассматривать как плоскость) и введём кратковременное локализованное возбуждение фазовой скорости. Это возбуждение не задаётся как постоянная деформация, а возникает в виде мгновенного импульса — аналогично капле, падающей на идеально спокойную поверхность воды. Импульс распространяется по среде в виде круговой волны и затем покидает область, оставляя её в исходном вакуумном состоянии.
Наш доблестный ИИ подготовил анимацию, на которой показано распространение такого фазового импульса в локально плоском участке глобальной фазовой геометрии. Ориентация фазы изображена стрелками, а индуцированные эффективные электромагнитные поля динамически возникают из геометрии фазового соединения.
Дисклеймер: Я не умею записывать анимацию, потому буду вставлять картинку из анимации. Но саму динамику можно будет посмотреть, запустив python-скрипт

Код для визуализации под катом. Для того, чтобы посмотреть под другим углом — поменяйте переменные VIEW_ELEV и VIEW_AZIM.
Скрытый текст
""" S² / O(3) sigma-model: "drop in a pond" (single impulse) + OPEN boundaries + E/B visualization ============================================================================================ What this script demonstrates (popular S²-interface, close to your core idea): • Calm vacuum: n(x,y) = (0,0,1) everywhere (red arrows point straight up). • A SINGLE excitation at t=0: we do NOT permanently deform the center. Instead we give a short, localized *initial velocity* (an impulse), like a droplet hitting a pond. After the wave passes, the interior returns to calm vacuum (like the pond surface). • Circular outward wave on a local plane patch of the "world sphere". • OPEN (radiating) boundaries: Mur/Sommerfeld 1st-order absorbing BC, to prevent reflections. • EM-like fields from geometry (U(1) fiber over S²): n ↦ angles (θ, φ) a_vec = (1 - cosθ) ∇φ a_0 = (1 - cosθ) ∂t φ E = -∂t a_vec - ∇a_0 (blue in-plane arrows) Bz = (∇×a_vec)_z (green heatmap + optional vertical arrows) Why this is "honest through the Lagrangian": Dynamics of n are derived from the sigma-model Lagrangian (no Skyrme term here): L = (κ/2) ( |∂t n|^2 - c^2 |∇n|^2 ), with |n|=1. Variation gives the constrained wave equation: ∂t² n - c² ∇² n = λ n, and we enforce the constraint by normalizing n after each step (standard numerical approach). Notes: • We choose an impulse that is *circularly polarized* in the plane near the center, so that the geometric connection has a nontrivial curvature (visible B). • This is a visualization demo, not a high-precision PDE solver. • If you want even "more open" boundaries, enlarge Lx,Ly or lower eps / increase sigma. Dependencies: numpy, matplotlib Run: python s2_open_drop_em_demo.py """ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from mpl_toolkits.mplot3d import Axes3D # noqa: F401 # ---------------------------- # Viewer / presentation settings # ---------------------------- VIEW_ELEV = 90 VIEW_AZIM = -60 FIGSIZE = (11, 8) # Arrow colors COLOR_N = "red" # n field COLOR_E = "blue" # E field # B is shown as a green heatmap; optional vertical arrows use green tones # ---------------------------- # Simulation parameters # ---------------------------- Nx, Ny = 140, 140 # grid resolution Lx, Ly = 14.0, 14.0 # physical size of patch (bigger => less boundary influence) c = 1.0 kappa = 1.0 # overall scale (doesn't change wave shapes here) dx = Lx / Nx dy = Ly / Ny # CFL stability (conservative) dt = 0.22 * min(dx, dy) / (c * np.sqrt(2)) T_total = 7.0 steps_per_frame = 3 nframes = int(T_total / (dt * steps_per_frame)) # Visualization density q_step_n = 7 # subsample step for n quiver q_step_E = 7 # subsample step for E quiver # Arrow lengths (visual only) LEN_N = 0.65 LEN_E = 0.75 # Optional: show vertical B arrows (can clutter). Heatmap is already good. SHOW_B_ARROWS = False q_step_B = 9 LEN_B = 0.55 # Impulse ("drop") parameters eps = 0.85 # impulse strength (increase carefully) sigma = 0.70 # impulse width # If eps is too high, the sigma-model nonlinearity + constraint can generate artifacts. # Better: keep eps moderate, increase sigma for smoother wave. # ---------------------------- # Grid # ---------------------------- x = np.linspace(-Lx/2, Lx/2, Nx, endpoint=False) y = np.linspace(-Ly/2, Ly/2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") Z = np.zeros_like(X) # Subsample grids for quivers XsN = X[::q_step_n, ::q_step_n] YsN = Y[::q_step_n, ::q_step_n] ZsN = Z[::q_step_n, ::q_step_n] XsE = X[::q_step_E, ::q_step_E] YsE = Y[::q_step_E, ::q_step_E] ZsE = Z[::q_step_E, ::q_step_E] XsB = X[::q_step_B, ::q_step_B] YsB = Y[::q_step_B, ::q_step_B] ZsB = Z[::q_step_B, ::q_step_B] # ---------------------------- # Open-boundary finite differences (no wrap) # ---------------------------- def laplacian_open(f): """ 2D Laplacian on an open domain: - interior: central second differences - edges: set to 0 here (handled by absorbing BC after time step) """ lap = np.zeros_like(f) lap[1:-1, 1:-1] = ( (f[2:, 1:-1] - 2*f[1:-1, 1:-1] + f[:-2, 1:-1]) / dx**2 + (f[1:-1, 2:] - 2*f[1:-1, 1:-1] + f[1:-1, :-2]) / dy**2 ) return lap def grad_open(f): """ 2D gradient on an open domain: - interior: central differences - edges: one-sided differences """ dfdx = np.empty_like(f) dfdy = np.empty_like(f) dfdx[1:-1, :] = (f[2:, :] - f[:-2, :]) / (2*dx) dfdx[0, :] = (f[1, :] - f[0, :]) / dx dfdx[-1, :] = (f[-1, :] - f[-2, :]) / dx dfdy[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2*dy) dfdy[:, 0] = (f[:, 1] - f[:, 0]) / dy dfdy[:, -1] = (f[:, -1] - f[:, -2]) / dy return dfdx, dfdy def unwrap_phase_2d(phi): """Phase unwrap to reduce π-jumps (demo-level).""" pu = np.unwrap(phi, axis=0) pu = np.unwrap(pu, axis=1) return pu def safe_angles_from_n(n): nx, ny, nz = n[..., 0], n[..., 1], n[..., 2] nz = np.clip(nz, -1.0, 1.0) theta = np.arccos(nz) phi = np.arctan2(ny, nx) return theta, phi # ---------------------------- # Mur / Sommerfeld absorbing boundary condition (1st order) # ---------------------------- rx = (c*dt - dx) / (c*dt + dx) ry = (c*dt - dy) / (c*dt + dy) def apply_mur_absorbing_bc(n_next, n_curr): """ Mur absorbing BC for outgoing waves on edges, applied componentwise. Left edge (i=0): u0^{n+1} = u1^{n} + rx (u1^{n+1} - u0^{n}) Right edge: uN^{n+1} = u_{N-1}^{n} + rx (u_{N-1}^{n+1} - uN^{n}) Similarly for y edges with ry. """ # x edges n_next[0, :, :] = n_curr[1, :, :] + rx * (n_next[1, :, :] - n_curr[0, :, :]) n_next[-1, :, :] = n_curr[-2, :, :] + rx * (n_next[-2, :, :] - n_curr[-1, :, :]) # y edges n_next[:, 0, :] = n_curr[:, 1, :] + ry * (n_next[:, 1, :] - n_curr[:, 0, :]) n_next[:, -1, :] = n_curr[:, -2, :] + ry * (n_next[:, -2, :] - n_curr[:, -1, :]) # corners: average neighbors to reduce corner artifacts n_next[0, 0, :] = 0.5 * (n_next[1, 0, :] + n_next[0, 1, :]) n_next[0, -1, :] = 0.5 * (n_next[1, -1, :] + n_next[0, -2, :]) n_next[-1, 0, :] = 0.5 * (n_next[-2, 0, :] + n_next[-1, 1, :]) n_next[-1, -1, :] = 0.5 * (n_next[-2, -1, :] + n_next[-1, -2, :]) # ---------------------------- # Dynamics from the sigma-model Lagrangian (leapfrog) # ---------------------------- def step_sigma_model_open(n_curr, n_prev): """ Leapfrog update for: ∂t² n - c² ∇² n = λ n, |n|=1 Unconstrained wave step: n_next = 2 n_curr - n_prev + dt² c² ∇² n_curr Then: - apply absorbing (Mur) boundary on edges - renormalize to enforce |n|=1 (constraint) """ lapx = laplacian_open(n_curr[..., 0]) lapy = laplacian_open(n_curr[..., 1]) lapz = laplacian_open(n_curr[..., 2]) n_next = np.empty_like(n_curr) n_next[..., 0] = 2*n_curr[..., 0] - n_prev[..., 0] + (dt**2) * (c**2) * lapx n_next[..., 1] = 2*n_curr[..., 1] - n_prev[..., 1] + (dt**2) * (c**2) * lapy n_next[..., 2] = 2*n_curr[..., 2] - n_prev[..., 2] + (dt**2) * (c**2) * lapz apply_mur_absorbing_bc(n_next, n_curr) # Enforce constraint |n|=1 everywhere norm = np.linalg.norm(n_next, axis=2, keepdims=True) n_next /= (norm + 1e-12) return n_next # ---------------------------- # Geometric U(1) connection and fields E, B # ---------------------------- def compute_connection_EB(n, n_prev): theta, _phi = safe_angles_from_n(n) theta_p, _phi_p = safe_angles_from_n(n_prev) nx, ny = n[..., 0], n[..., 1] nxp, nyp = n_prev[..., 0], n_prev[..., 1] # spatial derivatives of nx, ny dnx_dx, dnx_dy = grad_open(nx) dny_dx, dny_dy = grad_open(ny) # time derivatives of nx, ny dnx_dt = (nx - nxp) / dt dny_dt = (ny - nyp) / dt # stable phase-derivatives (NO atan2 / unwrap) denom = nx*nx + ny*ny + 1e-12 dphi_dx = (nx * dny_dx - ny * dnx_dx) / denom dphi_dy = (nx * dny_dy - ny * dnx_dy) / denom dphi_dt = (nx * dny_dt - ny * dnx_dt) / denom fac = (1.0 - np.cos(theta)) ax = fac * dphi_dx ay = fac * dphi_dy a0 = fac * dphi_dt # For ∂t a we need previous a as well nx2, ny2 = nxp, nyp dnxp_dx, dnxp_dy = grad_open(nx2) dnyp_dx, dnyp_dy = grad_open(ny2) dnxp_dt = (nxp - nx) / dt dnyp_dt = (nyp - ny) / dt denom_p = nx2*nx2 + ny2*ny2 + 1e-12 dphi_p_dx = (nx2 * dnyp_dx - ny2 * dnxp_dx) / denom_p dphi_p_dy = (nx2 * dnyp_dy - ny2 * dnxp_dy) / denom_p dphi_p_dt = (nx2 * dnyp_dt - ny2 * dnxp_dt) / denom_p fac_p = (1.0 - np.cos(theta_p)) ax_p = fac_p * dphi_p_dx ay_p = fac_p * dphi_p_dy a0_p = fac_p * dphi_p_dt dax_dt = (ax - ax_p) / dt day_dt = (ay - ay_p) / dt da0_dx, da0_dy = grad_open(a0) Ex = -dax_dt - da0_dx Ey = -day_dt - da0_dy day_dx, _ = grad_open(ay) _, dax_dy = grad_open(ax) Bz = day_dx - dax_dy return Ex, Ey, Bz # ---------------------------- # Initialize: calm vacuum + ONE impulse ("drop") # ---------------------------- n = np.zeros((Nx, Ny, 3), dtype=float) n[..., 2] = 1.0 # vacuum # Single impulse: give an initial "velocity" v in the tangent plane (XY). # This is the "drop hits pond" moment: no permanent deformation at t=0, only a kick. r2 = X**2 + Y**2 vamp = eps * np.exp(-r2 / (2*sigma**2)) # Circular polarization of the impulse in the plane: # alpha is the azimuth around center; v points tangentially (rotational impulse). # This tends to produce a clean EM-like curvature signal (B). alpha = np.arctan2(Y, X) vx = -vamp * np.sin(alpha) vy = +vamp * np.cos(alpha) vz = 0.0 # Leapfrog start: n_prev = n - dt * v n_prev = n.copy() n_prev[..., 0] -= dt * vx n_prev[..., 1] -= dt * vy # n_prev[..., 2] unchanged (vz=0) # Project back to S² (constraint) n_prev /= (np.linalg.norm(n_prev, axis=2, keepdims=True) + 1e-12) # ---------------------------- # Visualization setup # ---------------------------- fig = plt.figure(figsize=FIGSIZE) ax = fig.add_subplot(111, projection="3d") wf_step = 12 # plane wireframe density ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) # allow downward B arrows if enabled ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z (normal)") # For a stable B heatmap scaling, keep a running robust percentile estimate B_scale = 1e-6 def draw_frame(frame_idx): global n, n_prev, B_scale # Integrate for _ in range(steps_per_frame): n_next = step_sigma_model_open(n, n_prev) n_prev, n = n, n_next # Compute fields Ex, Ey, Bz = compute_connection_EB(n, n_prev) # Robust scaling for E and B display # (prevents "jumping" arrows/colormap due to a single outlier) Emag = np.sqrt(Ex**2 + Ey**2) E95 = np.percentile(Emag, 95) + 1e-12 B95 = np.percentile(np.abs(Bz), 95) + 1e-12 # Slowly update B_scale for smooth visualization B_scale = 0.9 * B_scale + 0.1 * B95 # Subsample for arrows ns = n[::q_step_n, ::q_step_n, :] Exs = Ex[::q_step_E, ::q_step_E] Eys = Ey[::q_step_E, ::q_step_E] # For E arrows: keep amplitude (not just direction), but clip to [-1,1] in display units Exd = np.clip(Exs / E95, -1.0, 1.0) Eyd = np.clip(Eys / E95, -1.0, 1.0) # Clear & redraw ax.cla() ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z (normal)") t = frame_idx * steps_per_frame * dt ax.set_title( f"Single 'drop' impulse on S²-field (OPEN boundaries). t={t:5.2f}\n" f"n: red (unit), E: blue (clipped @95%), Bz: green heatmap (±95%)", pad=18 ) # Plane wireframe ax.plot_wireframe( X[::wf_step, ::wf_step], Y[::wf_step, ::wf_step], Z[::wf_step, ::wf_step], linewidth=0.5, alpha=0.22 ) # --- B heatmap on the plane (green palette) --- # Use a diverging colormap but with greenish feel: # We'll map negative to light green, positive to dark green by custom normalization via 'Greens' # However Greens is one-sided; better use 'PiYG' or 'PRGn'—but you asked green/light-green. # We'll emulate by plotting two surfaces: positive and negative with different greens. B = Bz.copy() Bn = np.clip(B / (B_scale + 1e-12), -1.0, 1.0) # Positive part (0..1) darker green Bpos = np.clip(Bn, 0.0, 1.0) # Negative part (0..1) lighter green (use smaller alpha) Bneg = np.clip(-Bn, 0.0, 1.0) # Surface colors cmap = plt.cm.Greens # Positive: stronger alpha fc_pos = cmap(0.25 + 0.75 * Bpos) fc_pos[..., 3] = 0.38 * Bpos # alpha # Negative: very light green fc_neg = cmap(0.05 + 0.35 * Bneg) fc_neg[..., 3] = 0.22 * Bneg # alpha ax.plot_surface(X, Y, Z, facecolors=fc_pos, rstride=1, cstride=1, shade=False) ax.plot_surface(X, Y, Z, facecolors=fc_neg, rstride=1, cstride=1, shade=False) # --- n field (red arrows) --- ax.quiver( XsN, YsN, ZsN, ns[..., 0], ns[..., 1], ns[..., 2], length=LEN_N, normalize=True, color=COLOR_N, linewidth=0.7 ) # --- E field (blue arrows, in-plane) --- ax.quiver( XsE, YsE, ZsE, Exd, Eyd, np.zeros_like(Exd), length=LEN_E, normalize=False, color=COLOR_E, linewidth=0.9 ) # --- Optional: B arrows up/down (can clutter) --- if SHOW_B_ARROWS: Bzs = Bz[::q_step_B, ::q_step_B] pos = Bzs > 0 neg = Bzs < 0 if np.any(pos): ax.quiver( XsB[pos], YsB[pos], ZsB[pos], 0*XsB[pos], 0*YsB[pos], 1+0*ZsB[pos], length=LEN_B, normalize=True, color="green", linewidth=1.0 ) if np.any(neg): ax.quiver( XsB[neg], YsB[neg], ZsB[neg], 0*XsB[neg], 0*YsB[neg], -1+0*ZsB[neg], length=LEN_B, normalize=True, color="#7CFC90", linewidth=1.0 ) return [] anim = FuncAnimation(fig, draw_frame, frames=nframes, interval=30, blit=False, repeat=True) plt.show()
Смотрите — векторы электрического поля перпендикулярны направлению распространения волны, так как сонаправлены циркуляции фазовой энергии. Фазовая энергия вращения, благодаря сигма члену (скирмовский член
здесь не учитывается) — колеблется, а не просто уменьшается экспоненциально. Магнитное поле является ротором вектора электрического поля и направлено перпендикулярно Мировой поверхности. Но, поскольку поверхность у нас двумерная — на этой поверхности магнитное поле является точкой, скаляром — длиной этого вектора со знаком плюс или минус (зелёный/светло-зелёный).
А теперь — ещё интересная штука (ну, чтобы два раза не вставать, коль уж мы говорим о фотоне)
Красное смещение как эволюция времени, а не растяжение пространства
В стандартной космологии красное смещение трактуется как растяжение длин волн в расширяющемся пространстве. В нашей модели эта интерпретация принципиально иная.
Здесь фотон сохраняет свою внутреннюю фазовую структуру в процессе распространения. Изменяется не он сам, а скорость течения физического времени. Физическое время определяется операционально — через глобальную фазовую эволюцию вакуума. По мере изменения глобального радиуса кривизны Вселенной R0 меняется и характерная фазовая частота , определяющая все внутренние процессы.
В результате фотон, испущенный на ранней стадии космической эволюции и зарегистрированный на более поздней, будет измерен с иной частотой не потому, что его длина волны геометрически растянулась, а потому, что часы, которыми производится измерение, работают с другой фазовой скоростью. То-есть, красное смещение отражает дрейф физического масштаба времени, а не деформацию самого пространства. И получается так, что красное смещение — свойство наблюдателя, а не фотона.


Фиг.2 «красное смещение»
а) фотон достиг детектора early б) фотон достиг детектора late
Код скрипта под катом
Скрытый текст
""" 2D demo: phase-redshift from global SU(2) frequency drift (S² local patch) ========================================================================= Goal (as in your сosmology logic): • We DO NOT "stretch space". We keep a local S² patch ≈ plane (x,y). • A narrowband Gaussian wavepacket ("photon") propagates across the patch. • The global curvature radius R0(T) slowly increases with global parameter T. • The local phase frequency scale of *all internal excitations* drifts as ω(T) ∝ 1 / R0(T) (this is your cosmology assumption). • Operational / proper time t is related to global parameter T by an inverse law: dt/dT = ω* / ω(T) (this is the only way to get dt_obs/dt_em = ω_em/ω_obs) so when ω decreases, clocks run slower and measured photon frequency redshifts. Physics from a Lagrangian (kept explicit in code): We propagate a scalar "phase excitation" field ψ(x,y,T) with a time-dependent wave speed in global parameter T, derived by mapping a constant-c wave equation in operational time t into the global parameter T. Start from standard wave Lagrangian in operational time t: L = (χ/2) [ (∂t ψ)^2 - c^2 |∇ψ|^2 ]. Convert derivatives using dt/dT = ω*/ω(T) ⇒ ∂t = (ω(T)/ω*) ∂T. Plug in (slow-variation approximation; we neglect terms ~ dω/dT inside ∂t²): (∂t ψ)^2 = (ω/ω*)^2 (∂T ψ)^2. Up to the same approximation, the Euler-Lagrange equation becomes: ∂T² ψ - c_eff(T)^2 ∇² ψ = 0 with c_eff(T) = c * (ω(T)/ω*). This makes the packet's global oscillation rate drift ∝ ω(T), and the measured frequency in operational time t redshifts as ω drops. Visualization: • Show ψ(x,y) as a colormap (2D). • Two detectors at fixed x positions record ψ(T) and estimate the frequency ν(t) using zero-crossings, but with time converted to operational time t. • We print R0(T), ω(T), and the running ν_A, ν_B, and z_est ≈ ν_A/ν_B - 1. Notes: • This is a "clean didactic" simulation, not a full SU(2) field solver. • Boundaries are made "open enough" with a sponge (absorbing layer) to kill reflections. • Animation is intentionally slow/smooth: low steps_per_frame, longer interval. Dependencies: numpy, matplotlib Run: python phase_redshift_2d_demo.py """ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # ---------------------------- # 0) User-facing "constants" (publishable knobs) # ---------------------------- # Viewer / speed FPS = 30 # animation fps target (visual only) INTERVAL_MS = int(1000 / FPS) steps_per_frame = 2 # smaller => slower, smoother show_every_n_frames = 1 # keep 1 for smooth updates # Local patch geometry (S² ≈ plane) Nx, Ny = 360, 120 Lx, Ly = 24.0, 8.0 dx, dy = Lx / Nx, Ly / Ny # Wave physics (operational / local time t) c = 1.0 # physical propagation speed in operational time t chi = 1.0 # Lagrangian prefactor (does not affect shape here) # Cosmology knobs: global radius and phase frequency drift R0_init = 1.0 dR0_dT = 0.015 # positive => expansion in global parameter T omega_star = 1.0 # universal reference frequency ω* omega0 = 1.0 # sets ω(T)=omega0/R0(T) # IMPORTANT relation (your cosmology-consistent sign): # dt/dT = ω* / ω(T) so that dt_obs/dt_em = ω_em/ω_obs # (This is the inverse relation dt ∝ 1/ω mentioned in your cosmology text.) # Wavepacket ("photon") parameters (narrowband Gaussian beam) A = 1.0 k0 = 7.5 # carrier spatial wavenumber along +x sigma_x = 1.4 # packet width sigma_y = 0.8 x0 = -0.35 * Lx # launch position y0 = 0.0 # Detectors x_det_A = -0.10 * Lx # "earlier" (packet hits first) x_det_B = +0.30 * Lx # "later" (packet hits second) y_det = 0.0 # Frequency estimation settings min_abs_signal = 0.010 # ignore tiny values (avoid noise crossings) need_crossings = 2 # crossings needed before we show a stable frequency # Absorbing boundary (sponge) settings sponge_w = 30 # sponge thickness in grid cells sponge_strength = 0.035 # damping per global step (tune if reflections appear) # ---------------------------- # 1) Grid # ---------------------------- x = np.linspace(-Lx / 2, Lx / 2, Nx, endpoint=False) y = np.linspace(-Ly / 2, Ly / 2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") def idx_from_x(xx): return int(np.clip(np.round((xx + Lx/2) / dx), 0, Nx-1)) def idx_from_y(yy): return int(np.clip(np.round((yy + Ly/2) / dy), 0, Ny-1)) ixA, iyA = idx_from_x(x_det_A), idx_from_y(y_det) ixB, iyB = idx_from_x(x_det_B), idx_from_y(y_det) # ---------------------------- # 2) Cosmology: R0(T), ω(T), mapping dt/dT # ---------------------------- T = 0.0 # global evolution parameter t_op = 0.0 # operational / proper time (the one clocks use) def R0_of_T(T): # simplest: linear growth (you can replace with your ODE for R(T) later) return R0_init + dR0_dT * T def omega_of_T(T): # your cosmology assumption: ω(T) ∝ 1/R(T) return omega0 / R0_of_T(T) def dt_dT(T): # the crucial inverse relation for time dilation & redshift in your cosmology: # dt/dT = ω* / ω(T) return omega_star / omega_of_T(T) def c_eff_of_T(T): # mapping constant-c wave propagation in operational time t into global parameter T: # ∂t = (ω/ω*) ∂T ⇒ wave speed in T is c_eff = c * (ω/ω*) return c * (omega_of_T(T) / omega_star) # ---------------------------- # 3) Stable explicit scheme for ∂T²ψ - c_eff(T)² ∇²ψ = 0 # ---------------------------- # Conservative dt in global parameter T (CFL wrt maximal c_eff) # since ω(T) decreases as R grows, c_eff decreases over time (stability improves), # so we set dt_global based on initial c_eff. c_eff0 = c_eff_of_T(0.0) dt_global = 0.28 * min(dx, dy) / (c_eff0 * np.sqrt(2)) def laplacian_open(f): lap = np.zeros_like(f) lap[1:-1, 1:-1] = ( (f[2:, 1:-1] - 2*f[1:-1, 1:-1] + f[:-2, 1:-1]) / dx**2 + (f[1:-1, 2:] - 2*f[1:-1, 1:-1] + f[1:-1, :-2]) / dy**2 ) return lap # Sponge mask (0 inside, increasing toward edges) sponge = np.zeros((Nx, Ny), dtype=float) for i in range(Nx): di = min(i, Nx-1-i) if di < sponge_w: sponge[i, :] += (sponge_w - di) / sponge_w for j in range(Ny): dj = min(j, Ny-1-j) if dj < sponge_w: sponge[:, j] += (sponge_w - dj) / sponge_w sponge = np.clip(sponge, 0.0, 1.0) def apply_sponge(psi, psi_prev): # simple velocity damping in the sponge layer # v ≈ (psi - psi_prev)/dt → damp v near boundaries damp = np.exp(-sponge_strength * sponge) v = (psi - psi_prev) v *= damp psi_prev[:, :] = psi - v # ---------------------------- # 4) Initial condition: a right-moving narrowband Gaussian packet # ---------------------------- # In 1D, right-moving is ψ(x,0)=A cos(kx) exp(-(x-x0)^2/2σ^2) # with ∂tψ = +c ∂xψ at t=0. # We do the same here (beam in 2D) and convert ∂t to ∂T using ∂t=(ω/ω*)∂T. envelope = np.exp(-((X - x0)**2) / (2*sigma_x**2) - ((Y - y0)**2) / (2*sigma_y**2)) carrier = np.cos(k0 * (X - x0)) psi = A * envelope * carrier # spatial derivative for right-moving condition dpsi_dx = np.zeros_like(psi) dpsi_dx[1:-1, :] = (psi[2:, :] - psi[:-2, :]) / (2*dx) dpsi_dx[0, :] = (psi[1, :] - psi[0, :]) / dx dpsi_dx[-1, :] = (psi[-1, :] - psi[-2, :]) / dx # ∂tψ(0) = +c ∂xψ (right-moving) dpsi_dt0 = -c * dpsi_dx # Convert to ∂Tψ using ∂t = (ω/ω*) ∂T ⇒ ∂Tψ = (ω*/ω) ∂tψ omega_init = omega_of_T(0.0) dpsi_dT0 = (omega_star / omega_init) * dpsi_dt0 # Leapfrog init: psi_prev = psi - dt_global * ∂Tψ psi_prev = psi - dt_global * dpsi_dT0 # ---------------------------- # 5) Frequency estimator at detectors (zero-crossings in operational time t) # ---------------------------- class Detector: def __init__(self, name, ix, iy): self.name = name self.ix = ix self.iy = iy self.prev_val = None self.prev_t = None self.cross_times_t = [] # operational time of (positive-slope) zero-crossings def update(self, psi_val, t_now): # record a positive-slope zero crossing: ψ crosses from negative to positive # ignore tiny |ψ| to avoid numerical chatter far from the packet if self.prev_val is None: self.prev_val = psi_val self.prev_t = t_now return if abs(psi_val) < min_abs_signal and abs(self.prev_val) < min_abs_signal: self.prev_val = psi_val self.prev_t = t_now return if self.prev_val < 0.0 and psi_val >= 0.0: # linear interpolation to estimate crossing time dv = psi_val - self.prev_val if abs(dv) > 1e-12: frac = -self.prev_val / dv else: frac = 0.0 t_cross = self.prev_t + frac * (t_now - self.prev_t) # store only if it is not a duplicate (numerical safety) if len(self.cross_times_t) == 0 or (t_cross - self.cross_times_t[-1]) > 1e-6: self.cross_times_t.append(t_cross) self.prev_val = psi_val self.prev_t = t_now def frequency_hz(self): # one full period corresponds to two successive positive-slope zero crossings # (because each such crossing happens once per cycle) if len(self.cross_times_t) < need_crossings: return None # use last few periods for smoothing times = np.array(self.cross_times_t[-need_crossings:]) dt = np.diff(times) # dt is the period estimate Tavg = np.mean(dt) if Tavg <= 0: return None return 1.0 / Tavg detA = Detector("A", ixA, iyA) detB = Detector("B", ixB, iyB) # ---------------------------- # 6) Animation (2D) # ---------------------------- fig, ax = plt.subplots(figsize=(12, 4.2)) ax.set_title("Phase-redshift demo (S² local patch ≈ plane)") im = ax.imshow( psi.T, origin="lower", extent=[-Lx/2, Lx/2, -Ly/2, Ly/2], aspect="auto", cmap="coolwarm", vmin=-0.8, vmax=0.8, interpolation="bilinear" ) # detector markers ax.plot([x_det_A], [y_det], "ko", ms=6) ax.text(x_det_A, y_det + 0.35, "A (early)", color="k", ha="center", va="bottom") ax.plot([x_det_B], [y_det], "ko", ms=6) ax.text(x_det_B, y_det + 0.35, "B (late)", color="k", ha="center", va="bottom") ax.set_xlabel("x (local patch)") ax.set_ylabel("y (local patch)") # HUD text hud = ax.text( 0.02, 0.97, "", transform=ax.transAxes, ha="left", va="top", fontsize=10, family="monospace", bbox=dict(boxstyle="round", facecolor="white", alpha=0.85, edgecolor="none") ) plt.tight_layout() def step_once(): global psi, psi_prev, T, t_op # time-dependent effective speed in global parameter T c_eff = c_eff_of_T(T) # integrate operational time (this is the "clock time" used for measurement) t_op += dt_dT(T) * dt_global # leapfrog step: ψ_next = 2ψ - ψ_prev + dt² c_eff² ∇²ψ lap = laplacian_open(psi) psi_next = 2.0 * psi - psi_prev + (dt_global**2) * (c_eff**2) * lap # sponge to suppress reflections (acts on boundary velocity) apply_sponge(psi_next, psi) # shift time layers psi_prev, psi = psi, psi_next # advance global parameter T += dt_global def update(frame): # run a few physics steps per rendered frame for smoothness for _ in range(steps_per_frame): step_once() # detector updates in operational time t_op detA.update(psi[detA.ix, detA.iy], t_op) detB.update(psi[detB.ix, detB.iy], t_op) # update image im.set_data(psi.T) # compute current cosmology values R0 = R0_of_T(T) w = omega_of_T(T) # detector frequencies (in operational time) nuA = detA.frequency_hz() nuB = detB.frequency_hz() # estimated redshift from detector readings (if both exist) z_est = None if (nuA is not None) and (nuB is not None) and nuB > 0: z_est = (nuA / nuB) - 1.0 # HUD text (keep it readable and stable) lines = [ f"Global parameter T = {T:7.3f}", f"Operational time t = {t_op:7.3f}", f"R0(T) = {R0:7.4f} (set by dR0/dT = {dR0_dT})", f"ω(T) = ω0/R0(T) = {w:7.4f}", f"dt/dT = ω*/ω(T) = {dt_dT(T):7.4f}", f"c_eff(T) = c·ω/ω* = {c_eff_of_T(T):7.4f}", "", f"Detector A freq νA(t) = {nuA:7.3f} Hz" if nuA is not None else "Detector A freq νA(t) = (waiting crossings...)", f"Detector B freq νB(t) = {nuB:7.3f} Hz" if nuB is not None else "Detector B freq νB(t) = (waiting crossings...)", f"z_est ≈ νA/νB - 1 = {z_est:7.3f}" if z_est is not None else "z_est ≈ νA/νB - 1 = (waiting...)", "", "Interpretation: as R0 grows → ω drops → ν(t) drops (redshift) in operational time.", ] hud.set_text("\n".join(lines)) return (im, hud) anim = FuncAnimation( fig, update, interval=INTERVAL_MS, blit=False, repeat=True ) plt.show()
То-есть, та самая фаза, которая есть вращающаяся окружность U(1) в каждой точке Мировой поверхности и которую мы договорились выражать через вектор, который перпендикулярен плоскости вращения этой фазы — меняет скорость вращения в зависимости от радиуса Вселенной. Таким образом, когда Вселенная расширяется, вращение фазы замедляется и мы наблюдаем красное смещение. Когда Вселенная перестанет расширяться — мы не будем наблюдать какое либо смещение, а если начнёт сжиматься — мы увидим УФ-смещение. Кстати, фактически, если сильно глубоко погружаться в философию — то самое глобальное время задаёт пространство. Не будет вращения фазы — не будет и пространства. Но расширение здесь не метрическое (локальная плотность пространства не изменяется).
Ну, а теперь перейдём к структуре посложнее.
Электрон как топологический фазовый дефект
Если фотон соответствует распространяющемуся фазовому возбуждению, то массивные частицы связаны с локализованными топологическими структурами самого фазового поля, где фаза уже крутится вокруг «тяжёлых» направлений и наклонена по отношению к мировой поверхности. То есть, электрон — это не точечный объект, а устойчивый фазовый вихрь, вокруг топологического дефекта. Здесь, ядро электронного вихря (топологический дефект) не соответствует возбуждённому или «сжатому» состоянию вакуума. Напротив, оно представляет собой область, в которой сам фазовый параметр порядка перестаёт быть определённым, отмечая локальный разрыв фазового описания вакуума. Фактически, если очень упрощённо — в центре находится неупорядоченная фаза вакуума (метафорически — «первозданный вакуум»), ничто, где эффективное описание на языке разрушается; можно мыслить это как
для параметра порядка, из-за чего коэффициенты в эффективном лагранжиане деградируют.
В такой конфигурации фазовое поле не может оставаться в вакуумной ориентации. Вблизи ядра вихря фаза вынужденно сильно отклоняется от предпочтительного вакуумного направления, формируя локальную область с высокой фазовой кривизной и градиентной энергией.
Полная энергия этой статической конфигурации определяет массу покоя частицы. Гравитация возникает как вторичный эффект: локализованная плотность энергии изменяет локальную скорость фазовой эволюции, тем самым искажая течение физического времени вокруг вихря.
В этом смысле масса, гравитация и время не являются независимыми понятиями, а представляют собой разные аспекты одной и той же глубинной фазовой геометрии.

Код скрипта под катом. Так же можно поменять угол зрения и тип отображения скирмионного вихря Блох/Неель.
Скрытый текст
""" Static "electron" in 2+1D as a phase vortex on an S² field (visualized in 3D over a plane) ========================================================================================= What you get: • A static topological vortex/defect n(x,y) ∈ S² (red arrows) over a 2D plane patch. • An "electric-like" field E (blue arrows) computed as E = -∇Φ from an effective scalar potential Φ derived from the field's deviation from the vacuum direction. • A "gravitational potential / time dilation" map on the plane (colormap) derived from the energy density of the vortex (sigma-model energy). Notes (important): • In 2+1D, "magnetic field" is naturally a pseudoscalar Bz; here we focus on a static object. • A strictly static Berry-connection EM construction gives E=0 if a0=0. For a charged static object we need an effective scalar potential. In the reduced S² toy model we take Φ ∝ (1 - n_z), i.e. how much the field deviates from the vacuum (light axis). Then E=-∇Φ is radial and matches the expected "charge-like" behavior in 2D. • If you want, you can also visualize an O(3) analogue of Maurer–Cartan current: J_i = n × ∂_i n (this is not full SU(2) L_mu = U†∂_μU; it's the natural so(3) proxy in the S² reduction). Dependencies: numpy, matplotlib Run: python static_electron_vortex_3d.py """ import numpy as np import matplotlib.pyplot as plt # ---------------------------- # View controls (put FIRST, as requested) # ---------------------------- VIEW_ELEV = 90 # elevation angle (deg) VIEW_AZIM = -55 # azimuth angle (deg) bloch = True # ---------------------------- # Domain / resolution # ---------------------------- Nx, Ny = 150, 150 Lx, Ly = 14.0, 14.0 dx, dy = Lx / Nx, Ly / Ny x = np.linspace(-Lx/2, Lx/2, Nx, endpoint=False) y = np.linspace(-Ly/2, Ly/2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") Z = np.zeros_like(X) # ---------------------------- # Vortex profile (static "electron") # ---------------------------- # n(r,phi) = (sinθ(r) cos(m phi), sinθ(r) sin(m phi), cosθ(r)) # with θ(0)=π (down) and θ(∞)=0 (vacuum up) gives a skyrmion-like texture (topological defect). m = 1 # winding number (charge-like topological index) core = 0.65 # core size (smaller => tighter core) p = 2.0 # profile sharpness r = np.sqrt(X**2 + Y**2) + 1e-12 phi = np.arctan2(Y, X) # Smooth monotone profile: θ(0)=π, θ(∞)=0 theta = 2.0 * np.arctan((core / r) ** p) # Field n # Bloch if bloch: gamma = np.pi / 2 # +π/2 = Bloch (тангенциальный), 0 = Néel (радиальный) Phi = m * phi + gamma nx = np.sin(theta) * np.cos(Phi) ny = np.sin(theta) * np.sin(Phi) else: # Neel nx = np.sin(theta) * np.cos(m * phi) ny = np.sin(theta) * np.sin(m * phi) nz = np.cos(theta) n = np.stack([nx, ny, nz], axis=2) # Enforce unit norm (numerical safety) n /= (np.linalg.norm(n, axis=2, keepdims=True) + 1e-12) # ---------------------------- # Finite differences (open boundaries) # ---------------------------- def grad_open(f): dfdx = np.empty_like(f) dfdy = np.empty_like(f) dfdx[1:-1, :] = (f[2:, :] - f[:-2, :]) / (2 * dx) dfdx[0, :] = (f[1, :] - f[0, :]) / dx dfdx[-1, :] = (f[-1, :] - f[-2, :]) / dx dfdy[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2 * dy) dfdy[:, 0] = (f[:, 1] - f[:, 0]) / dy dfdy[:, -1] = (f[:, -1] - f[:, -2]) / dy return dfdx, dfdy # ---------------------------- # Energy density (sigma-model + simple "mass" potential) # ---------------------------- # Sigma-model static energy density: E_grad ~ (1/2) |∇n|^2 # Add a "mass" / easy-axis potential V ~ μ^2 (1 - n_z) to prefer vacuum nz=1. kappa = 1.0 mu2 = 0.8 dnx_dx, dnx_dy = grad_open(nx) dny_dx, dny_dy = grad_open(ny) dnz_dx, dnz_dy = grad_open(nz) grad2 = (dnx_dx**2 + dnx_dy**2 + dny_dx**2 + dny_dy**2 + dnz_dx**2 + dnz_dy**2) E_grad = 0.5 * kappa * grad2 V = mu2 * (1.0 - nz) # easy-axis penalty E_density = E_grad + V # ---------------------------- # "Gravitational potential" / time-dilation proxy from energy density # ---------------------------- # In your ontology: localized energy slows local time. Here we build a smooth map: # gpot = -alpha * E_density (more negative near core) # or an omega(x)=omega0/(1+alpha E) type. For plotting, keep it simple. alpha_g = 1.2 gpot = -alpha_g * E_density # Normalize for display stability gpot_disp = (gpot - np.percentile(gpot, 5)) / (np.percentile(gpot, 95) - np.percentile(gpot, 5) + 1e-12) gpot_disp = np.clip(gpot_disp, 0.0, 1.0) # ---------------------------- # "Electric potential" and E-field (blue) # ---------------------------- # Reduced-model choice: scalar potential Φ proportional to deviation from vacuum along the light axis. # Φ = (1 - n_z) is zero in vacuum and peaks at the core. Then E = -∇Φ gives a radial field. Phi = (1.0 - nz) dPhi_dx, dPhi_dy = grad_open(Phi) Ex = -dPhi_dx Ey = -dPhi_dy # ---------------------------- # Optional: O(3) proxy of Maurer–Cartan spatial current J_i = n × ∂_i n # ---------------------------- SHOW_MC_CURRENT = False if SHOW_MC_CURRENT: dn_dx = np.stack([dnx_dx, dny_dx, dnz_dx], axis=2) dn_dy = np.stack([dnx_dy, dny_dy, dnz_dy], axis=2) Jx = np.cross(n, dn_dx) # 3-vector at each point Jy = np.cross(n, dn_dy) # 3-vector at each point # If you want to draw it, pick a component or a combination (e.g. along z), or draw in-plane vectors. # ---------------------------- # Visualization settings # ---------------------------- # Subsampling for arrows (quiver) q_step_n = 7 q_step_E = 7 XsN = X[::q_step_n, ::q_step_n] YsN = Y[::q_step_n, ::q_step_n] ZsN = Z[::q_step_n, ::q_step_n] nS = n[::q_step_n, ::q_step_n, :] XsE = X[::q_step_E, ::q_step_E] YsE = Y[::q_step_E, ::q_step_E] ZsE = Z[::q_step_E, ::q_step_E] ExS = Ex[::q_step_E, ::q_step_E] EyS = Ey[::q_step_E, ::q_step_E] # Scale E arrows to be readable but not insane Emag = np.sqrt(ExS**2 + EyS**2) + 1e-12 E95 = np.percentile(Emag, 95) + 1e-12 ExD = np.clip(ExS / E95, -1.0, 1.0) EyD = np.clip(EyS / E95, -1.0, 1.0) LEN_N = 0.65 LEN_E = 0.75 # ---------------------------- # Plot # ---------------------------- fig = plt.figure(figsize=(11, 8)) ax = fig.add_subplot(111, projection="3d") ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z (normal)") ax.set_title("Static electron vortex (2+1D): n-field (red), E-field (blue), grav. potential (plane)") # Plane wireframe (light) wf_step = 12 ax.plot_wireframe( X[::wf_step, ::wf_step], Y[::wf_step, ::wf_step], Z[::wf_step, ::wf_step], linewidth=0.5, alpha=0.20 ) # Plane colormap (gravitational potential proxy) # User asked "gravitational potential" and suggested brown; use a brownish cmap. cmap = plt.cm.copper fc = cmap(gpot_disp) fc[..., 3] = 0.55 # alpha z_eps = 1e-3 ax.plot_surface( X, Y, Z + z_eps, facecolors=fc, rstride=1, cstride=1, shade=False, linewidth=0, antialiased=False ) # n arrows (red) ax.quiver( XsN, YsN, ZsN, nS[..., 0], nS[..., 1], nS[..., 2], length=LEN_N, normalize=True, color="red", linewidth=0.75 ) # E arrows (blue) in-plane ax.quiver( XsE, YsE, ZsE, ExD, EyD, np.zeros_like(ExD), length=LEN_E, normalize=False, color="blue", linewidth=0.95 ) # Optional marker at core ax.scatter([0.0], [0.0], [0.0], s=30, c="k") plt.tight_layout() plt.show()
А теперь, немного усложним задачу.
Спин и магнитный момент как внутренняя фазовая динамика
Очевидно, что внутренняя структура электронного вихря не является статичной. Фазовая конфигурация испытывает непрерывную внутреннюю прецессию, управляемую той же динамикой, которая задаёт фазовый поток вакуума. Это внутреннее фазовое вращение проявляется как спин частицы. Связанная с ним циркуляция фазового поля порождает эффективный магнитный дипольный момент. В отличие от классической модели вращающейся заряженной сферы, этот магнитный момент возникает не из механического движения вещества, а из внутренней фазовой геометрии. Таким образом, магнитное поле электрона является прямым следствием его внутренней фазовой динамики.

Код скрипта под катом
Скрытый текст
""" Spinning electron-vortex (2+1D) visualized in 3D over a plane ============================================================ What this animation shows (concept demo, consistent with our 2+1D reduction): • A static topological vortex n(x,y) ∈ S² ("electron") on a 2D patch, drawn as RED arrows. • The vortex core then starts an *internal twist / precession* (spin-analogue) and this generates a pseudoscalar magnetic field Bz (out-of-plane), drawn as a CYAN heatmap: - darker cyan : Bz > 0 - light cyan : Bz < 0 • You can switch between Néel-like (radial) and Bloch-like (tangential) vortex via BLOCH. Important physics/ontology notes (no hand-waving): • In 2+1D, magnetic field is naturally a pseudoscalar Bz (single component). • A *global* rigid rotation Phi -> Phi + const(t) would NOT change ∇Phi and would NOT generate a field (pure gauge-like). To get a real “spin core”, we twist only near the core: Phi(x,y,t) = m*atan2(y,x) + gamma0 + delta(t)*g(r) where g(r) localizes the twist. This creates time-dependent spatial gradients and produces a nontrivial Bz from the geometric U(1) connection. Field construction (S² toy model): • n = (sinθ cosPhi, sinθ sinPhi, cosθ) with θ(r) going from π at core to 0 at infinity. • Define a geometric U(1) connection on S²: A = (1 - cosθ) ∇Phi then Bz = (∇×A)_z = ∂x Ay - ∂y Ax This is the same "Berry/connection curvature" construction we used for the photon demo. Dependencies: numpy, matplotlib Run: python spinning_vortex_bz_anim.py """ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # ---------------------------- # View controls FIRST (as requested) # ---------------------------- VIEW_ELEV = 90 VIEW_AZIM = -55 # ---------------------------- # Switches / main knobs # ---------------------------- BLOCH = True # True: Bloch (tangential), False: Néel (radial) SHOW_E = False # optional: compute/draw E from a0 and A(t) (not needed for this demo) # Vortex / core profile m = 1 # winding (topological index) core = 0.65 # core size p = 2.0 # profile sharpness # "Spin" (internal twist) parameters OMEGA0 = 2.2 # max angular speed of the core twist (in animation time units) t_ramp = 1.2 # how long to ramp up spin (smooth start) r_spin = 1.4 # radius scale of the spinning core region (localization) # Domain Nx, Ny = 140, 140 Lx, Ly = 14.0, 14.0 dx, dy = Lx / Nx, Ly / Ny # Animation dt = 0.03 # animation time step (not PDE time; we're animating a prescribed texture) nframes = 420 interval_ms = 33 # ~30 fps repeat_anim = True # Rendering density q_step_n = 7 LEN_N = 0.65 # Plane rendering wf_step = 12 B_ALPHA_MAX = 0.55 z_eps = 1e-3 # ---------------------------- # Grid # ---------------------------- x = np.linspace(-Lx/2, Lx/2, Nx, endpoint=False) y = np.linspace(-Ly/2, Ly/2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") Z = np.zeros_like(X) r = np.sqrt(X**2 + Y**2) + 1e-12 phi = np.arctan2(Y, X) # vortex helicity gamma0 = (np.pi/2) if BLOCH else 0.0 # ---------------------------- # Finite differences (open) # ---------------------------- def grad_open(f): dfdx = np.empty_like(f) dfdy = np.empty_like(f) dfdx[1:-1, :] = (f[2:, :] - f[:-2, :]) / (2*dx) dfdx[0, :] = (f[1, :] - f[0, :]) / dx dfdx[-1, :] = (f[-1, :] - f[-2, :]) / dx dfdy[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2*dy) dfdy[:, 0] = (f[:, 1] - f[:, 0]) / dy dfdy[:, -1] = (f[:, -1] - f[:, -2]) / dy return dfdx, dfdy # ---------------------------- # Vortex profile θ(r) # ---------------------------- theta = 2.0 * np.arctan((core / r) ** p) sinth = np.sin(theta) costh = np.cos(theta) # core localization for spin twist g_spin = np.exp(-(r**2) / (2.0 * r_spin**2)) # ---------------------------- # Time-dependent "spin" twist delta(t) # ---------------------------- def smooth_ramp(t, t0): # smooth ramp 0->1 over timescale t0 if t <= 0: return 0.0 if t >= t0: return 1.0 s = t / t0 # smoothstep return s*s*(3 - 2*s) def delta_of_t(t): # twist angle delta(t) = ∫ Ω(t) dt; Ω ramps up smoothly to OMEGA0 # We'll use delta(t) = OMEGA0 * t * ramp(t), which is good enough visually. return OMEGA0 * t * smooth_ramp(t, t_ramp) def omega_of_t(t): return OMEGA0 * smooth_ramp(t, t_ramp) # ---------------------------- # Compute n(x,y,t), A, Bz # ---------------------------- def compute_fields(t): # Internal twist localized in the core delta = delta_of_t(t) # IMPORTANT: spatially localized twist => real gradients change with time Phi = m * phi + gamma0 + delta * g_spin nx = sinth * np.cos(Phi) ny = sinth * np.sin(Phi) nz = costh # U(1) connection A = (1 - cosθ) ∇Phi #dPhi_dx, dPhi_dy = grad_open(Phi) #fac = (1.0 - nz) #Ax = fac * dPhi_dx #Ay = fac * dPhi_dy # --- stable phase-derivatives: NO atan2 / NO unwrap --- dnx_dx, dnx_dy = grad_open(nx) dny_dx, dny_dy = grad_open(ny) den = nx*nx + ny*ny + 1e-12 # epsilon avoids 0/0 near vacuum/core dPhi_dx = (nx * dny_dx - ny * dnx_dx) / den dPhi_dy = (nx * dny_dy - ny * dnx_dy) / den fac = (1.0 - nz) Ax = fac * dPhi_dx Ay = fac * dPhi_dy # Bz = curl A (pseudoscalar in 2D) dAy_dx, _ = grad_open(Ay) _, dAx_dy = grad_open(Ax) Bz = dAy_dx - dAx_dy return nx, ny, nz, Bz # ---------------------------- # Cyan diverging plane colors for Bz # ---------------------------- def cyan_diverging_facecolors(Bz): """ Map Bz to RGBA without relying on fragile 3D transparency sorting: Bz>0 -> stronger cyan Bz<0 -> light cyan """ # robust scale to avoid flicker s = np.percentile(np.abs(Bz), 95) + 1e-12 b = np.clip(Bz / s, -1.0, 1.0) # base RGB for positive and negative # pos: (0, 1, 1) neg: (0.70, 1, 1) (lighter cyan) fc = np.zeros((Nx, Ny, 4), dtype=float) # positive pos = b > 0 fc[pos, 0] = 0.00 fc[pos, 1] = 1.00 fc[pos, 2] = 1.00 fc[pos, 3] = B_ALPHA_MAX * b[pos] # negative neg = b < 0 fc[neg, 0] = 0.70 fc[neg, 1] = 1.00 fc[neg, 2] = 1.00 fc[neg, 3] = B_ALPHA_MAX * (-b[neg]) # near zero: transparent return fc # ---------------------------- # Figure # ---------------------------- fig = plt.figure(figsize=(11, 8)) ax = fig.add_subplot(111, projection="3d") def draw_scene(t): nx, ny, nz, Bz = compute_fields(t) ax.cla() ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z (normal)") mode = "Bloch (tangential)" if BLOCH else "Néel (radial)" ax.set_title( f"Static vortex → spinning core (2+1D) | {mode}\n" f"t={t:5.2f}, Ω(t)={omega_of_t(t):.2f} | n: red arrows | Bz: cyan heatmap", pad=18 ) # plane wireframe ax.plot_wireframe( X[::wf_step, ::wf_step], Y[::wf_step, ::wf_step], Z[::wf_step, ::wf_step], linewidth=0.5, alpha=0.20 ) # Bz heatmap (single surface; avoids z-fighting artifacts) fc = cyan_diverging_facecolors(Bz) ax.plot_surface( X, Y, Z + z_eps, facecolors=fc, rstride=1, cstride=1, shade=False, linewidth=0, antialiased=False ) # n arrows (subsample) Xs = X[::q_step_n, ::q_step_n] Ys = Y[::q_step_n, ::q_step_n] Zs = Z[::q_step_n, ::q_step_n] nxs = nx[::q_step_n, ::q_step_n] nys = ny[::q_step_n, ::q_step_n] nzs = nz[::q_step_n, ::q_step_n] ax.quiver( Xs, Ys, Zs, nxs, nys, nzs, length=LEN_N, normalize=True, color="red", linewidth=0.75 ) # core marker ax.scatter([0.0], [0.0], [0.0], s=30, c="k") return [] def update(frame): t = frame * dt return draw_scene(t) anim = FuncAnimation(fig, update, frames=nframes, interval=interval_ms, blit=False, repeat=repeat_anim) plt.tight_layout() plt.show()
То-есть, возвращаясь к фотону — градиент фазовой энергии рождал векторное электрическое поле, ротор этого поля рождал магнитное поле. Здесь, градиент кривизны фазы рождает то-же электрическое поле, ротор этого электрического поля рождает магнитное. Заметьте — в центре вихря магнитное поле имеет один знак, а на его периферии другой.
А что если мы попробуем подвигать электрон?
Когда весь фазовый вихрь перемещается в пространстве, внутренние фазовые токи становятся пространственно несимметричными. Это приводит к появлению дополнительных эффективных магнитных полей, что согласуется с релятивистской связью между электрическими и магнитными компонентами. В рамках этой модели магнитные поля не являются фундаментальными сущностями, а представляют собой проявления движущихся или вращающихся фазовых структур.

Код анимации под катом
Скрытый текст
""" Moving + spinning electron vortex (2+1D) in 3D isometric view ============================================================= This is a publishable, heavily commented demo script. We work in 2+1D (x,y,t), but visualize the phase vector field n(x,y,t) ∈ S² in 3D. What is shown: • Red arrows: phase orientation n(x,y,t) (the "phase vector" on S²). • Blue arrows: electric-like field E(x,y,t), computed from the same geometric connection. • Plane color: magnetic pseudoscalar Bz (2+1D "magnetic field"), shown with sign: Bz > 0 -> darker blue (more positive) Bz < 0 -> lighter cyan (more negative) The plane is tinted light-brown for contrast (so “white” is not mistaken for zero). Physics choices (consistent with our reduced model): • Static vortex texture: n = (sinθ cosΦ, sinθ sinΦ, cosθ), θ(r): π at the core -> 0 in vacuum (easy-axis vacuum is +z). • "Spin" (internal dynamics) = localized twist of phase near the core: Φ = m*phi + gamma0 + delta(t) g_spin(r), with g_spin localized around r=0. IMPORTANT: a global rotation Φ->Φ+const(t) is a gauge-like trivial change and would not generate meaningful spatial fields. We twist the CORE only. • Geometric U(1) connection on S² (Berry-like): A = (1 - cosθ) ∇Φ a0 = (1 - cosθ) ∂tΦ Then define (2+1D EM analogue): E = -∂t A - ∇a0 Bz_spin = (∇×A)_z • Motion contribution (kinematic mixing, for visualization / sanity): Bz_move ≈ (v × E)_z = vx*Ey - vy*Ex In this demo we superpose: Bz_total = B_spin_gain * Bz_spin + B_move_gain * Bz_move Switches: • BLOCH = True/False (Bloch tangential vs Néel radial vortex). • SHOW_B_SPIN / SHOW_B_MOVE • Gains B_spin_gain / B_move_gain Dependencies: numpy, matplotlib Run: python moving_spinning_vortex_3d_full.py """ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # ============================================================================= # 0) VIEW CONTROLS (FIRST, as requested) # ============================================================================= VIEW_ELEV = 90 VIEW_AZIM = -55 # ============================================================================= # 1) MAIN SWITCHES / PARAMS (put here so users can "poke" the model) # ============================================================================= BLOCH = True # True: Bloch (tangential), False: Néel (radial) # Show which contributions to B we include SHOW_B_SPIN = True SHOW_B_MOVE = True # Relative weights for the two contributions B_spin_gain = 1.0 B_move_gain = 1.0 # Base plane tint (light-brown) so that "white" does not look like background truth BASE_PLANE_COLOR = (0.80, 0.68, 0.55, 0.70) # RGBA # Vortex parameters m = 1 core = 0.65 p = 2.0 # Internal twist ("spin") parameters OMEGA0 = 2.0 # max core twist angular speed (animation time units) t_ramp = 1.2 # smooth start duration r_spin = 1.4 # core twist localization radius # Translation path (left -> right) Lx, Ly = 14.0, 14.0 x0_start = -0.75 * Lx x0_end = +0.75 * Lx y0 = 0.0 # Grid Nx, Ny = 160, 160 dx, dy = Lx / Nx, Ly / Ny # Animation dt = 0.03 frames = 420 interval_ms = 33 repeat_anim = True # Drawing density q_step_n = 7 q_step_E = 10 LEN_N = 0.65 LEN_E = 0.80 # Plane wireframe and overlay tuning wf_step = 12 z_eps = 1e-3 E_clip_pct = 95 B_clip_pct = 95 B_ALPHA_MAX = 0.85 # ============================================================================= # 2) GRID # ============================================================================= x = np.linspace(-Lx/2, Lx/2, Nx, endpoint=False) y = np.linspace(-Ly/2, Ly/2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") Z0 = np.zeros_like(X) # Subsample coordinates for quivers XsN = X[::q_step_n, ::q_step_n] YsN = Y[::q_step_n, ::q_step_n] ZsN = Z0[::q_step_n, ::q_step_n] XsE = X[::q_step_E, ::q_step_E] YsE = Y[::q_step_E, ::q_step_E] ZsE = Z0[::q_step_E, ::q_step_E] # ============================================================================= # 3) NUMERICAL UTILITIES # ============================================================================= def smoothstep(s: float) -> float: s = np.clip(s, 0.0, 1.0) return s*s*(3 - 2*s) def ramp01(t: float, t0: float) -> float: """Smooth ramp 0->1 during [0, t0].""" if t <= 0: return 0.0 if t >= t0: return 1.0 s = t / t0 return s*s*(3 - 2*s) def omega_of_t(t: float) -> float: return OMEGA0 * ramp01(t, t_ramp) def delta_of_t(t: float) -> float: # For visualization: delta(t) ≈ ∫Ω(t)dt ~ Ω0 * t * ramp(t) return OMEGA0 * t * ramp01(t, t_ramp) def x0_of_t(t: float) -> float: """Move x0 from start to end smoothly across the full animation duration.""" Ttot = frames * dt s = smoothstep(t / Ttot) return x0_start + (x0_end - x0_start) * s def grad_open(f: np.ndarray): """Open-boundary finite differences (no periodic wrap).""" dfdx = np.empty_like(f) dfdy = np.empty_like(f) dfdx[1:-1, :] = (f[2:, :] - f[:-2, :]) / (2*dx) dfdx[0, :] = (f[1, :] - f[0, :]) / dx dfdx[-1, :] = (f[-1, :] - f[-2, :]) / dx dfdy[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2*dy) dfdy[:, 0] = (f[:, 1] - f[:, 0]) / dy dfdy[:, -1] = (f[:, -1] - f[:, -2]) / dy return dfdx, dfdy # ============================================================================= # 4) VORTEX FIELD n(x,y,t) # ============================================================================= gamma0 = (np.pi/2) if BLOCH else 0.0 def build_n_fields(t: float): """ Construct n(x,y,t) for a moving vortex with localized core twist. Returns (nx, ny, nz, theta, g_spin). """ x0 = x0_of_t(t) # Coordinates in the vortex frame Xr = X - x0 Yr = Y - y0 r = np.sqrt(Xr*Xr + Yr*Yr) + 1e-12 phi = np.arctan2(Yr, Xr) # Radial profile θ(r): π at core -> 0 at infinity theta = 2.0 * np.arctan((core / r) ** p) sinth = np.sin(theta) costh = np.cos(theta) # Localized twist (spin analogue) g_spin = np.exp(-(r*r) / (2.0 * r_spin*r_spin)) Phi = m * phi + gamma0 + delta_of_t(t) * g_spin # n on S² nx = sinth * np.cos(Phi) ny = sinth * np.sin(Phi) nz = costh # Normalize (safety) inv = 1.0 / (np.sqrt(nx*nx + ny*ny + nz*nz) + 1e-12) nx *= inv; ny *= inv; nz *= inv return nx, ny, nz, theta, g_spin # ============================================================================= # 5) GEOMETRIC CONNECTION -> A, a0, E, Bz # ============================================================================= def phase_derivatives_from_n(nx, ny): """ Stable derivatives of phase Φ without atan2 unwrap / branch cuts. ∂i Φ = (nx ∂i ny - ny ∂i nx)/(nx^2+ny^2) """ dnx_dx, dnx_dy = grad_open(nx) dny_dx, dny_dy = grad_open(ny) den = nx*nx + ny*ny + 1e-12 dPhi_dx = (nx * dny_dx - ny * dnx_dx) / den dPhi_dy = (nx * dny_dy - ny * dnx_dy) / den return dPhi_dx, dPhi_dy def phi_time_derivative_from_n(nx, ny, nx_prev, ny_prev): """ Stable time derivative ∂tΦ via: ∂t Φ ≈ (nx ∂t ny - ny ∂t nx)/(nx^2+ny^2) """ den = nx*nx + ny*ny + 1e-12 dnx_dt = (nx - nx_prev) / dt dny_dt = (ny - ny_prev) / dt dPhi_dt = (nx * dny_dt - ny * dnx_dt) / den return dPhi_dt def compute_fields_from_connection( t, nx, ny, nz, nx_prev, ny_prev, nz_prev ): """ Compute: A = (1-cosθ)∇Φ with (1-cosθ)=(1-nz) a0 = (1-nz)∂tΦ E = -∂tA - ∇a0 Bz_spin = curl A """ # Spatial derivatives of Φ (stable, no atan2) dPhi_dx, dPhi_dy = phase_derivatives_from_n(nx, ny) fac = (1.0 - nz) Ax = fac * dPhi_dx Ay = fac * dPhi_dy # Spin magnetic field: curl A dAy_dx, _ = grad_open(Ay) _, dAx_dy = grad_open(Ax) Bz_spin = dAy_dx - dAx_dy # Temporal derivative ∂tΦ (stable) dPhi_dt = phi_time_derivative_from_n(nx, ny, nx_prev, ny_prev) a0 = fac * dPhi_dt # Build A at previous frame for ∂tA dPhi_p_dx, dPhi_p_dy = phase_derivatives_from_n(nx_prev, ny_prev) fac_p = (1.0 - nz_prev) Ax_p = fac_p * dPhi_p_dx Ay_p = fac_p * dPhi_p_dy dAx_dt = (Ax - Ax_p) / dt dAy_dt = (Ay - Ay_p) / dt da0_dx, da0_dy = grad_open(a0) Ex = -dAx_dt - da0_dx Ey = -dAy_dt - da0_dy return Ex, Ey, Bz_spin # ============================================================================= # 6) COLORING: asymmetric Bz overlay on tinted plane # ============================================================================= def bz_facecolors_asymmetric(B, base_rgba, clip_pct=95, alpha_max=0.85): """ Plane facecolors where sign of B is encoded by two different "blue" ramps: B > 0 : white -> darker blue B < 0 : white -> light cyan Base plane is tinted (brown) to avoid "white means background". Note: In matplotlib 3D, per-face alpha is imperfect; we keep it simple but readable. """ # Robust scale avoids flicker s = np.percentile(np.abs(B), clip_pct) + 1e-12 b = np.clip(B / s, -1.0, 1.0) fc = np.zeros((Nx, Ny, 4), dtype=float) fc[..., 0] = base_rgba[0] fc[..., 1] = base_rgba[1] fc[..., 2] = base_rgba[2] fc[..., 3] = base_rgba[3] a = alpha_max * np.abs(b) # Positive ramp -> darker blue pos = b > 0 if np.any(pos): target = np.array([0.00, 0.50, 0.95]) # dark-ish blue white = np.array([1.00, 1.00, 1.00]) w = np.abs(b[pos]) # need proper broadcasting rgb = white*(1 - w[..., None]) + target*(w[..., None]) fc[pos, 0] = rgb[..., 0] fc[pos, 1] = rgb[..., 1] fc[pos, 2] = rgb[..., 2] fc[pos, 3] = np.maximum(fc[pos, 3], a[pos]) # Negative ramp -> light cyan neg = b < 0 if np.any(neg): target = np.array([0.55, 0.90, 1.00]) # light cyan white = np.array([1.00, 1.00, 1.00]) w = np.abs(b[neg]) rgb = white*(1 - w[..., None]) + target*(w[..., None]) fc[neg, 0] = rgb[..., 0] fc[neg, 1] = rgb[..., 1] fc[neg, 2] = rgb[..., 2] fc[neg, 3] = np.maximum(fc[neg, 3], a[neg]) return fc # ============================================================================= # 7) ANIMATION SETUP # ============================================================================= fig = plt.figure(figsize=(11, 8)) ax = fig.add_subplot(111, projection="3d") # Seed previous fields for time-derivatives t_init = 0.0 nx_prev, ny_prev, nz_prev, _, _ = build_n_fields(t_init) def draw_frame(t: float): global nx_prev, ny_prev, nz_prev # Current n-field nx, ny, nz, _, _ = build_n_fields(t) # Fields from connection Ex, Ey, Bz_spin = compute_fields_from_connection( t, nx, ny, nz, nx_prev, ny_prev, nz_prev ) # Update prev for next frame nx_prev, ny_prev, nz_prev = nx, ny, nz # "Motion" magnetic contribution: B_move ≈ (v × E)_z # Estimate instantaneous velocity vx from x0(t) x_now = x0_of_t(t) x_prev = x0_of_t(max(t - dt, 0.0)) vx = (x_now - x_prev) / dt vy = 0.0 Bz_move = vx * Ey - vy * Ex # Superposition B_total = np.zeros_like(Bz_spin) if SHOW_B_SPIN: B_total += B_spin_gain * Bz_spin if SHOW_B_MOVE: B_total += B_move_gain * Bz_move # ---- PLOT ---- ax.cla() ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z") mode = "Bloch" if BLOCH else "Néel" title_lines = [ f"Moving + spinning vortex (2+1D) | {mode}", f"t={t:5.2f} x0(t)={x_now:+.2f} vx≈{vx:+.2f} Ω(t)={omega_of_t(t):.2f}", f"B = {('spin' if SHOW_B_SPIN else '')}{(' + ' if (SHOW_B_SPIN and SHOW_B_MOVE) else '')}{('move' if SHOW_B_MOVE else '')} " f"(gains: {B_spin_gain:.2f}, {B_move_gain:.2f})", "n: red arrows E: blue arrows Bz (pos/neg): plane colors" ] ax.set_title("\n".join(title_lines), pad=18) # Plane wireframe ax.plot_wireframe( X[::wf_step, ::wf_step], Y[::wf_step, ::wf_step], Z0[::wf_step, ::wf_step], linewidth=0.5, alpha=0.20 ) # Bz overlay (asymmetric blue ramps on brown base) fc = bz_facecolors_asymmetric(B_total, BASE_PLANE_COLOR, clip_pct=B_clip_pct, alpha_max=B_ALPHA_MAX) ax.plot_surface( X, Y, Z0 + z_eps, facecolors=fc, rstride=1, cstride=1, shade=False, linewidth=0, antialiased=False ) # Red arrows: n nxs = nx[::q_step_n, ::q_step_n] nys = ny[::q_step_n, ::q_step_n] nzs = nz[::q_step_n, ::q_step_n] ax.quiver( XsN, YsN, ZsN, nxs, nys, nzs, length=LEN_N, normalize=True, color="red", linewidth=0.75 ) # Blue arrows: E (in-plane), clipped for readability ExS = Ex[::q_step_E, ::q_step_E] EyS = Ey[::q_step_E, ::q_step_E] Em = np.sqrt(ExS*ExS + EyS*EyS) + 1e-12 sE = np.percentile(Em, E_clip_pct) + 1e-12 ExD = np.clip(ExS / sE, -1.0, 1.0) EyD = np.clip(EyS / sE, -1.0, 1.0) ax.quiver( XsE, YsE, ZsE, ExD, EyD, np.zeros_like(ExD), length=LEN_E, normalize=False, color="blue", linewidth=0.95, alpha=0.95 ) # Core marker ax.scatter([x_now], [0.0], [0.0], s=35, c="k") return [] def update(frame: int): t = frame * dt return draw_frame(t) anim = FuncAnimation( fig, update, frames=frames, interval=interval_ms, blit=False, repeat=repeat_anim ) plt.tight_layout() plt.show()
Таким образом, различные проявления фазовой динамики, которые являются тем, что мы привыкли измерять, как гравитационное, электрическое, магнитное поля — в данной модели являются следствием динамики единственной сущности. Фазовые вихри действительно будут взаимодействовать точно так же, как мы привыкли это наблюдать. Однако, заметьте — поскольку все поля являются порождением динамической фазовой структуры (производными проекциями), то эти поля не влияют на сам электрон. Помните, у Ландау — проблема самодействия движущегося электрона и искусственное ограничение на то, чтобы собственные поля выкидывать из расчётов? Здесь нет необходимости в таком ограничении.
А если мы его подвигаем ну очень быстро?
Поскольку физическое время определяется фазовой эволюцией, любое изменение фазовой динамики автоматически приводит к релятивистским эффектам. Замедление времени и лоренцево сокращение длины возникают не из кинематических постулатов, а из внутренней геометрии самого фазового поля. В следующей визуализации показано, как лоренцево сокращение и замедление времени естественным образом проявляются при движении фазовых структур через вакуум.
(упрощение: мы не решаем полевую задачу для движущегося солитона, а строим кинематическую модель: переносим вихрь, вводим лоренцеву деформацию и смотрим, как при этом смешиваются эффективные поля)

Код анимации под катом
Скрытый текст
""" Moving + spinning vortex with Lorentz contraction & time dilation (2+1D) in 3D view ================================================================================== We are in a reduced 2+1D demo: space is (x,y), field is n(x,y,t) ∈ S². We show: • Red arrows: n(x,y,t) • Blue arrows: E(x,y,t) from the geometric connection • Plane colors: Bz_total = B_spin + B_move with sign-coded blue ramps on a brown plane NEW in this version: • Lorentz-like kinematics for a moving vortex: - length contraction along the direction of motion (x) - time dilation for internal rotation ("spin rate") In a strict 3+1D theory this would be derived; here we implement the *conceptual mechanism*: - Spatial contraction: replace r² = (x-x0)² + (y-y0)² by r² = (γ (x-x0))² + (y-y0)² - Time dilation for internal twist: use proper time τ: dτ = dt / γ delta(t) = ∫ Ω(τ) dτ => effectively Ω_lab = Ω0 / γ Switches: LORENTZ = True/False BLOCH = True/False SHOW_B_SPIN / SHOW_B_MOVE Gains B_spin_gain / B_move_gain Dependencies: numpy, matplotlib """ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # ============================================================================= # 0) VIEW CONTROLS (FIRST) # ============================================================================= VIEW_ELEV = 90 VIEW_AZIM = -55 # ============================================================================= # 1) MAIN SWITCHES / PARAMS # ============================================================================= BLOCH = True # NEW: Lorentz kinematics switches LORENTZ = True C_LIGHT = 1.0 # "c" in our units; keep 1.0 # Show which contributions to B we include SHOW_B_SPIN = True SHOW_B_MOVE = True # Relative weights for the two contributions B_spin_gain = 1.0 B_move_gain = 1.0 # Base plane tint (light-brown) so white isn't "background truth" BASE_PLANE_COLOR = (0.80, 0.68, 0.55, 0.70) # RGBA # Vortex parameters m = 1 core = 0.65 p = 2.0 # Internal twist ("spin") parameters OMEGA0 = 2.0 # max internal angular speed in proper time (conceptually) t_ramp = 1.2 # smooth start duration r_spin = 1.4 # localization radius for core twist # Translation path (left -> right) Lx, Ly = 14.0, 14.0 #x0_start = -0.75 * Lx x0_start = 0 #x0_end = +0.75 * Lx x0_end = +Lx/2 * Lx y0 = 0.0 vx_max = 0.6 # желаемый максимум (<1) # Почти классика - 0.3 # Видимое Лоренц-сжатие 0.5 # Ультрарелятивистский “блин” 0.8–0.9 # Grid Nx, Ny = 160, 160 #Nx, Ny = 220, 220 dx, dy = Lx / Nx, Ly / Ny # Animation dt = 0.03 frames = 420 interval_ms = 33 repeat_anim = True # Drawing density q_step_n = 7 q_step_E = 10 LEN_N = 0.65 LEN_E = 0.80 # Plane wireframe and overlay tuning wf_step = 12 z_eps = 1e-3 E_clip_pct = 95 B_clip_pct = 95 B_ALPHA_MAX = 0.85 # ============================================================================= # 2) GRID # ============================================================================= x = np.linspace(-Lx/2, Lx/2, Nx, endpoint=False) y = np.linspace(-Ly/2, Ly/2, Ny, endpoint=False) X, Y = np.meshgrid(x, y, indexing="ij") Z0 = np.zeros_like(X) # Subsample coords for quivers XsN = X[::q_step_n, ::q_step_n] YsN = Y[::q_step_n, ::q_step_n] ZsN = Z0[::q_step_n, ::q_step_n] XsE = X[::q_step_E, ::q_step_E] YsE = Y[::q_step_E, ::q_step_E] ZsE = Z0[::q_step_E, ::q_step_E] # ============================================================================= # 3) NUMERICAL UTILITIES # ============================================================================= def smoothstep(s: float) -> float: s = np.clip(s, 0.0, 1.0) return s*s*(3 - 2*s) def ramp01(t: float, t0: float) -> float: if t <= 0: return 0.0 if t >= t0: return 1.0 s = t / t0 return s*s*(3 - 2*s) #def x0_of_t(t: float) -> float: # Ttot = frames * dt # s = smoothstep(t / Ttot) # return x0_start + (x0_end - x0_start) * s def x0_of_t(t): Ttot = frames * dt s = smoothstep(t / Ttot) return x0_start + vx_max * Ttot * s def grad_open(f: np.ndarray): dfdx = np.empty_like(f) dfdy = np.empty_like(f) dfdx[1:-1, :] = (f[2:, :] - f[:-2, :]) / (2*dx) dfdx[0, :] = (f[1, :] - f[0, :]) / dx dfdx[-1, :] = (f[-1, :] - f[-2, :]) / dx dfdy[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2*dy) dfdy[:, 0] = (f[:, 1] - f[:, 0]) / dy dfdy[:, -1] = (f[:, -1] - f[:, -2]) / dy return dfdx, dfdy def safe_gamma(vx: float, vy: float = 0.0): v2 = vx*vx + vy*vy # clamp to avoid blow-up if user puts vx>=c v2 = min(v2, 0.9999 * C_LIGHT*C_LIGHT) return 1.0 / np.sqrt(1.0 - v2/(C_LIGHT*C_LIGHT)) # ============================================================================= # 4) TIME: proper time accumulator for time dilation # ============================================================================= # We integrate proper time τ(t) = ∫ dt / γ(t) tau = 0.0 def omega_proper(t: float) -> float: # internal spin speed defined in *proper time* return OMEGA0 * ramp01(t, t_ramp) # ============================================================================= # 5) VORTEX FIELD n(x,y,t) # ============================================================================= gamma0 = (np.pi/2) if BLOCH else 0.0 def build_n_fields(t: float, vx: float, vy: float, delta_angle: float): """ Construct n(x,y,t) for a moving vortex with localized core twist. If LORENTZ is True, apply length contraction along x by γ. delta_angle is the internal twist phase (already time-dilated via τ). """ x0 = x0_of_t(t) # coords relative to moving core Xr = X - x0 Yr = Y - y0 # Lorentz contraction along direction of motion (x) if LORENTZ: gam = safe_gamma(vx, vy) Xr_eff = gam * Xr # contracted shape in lab frame => field varies faster in x else: gam = 1.0 Xr_eff = Xr r = np.sqrt(Xr_eff*Xr_eff + Yr*Yr) + 1e-12 phi = np.arctan2(Yr, Xr_eff) # angle in the deformed core coordinates # radial profile θ(r): π at core -> 0 at infinity theta = 2.0 * np.arctan((core / r) ** p) sinth = np.sin(theta) costh = np.cos(theta) # localized twist profile g_spin = np.exp(-(r*r) / (2.0 * r_spin*r_spin)) # Phase Phi = m * phi + gamma0 + delta_angle * g_spin nx = sinth * np.cos(Phi) ny = sinth * np.sin(Phi) nz = costh inv = 1.0 / (np.sqrt(nx*nx + ny*ny + nz*nz) + 1e-12) nx *= inv; ny *= inv; nz *= inv return nx, ny, nz # ============================================================================= # 6) GEOMETRIC CONNECTION -> E, B # ============================================================================= def phase_derivatives_from_n(nx, ny): """∂iΦ = (nx ∂i ny - ny ∂i nx)/(nx^2+ny^2) (stable, no atan2 unwrap).""" dnx_dx, dnx_dy = grad_open(nx) dny_dx, dny_dy = grad_open(ny) den = nx*nx + ny*ny + 1e-12 dPhi_dx = (nx * dny_dx - ny * dnx_dx) / den dPhi_dy = (nx * dny_dy - ny * dnx_dy) / den return dPhi_dx, dPhi_dy def phi_time_derivative_from_n(nx, ny, nx_prev, ny_prev): """∂tΦ ≈ (nx ∂t ny - ny ∂t nx)/(nx^2+ny^2).""" den = nx*nx + ny*ny + 1e-12 dnx_dt = (nx - nx_prev) / dt dny_dt = (ny - ny_prev) / dt return (nx * dny_dt - ny * dnx_dt) / den def compute_fields_from_connection(nx, ny, nz, nx_prev, ny_prev, nz_prev): """ A = (1-nz) ∇Φ a0 = (1-nz) ∂tΦ E = -∂tA - ∇a0 Bz_spin = curl A """ dPhi_dx, dPhi_dy = phase_derivatives_from_n(nx, ny) fac = (1.0 - nz) Ax = fac * dPhi_dx Ay = fac * dPhi_dy dAy_dx, _ = grad_open(Ay) _, dAx_dy = grad_open(Ax) Bz_spin = dAy_dx - dAx_dy dPhi_dt = phi_time_derivative_from_n(nx, ny, nx_prev, ny_prev) a0 = fac * dPhi_dt da0_dx, da0_dy = grad_open(a0) # A_prev for ∂tA dPhi_p_dx, dPhi_p_dy = phase_derivatives_from_n(nx_prev, ny_prev) fac_p = (1.0 - nz_prev) Ax_p = fac_p * dPhi_p_dx Ay_p = fac_p * dPhi_p_dy dAx_dt = (Ax - Ax_p) / dt dAy_dt = (Ay - Ay_p) / dt Ex = -dAx_dt - da0_dx Ey = -dAy_dt - da0_dy return Ex, Ey, Bz_spin # ============================================================================= # 7) COLORING: asymmetric Bz overlay on tinted plane # ============================================================================= def bz_facecolors_asymmetric(B, base_rgba, clip_pct=95, alpha_max=0.85): s = np.percentile(np.abs(B), clip_pct) + 1e-12 b = np.clip(B / s, -1.0, 1.0) fc = np.zeros((Nx, Ny, 4), dtype=float) fc[..., 0] = base_rgba[0] fc[..., 1] = base_rgba[1] fc[..., 2] = base_rgba[2] fc[..., 3] = base_rgba[3] a = alpha_max * np.abs(b) # positive: white -> darker blue pos = b > 0 if np.any(pos): target = np.array([0.00, 0.50, 0.95]) white = np.array([1.00, 1.00, 1.00]) w = np.abs(b[pos]) rgb = white*(1 - w[..., None]) + target*(w[..., None]) fc[pos, 0] = rgb[..., 0] fc[pos, 1] = rgb[..., 1] fc[pos, 2] = rgb[..., 2] fc[pos, 3] = np.maximum(fc[pos, 3], a[pos]) # negative: white -> light cyan neg = b < 0 if np.any(neg): target = np.array([0.55, 0.90, 1.00]) white = np.array([1.00, 1.00, 1.00]) w = np.abs(b[neg]) rgb = white*(1 - w[..., None]) + target*(w[..., None]) fc[neg, 0] = rgb[..., 0] fc[neg, 1] = rgb[..., 1] fc[neg, 2] = rgb[..., 2] fc[neg, 3] = np.maximum(fc[neg, 3], a[neg]) return fc # ============================================================================= # 8) ANIMATION # ============================================================================= fig = plt.figure(figsize=(11, 8)) ax = fig.add_subplot(111, projection="3d") # Seed previous fields t_init = 0.0 # initial vx estimate vx_init = (x0_of_t(dt) - x0_of_t(0.0)) / dt delta_init = 0.0 nx_prev, ny_prev, nz_prev = build_n_fields(t_init, vx_init, 0.0, delta_init) def update(frame: int): global nx_prev, ny_prev, nz_prev, tau t = frame * dt # velocity estimate from x0(t) x_now = x0_of_t(t) x_prev = x0_of_t(max(t - dt, 0.0)) vx = (x_now - x_prev) / dt vy = 0.0 gam = safe_gamma(vx, vy) # Proper time integration for time dilation: dτ = dt/γ if LORENTZ: tau += dt / gam delta_angle = omega_proper(tau) * tau # rough but monotone; good for demo else: tau += dt delta_angle = omega_proper(t) * t # Build field nx, ny, nz = build_n_fields(t, vx, vy, delta_angle) # Fields from connection Ex, Ey, Bz_spin = compute_fields_from_connection(nx, ny, nz, nx_prev, ny_prev, nz_prev) # Update prev nx_prev, ny_prev, nz_prev = nx, ny, nz # Motion contribution: B_move ≈ (v × E)_z Bz_move = vx * Ey - vy * Ex # Superposed magnetic field B_total = np.zeros_like(Bz_spin) if SHOW_B_SPIN: B_total += B_spin_gain * Bz_spin if SHOW_B_MOVE: B_total += B_move_gain * Bz_move # ---- Draw ---- ax.cla() ax.view_init(elev=VIEW_ELEV, azim=VIEW_AZIM) ax.set_xlim(-Lx/2, Lx/2) ax.set_ylim(-Ly/2, Ly/2) ax.set_zlim(-1.1, 2.0) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z") mode = "Bloch" if BLOCH else "Néel" lor = "ON" if LORENTZ else "OFF" ax.set_title( f"Moving + spinning vortex (2+1D) | {mode} | Lorentz={lor}\n" f"t={t:5.2f} τ={tau:5.2f} x0={x_now:+.2f} vx≈{vx:+.2f} γ≈{gam:.3f} Ω_lab≈{omega_proper(tau)/gam if LORENTZ else omega_proper(t):.2f}\n" f"n: red E: blue Bz: plane colors (B = spin + move)", pad=18 ) # Wireframe ax.plot_wireframe( X[::wf_step, ::wf_step], Y[::wf_step, ::wf_step], Z0[::wf_step, ::wf_step], linewidth=0.5, alpha=0.20 ) # B overlay fc = bz_facecolors_asymmetric(B_total, BASE_PLANE_COLOR, clip_pct=B_clip_pct, alpha_max=B_ALPHA_MAX) ax.plot_surface( X, Y, Z0 + z_eps, facecolors=fc, rstride=1, cstride=1, shade=False, linewidth=0, antialiased=False ) # n arrows (red) nxs = nx[::q_step_n, ::q_step_n] nys = ny[::q_step_n, ::q_step_n] nzs = nz[::q_step_n, ::q_step_n] ax.quiver( XsN, YsN, ZsN, nxs, nys, nzs, length=LEN_N, normalize=True, color="red", linewidth=0.75 ) # E arrows (blue), clipped ExS = Ex[::q_step_E, ::q_step_E] EyS = Ey[::q_step_E, ::q_step_E] Em = np.sqrt(ExS*ExS + EyS*EyS) + 1e-12 sE = np.percentile(Em, E_clip_pct) + 1e-12 ExD = np.clip(ExS / sE, -1.0, 1.0) EyD = np.clip(EyS / sE, -1.0, 1.0) ax.quiver( XsE, YsE, ZsE, ExD, EyD, np.zeros_like(ExD), length=LEN_E, normalize=False, color="blue", linewidth=0.95, alpha=0.95 ) # core marker ax.scatter([x_now], [0.0], [0.0], s=35, c="k") return [] anim = FuncAnimation(fig, update, frames=frames, interval=interval_ms, blit=False, repeat=repeat_anim) plt.tight_layout() plt.show()
У читателя неизбежно возникают следующие справедливые вопросы. В предложенной модели (я это подчёркиваю — именно в предложенной модели) гравитационное поле интерпретируется как мера глобальной кривизны фазовой структуры вакуума, электрическое поле — как градиент этой кривизны, а магнитное поле — как мера локальной закрученности фазовой связи. Эти величины демонстрируют правильные взаимные ориентации, корректные трансформационные свойства и воспроизводят стандартные уравнения движения. Однако почему именно эти геометрические характеристики фазового поля следует интерпретировать как реальные физические взаимодействия? Почему фазовая кривизна приводит к универсальному притяжению? Почему разные электрические заряды притягиваются, а одноимённые отталкиваются? Почему магнитные полюса демонстрируют характерную дипольную структуру сил?
Ключевой факт в том, что в данной модели эти поля не являются произвольно введёнными абстрактными величинами. Они возникают как единственные инвариантные геометрические объекты, допускаемые динамикой фазовой среды, и непосредственно входят в уравнения эволюции всех локализованных фазовых структур. Иными словами, речь идёт не о произвольных «метках» фазового поля, а о тех компонентах фазовой геометрии, которые определяют минимизацию действия и, следовательно, реальную динамику всех возбуждений вакуума.
Гравитационное поле проявляется как глобальная деформация фазового времени и потому одинаково влияет на все локальные структуры, независимо от их внутренней конфигурации. Электрическое поле соответствует градиенту фазовой динамики и приводит к направленному дрейфу фазовых вихрей, причём знак взаимодействия определяется относительной ориентацией фазового дефекта и фоновой фазовой структуры. Магнитное поле, в свою очередь, отражает вихревую компоненту фазовой связи и задаёт взаимную ориентацию движущихся фазовых структур.
Таким образом, силы притяжения и отталкивания в данной теории не вводятся как дополнительные постулаты. Они являются прямым следствием того, что локализованные фазовые дефекты эволюционируют в геометрически искривлённой фазовой среде, следуя принципу минимального действия. Именно поэтому соответствующие геометрические поля не просто «похожи» на электромагнитные и гравитационные — они и являются их фундаментальной фазовой реализацией.
Эти поля интерпретируются как физические не потому, что мы так решили, а потому что именно они управляют динамикой всех возбуждений фазовой среды и определяют их реальные траектории и взаимодействия.
В этой теории сила не вводится как самостоятельная первичная сущность. Она возникает как удобное описание того, с какой скоростью и в каком направлении локализованные фазовые структуры перестраиваются в ответ на геометрические свойства окружающего фазового поля.
Иначе говоря, движение частицы определяется не «приложенной силой», а формой фазового ландшафта, в котором она существует. Траектория соответствует такому изменению фазовой конфигурации, при котором суммарная фазовая энергия изменяется наименьшим возможным образом — в полном согласии с вариационным принципом.
В ньютоновской механике сила служит промежуточным понятием между геометрией движения и изменением импульса. В фазовой формулировке эту роль напрямую играет геометрия самого фазового поля: «сила» оказывается лишь эффективным языком описания фазовой динамики.
Промежуточный итог
Я очень надеюсь на то, что мне удалось донести основную идею, онтологию теории. Здесь, разумеется, нужно подключать интуицию. Экстраполяция на пространство 3+1D — достаточно заковыриста, но когда Вам это удастся, думаю, вы поразитесь красоте возникающей картины!
Мне хотелось бы услышать — насколько интересна такая подача материала? Что следует исправить или расширить?
Кроме того, буду рад любой помощи с визуализацией (предпочтительно в динамике) этой модели.
