From b36841fb1903e9945cb4a1dbc4dd7761556e07e2 Mon Sep 17 00:00:00 2001
From: Samo Penic <samo.penic@fe.uni-lj.si>
Date: Mon, 28 Apr 2014 10:40:08 +0000
Subject: [PATCH] Merge branch 'trout-rbc'

---
 src/io.c                   |   35 ++
 src/stats.c                |   83 +++++
 src/stats.h                |    6 
 src/tape                   |   19 
 src/vesicle.c              |    3 
 config.h.in                |    6 
 src/initial_distribution.c |   16 
 src/general.h              |    5 
 src/vertexmove.c           |   25 +
 src/io.h                   |    4 
 src/Makefile.am            |   28 
 src/timestep.c             |   77 ++++
 src/shcomplex.c            |  172 +++++++++++
 src/timestep.h             |    2 
 config.h                   |    6 
 src/shcomplex.h            |    9 
 src/triangle.c             |   96 +++---
 src/cell.c                 |   15 
 src/main.c                 |   13 
 configure.ac               |    3 
 src/spherical_trisurf_ff.c |   29 -
 src/poly.c                 |   26 +
 src/vertex.c               |    8 
 src/sh.h                   |    2 
 src/spherical_trisurf.c    |   28 -
 aclocal.m4                 |  122 +++++++
 src/frame.c                |    1 
 src/sh.c                   |   47 +++
 src/vertex.h               |    2 
 29 files changed, 729 insertions(+), 159 deletions(-)

diff --git a/aclocal.m4 b/aclocal.m4
index 72a1419..3a9a040 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
 
 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
@@ -32,10 +32,10 @@
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.13'
+[am__api_version='1.14'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.13.3], [],
+m4_if([$1], [1.14.1], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -51,7 +51,7 @@
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.13.3])dnl
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -418,6 +418,12 @@
 # This macro actually does too much.  Some checks are only needed if
 # your package does certain things.  But this isn't really a big deal.
 
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
 # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
 # AM_INIT_AUTOMAKE([OPTIONS])
 # -----------------------------------------------
@@ -526,14 +532,54 @@
 AC_CONFIG_COMMANDS_PRE(dnl
 [m4_provide_if([_AM_COMPILER_EXEEXT],
   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
-])
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi])
 
 dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
 dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
 dnl mangled by Autoconf and run in a shell conditional statement.
 m4_define([_AC_COMPILER_EXEEXT],
 m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
-
 
 # When config.status generates a header, we must update the stamp-h file.
 # This file resides in the same directory as the config header
@@ -716,6 +762,70 @@
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
diff --git a/config.h b/config.h
index 9a07c00..ac9c24a 100644
--- a/config.h
+++ b/config.h
@@ -7,6 +7,12 @@
 /* Define to 1 if you have the `confuse' library (-lconfuse). */
 #define HAVE_LIBCONFUSE 1
 
+/* Define to 1 if you have the `gsl' library (-lgsl). */
+#define HAVE_LIBGSL 1
+
+/* Define to 1 if you have the `gslcblas' library (-lgslcblas). */
+#define HAVE_LIBGSLCBLAS 1
+
 /* Define to 1 if you have the `m' library (-lm). */
 #define HAVE_LIBM 1
 
diff --git a/config.h.in b/config.h.in
index c692c55..f865b7a 100644
--- a/config.h.in
+++ b/config.h.in
@@ -6,6 +6,12 @@
 /* Define to 1 if you have the `confuse' library (-lconfuse). */
 #undef HAVE_LIBCONFUSE
 
+/* Define to 1 if you have the `gsl' library (-lgsl). */
+#undef HAVE_LIBGSL
+
+/* Define to 1 if you have the `gslcblas' library (-lgslcblas). */
+#undef HAVE_LIBGSLCBLAS
+
 /* Define to 1 if you have the `m' library (-lm). */
 #undef HAVE_LIBM
 
diff --git a/configure.ac b/configure.ac
index 791a930..2ebed26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,6 +15,9 @@
 # FIXME: Replace `main' with a function in `-lm':
 AC_CHECK_LIB([m], [pow])
 
+AC_CHECK_LIB([gslcblas],[cblas_dgemm])
+AC_CHECK_LIB([gsl],[gsl_blas_dgemm])
+
 # Checks for header files.
 AC_CHECK_HEADERS([stdlib.h string.h])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index e899cd3..20bae62 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,17 +1,17 @@
 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 bondflip.c main.c poly.c
-#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 poly.c
+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 bondflip.c main.c poly.c stats.c sh.c shcomplex.c
 AM_CFLAGS = -Wall -Werror
-co_testdir=../
-co_test_PROGRAMS=co_test
-co_test_SOURCES= general.c vertex.c bond.c triangle.c cell.c vesicle.c initial_distribution.c io.c energy.c sh.c co_test.c frame.c bondflip.c poly.c
-spherical_trisurfdir=../
-spherical_trisurf_PROGRAMS = spherical_trisurf
-spherical_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 spherical_trisurf.c sh.c bondflip.c poly.c
-spherical_trisurf_ffdir=../
-spherical_trisurf_ff_PROGRAMS = spherical_trisurf_ff
-spherical_trisurf_ff_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 spherical_trisurf_ff.c sh.c bondflip.c poly.c
+#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 poly.c stats.c shcomplex.c
+#co_testdir=../
+#co_test_PROGRAMS=co_test
+#co_test_SOURCES= general.c vertex.c bond.c triangle.c cell.c vesicle.c initial_distribution.c io.c energy.c sh.c co_test.c frame.c bondflip.c poly.c stats.c shcomplex.c
+#spherical_trisurfdir=../
+#spherical_trisurf_PROGRAMS = spherical_trisurf
+#spherical_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 spherical_trisurf.c sh.c bondflip.c poly.c stats.c shcomplex.c
+#spherical_trisurf_ffdir=../
+#spherical_trisurf_ff_PROGRAMS = spherical_trisurf_ff
+#spherical_trisurf_ff_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 spherical_trisurf_ff.c sh.c bondflip.c poly.c stats.c shcomplex.c
diff --git a/src/cell.c b/src/cell.c
index 97f2fe7..ed86b16 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -44,7 +44,6 @@
 }
 
 
-//TODO: not debugged at all!
 inline ts_uint vertex_self_avoidance(ts_vesicle *vesicle, ts_vertex *vtx){
     ts_uint cellidx;
     ts_uint ncx, ncy,ncz;
@@ -68,7 +67,6 @@
 }
 
 
-//TODO: looks ok, but debug anyway in the future
 inline ts_bool cell_add_vertex(ts_cell *cell, ts_vertex *vtx){
 	ts_uint i;
 	for(i=0;i<cell->nvertex;i++){
@@ -124,7 +122,7 @@
     return TS_SUCCESS;
 }
 
-// TODO: compiles ok, but it is completely untested and undebugged. It was debugged before rewrite, but this was long time ago.
+
 ts_bool cell_occupation_number_and_internal_proximity(ts_cell_list *clist, ts_uint cellidx, ts_vertex *vtx){
     ts_uint ncx,ncy,ncz,remainder,cell_occupation;
     ts_uint i,j,k,l,neigh_cidx;
@@ -151,11 +149,16 @@
                     for(l=0;l<cell_occupation;l++){
 
 				//carefull with this checks!
-                        if(clist->cell[neigh_cidx]->vertex[l]->idx!=vtx->idx){
+                        if(clist->cell[neigh_cidx]->vertex[l]!=vtx){
                     //        fprintf(stderr,"calling dist on vertex %i\n",l);
                            dist=vtx_distance_sq(clist->cell[neigh_cidx]->vertex[l],vtx);
-                    //        fprintf(stderr,"dist was %f\n",dist);
-                            if(dist<=1.0) return TS_FAIL;
+
+//				if(vtx->idx==1)
+//				fprintf(stderr,"VTX(0) ima bliznji vertex z indeksom, %d, tipa %d \n", clist->cell[neigh_cidx]->vertex[l]->idx, clist->cell[neigh_cidx]->vertex[l]->id);
+//				if(vtx->idx==0 && clist->cell[neigh_cidx]->vertex[l]->idx==0)
+//                            fprintf(stderr,"*** dist was %f\n",dist);
+				
+                            if(dist<=1.0 || (dist<=clist->dmin_interspecies && (clist->cell[neigh_cidx]->vertex[l]->id != vtx->id))) return TS_FAIL;
                         }
                     }
                 }
diff --git a/src/frame.c b/src/frame.c
index aeaef21..237aa87 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2,6 +2,7 @@
 #include "general.h"
 #include "cell.h"
 #include "frame.h"
+
 ts_bool centermass(ts_vesicle *vesicle){
     ts_uint i,j, n=vesicle->vlist->n;
     ts_vertex **vtx=vesicle->vlist->vtx;
diff --git a/src/general.h b/src/general.h
index 79da2ba..8165505 100644
--- a/src/general.h
+++ b/src/general.h
@@ -3,6 +3,7 @@
 
 #include<stdarg.h>
 #include<stdio.h>
+#include<gsl/gsl_complex.h>
 /* @brief This is a header file, defining general constants and structures.
   * @file header.h
   * @author Samo Penic
@@ -47,6 +48,8 @@
 #define TS_FAIL 1
 
 /* CONSTANTS */
+
+#define TS_ID_FILAMENT 1
 
 /* DATA TYPES */
 /** @brief Sets the default datatype for ts_double
@@ -213,12 +216,14 @@
     ts_double dcell;
     ts_double shift;
     ts_double max_occupancy;
+	ts_double dmin_interspecies;
 } ts_cell_list;
 
 
 typedef struct {
     ts_uint l;
     ts_double **ulm;
+    gsl_complex **ulmComplex;
     ts_double **sumUlm2;
     ts_uint N;
     ts_double **co;
diff --git a/src/initial_distribution.c b/src/initial_distribution.c
index 3c27e55..bff9f05 100644
--- a/src/initial_distribution.c
+++ b/src/initial_distribution.c
@@ -11,6 +11,8 @@
 #include "energy.h"
 #include "poly.h"
 #include "io.h"
+#include "sh.h"
+#include "shcomplex.h"
 
 ts_vesicle *initial_distribution_dipyramid(ts_uint nshell, ts_uint ncmax1, ts_uint ncmax2, ts_uint ncmax3, ts_double stepsize){
 	ts_fprintf(stdout,"Starting initial_distribution on vesicle with %u shells!...\n",nshell);
@@ -41,7 +43,9 @@
 
 	vesicle=initial_distribution_dipyramid(tape->nshell,tape->ncxmax,tape->ncymax,tape->nczmax,tape->stepsize);
 	// Nucleus:
-	vesicle->R_nucleus=tape->R_nucleus;
+	vesicle->R_nucleus=tape->R_nucleus*tape->R_nucleus;
+
+	vesicle->clist->dmin_interspecies = tape->dmin_interspecies*tape->dmin_interspecies;
 
 	//Initialize grafted polymers (brush):
 	vesicle->poly_list=init_poly_list(tape->npoly,tape->nmono, vesicle->vlist, vesicle);
@@ -69,6 +73,9 @@
 		}
 	}
 
+	for(i=0;i<vesicle->filament_list->n;i++){
+		vertex_list_assign_id(vesicle->filament_list->poly[i]->vlist,TS_ID_FILAMENT);
+	}
 
 //	vesicle->spring_constant=tape->kspring;
 //	poly_assign_spring_const(vesicle);
@@ -87,7 +94,12 @@
 
 	vesicle->pressure= tape->pressure;
 	vesicle->pswitch=tape->pswitch;
-
+    if(tape->shc>0){
+	    vesicle->sphHarmonics=complex_sph_init(vesicle->vlist,tape->shc);
+    }
+    else {
+        vesicle->sphHarmonics=NULL;
+    }
     return vesicle;
 
 }
diff --git a/src/io.c b/src/io.c
index b222081..d001b7e 100644
--- a/src/io.c
+++ b/src/io.c
@@ -918,6 +918,39 @@
 
 
 
+ts_bool write_pov_file(ts_vesicle *vesicle, char *filename){
+	FILE *fh;
+	ts_uint i;
+	
+	fh=fopen(filename, "w");
+	if(fh==NULL){
+		err("Cannot open file %s for writing");
+		return TS_FAIL;
+	}
+
+	for(i=0;i<vesicle->tlist->n;i++){
+	
+	fprintf(fh,"\ttriangle {");
+	fprintf(fh,"\t<%e,%e,%e> <%e,%e,%e> <%e,%e,%e> }\n", 
+	vesicle->tlist->tria[i]->vertex[0]->x,
+	vesicle->tlist->tria[i]->vertex[0]->y,
+	vesicle->tlist->tria[i]->vertex[0]->z,
+
+	vesicle->tlist->tria[i]->vertex[1]->x,
+	vesicle->tlist->tria[i]->vertex[1]->y,
+	vesicle->tlist->tria[i]->vertex[1]->z,
+
+	vesicle->tlist->tria[i]->vertex[2]->x,
+	vesicle->tlist->tria[i]->vertex[2]->y,
+	vesicle->tlist->tria[i]->vertex[2]->z
+	);
+	}
+		
+	fclose(fh);
+	return TS_SUCCESS;
+}
+
+
 ts_tape *parsetape(char *filename){
   //  long int nshell=17,ncxmax=60, ncymax=60, nczmax=60, npoly=10, nmono=20, pswitch=0;  // THIS IS DUE TO CONFUSE BUG!
     ts_tape *tape=(ts_tape *)calloc(1,sizeof(ts_tape));
@@ -937,6 +970,7 @@
 	CFG_SIMPLE_INT("nfono",&tape->nfono),
 	CFG_SIMPLE_INT("R_nucleus",&tape->R_nucleus),
 	CFG_SIMPLE_FLOAT("dmax", &tape->dmax),
+	CFG_SIMPLE_FLOAT("dmin_interspecies", &tape->dmin_interspecies),
         CFG_SIMPLE_FLOAT("xk0",&tape->xk0),
 	CFG_SIMPLE_INT("pswitch",&tape->pswitch),
 	CFG_SIMPLE_FLOAT("pressure",&tape->pressure),
@@ -954,6 +988,7 @@
         CFG_SIMPLE_INT("smp_cores",&tape->brezveze0),
         CFG_SIMPLE_INT("cluster_nodes",&tape->brezveze1),
         CFG_SIMPLE_INT("distributed_processes",&tape->brezveze2),
+	CFG_SIMPLE_INT("spherical_harmonics_coefficients",&tape->shc),
         CFG_END()
     };
     cfg_t *cfg;    
diff --git a/src/io.h b/src/io.h
index bfc6173..699c73e 100644
--- a/src/io.h
+++ b/src/io.h
@@ -26,6 +26,7 @@
     	long int brezveze2;
     	ts_double xk0;
 	ts_double dmax;
+	ts_double dmin_interspecies;
 	ts_double stepsize;
 	ts_double kspring;
 	ts_double xi;
@@ -34,6 +35,7 @@
 	long int inititer;
 	long int mcsweeps;
 	long int quiet;
+	long int shc;
 } ts_tape;
 
 typedef struct{
@@ -98,6 +100,8 @@
 ts_bool write_vertex_vtk_file(ts_vesicle *vesicle,ts_char *filename, ts_char *text);
 ts_bool write_vertex_xml_file(ts_vesicle *vesicle, ts_uint timestepno);
 ts_bool write_master_xml_file(ts_char *filename);
+ts_bool write_pov_file(ts_vesicle *vesicle, char *filename);
+
 ts_tape *parsetape(char *filename);
 ts_bool tape_free(ts_tape *tape);
 
diff --git a/src/main.c b/src/main.c
index 588e277..25f1343 100644
--- a/src/main.c
+++ b/src/main.c
@@ -11,6 +11,8 @@
 #include "frame.h"
 #include "timestep.h"
 #include "poly.h"
+#include "sh.h"
+#include "shcomplex.h"
 
 /** Entrance function to the program
   * @param argv is a number of parameters used in program call (including the program name
@@ -45,11 +47,20 @@
 		// nove vrednosti iz tapea...
 		vesicle->bending_rigidity=tape->xk0;
 		vtx_set_global_values(vesicle);
+		vesicle->pswitch =tape->pswitch;
 		vesicle->pressure=tape->pressure;
 		vesicle->dmax=tape->dmax*tape->dmax;
 		poly_assign_filament_xi(vesicle,tape);
+		vesicle->clist->dmin_interspecies = tape->dmin_interspecies*tape->dmin_interspecies;
+        /* spherical harmonics */
+        if(tape->shc>0){
+	        vesicle->sphHarmonics=complex_sph_init(vesicle->vlist,tape->shc);
+        }
+        else {
+            vesicle->sphHarmonics=NULL;
+        }
 
-		if(command_line_args.reset_iteration_count) start_iteration=tape->inititer-1;
+		if(command_line_args.reset_iteration_count) start_iteration=tape->inititer;
 		else start_iteration++;
 
 		if(start_iteration>=tape->iterations){
diff --git a/src/poly.c b/src/poly.c
index 5cfc6e0..b2b13f9 100644
--- a/src/poly.c
+++ b/src/poly.c
@@ -58,7 +58,6 @@
 	ts_uint gvtxi;
 	ts_double xnorm,ynorm,znorm,normlength;
 	ts_double dphi,dh;
-	ts_uint ji;
 
 	// Grafting polymers:
 	if (vlist!=NULL){
@@ -108,14 +107,29 @@
 	else
 	{
 	/* Make filaments inside the vesicle. Helix with radius... Dist. between poly vertices put to 1*/
-		dphi = 2.0*asin(1.0/2.0/vesicle->R_nucleus)*1.001;
+	ts_double a,R,H,tantheta,h,r,phi,A0=1.2;
+
+		a = A0*(ts_double)vesicle->nshell;
+		R = A0*((ts_double)vesicle->nshell)/(2.0*sin(M_PI/5.0));
+		H = sqrt(a*a - R*R);
+		tantheta = sqrt(R*R - a*a/4.0)/H;
+		
+		h = -H + sqrt(vesicle->clist->dmin_interspecies)*1.5;
+		r = (H-fabs(h))*tantheta - sqrt(vesicle->clist->dmin_interspecies)*1.5;
+		dphi = 2.0*asin(1.0/2.0/r)*1.001;
 		dh = dphi/2.0/M_PI*1.001;
+		phi=0.0;
 		for(i=0;i<poly_list->n;i++){
 			for (j=0;j<poly_list->poly[i]->vlist->n;j++){
-				ji = j + i*poly_list->poly[i]->vlist->n;
-				poly_list->poly[i]->vlist->vtx[j]->x = vesicle->R_nucleus*cos(ji*dphi);
-				poly_list->poly[i]->vlist->vtx[j]->y = vesicle->R_nucleus*sin(ji*dphi);
-				poly_list->poly[i]->vlist->vtx[j]->z = ji*dh - (dh*poly_list->n*poly_list->poly[i]->vlist->n/2.0);
+				h = h + dh;
+				r = (H-fabs(h))*tantheta - sqrt(vesicle->clist->dmin_interspecies)*1.5;
+				dphi = 2.0*asin(1.0/2.0/r)*1.001;
+				dh = dphi/2.0/M_PI*1.001;
+				phi+=dphi;
+				//ji = j + i*poly_list->poly[i]->vlist->n;
+				poly_list->poly[i]->vlist->vtx[j]->x = r*cos(phi);
+				poly_list->poly[i]->vlist->vtx[j]->y = r*sin(phi);
+				poly_list->poly[i]->vlist->vtx[j]->z = h;// ji*dh - (dh*poly_list->n*poly_list->poly[i]->vlist->n/2.0);
 			}
 		}
 	}
diff --git a/src/sh.c b/src/sh.c
index 0c4b06d..f5c310a 100644
--- a/src/sh.c
+++ b/src/sh.c
@@ -49,6 +49,7 @@
 
 ts_bool sph_free(ts_spharm *sph){
     int i,j;
+    if(sph==NULL) return TS_FAIL;
     for(i=0;i<sph->l;i++){
         if(sph->ulm[i]!=NULL) free(sph->ulm[i]);
         if(sph->sumUlm2[i]!=NULL) free(sph->sumUlm2[i]);
@@ -189,7 +190,7 @@
 		K=-sqrt(1.0/(M_PI))*cos(m*fi);
 	}
 	
-	return K*sqrt((2.0*l+1.0)/2.0*fac1/fac2)*plgndr(l,abs(m),cos(theta));	
+	return K*sqrt((2.0*l+1.0)/2.0*(ts_double)(fac1/fac2))*plgndr(l,abs(m),cos(theta));	
 }
 
 
@@ -200,7 +201,7 @@
 #ifdef TS_DOUBLE_DOUBLE
     coord->e1=sqrt(x*x+y*y+z*z);
     if(z==0) coord->e3=M_PI/2.0;
-    else coord->e3=atan(sqrt(x*x+y*y)/z);
+    else coord->e3=atan2(sqrt(x*x+y*y),z);
     coord->e2=atan2(y,x);
 #endif
 #ifdef TS_DOUBLE_FLOAT
@@ -218,6 +219,23 @@
 
     return TS_SUCCESS;
 }
+
+
+ts_bool sph2cart(ts_coord *coord){
+    coord->coord_type=TS_COORD_CARTESIAN;
+    ts_double x,y,z;
+
+    x=coord->e1*cos(coord->e2)*sin(coord->e3);
+    y=coord->e1*sin(coord->e2)*sin(coord->e3);
+    z=coord->e1*cos(coord->e3);
+
+    coord->e1=x;
+    coord->e2=y;
+    coord->e3=z;
+
+    return TS_SUCCESS;
+}
+
 
 /* Function returns radius of the sphere with the same volume as vesicle (r0) */
 ts_double getR0(ts_vesicle *vesicle){
@@ -379,3 +397,28 @@
 	sph->N++;
 return TS_SUCCESS;
 }
+
+
+ts_bool saveAvgUlm2(ts_vesicle *vesicle){
+
+	FILE *fh;
+	
+	fh=fopen("sph2out.dat", "w");
+	if(fh==NULL){
+		err("Cannot open file %s for writing");
+		return TS_FAIL;
+	}
+
+	ts_spharm *sph=vesicle->sphHarmonics;
+	ts_int i,j;
+	fprintf(fh,"l,\tm,\tulm^2avg\n");
+	for(i=0;i<sph->l;i++){
+    		for(j=0;j<2*i+1;j++){
+		fprintf(fh,"%d,\t%d,\t%e\n", i, j-i, sph->sumUlm2[i][j]/(ts_double)sph->N);
+
+    		}
+    fprintf(fh,"\n");
+	}
+	fclose(fh);
+	return TS_SUCCESS;
+}
diff --git a/src/sh.h b/src/sh.h
index 7853139..dabece2 100644
--- a/src/sh.h
+++ b/src/sh.h
@@ -6,6 +6,7 @@
 ts_double shY(ts_int l,ts_int m,ts_double theta,ts_double fi);
 
 ts_bool *cart2sph(ts_coord *coord, ts_double x, ts_double y, ts_double z);
+ts_bool sph2cart(ts_coord *coord);
 ts_bool precomputeShCoeff(ts_spharm *sph);
 ts_spharm *sph_init(ts_vertex_list *vlist, ts_uint l);
 ts_bool sph_free(ts_spharm *sph);
@@ -13,4 +14,5 @@
 ts_bool preparationSh(ts_vesicle *vesicle, ts_double r0);
 ts_bool calculateYlmi(ts_vesicle *vesicle);
 ts_bool calculateUlm(ts_vesicle *vesicle);
+ts_bool saveAvgUlm2(ts_vesicle *vesicle);
 #endif
diff --git a/src/shcomplex.c b/src/shcomplex.c
new file mode 100644
index 0000000..7d8c9d8
--- /dev/null
+++ b/src/shcomplex.c
@@ -0,0 +1,172 @@
+#include<math.h>
+#include<stdlib.h>
+#include<gsl/gsl_complex.h>
+#include<gsl/gsl_complex_math.h>
+#include<gsl/gsl_sf_legendre.h>
+
+#include<gsl/gsl_matrix.h>
+#include<gsl/gsl_vector.h>
+#include<gsl/gsl_linalg.h>
+#include "general.h"
+#include "sh.h"
+#include "shcomplex.h"
+
+
+ts_spharm *complex_sph_init(ts_vertex_list *vlist, ts_uint l){
+    ts_uint j,i;
+    ts_spharm *sph=(ts_spharm *)malloc(sizeof(ts_spharm));
+
+    sph->N=0;
+    /* lets initialize Ylm for each vertex. */
+    sph->Ylmi=(ts_double ***)calloc(l,sizeof(ts_double **));
+    for(i=0;i<l;i++){
+            sph->Ylmi[i]=(ts_double **)calloc(2*i+1,sizeof(ts_double *));
+            for(j=0;j<(2*i+1);j++){
+                sph->Ylmi[i][j]=(ts_double *)calloc(vlist->n,sizeof(ts_double));
+            }
+    }
+        
+    /* lets initialize ulm */
+    sph->ulm=(ts_double **)calloc(l,sizeof(ts_double *));
+    sph->ulmComplex=(gsl_complex **)calloc(l,sizeof(gsl_complex *));
+    for(j=0;j<l;j++){
+        sph->ulm[j]=(ts_double *)calloc(2*j+1,sizeof(ts_double));
+        sph->ulmComplex[j]=(gsl_complex *)calloc(2*j+1,sizeof(gsl_complex));
+    }
+
+    /* lets initialize sum of Ulm2 */
+    sph->sumUlm2=(ts_double **)calloc(l,sizeof(ts_double *));
+    for(j=0;j<l;j++){
+        sph->sumUlm2[j]=(ts_double *)calloc(2*j+1,sizeof(ts_double));
+    }
+
+    /* lets initialize co */
+//NOTE: C is has zero based indexing. Code is imported from fortran and to comply with original indexes we actually generate one index more. Also second dimension is 2*j+2 instead of 2*j+2. elements starting with 0 are useles and should be ignored!
+    sph->co=(ts_double **)calloc(l+1,sizeof(ts_double *));
+    for(j=0;j<=l;j++){
+        sph->co[j]=(ts_double *)calloc(2*j+2,sizeof(ts_double));
+    }
+
+    sph->l=l;   
+
+    /* Calculate coefficients that will remain constant during all the simulation */ 
+   precomputeShCoeff(sph);
+    
+    return sph;
+}
+
+ts_bool complex_sph_free(ts_spharm *sph){
+    int i,j;
+    if(sph==NULL) return TS_FAIL;
+    for(i=0;i<sph->l;i++){
+        if(sph->ulm[i]!=NULL) free(sph->ulm[i]);
+        if(sph->ulmComplex[i]!=NULL) free(sph->ulmComplex[i]);
+        if(sph->sumUlm2[i]!=NULL) free(sph->sumUlm2[i]);
+        if(sph->co[i]!=NULL) free(sph->co[i]);
+    }
+        if(sph->co[sph->l]!=NULL) free(sph->co[sph->l]);
+    if(sph->co != NULL) free(sph->co);
+    if(sph->ulm !=NULL) free(sph->ulm);
+    if(sph->ulmComplex !=NULL) free(sph->ulmComplex);
+
+        if(sph->Ylmi!=NULL) {
+            for(i=0;i<sph->l;i++){
+                if(sph->Ylmi[i]!=NULL){
+                    for(j=0;j<i*2+1;j++){
+                        if(sph->Ylmi[i][j]!=NULL) free (sph->Ylmi[i][j]);
+                    }
+                    free(sph->Ylmi[i]);
+                }
+            }
+            free(sph->Ylmi);
+        }
+
+    free(sph);
+    return TS_SUCCESS;
+}
+
+
+ts_bool calculateUlmComplex(ts_vesicle *vesicle){
+    ts_int i,j,k,m,l;
+    ts_vertex *cvtx;
+    ts_coord coord;
+/* set all values to zero */
+    for(i=0;i<vesicle->sphHarmonics->l;i++){
+        for(j=0;j<2*i+1;j++) GSL_SET_COMPLEX(&(vesicle->sphHarmonics->ulmComplex[i][j]),0.0,0.0);
+    }
+
+    for(k=0;k<vesicle->vlist->n; k++){
+        cvtx=vesicle->vlist->vtx[k];
+	cart2sph(&coord,cvtx->x,cvtx->y,cvtx->z);
+        for(i=0;i<vesicle->sphHarmonics->l;i++){
+            for(j=0;j<2*i+1;j++){
+		m=j-i;
+		l=i;
+		if(m>=0){	
+	//	fprintf(stderr, "Racunam za l=%d, m=%d\n", l,m);
+                vesicle->sphHarmonics->ulmComplex[i][j]=gsl_complex_add(vesicle->sphHarmonics->ulmComplex[i][j], gsl_complex_conjugate(gsl_complex_mul_real(gsl_complex_polar(1.0,(ts_double)m*coord.e2),cvtx->solAngle*cvtx->relR*gsl_sf_legendre_sphPlm(l,m,cos(coord.e3)))) );
+		} else {
+	//	fprintf(stderr, "Racunam za l=%d, abs(m=%d)\n", l,m);
+                vesicle->sphHarmonics->ulmComplex[i][j]=gsl_complex_add(vesicle->sphHarmonics->ulmComplex[i][j], gsl_complex_conjugate(gsl_complex_mul_real(gsl_complex_polar(1.0,(ts_double)m*coord.e2),cvtx->solAngle*cvtx->relR*pow(-1,m)*gsl_sf_legendre_sphPlm(l,-m,cos(coord.e3)))) );
+
+		}
+            }
+        }
+    }
+    return TS_SUCCESS;
+}
+
+ts_bool storeUlmComplex2(ts_vesicle *vesicle){
+
+	ts_spharm *sph=vesicle->sphHarmonics;
+	ts_int i,j;
+	for(i=0;i<sph->l;i++){
+    		for(j=0;j<2*i+1;j++){
+        		sph->sumUlm2[i][j]+=gsl_complex_abs2(sph->ulmComplex[i][j]);
+    		}
+	}
+	sph->N++;
+	return TS_SUCCESS;
+}
+
+
+ts_double calculateKc(ts_vesicle *vesicle, ts_int lmin, ts_int lmax){
+    ts_int min=lmin;
+    ts_int max=lmax; //vesicle->sphHarmonics->l-3;
+    ts_long i,j;
+    ts_double retval, bval;
+    gsl_matrix *A=gsl_matrix_alloc(max-min,2);
+    gsl_vector *tau=gsl_vector_alloc(2);
+    gsl_vector *b=gsl_vector_alloc(max-min);
+    gsl_vector *x=gsl_vector_alloc(2);
+    gsl_vector *res=gsl_vector_alloc(max-min);
+
+    //solving (A^T*A)*x=A^T*b
+    //fill the data for matrix A and vector b
+    for(i=min;i<max;i++){
+            gsl_matrix_set(A, i-min,0,(ts_double)((i-1)*(i+2)));
+            gsl_matrix_set(A, i-min,1,(ts_double)((i-1)*(i+2)*(i+1)*i));
+//            fprintf(stderr,"%e %e\n", gsl_matrix_get(A,i-min,0), gsl_matrix_get(A,i-min,1));
+            bval=0.0;
+            //average for m from 0..l (only positive m's)
+            for(j=0;j<=i;j++){
+                bval+=vesicle->sphHarmonics->sumUlm2[i][(j+i)];
+            }
+                bval=bval/(ts_double)vesicle->sphHarmonics->N/(ts_double)(i+1);
+
+            gsl_vector_set(b,i-min,1.0/bval);
+//            fprintf(stderr,"%e\n", 1.0/gsl_vector_get(b,i-min));
+    }
+//    fprintf(stderr,"b[2]=%e\n",gsl_vector_get(b,1));
+    gsl_linalg_QR_decomp(A,tau);
+    gsl_linalg_QR_lssolve(A,tau,b,x,res);
+//    fprintf(stderr,"kc=%e\n",gsl_vector_get(x,1));
+    retval=gsl_vector_get(x,1);
+    gsl_matrix_free(A);
+    gsl_vector_free(tau);
+    gsl_vector_free(b);
+    gsl_vector_free(x);
+    gsl_vector_free(res);
+    
+    return retval;
+}
diff --git a/src/shcomplex.h b/src/shcomplex.h
new file mode 100644
index 0000000..fdd0eb0
--- /dev/null
+++ b/src/shcomplex.h
@@ -0,0 +1,9 @@
+#ifndef _H_SH_COMPLEX
+#define _H_SH_COMPLEX
+#include "general.h"
+ts_bool storeUlmComplex2(ts_vesicle *vesicle);
+ts_spharm *complex_sph_init(ts_vertex_list *vlist, ts_uint l);
+ts_bool complex_sph_free(ts_spharm *sph);
+ts_bool calculateUlmComplex(ts_vesicle *vesicle);
+ts_double calculateKc(ts_vesicle *vesicle, ts_int lmin, ts_int lmax);
+#endif
diff --git a/src/spherical_trisurf.c b/src/spherical_trisurf.c
index 7fa40f9..0669981 100644
--- a/src/spherical_trisurf.c
+++ b/src/spherical_trisurf.c
@@ -61,10 +61,11 @@
 calculateUlm(vesicle);
 
 //preloop:
+ts_double vmsr, bfsr;
 for(i=0;i<1000;i++){
 	cell_occupation(vesicle);
 	for(j=0;j<1000;j++){
-		single_timestep(vesicle);
+		single_timestep(vesicle, &vmsr, &bfsr);
 	}	
 	centermass(vesicle);
 	fprintf(stderr, "Preloop %d completed.\n",i+1);
@@ -75,7 +76,7 @@
 	for(j=0;j<200;j++){
 		cell_occupation(vesicle);
 		for(k=0;k<5;k++){
-		single_timestep(vesicle);
+		single_timestep(vesicle, &vmsr, &bfsr);
 		}
 		centermass(vesicle);
 	}	
@@ -103,26 +104,3 @@
 
 
 
-ts_bool saveAvgUlm2(ts_vesicle *vesicle){
-
-	FILE *fh;
-	
-	fh=fopen("sph2out.dat", "w");
-	if(fh==NULL){
-		err("Cannot open file %s for writing");
-		return TS_FAIL;
-	}
-
-	ts_spharm *sph=vesicle->sphHarmonics;
-	ts_int i,j;
-	fprintf(fh,"l,\tm,\tulm^2avg\n");
-	for(i=0;i<sph->l;i++){
-    		for(j=0;j<2*i+1;j++){
-		fprintf(fh,"%d,\t%d,\t%e\n", i, j-i, sph->sumUlm2[i][j]/(ts_double)sph->N);
-
-    		}
-    fprintf(fh,"\n");
-	}
-	fclose(fh);
-	return TS_SUCCESS;
-}
diff --git a/src/spherical_trisurf_ff.c b/src/spherical_trisurf_ff.c
index 867f37d..157b0e4 100644
--- a/src/spherical_trisurf_ff.c
+++ b/src/spherical_trisurf_ff.c
@@ -44,10 +44,11 @@
 preparationSh(vesicle,r0);
 calculateYlmi(vesicle);
 calculateUlm(vesicle);
+ts_double vmsr,bfsr;
 for(i=0;i<500;i++){
 	cell_occupation(vesicle);
 	for(j=0;j<1000;j++){
-		single_timestep(vesicle);
+		single_timestep(vesicle,&vmsr,&bfsr);
 	}	
 	centermass(vesicle);
 	fprintf(stderr, "Preloop %d completed.\n",i+1);
@@ -62,7 +63,7 @@
 for(i=0;i<10000;i++){
 	cell_occupation(vesicle);
 	for(j=0;j<1000;j++){
-		single_timestep(vesicle);
+		single_timestep(vesicle,&vmsr,&bfsr);
 	}	
 	centermass(vesicle);
     vesicle_volume(vesicle);
@@ -86,27 +87,3 @@
 }
 
 
-
-ts_bool saveAvgUlm2(ts_vesicle *vesicle){
-
-	FILE *fh;
-	
-	fh=fopen("sph2out.dat", "w");
-	if(fh==NULL){
-		err("Cannot open file %s for writing");
-		return TS_FAIL;
-	}
-
-	ts_spharm *sph=vesicle->sphHarmonics;
-	ts_int i,j;
-	fprintf(fh,"l,\tm,\tulm^2avg\n");
-	for(i=0;i<sph->l;i++){
-    		for(j=0;j<2*i+1;j++){
-		fprintf(fh,"%d,\t%d,\t%e\n", i, j-i, sph->sumUlm2[i][j]/(ts_double)sph->N);
-
-    		}
-    fprintf(fh,"\n");
-	}
-	fclose(fh);
-	return TS_SUCCESS;
-}
diff --git a/src/stats.c b/src/stats.c
new file mode 100644
index 0000000..077781e
--- /dev/null
+++ b/src/stats.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <time.h>
+//#include <gsl/gsl_math.h>
+//#include <gsl/gsl_blas.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_eigen.h>
+#include <gsl/gsl_sort_vector.h>
+#include "general.h"
+ 
+void gyration_eigen(ts_vesicle *vesicle, ts_double *l1, ts_double *l2, ts_double *l3){
+	gsl_matrix *matrix = gsl_matrix_alloc(3,3);
+	gsl_vector *eig = gsl_vector_alloc(3);
+	gsl_eigen_symm_workspace *workspace = gsl_eigen_symm_alloc(3);
+	ts_uint i,j,k;
+	ts_double mat[3][3];
+	ts_double vec[3];
+
+	for(i = 0; i < 3; i++)
+        	for(j = 0; j < 3; j++)
+            		mat[i][j]=0;
+ 
+	for(k=0;k<vesicle->vlist->n;k++){
+		vec[0]=vesicle->vlist->vtx[k]->x;
+		vec[1]=vesicle->vlist->vtx[k]->y;
+		vec[2]=vesicle->vlist->vtx[k]->z;
+		for(i = 0; i < 3; i++)
+        		for(j = 0; j <= i; j++)
+				mat[i][j]+=vec[i]*vec[j];
+	}
+
+// Normalize gyration tensor:
+	for(i = 0; i < 3; i++)
+        	for(j = 0; j <= i; j++)
+			mat[i][j]=mat[i][j]/(ts_double)vesicle->vlist->n;
+
+
+// diagonal elements are copied twice!	
+	for(i = 0; i < 3; i++)
+        	for(j = 0; j <= i; j++){
+            		gsl_matrix_set(matrix,i,j,mat[i][j]);
+            		gsl_matrix_set(matrix,j,i,mat[i][j]);
+	}
+/*
+for(i = 0; i < 3; i++)
+    {
+        for(j = 0; j < 3; j++)
+            printf("%g ", gsl_matrix_get(matrix, i, j));
+        printf("\n");
+    }
+    printf("\n");
+*/
+	gsl_eigen_symm(matrix, eig, workspace);
+	gsl_sort_vector(eig);
+/* printf("** eigenvalues    \n");
+    for(i = 0; i < 3; i++){
+        printf("%3d %25.17e\n", i, gsl_vector_get(eig, i));
+} */
+	*l1=gsl_vector_get(eig,0);
+	*l2=gsl_vector_get(eig,1);
+	*l3=gsl_vector_get(eig,2);
+
+	gsl_eigen_symm_free(workspace);
+	gsl_matrix_free(matrix);
+	gsl_vector_free(eig);
+}
+
+ts_ulong get_epoch(){
+	time_t currTime;
+	currTime = time(NULL);
+	return (ts_ulong)currTime;
+}
+
+ts_bool get_area_volume(ts_vesicle *vesicle, ts_double *area, ts_double *volume){
+	ts_uint i;
+	*volume=0.0;
+	*area=0.0;
+	for(i=0;i<vesicle->tlist->n;i++){
+		*volume+=vesicle->tlist->tria[i]->volume;
+		*area+=vesicle->tlist->tria[i]->area;
+	}
+	return TS_SUCCESS;
+} 
diff --git a/src/stats.h b/src/stats.h
new file mode 100644
index 0000000..223a99b
--- /dev/null
+++ b/src/stats.h
@@ -0,0 +1,6 @@
+#ifndef _H_STATS
+#define _H_STATS
+void gyration_eigen(ts_vesicle *vesicle, ts_double *l1, ts_double *l2, ts_double *l3);
+ts_ulong get_epoch();
+ts_bool get_area_volume(ts_vesicle *vesicle, ts_double *area, ts_double *volume);
+#endif
diff --git a/src/tape b/src/tape
index bd62b6c..0801375 100644
--- a/src/tape
+++ b/src/tape
@@ -3,6 +3,8 @@
 nshell=17
 # dmax is the max. bond length (in units l_min)
 dmax=1.7
+# dmin_interspecies in the min. dist. between different vertex species (in units l_min)
+dmin_interspecies=1.2
 # bending rigidity of the membrane (in units kT)
 xk0=10.0
 # max step size (in units l_min)
@@ -12,11 +14,11 @@
 # (pswitch=1: calc. p*dV energy contribution)
 pswitch = 0
 # pressure difference: p_inside - p_outside (in units kT/l_min^3):
-pressure=0.1
+pressure=0.0
 
 ####### Polymer (brush) definitions ###########
 # npoly is a number of polymers attached to npoly distinct vertices on vesicle
-npoly=300
+npoly=0
 # nmono is a number of monomers in each polymer
 nmono=10
 # Spring constant between monomers of the polymer
@@ -24,15 +26,15 @@
 
 ####### Filament (inside the vesicle) definitions ###########
 # nfil is a number of filaments inside the vesicle
-nfil=1
+nfil=0
 # nfono is a number of monomers in each filament
 nfono=300
 # Persistence lenght of the filaments (in units l_min)
-xi=100
+xi=0
 
 ####### Nucleus (inside the vesicle) ###########
 # Radius of an impenetrable hard sphere inside the vesicle
-R_nucleus=5
+R_nucleus=0
 
 #######  Cell definitions ############
 nxmax=60
@@ -42,13 +44,16 @@
 
 ####### Program Control ############
 #how many MC sweeps between subsequent records of states to disk
-mcsweeps=500
+mcsweeps=2500
 #how many initial mcsweeps*inititer MC sweeps before recording to disk?
 inititer=0
 #how many records do you want on the disk iteration are there in a run?
-iterations=20
+iterations=15000
 
 
+###### Spherical harmonics ###########
+spherical_harmonics_coefficients=21
+
 #shut up if we are using cluster!!!
 quiet=false
 
diff --git a/src/timestep.c b/src/timestep.c
index d631d42..a8f0f94 100644
--- a/src/timestep.c
+++ b/src/timestep.c
@@ -8,51 +8,103 @@
 #include "bondflip.h"
 #include "frame.h"
 #include "io.h"
+#include "stats.h"
+#include "sh.h"
+#include "shcomplex.h"
+#include "vesicle.h"
 
 ts_bool run_simulation(ts_vesicle *vesicle, ts_uint mcsweeps, ts_uint inititer, ts_uint iterations, ts_uint start_iteration){
-	ts_uint i, j;
-
+	ts_uint i, j,k;
+	ts_double r0,kc1,kc2,kc3,kc4;
+	ts_double l1,l2,l3,volume=0.0,area=0.0,vmsr,bfsr, vmsrt, bfsrt;
+	ts_ulong epochtime;
+	FILE *fd1;
+// 	char filename[255];
+	FILE *fd=fopen("statistics.csv","w");
+	if(fd==NULL){
+		fatal("Cannot open statistics.csv file for writing",1);
+	}
+	fprintf(fd, "Epoch OuterLoop VertexMoveSucessRate BondFlipSuccessRate Volume Area lamdba1 lambda2 lambda3 Kc(2-9) Kc(6-9) Kc(2-end) Kc(3-6)\n");
 	centermass(vesicle);
 	cell_occupation(vesicle);
 	if(start_iteration<inititer) ts_fprintf(stdout, "Starting simulation (first %d x %d MC sweeps will not be recorded on disk)\n", inititer, mcsweeps);
 	for(i=start_iteration;i<inititer+iterations;i++){
+		vmsr=0.0;
+		bfsr=0.0;
 		for(j=0;j<mcsweeps;j++){
-			single_timestep(vesicle);
+			single_timestep(vesicle, &vmsrt, &bfsrt);
+			vmsr+=vmsrt;
+			bfsr+=bfsrt;
 		}
+		vmsr/=(ts_double)mcsweeps;
+		bfsr/=(ts_double)mcsweeps;
 		centermass(vesicle);
 		cell_occupation(vesicle);
 		ts_fprintf(stdout,"Done %d out of %d iterations (x %d MC sweeps).\n",i+1,inititer+iterations,mcsweeps);
             dump_state(vesicle,i);
 		if(i>=inititer){
 			write_vertex_xml_file(vesicle,i-inititer);
+			write_master_xml_file("test.pvd");
+			epochtime=get_epoch();			
+			gyration_eigen(vesicle, &l1, &l2, &l3);
+			vesicle_volume(vesicle); //calculates just volume. Area is not added to ts_vesicle yet!
+			get_area_volume(vesicle, &area,&volume); //that's why I must recalculate area (and volume for no particular reason).
+			r0=getR0(vesicle);
+            if(vesicle->sphHarmonics!=NULL){
+			    preparationSh(vesicle,r0);
+			    //calculateYlmi(vesicle);
+			    calculateUlmComplex(vesicle);
+			    storeUlmComplex2(vesicle);
+			    saveAvgUlm2(vesicle);
+                kc1=calculateKc(vesicle, 2,9);
+                kc2=calculateKc(vesicle, 6,9);
+                kc3=calculateKc(vesicle, 2,vesicle->sphHarmonics->l);
+                kc4=calculateKc(vesicle, 3,6);
+            
+				fd1=fopen("state.dat","w");
+				fprintf(fd1,"%e %e\n",vesicle->volume, getR0(vesicle));
+				for(k=0;k<vesicle->vlist->n;k++){
+					fprintf(fd1,"%e %e %e %e %e\n",
+						vesicle->vlist->vtx[k]->x,
+						vesicle->vlist->vtx[k]->y,
+						vesicle->vlist->vtx[k]->z,
+						vesicle->vlist->vtx[k]->solAngle,
+						vesicle->vlist->vtx[k]->relR
+					);
+				}
+				fclose(fd1);
+            }
+
+			fprintf(fd, "%lu %u %e %e %1.16e %1.16e %1.16e %1.16e %1.16e %1.16e %1.16e %1.16e %1.16e\n",epochtime,i,vmsr,bfsr,volume, area,l1,l2,l3,kc1, kc2, kc3,kc4);
+		    fflush(fd);	
+		//	sprintf(filename,"timestep-%05d.pov",i-inititer);
+		//	write_pov_file(vesicle,filename);
 		}
 	}
+	fclose(fd);
 	return TS_SUCCESS;
 }
 
-ts_bool single_timestep(ts_vesicle *vesicle){
+ts_bool single_timestep(ts_vesicle *vesicle,ts_double *vmsr, ts_double *bfsr){
     ts_bool retval;
     ts_double rnvec[3];
     ts_uint i,j,b;
+    ts_uint vmsrcnt=0;
     for(i=0;i<vesicle->vlist->n;i++){
         rnvec[0]=drand48();
         rnvec[1]=drand48();
         rnvec[2]=drand48();
         retval=single_verticle_timestep(vesicle,vesicle->vlist->vtx[i],rnvec);
+	if(retval==TS_SUCCESS) vmsrcnt++;        
     }
 
-//	ts_int cnt=0;
+	ts_int bfsrcnt=0;
     for(i=0;i<3*vesicle->vlist->n;i++){
-//why is rnvec needed in bondflip?
-/*        rnvec[0]=drand48();
-        rnvec[1]=drand48();
-        rnvec[2]=drand48();
-*/ 
 	b=rand() % vesicle->blist->n;
         //find a bond and return a pointer to a bond...
         //call single_bondflip_timestep...
         retval=single_bondflip_timestep(vesicle,vesicle->blist->bond[b],rnvec);
-//	if(retval==TS_SUCCESS) cnt++;        
+	if(retval==TS_SUCCESS) bfsrcnt++;        
     }
 
 	for(i=0;i<vesicle->poly_list->n;i++){
@@ -76,7 +128,8 @@
  
 
 //	printf("Bondflip success rate in one sweep: %d/%d=%e\n", cnt,3*vesicle->blist->n,(double)cnt/(double)vesicle->blist->n/3.0);
-	if(retval);
+	*vmsr=(ts_double)vmsrcnt/(ts_double)vesicle->vlist->n;
+	*bfsr=(ts_double)bfsrcnt/(ts_double)vesicle->vlist->n/3.0;
     return TS_SUCCESS;
 }
 
diff --git a/src/timestep.h b/src/timestep.h
index dd18481..0d8dc74 100644
--- a/src/timestep.h
+++ b/src/timestep.h
@@ -1,5 +1,5 @@
 #ifndef _TIMESTEP_H
 #define _TIMESTEP_H
-ts_bool single_timestep(ts_vesicle *vesicle);
+ts_bool single_timestep(ts_vesicle *vesicle, ts_double *vmsr, ts_double *bfsr);
 ts_bool run_simulation(ts_vesicle *vesicle, ts_uint mcsweeps, ts_uint inititer, ts_uint iterations, ts_uint start_simulation);
 #endif
diff --git a/src/triangle.c b/src/triangle.c
index 311e138..7dd5a6e 100644
--- a/src/triangle.c
+++ b/src/triangle.c
@@ -5,6 +5,7 @@
 #include<math.h>
 
 /** @brief Prepares the list for triangles.
+  * @returns pointer to empty data structure for maintaining triangle list.
   *
   * Create empty list for holding the information on triangles. Triangles are
   * added later on with triangle_add().
@@ -27,14 +28,17 @@
 }
 
 /** @brief Add the triangle to the triangle list and create necessary data
- * structures.
+  * structures.
+  * @param *tlist is a pointer to triangle list where triangle should be created
+  * @param *vtx1, *vtx2, *vtx3 are the three vertices defining the triangle
+  * @returns pointer to the newly created triangle on success and NULL if
+  * triangle could not be created. It breaks program execution if memory
+  * allocation of triangle list can't be done.
   *
-  * Add the triangle ts_triangle with ts_triangle_data to the ts_triangle_list.
+  * Add the triangle ts_triangle to the ts_triangle_list.
   * The triangle list is resized, the ts_triangle is allocated and
-  * ts_triangle_data is allocated and zeroed. The function receives 4 arguments:
-  * ts_triangle_list *tlist as list of triangles and 3 ts_vertex *vtx as
-  * vertices that are used to form a triangle. Returns a pointer to newly
-  * created triangle. This pointer doesn't need assigning, since it is
+  * triangle data is zeroed. Returned pointer to newly
+  * created triangle doesn't need assigning, since it is
   * referenced by triangle list.
   *
   * WARNING: Function can be accelerated a bit by removing the NULL checks.
@@ -57,7 +61,6 @@
 
         tlist->tria[tlist->n-1]=(ts_triangle *)calloc(1,sizeof(ts_triangle));
         if(tlist->tria[tlist->n-1]==NULL) fatal("Cannot reallocate memory for additional ts_triangle.",5);
-  //      tlist->tria[tlist->n-1]->data=(ts_triangle_data *)calloc(1,sizeof(ts_triangle_data));
 
         //NOW insert vertices!
         tlist->tria[tlist->n - 1]->idx=tlist->n-1;
@@ -68,9 +71,14 @@
 }
 
 /** @brief Add the neigbour to triangles.
+  * @param *tria is a first triangle.
+  * @param *ntria is a second triangle.
+  * @returns TS_SUCCES on sucessful adition to the list, TS_FAIL if triangles
+  * are NULL and breaks execution FATALY if memory allocation error occurs.
   *
   * Add the neigbour to the list of neighbouring triangles. The
-  * neighbouring triangles are those, who share two vertices. Function resizes
+  * neighbouring triangles are those, who share two vertices and corresponding
+  * bond. Function resizes
   * the list and adds the pointer to neighbour. It receives two arguments of
   * ts_triangle type. It then adds second triangle to the list of first
   * triangle, but not the opposite. Upon
@@ -84,42 +92,40 @@
   * debugging stupid NULL pointers.
   *
   * Example of usage:
-  *		triangle_remove_neighbour(tlist->tria[3], tlist->tria[4]);
+  *		triangle_add_neighbour(tlist->tria[3], tlist->tria[4]);
   *
-  *	    Triangles 3 and 4 are not neighbours anymore.
+  *	    Triangle 4 is a neighbour of triangle 3, but (strangely) not the
+  *	    oposite. The function should be called again with the changed order of
+  *	    triangles to make neighbourship mutual.
   *		
   */
 
 ts_bool triangle_add_neighbour(ts_triangle *tria, ts_triangle *ntria){
     if(tria==NULL || ntria==NULL) return TS_FAIL;
-/*TODO: check if the neighbour already exists! Now there is no such check
- * because of the performance issue. */
 	tria->neigh_no++;
 	tria->neigh=realloc(tria->neigh,tria->neigh_no*sizeof(ts_triangle *));
 	if(tria->neigh == NULL)
 			fatal("Reallocation of memory failed during insertion of triangle neighbour in triangle_add_neighbour",3);
-	tria->neigh[tria->neigh_no-1]=ntria;
-  
- 
-/* we repeat the procedure for the neighbour */  
-/*	ntria->data->neigh_no++;
-	ntria->data->neigh=realloc(ntria->data->neigh,ntria->data->neigh_no*sizeof(ts_triangle *));
-	if(ntria->data->neigh == NULL)
-			fatal("Reallocation of memory failed during insertion of triangle neighbour in triangle_add_neighbour",3);
-	ntria->data->neigh[ntria->data->neigh_no-1]=tria;
-*/
+	tria->neigh[tria->neigh_no-1]=ntria; 
 	return TS_SUCCESS;
 }
 
 /** @brief Remove the neigbours from triangle.
+  * @param *tria is a first triangle.
+  * @param *ntria is neighbouring triangle.
+  * @returns TS_SUCCESS on successful removal, TS_FAIL if triangles are not
+  * neighbours and it breaks program execution FATALY if memory allocation
+  * problem occurs.
   *
   * Removes the neigbour from the list of neighbouring triangles. The
-  * neighbouring triangles are those, who share two vertices. Function resizes
+  * neighbouring triangles are those, who share two vertices and corresponding
+  * bond. Function resizes
   * the list and deletes the pointer to neighbour. It receives two arguments of
-  * ts_triangle type. It then removes eachother form eachother's list. Upon
+  * ts_triangle type. It then mutually removes triangles from eachouther
+  * neighbour list. Upon
   * success it returns TS_SUCCESS, upon failure to find the triangle in the
-  * neighbour list returns TS_FAIL and it FATALY ends when the datastructure
-  * cannot be resized.
+  * neighbour list returns TS_FAIL. It FATALY breaks program execution when the datastructure
+  * cannot be resized due to memory constrain problems.
   *
   * WARNING: The function doesn't check whether the pointer is NULL or invalid. It is the
   * job of programmer to make sure the pointer is valid.
@@ -144,10 +150,8 @@
     }
     if(j==i) {
         return TS_FAIL; 
-        //fatal("In triangle_remove_neighbour: Specified neighbour does not exist for given triangle",3);
     }
     tria->neigh_no--;
-//	fprintf(stderr,"*** tria_number=%d\n",tria->neigh_no);
     tria->neigh=(ts_triangle **)realloc(tria->neigh,tria->neigh_no*sizeof(ts_triangle *));
 	if(tria->neigh == NULL){
 		fprintf(stderr,"Ooops: tria->neigh_no=%d\n",tria->neigh_no);
@@ -163,10 +167,8 @@
     }
     if(j==i) {
         return TS_FAIL; 
-        //fatal("In triangle_remove_neighbour: Specified neighbour does not exist for given triangle",3);
     }
     ntria->neigh_no--;
-//	fprintf(stderr,"*** ntria_number=%d\n",ntria->neigh_no);
     ntria->neigh=(ts_triangle **)realloc(ntria->neigh,ntria->neigh_no*sizeof(ts_triangle *));
 	if(ntria->neigh == NULL){
 		fprintf(stderr,"Ooops: ntria->neigh_no=%d\n",ntria->neigh_no);
@@ -176,25 +178,33 @@
 }
 
 
-/** @brief Calculates normal vector of the triangle.
-
+/** @brief Calculates normal vector of the triangle, its corresponding area and volume.
+  * @param *tria is a triangle pointer for which normal, area and volume is
+  * to be calculated.
+  * @returns TS_SUCCESS on success. (always)
   *
   * Calculate normal vector of the triangle (xnorm, ynorm and znorm) and stores
-  * information in underlying ts_triangle_data data_structure.
+  * information. At the same time
+  * triangle area is determined, since we already have the normal and volume of
+  * triangular pyramid with given triangle as a base and vesicle centroid as a
+  * tip. 
   *
   * Function receives one argument of type ts_triangle. It should be corectly
-  * initialized with underlying data structure of type ts_triangle_data. the
-  * result is stored in triangle->data->xnorm, triangle->data->ynorm,
-  * triangle->data->znorm. Returns TS_SUCCESS on completion. 
+  * initialized. The
+  * result is stored in triangle->xnorm, triangle->ynorm, triangle->znorm.
+  * Area and volume are stored into triangle->area and triangle->volume.
+  * Returns TS_SUCCESS on completion. 
   *
-  * NOTE: Function uses math.h library. pow function implementation is selected
-  * accordind to the setting in genreal.h
+  * NOTE: Function uses math.h library. Function pow implementation is selected
+  * accordind to the used TS_DOUBLE_* definition set in general.h, so it should
+  * be compatible with any type of floating point precision.
   *
   * Example of usage:
   *		triangle_normal_vector(tlist->tria[3]);
   *
   *	    Computes normals and stores information into tlist->tria[3]->xnorm,
-  *	    tlist->tria[3]->ynorm, tlist->tria[3]->znorm.
+  *	    tlist->tria[3]->ynorm, tlist->tria[3]->znorm tlist->tria[3]->area and
+  *	    tlist->tria[3]->volume.
   *		
   */
 ts_bool triangle_normal_vector(ts_triangle *tria){
@@ -239,13 +249,9 @@
 	return TS_SUCCESS;
 }
 
-
-
-
-
-
 /** @brief Frees the memory allocated for data structure of triangle list
- * (ts_triangle_list)
+  * @param *tlist is a pointer to datastructure triangle list to be freed.
+  * @returns TS_SUCCESS on success (always).
   *
   * Function frees the memory of ts_triangle_list previously allocated. It
   * accepts one argument, the address of data structure. It destroys all
diff --git a/src/vertex.c b/src/vertex.c
index 38647aa..f733d49 100644
--- a/src/vertex.c
+++ b/src/vertex.c
@@ -6,6 +6,14 @@
 #include "bond.h"
 #include<stdio.h>
 
+ts_bool vertex_list_assign_id(ts_vertex_list *vlist, ts_uint id){
+	ts_uint i;	
+	for(i=0;i<vlist->n;i++){
+		vlist->vtx[i]->id = id;
+	}
+	return TS_SUCCESS;
+}
+
 ts_vertex_list *init_vertex_list(ts_uint N){	
 	ts_int i;
     ts_vertex_list *vlist=(ts_vertex_list *)malloc(sizeof(ts_vertex_list));
diff --git a/src/vertex.h b/src/vertex.h
index 97775d2..cca12ee 100644
--- a/src/vertex.h
+++ b/src/vertex.h
@@ -1,6 +1,8 @@
 #ifndef _VERTEX_H
 #define _VERTEX_H
 
+ts_bool vertex_list_assign_id(ts_vertex_list *vlist, ts_uint id);
+
 /** @brief Creates initial vertex list
  *  
  *  Allocates memory and initializes the vertices.
diff --git a/src/vertexmove.c b/src/vertexmove.c
index da8e70f..6bc730e 100644
--- a/src/vertexmove.c
+++ b/src/vertexmove.c
@@ -67,11 +67,18 @@
 		}
 	}
 
-    //self avoidance check with distant vertices
-     cellidx=vertex_self_avoidance(vesicle, vtx);
-    //check occupation number
-     retval=cell_occupation_number_and_internal_proximity(vesicle->clist,cellidx,vtx);
-	
+// TODO: Maybe faster if checks only nucleus-neighboring cells
+// Nucleus penetration check:
+	if (vtx->x*vtx->x + vtx->y*vtx->y + vtx->z*vtx->z < vesicle->R_nucleus){
+		vtx=memcpy((void *)vtx,(void *)&backupvtx[0],sizeof(ts_vertex));
+		return TS_FAIL;
+	}
+
+//self avoidance check with distant vertices
+	cellidx=vertex_self_avoidance(vesicle, vtx);
+	//check occupation number
+	retval=cell_occupation_number_and_internal_proximity(vesicle->clist,cellidx,vtx);
+
     if(retval==TS_FAIL){
 		vtx=memcpy((void *)vtx,(void *)&backupvtx[0],sizeof(ts_vertex));
         return TS_FAIL;
@@ -291,12 +298,18 @@
 		}
 	}
 
+// TODO: Maybe faster if checks only nucleus-neighboring cells
+// Nucleus penetration check:
+	if (vtx->x*vtx->x + vtx->y*vtx->y + vtx->z*vtx->z < vesicle->R_nucleus){
+		vtx=memcpy((void *)vtx,(void *)&backupvtx,sizeof(ts_vertex));
+		return TS_FAIL;
+	}
+
 
 	//self avoidance check with distant vertices
 	cellidx=vertex_self_avoidance(vesicle, vtx);
 	//check occupation number
 	retval=cell_occupation_number_and_internal_proximity(vesicle->clist,cellidx,vtx);
-	
 	if(retval==TS_FAIL){
 		vtx=memcpy((void *)vtx,(void *)&backupvtx,sizeof(ts_vertex));
         return TS_FAIL;
diff --git a/src/vesicle.c b/src/vesicle.c
index 43b16b5..f63eb12 100644
--- a/src/vesicle.c
+++ b/src/vesicle.c
@@ -6,6 +6,8 @@
 #include "cell.h"
 #include "stdlib.h"
 #include "poly.h"
+#include "sh.h"
+#include "shcomplex.h"
 
 ts_vesicle *init_vesicle(ts_uint N, ts_uint ncmax1, ts_uint ncmax2, ts_uint
 ncmax3, ts_double stepsize){
@@ -35,6 +37,7 @@
     triangle_list_free(vesicle->tlist);
     cell_list_free(vesicle->clist);
     poly_list_free(vesicle->poly_list);
+    complex_sph_free(vesicle->sphHarmonics);
     free(vesicle);
     return TS_SUCCESS;
 }

--
Gitblit v1.9.3