From 88f45143117f3ae973be6e3ea5dac8063a7b8ece Mon Sep 17 00:00:00 2001
From: Samo Penic <samo@amalthea>
Date: Sat, 19 Mar 2011 18:35:08 +0000
Subject: [PATCH] Added spherical harmonics routine.I've got a feeling that some harmonics are not calculated correctly!

---
 src/Makefile.am  |    7 +
 src/shdiscover.c |   80 ++++++++++++++++++++
 src/sh.h         |    9 ++
 src/sh.c         |   90 ++++++++++++++++++++++
 4 files changed, 184 insertions(+), 2 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 25fc76f..66eec22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,8 @@
 trisurfdir=../
 trisurf_PROGRAMS = trisurf
 trisurf_SOURCES = general.c vertex.c bond.c triangle.c cell.c vesicle.c initial_distribution.c io.c frame.c energy.c timestep.c vertexmove.c main.c
-trisurf_LDFLAGS = -lm -lconfuse
-trisurf_CFLAGS = -Wall -Werror
+#trisurf_LDFLAGS = -lm -lconfuse
+shdiscoverdir=../
+shdiscover_PROGRAMS= shdiscover
+shdiscover_SOURCES= general.c vertex.c bond.c triangle.c cell.c vesicle.c initial_distribution.c io.c energy.c sh.c shdiscover.c
+AM_CFLAGS = -Wall -Werror
diff --git a/src/sh.c b/src/sh.c
new file mode 100644
index 0000000..b494b25
--- /dev/null
+++ b/src/sh.c
@@ -0,0 +1,90 @@
+#include<math.h>
+#include<stdlib.h>
+#include "general.h"
+#include "sh.h"
+
+/* Gives you legendre polynomials. Taken from NR, p. 254 */
+ts_double plgndr(ts_int l, ts_int m, ts_float x){
+	ts_double fact, pll, pmm, pmmp1, somx2;
+	ts_int i,ll;
+
+#ifdef TS_DOUBLE_DOUBLE
+	if(m<0 || m>l || fabs(x)>1.0)
+		fatal("Bad arguments in routine plgndr",1);
+#endif
+#ifdef TS_DOUBLE_FLOAT
+	if(m<0 || m>l || fabsf(x)>1.0)
+		fatal("Bad arguments in routine plgndr",1);
+#endif
+#ifdef TS_DOUBLE_LONGDOUBLE
+	if(m<0 || m>l || fabsl(x)>1.0)
+		fatal("Bad arguments in routine plgndr",1);
+#endif
+	pmm=1.0;
+	if (m>0) {
+#ifdef TS_DOUBLE_DOUBLE
+		somx2=sqrt((1.0-x)*(1.0+x));
+#endif
+#ifdef TS_DOUBLE_FLOAT
+		somx2=sqrtf((1.0-x)*(1.0+x));
+#endif
+#ifdef TS_DOUBLE_LONGDOUBLE
+		somx2=sqrtl((1.0-x)*(1.0+x));
+#endif
+		fact=1.0;
+		for (i=1; i<=m;i++){
+			pmm *= -fact*somx2;
+			fact +=2.0;
+		}
+	}
+
+	if (l == m) return pmm;
+	else {
+		pmmp1=x*(2*m+1)*pmm;
+		if(l==(m+1)) return(pmmp1);
+		else {
+			pll=0; /* so it can not be uninitialized */
+			for(ll=m+2;ll<=l;ll++){
+				pll=(x*(2*ll-1)*pmmp1-(ll+m-1)*pmm)/(ll-m);
+				pmm=pmmp1;
+				pmmp1=pll;
+			}
+			return(pll);
+		}
+	}
+}
+
+
+/*Computes Y(l,m,theta,fi) (Miha's definition that is different from common definition for  factor srqt(1/(2*pi)) */
+ts_double shY(ts_int l,ts_int m,ts_double theta,ts_double fi){
+	ts_double fac1, fac2, K;
+	int i;
+
+	if(l<0 || m>l || m<-l)
+		fatal("Error using shY function!",1);
+
+	fac1=1.0;
+	for(i=1; i<=l-m;i++){
+		fac1 *= i;
+	}
+	fac2=1.0;
+	for(i=1; i<=l+m;i++){
+		fac2 *= i;
+	}
+
+	if(m==0){
+		K=sqrt(1.0/(2.0*M_PI));
+	}
+	else if (m>0) {
+		K=sqrt(1.0/(M_PI))*cos(m*fi);
+	} 
+	else {
+		//K=pow(-1.0,abs(m))*sqrt(1.0/(2.0*M_PI))*cos(m*fi);
+		if(abs(m)%2==0)
+		K=sqrt(1.0/(M_PI))*sin(m*fi);
+		else
+		K=-sqrt(1.0/(M_PI))*sin(m*fi);
+	}
+	
+	return K*sqrt((2.0*l+1.0)/2.0*fac1/fac2)*plgndr(l,abs(m),cos(theta));	
+}
diff --git a/src/sh.h b/src/sh.h
new file mode 100644
index 0000000..1255f52
--- /dev/null
+++ b/src/sh.h
@@ -0,0 +1,9 @@
+#ifndef _H_SH
+#define _H_SH
+#include "general.h"
+
+ts_double plgndr(ts_int l, ts_int m, ts_float x);
+ts_double shY(ts_int l,ts_int m,ts_double theta,ts_double fi);
+
+
+#endif
diff --git a/src/shdiscover.c b/src/shdiscover.c
new file mode 100644
index 0000000..9783ef6
--- /dev/null
+++ b/src/shdiscover.c
@@ -0,0 +1,80 @@
+#include "general.h"
+#include "vertex.h"
+#include "initial_distribution.h"
+#include "io.h"
+#include "vesicle.h"
+#include "sh.h"
+#include "frame.c"
+#include <math.h>
+#include <stdlib.h>
+int main(int argc, char *argv[]){
+
+ts_fprintf(stdout,"SHdiscover was called with %d coefficients!\n",argc-1);
+ts_uint n,i,j,l;
+ts_int m;
+ts_double fi,theta,r,Y;
+ts_vesicle *vesicle=initial_distribution_dipyramid(17,60,60,60,0.15);
+ts_vertex_list *vlist=vesicle->vlist;
+centermass(vesicle);
+ts_fprintf(stdout,"Vesicle has a CenterMass in %f,%f,%f\n",vesicle->cm[0],vesicle->cm[1], vesicle->cm[2]);
+
+n=vlist->n;
+
+ts_fprintf(stdout,"Tests\n");
+ts_fprintf(stdout,"P(0,0,0.5)=%f (%f)\n",plgndr(0,0,0.5),1.0);
+ts_fprintf(stdout,"P(1,0,0.5)=%f (%f)\n",plgndr(1,0,0.5),0.5);
+ts_fprintf(stdout,"P(2,0,0.5)=%f (%f)\n",plgndr(2,0,0.5),0.5*(3*0.5*0.5-1));
+
+ts_fprintf(stdout,"Y(0,0,pi/6,pi/4)=%f (%f)\n",shY(0,0,M_PI/6,M_PI/4),sqrt(1/(4*M_PI)));
+ts_fprintf(stdout,"Y(1,0,pi/6,pi/4)=%f (%f)\n",shY(1,0,M_PI/6,M_PI/4),sqrt(3/(4*M_PI))*cos(M_PI/6));
+ts_fprintf(stdout,"Y(1,0,4*pi/6,6*pi/4)=%f (%f)\n",shY(1,0,4*M_PI/6,6*M_PI/4),sqrt(3/(4*M_PI))*cos(4*M_PI/6));
+ts_fprintf(stdout,"Y(1,1,pi/6,pi/4)=%f (%f)\n",shY(1,1,M_PI/6,M_PI/4),-sqrt(3/(8*M_PI))*sin(M_PI/6)*sin(M_PI/4));
+ts_fprintf(stdout,"Y(2,0,pi/6,pi/4)=%f (%f)\n",shY(2,0,M_PI/6,M_PI/4),sqrt(5/(4*M_PI))*(3.0/2.0*cos(M_PI/6)*cos(M_PI/6)-1.0/2.0));
+ts_fprintf(stdout,"Y(2,-2,pi/6,pi/4)=%f (0)\n",shY(2,-2,M_PI/6,M_PI/4));
+ts_fprintf(stdout,"Y(2,2,pi/6,pi/4)=%f (0)\n",shY(2,2,M_PI/6,M_PI/4));
+	
+	for(j=1;j<argc;j++){
+		l=(int)sqrt(j-1); /* determine l from dataline */
+		m=j-1-l*(l+1); /* determine m from dataline */
+		ts_fprintf(stdout,"l=%d, m=%d, u=%s\n",l,m,argv[j]);
+	}
+
+/*we calculate new position of each vertex of vesicle */
+for(i=0;i<n;i++){
+	fi=atan2(vlist->vtx[i]->data->y, vlist->vtx[i]->data->x);
+/*	theta=atan2(
+	    sqrt(vlist->vtx[i]->data->x*vlist->vtx[i]->data->x + 
+		vlist->vtx[i]->data->y*vlist->vtx[i]->data->y),
+		vlist->vtx[i]->data->z 
+	    ); */
+	theta=acos(
+		vlist->vtx[i]->data->z /
+	    sqrt(vlist->vtx[i]->data->x*vlist->vtx[i]->data->x + 
+		vlist->vtx[i]->data->y*vlist->vtx[i]->data->y+
+		vlist->vtx[i]->data->z*vlist->vtx[i]->data->z)
+
+		);
+
+
+
+	r=0.0;
+	for(j=1;j<argc;j++){
+		l=(int)sqrt(j-1); /* determine l from dataline */
+		m=j-1-l*(l+1); /* determine m from dataline */
+		Y=shY(l,m,theta,fi);
+		r+=fabs(atof(argv[j])*Y);
+		/*ts_fprintf(stdout,"l=%d, m=%d, u=%s\n",l,m,argv[j]);*/
+	}
+
+	vlist->vtx[i]->data->z=fabs(r)*cos(theta);
+	vlist->vtx[i]->data->x=fabs(r)*sin(theta)*cos(fi);
+	vlist->vtx[i]->data->y=fabs(r)*sin(theta)*sin(fi);
+}
+
+write_vertex_xml_file(vesicle,0);
+write_master_xml_file("test.pvd");
+
+
+vesicle_free(vesicle);
+return 0;
+}

--
Gitblit v1.9.3