| commit | author | age | ||
| 7f6076 | 1 | /* vim: set ts=4 sts=4 sw=4 noet : */ |
| d7639a | 2 | #include<stdlib.h> |
| SP | 3 | #include "general.h" |
| 4 | #include "energy.h" | |
| 5 | #include "vertex.h" | |
| 6 | #include<math.h> | |
| 7 | #include<stdio.h> | |
| a00f10 | 8 | |
| SP | 9 | |
| 10 | /** @brief Wrapper that calculates energy of every vertex in vesicle | |
| 11 | * | |
| 12 | * Function calculated energy of every vertex in vesicle. It can be used in | |
| 13 | * initialization procedure or in recalculation of the energy after non-MCsweep * operations. However, when random move of vertex or flip of random bond occur * call to this function is not necessary nor recommended. | |
| 14 | * @param *vesicle is a pointer to vesicle. | |
| 15 | * @returns TS_SUCCESS on success. | |
| 16 | */ | |
| d7639a | 17 | ts_bool mean_curvature_and_energy(ts_vesicle *vesicle){ |
| SP | 18 | |
| f74313 | 19 | ts_uint i; |
| d7639a | 20 | |
| f74313 | 21 | ts_vertex_list *vlist=vesicle->vlist; |
| SP | 22 | ts_vertex **vtx=vlist->vtx; |
| d7639a | 23 | |
| SP | 24 | for(i=0;i<vlist->n;i++){ |
| f74313 | 25 | energy_vertex(vtx[i]); |
| b01cc1 | 26 | |
| d7639a | 27 | } |
| SP | 28 | |
| 29 | return TS_SUCCESS; | |
| 30 | } | |
| 31 | ||
| a00f10 | 32 | /** @brief Calculate energy of a bond (in models where energy is bond related) |
| SP | 33 | * |
| 34 | * This function is experimental and currently only used in polymeres calculation (PEGs or polymeres inside the vesicle). | |
| 35 | * | |
| 36 | * @param *bond is a pointer to a bond between two vertices in polymere | |
| 37 | * @param *poly is a pointer to polymere in which we calculate te energy of the bond | |
| 38 | * @returns TS_SUCCESS on successful calculation | |
| 39 | */ | |
| fedf2b | 40 | inline ts_bool bond_energy(ts_bond *bond,ts_poly *poly){ |
| 304510 | 41 | //TODO: This value to be changed and implemented in data structure: |
| M | 42 | ts_double d_relaxed=1.0; |
| 43 | bond->energy=poly->k*pow(bond->bond_length-d_relaxed,2); | |
| fedf2b | 44 | return TS_SUCCESS; |
| M | 45 | }; |
| 46 | ||
| e6efc6 | 47 | /** @brief Calculation of the bending energy of the vertex. |
| a00f10 | 48 | * |
| e6efc6 | 49 | * Main function that calculates energy of the vertex \f$i\f$. Function returns \f$\frac{1}{2}(c_1+c_2-c)^2 s\f$, where \f$(c_1+c_2)/2\f$ is mean curvature, |
| SP | 50 | * \f$c/2\f$ is spontaneous curvature and \f$s\f$ is area per vertex \f$i\f$. |
| 51 | * | |
| 52 | * Nearest neighbors (NN) must be ordered in counterclockwise direction for this function to work. | |
| a00f10 | 53 | * Firstly NNs that form two neighboring triangles are found (\f$j_m\f$, \f$j_p\f$ and common \f$j\f$). Later, the scalar product of vectors \f$x_1=(\mathbf{i}-\mathbf{j_p})\cdot (\mathbf{i}-\mathbf{j_p})(\mathbf{i}-\mathbf{j_p})\f$, \f$x_2=(\mathbf{j}-\mathbf{j_p})\cdot (\mathbf{j}-\mathbf{j_p})\f$ and \f$x_3=(\mathbf{j}-\mathbf{j_p})\cdot (\mathbf{i}-\mathbf{j_p})\f$ are calculated. From these three vectors the \f$c_{tp}=\frac{1}{\tan(\varphi_p)}\f$ is calculated, where \f$\varphi_p\f$ is the inner angle at vertex \f$j_p\f$. The procedure is repeated for \f$j_m\f$ instead of \f$j_p\f$ resulting in \f$c_{tn}\f$. |
| SP | 54 | * |
| 854cb6 | 55 | \begin{tikzpicture}{ |
| a00f10 | 56 | \coordinate[label=below:$i$] (i) at (2,0); |
| SP | 57 | \coordinate[label=left:$j_m$] (jm) at (0,3.7); |
| 58 | \coordinate[label=above:$j$] (j) at (2.5,6.4); | |
| 59 | \coordinate[label=right:$j_p$] (jp) at (4,2.7); | |
| d7639a | 60 | |
| a00f10 | 61 | \draw (i) -- (jm) -- (j) -- (jp) -- (i) -- (j); |
| SP | 62 | |
| 63 | \begin{scope} | |
| 64 | \path[clip] (jm)--(i)--(j); | |
| 65 | \draw (jm) circle (0.8); | |
| 66 | \node[right] at (jm) {$\varphi_m$}; | |
| 67 | \end{scope} | |
| 68 | ||
| 69 | \begin{scope} | |
| 70 | \path[clip] (jp)--(i)--(j); | |
| 71 | \draw (jp) circle (0.8); | |
| 72 | \node[left] at (jp) {$\varphi_p$}; | |
| 73 | \end{scope} | |
| 74 | ||
| 75 | %%vertices | |
| 76 | \draw [fill=gray] (i) circle (0.1); | |
| 77 | \draw [fill=white] (j) circle (0.1); | |
| 78 | \draw [fill=white] (jp) circle (0.1); | |
| 79 | \draw [fill=white] (jm) circle (0.1); | |
| 80 | %\node[draw,circle,fill=white] at (i) {}; | |
| 854cb6 | 81 | \end{tikzpicture} |
| a00f10 | 82 | |
| SP | 83 | * The curvature is then calculated as \f$\mathbf{h}=\frac{1}{2}\Sigma_{k=0}^{\mathrm{neigh\_no}} c_{tp}^{(k)}+c_{tm}^{(k)} (\mathbf{j_k}-\mathbf{i})\f$, where \f$c_{tp}^{(k)}+c_{tm}^k=2\sigma^{(k)}\f$ (length in dual lattice?) and the previous equation can be written as \f$\mathbf{h}=\Sigma_{k=0}^{\mathrm{neigh\_no}}\sigma^{(k)}\cdot(\mathbf{j}-\mathbf{i})\f$ (See Kroll, p. 384, eq 70). |
| 84 | * | |
| 85 | * From the curvature the enery is calculated by equation \f$E=\frac{1}{2}\mathbf{h}\cdot\mathbf{h}\f$. | |
| 86 | * @param *vtx is a pointer to vertex at which we want to calculate the energy | |
| 87 | * @returns TS_SUCCESS on successful calculation. | |
| 88 | */ | |
| d7639a | 89 | inline ts_bool energy_vertex(ts_vertex *vtx){ |
| SP | 90 | ts_uint jj; |
| 91 | ts_uint jjp,jjm; | |
| 92 | ts_vertex *j,*jp, *jm; | |
| 93 | ts_triangle *jt; | |
| a63f17 | 94 | ts_double s=0.0,xh=0.0,yh=0.0,zh=0.0,txn=0.0,tyn=0.0,tzn=0.0; |
| d7639a | 95 | ts_double x1,x2,x3,ctp,ctm,tot,xlen; |
| SP | 96 | ts_double h,ht; |
| 8f6a69 | 97 | for(jj=1; jj<=vtx->neigh_no;jj++){ |
| d7639a | 98 | jjp=jj+1; |
| 8f6a69 | 99 | if(jjp>vtx->neigh_no) jjp=1; |
| d7639a | 100 | jjm=jj-1; |
| 8f6a69 | 101 | if(jjm<1) jjm=vtx->neigh_no; |
| SP | 102 | j=vtx->neigh[jj-1]; |
| 103 | jp=vtx->neigh[jjp-1]; | |
| 104 | jm=vtx->neigh[jjm-1]; | |
| 105 | jt=vtx->tristar[jj-1]; | |
| f74313 | 106 | x1=vtx_distance_sq(vtx,jp); //shouldn't be zero! |
| SP | 107 | x2=vtx_distance_sq(j,jp); // shouldn't be zero! |
| 8f6a69 | 108 | x3=(j->x-jp->x)*(vtx->x-jp->x)+ |
| SP | 109 | (j->y-jp->y)*(vtx->y-jp->y)+ |
| 110 | (j->z-jp->z)*(vtx->z-jp->z); | |
| d7639a | 111 | |
| SP | 112 | #ifdef TS_DOUBLE_DOUBLE |
| 113 | ctp=x3/sqrt(x1*x2-x3*x3); | |
| 114 | #endif | |
| 115 | #ifdef TS_DOUBLE_FLOAT | |
| 116 | ctp=x3/sqrtf(x1*x2-x3*x3); | |
| 117 | #endif | |
| 118 | #ifdef TS_DOUBLE_LONGDOUBLE | |
| 119 | ctp=x3/sqrtl(x1*x2-x3*x3); | |
| 120 | #endif | |
| f74313 | 121 | x1=vtx_distance_sq(vtx,jm); |
| SP | 122 | x2=vtx_distance_sq(j,jm); |
| 8f6a69 | 123 | x3=(j->x-jm->x)*(vtx->x-jm->x)+ |
| SP | 124 | (j->y-jm->y)*(vtx->y-jm->y)+ |
| 125 | (j->z-jm->z)*(vtx->z-jm->z); | |
| d7639a | 126 | #ifdef TS_DOUBLE_DOUBLE |
| SP | 127 | ctm=x3/sqrt(x1*x2-x3*x3); |
| 128 | #endif | |
| 129 | #ifdef TS_DOUBLE_FLOAT | |
| 130 | ctm=x3/sqrtf(x1*x2-x3*x3); | |
| 131 | #endif | |
| 132 | #ifdef TS_DOUBLE_LONGDOUBLE | |
| 133 | ctm=x3/sqrtl(x1*x2-x3*x3); | |
| 134 | #endif | |
| 135 | tot=ctp+ctm; | |
| 136 | tot=0.5*tot; | |
| a63f17 | 137 | |
| f74313 | 138 | xlen=vtx_distance_sq(j,vtx); |
| a63f17 | 139 | /* |
| d7639a | 140 | #ifdef TS_DOUBLE_DOUBLE |
| 8f6a69 | 141 | vtx->bond[jj-1]->bond_length=sqrt(xlen); |
| d7639a | 142 | #endif |
| SP | 143 | #ifdef TS_DOUBLE_FLOAT |
| 8f6a69 | 144 | vtx->bond[jj-1]->bond_length=sqrtf(xlen); |
| d7639a | 145 | #endif |
| SP | 146 | #ifdef TS_DOUBLE_LONGDOUBLE |
| 8f6a69 | 147 | vtx->bond[jj-1]->bond_length=sqrtl(xlen); |
| d7639a | 148 | #endif |
| SP | 149 | |
| 8f6a69 | 150 | vtx->bond[jj-1]->bond_length_dual=tot*vtx->bond[jj-1]->bond_length; |
| a63f17 | 151 | */ |
| d7639a | 152 | s+=tot*xlen; |
| 8f6a69 | 153 | xh+=tot*(j->x - vtx->x); |
| SP | 154 | yh+=tot*(j->y - vtx->y); |
| 155 | zh+=tot*(j->z - vtx->z); | |
| 41a035 | 156 | txn+=jt->xnorm; |
| SP | 157 | tyn+=jt->ynorm; |
| 158 | tzn+=jt->znorm; | |
| d7639a | 159 | } |
| SP | 160 | |
| 161 | h=xh*xh+yh*yh+zh*zh; | |
| 162 | ht=txn*xh+tyn*yh + tzn*zh; | |
| 163 | s=s/4.0; | |
| 164 | #ifdef TS_DOUBLE_DOUBLE | |
| 165 | if(ht>=0.0) { | |
| 8f6a69 | 166 | vtx->curvature=sqrt(h); |
| d7639a | 167 | } else { |
| 8f6a69 | 168 | vtx->curvature=-sqrt(h); |
| d7639a | 169 | } |
| SP | 170 | #endif |
| 171 | #ifdef TS_DOUBLE_FLOAT | |
| 172 | if(ht>=0.0) { | |
| 8f6a69 | 173 | vtx->curvature=sqrtf(h); |
| d7639a | 174 | } else { |
| 8f6a69 | 175 | vtx->curvature=-sqrtf(h); |
| d7639a | 176 | } |
| SP | 177 | #endif |
| 178 | #ifdef TS_DOUBLE_LONGDOUBLE | |
| 179 | if(ht>=0.0) { | |
| 8f6a69 | 180 | vtx->curvature=sqrtl(h); |
| d7639a | 181 | } else { |
| 8f6a69 | 182 | vtx->curvature=-sqrtl(h); |
| d7639a | 183 | } |
| SP | 184 | #endif |
| dac2e5 | 185 | // c is forced curvature energy for each vertex. Should be set to zero for |
| 8f6a69 | 186 | // normal circumstances. |
| e6efc6 | 187 | /* the following statement is an expression for $\frac{1}{2}\int(c_1+c_2-c_0^\prime)^2\mathrm{d}A$, where $c_0^\prime=2c_0$ (twice the spontaneous curvature) */ |
| 8f6a69 | 188 | vtx->energy=0.5*s*(vtx->curvature/s-vtx->c)*(vtx->curvature/s-vtx->c); |
| d7639a | 189 | |
| SP | 190 | return TS_SUCCESS; |
| 191 | } | |
| e5858f | 192 | |
| SP | 193 | |
| 194 | ||
| 195 | ts_bool sweep_attraction_bond_energy(ts_vesicle *vesicle){ | |
| 196 | int i; | |
| 197 | for(i=0;i<vesicle->blist->n;i++){ | |
| 198 | attraction_bond_energy(vesicle->blist->bond[i], vesicle->tape->w); | |
| 199 | } | |
| 200 | return TS_SUCCESS; | |
| 201 | } | |
| 202 | ||
| 203 | ||
| 204 | inline ts_bool attraction_bond_energy(ts_bond *bond, ts_double w){ | |
| 205 | ||
| 206 | if(fabs(bond->vtx1->c)>1e-16 && fabs(bond->vtx2->c)>1e-16){ | |
| 032273 | 207 | bond->energy=-w; |
| e5858f | 208 | } |
| SP | 209 | else { |
| 210 | bond->energy=0.0; | |
| 211 | } | |
| 212 | return TS_SUCCESS; | |
| 213 | } | |
| 250de4 | 214 | |
| SP | 215 | ts_double direct_force_energy(ts_vesicle *vesicle, ts_vertex *vtx, ts_vertex *vtx_old){ |
| 216 | if(fabs(vtx->c)<1e-15) return 0.0; | |
| 217 | // printf("was here"); | |
| 218 | if(fabs(vesicle->tape->F)<1e-15) return 0.0; | |
| 219 | ||
| 220 | ts_double norml,ddp=0.0; | |
| 221 | ts_uint i; | |
| 222 | ts_double xnorm=0.0,ynorm=0.0,znorm=0.0; | |
| 02d65c | 223 | /*find normal of the vertex as sum of all the normals of the triangles surrounding it. */ |
| 250de4 | 224 | for(i=0;i<vtx->tristar_no;i++){ |
| 02d65c | 225 | xnorm+=vtx->tristar[i]->xnorm; |
| MF | 226 | ynorm+=vtx->tristar[i]->ynorm; |
| 227 | znorm+=vtx->tristar[i]->znorm; | |
| 250de4 | 228 | } |
| SP | 229 | /*normalize*/ |
| 230 | norml=sqrt(xnorm*xnorm+ynorm*ynorm+znorm*znorm); | |
| 231 | xnorm/=norml; | |
| 232 | ynorm/=norml; | |
| 233 | znorm/=norml; | |
| 234 | /*calculate ddp, perpendicular displacement*/ | |
| c372c1 | 235 | ddp=xnorm*(vtx->x-vtx_old->x)+ynorm*(vtx->y-vtx_old->y)+znorm*(vtx->z-vtx_old->z); |
| 250de4 | 236 | /*calculate dE*/ |
| SP | 237 | // printf("ddp=%e",ddp); |
| 238 | return vesicle->tape->F*ddp; | |
| 239 | ||
| 240 | } | |
| 7ec6fb | 241 | |
| SP | 242 | void stretchenergy(ts_vesicle *vesicle, ts_triangle *triangle){ |
| 04694f | 243 | triangle->energy=vesicle->tape->xkA0/2.0*pow((triangle->area/vesicle->tlist->a0-1.0),2); |
| 7ec6fb | 244 | } |