Changeset - e40119cdbdb9
[Not reviewed]
default
0 8 0
Roeland Merks - 15 years ago 2010-10-14 21:58:12
roeland.merks@cwi.nl
A few last updates before submitting the revised Plant Phys. paper. Corrected the invocation of TransporterDialog and added parameter 'yield_threshold'

user: Roeland Merks <roeland.merks@cwi.nl>
branch 'default'
changed src/ChangeLog
changed src/VirtualLeafpar.tmpl
changed src/mesh.cpp
changed src/parameter.cpp
changed src/parameter.h
changed src/pardialog.cpp
changed src/pardialog.h
changed src/wallitem.cpp
8 files changed with 230 insertions and 192 deletions:
0 comments (0 inline, 0 general)
src/ChangeLog
Show inline comments
 
2010-10-14    <merks@cwi.nl>
 

	
 
	* mesh.cpp: In response to referees' comments, added new parameter "yield_threshold" instead of fixed parameter '4' for yield threshold. 
 

	
 
	* wallitem.cpp: when clicking a wall, both the wall type was cycled and the transporterdialog popped up. Corrected this - for wall type cycling, hold the Control button while left clicking. TransporterDialog only pops up for left click. Also made sure the wall is redrawn after changing the transporter values.
 
	
 

	
 
	* cell.cpp (DivideWalls): accomodated for rename of Circumference -> WallCircumference
 

	
 
	* hull.h: added an operator< to sort Points
 

	
 
	* hull.cpp: added an operator< to sort Points
 

	
 
	* cellbase.cpp (ExactCircumference): I added a new function ExactCircumference, yielding the circumference of the cell along its wall_elements
 

	
 
	* VirtualLeaf.cpp: adjust info_string to accomodate for new name of function CellBase::Circumference -> CellBase::WallCircumference
 
	* mesh.cpp: corrected Mesh::Compactness, the boundary coordinates need to be sorted in x,y order for the convex hull algorithm (thanks Margriet!). I updated CSVExportCellData so it exports the circumferences of hull and boundary_polygon.
 
	
 
2010-10-14    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeafpar.tmpl (export_fn_prefix): changed to 'cell.'
 

	
 
	* canvas.cpp (TimeStepWrap): Removed TimeStamp(). Cell data
 
	filename now incorporates iteration number.
 

	
 
	* canvas.h (MainBase): Removed TimeStamp().
 
	
 

	
 
2010-10-08    <guravage@caterpie.sen.cwi.nl>
 

	
 

	
 
	* pardialog.h:
 
	* pardialog.cpp:
 
	* parameter.h:
 
	* parameter.cpp: Regenerated to include export_interval and export_fn_prefix.
 

	
 
	* VirtualLeafpar.tmpl: Appended export_interval and export_fn_prefix.
 

	
 
	* canvas.h (MainBase): Declared polymorphic exportCellData() functions.
 

	
 
	* canvas.cpp:
 
	(TimeStamp): New private TimeStamp() function.
 
	(TimeStepWrap): Added invocation of exportCellData().
 
	(exportCellData): Created two polymorphic functions: one with a
 
	single QString argument, the other with no argument. The former is
 
	called from TimeStepWrap() while the latter is called from the
 
	"Export cell areas" item in the file menu.
 

	
 

	
 
2010-10-07    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* canvas.cpp (exportCellData): Added a Q3FileDialog to inquire
 
	where to write the exportCellData.
 

	
 
2010-06-28    <guravage@caterpie.sen.cwi.nl>
 

	
 

	
 
	* VirtualLeaf-install.nsi: Grab gpl3.txt from doc directory.
 

	
 
	* canvas.cpp (gpl): gpl3.txt can be either in an ancestor doc
 
	directory (Linux) or a decedent doc directory (Windows, via the
 
	binary installer).
 

	
 
	* VirtualLeaf-install.nsi: Add VirtualLeaf doc directory.
 

	
 
2010-06-25    <guravage@caterpie.sen.cwi.nl>
 

	
 

	
 
	* gpl3.txt: Moved gpl3.txt from doc to src directory.
 

	
 
	* VirtualLeaf.pro: Added -Wno-write-strings and -Wno-unused-parameter to QMAKE_CXXFLAGS.
 

	
 
	* libplugin.pro: Ditto.
 

	
 
	* parameter.cpp: Result of adding datadir changes to make_parameter_source.pl.
 
	* parameter.h: Ditto.
 

	
 
	* output.h: Declared new function (AppendHomeDirIfPathRelative).
 

	
 
	* output.cpp (AppendHomeDirIfPathRelative): Added new function.
 

	
 
	* canvas.cpp (gpl): Moving gpl3.txt from doc to src obviates the need to docDir.cd("../doc").
 

	
 
	* VirtualLeaf-install.nsi: Grab gpl3.txt from src directory.
 
	Add missing libiconv/bin, libxml2bin and libz/bin directories.
 
	Copy libiconv-2.dll, libxml2.dll and zlib1.dll from relative paths.
 

	
 
	* VirtualLeaf.pro: copy gpl3.txt as part of QMAKE_POST_LINK.
 

	
 
2010-06-24    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* libplugin.pro: Use correct library path.
 
	* VirtualLeaf.pro: Ditto.
 

	
 
	* VirtualLeaf.cpp (DrawCell): Iterate over NChem to construct info_string.
 

	
 
2010-06-23    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* simitembase.cpp: Removed NULL assignments to unused variables.
 
	* VirtualLeaf.cpp: Ditto.
 
	* apoplastitem.cpp: Ditto.
 
	* canvas.cpp: Ditto.
 
	* cell.cpp: Ditto.
 
	* cellbase.h: Ditto.
 
	* forwardeuler.cpp: Ditto.
 
	* mainbase.h: Ditto.
 
	* nodeitem.cpp: Ditto.
 
	* qcanvasarrow.h: Ditto.
 
	* simitembase.cpp: Ditto.
 

	
 

	
 
	* Makefile (clean): Add -f Makefile argument to each make invocation.
 

	
 
	* VirtualLeaf-install.nsi: New gpl license text.
 

	
 
	* VirtualLeaf.pro: Disabled console mode.
 

	
 
	* mesh.cpp (Clear): Added parentheses to qDebug statments.
 
	(TestIllegalWalls): Replaced qDebug().
 

	
 
	* canvas.cpp (mouseReleaseEvent): Replaced qDebug() with cerr since qDebug complains about *node_set.
 

	
 
	* wall.cpp (CorrectWall): Rplaced gDebug() with cerr in transform call and when printing *this.
 

	
 
2010-06-22    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* Makefile (tutorials): Add tutorials target.
 

	
 
2010-06-21    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* parameter.cpp: Added particular reassignment of datadir.
 

	
 
	* canvas.cpp (gpl): Added GPL3 License text. Display detail text only if the source text file exists.
 

	
 
2010-06-18    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* canvas.cpp (gpl): Added gpl slot to display GPL license.
 

	
 
	* VirtualLeaf.pro: Changed default LIBXML2DIR, LIBICONVDIR and LIBZDIR to corresponding distribution lib directories.
 
	* libplugin.pro: Ditto.
 

	
 
	* Makefile (clean): add if stmt not to `touch` on windows.
 

	
 
2010-06-17    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed perl references.
 
	* libplugin.pro: Ditto.
 

	
 
2010-06-15    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed xmlwritecode.cpp from SOURCES list.
 

	
 
	* xmlwrite.cpp (XMLSave): Removed references to XMLWriteLeafSourceCode and XMLWriteReactionsCode.
 
	* xmlwrite.h (XMLIO): Ditto!
 

	
 
	* mesh.cpp (findNextBoundaryNode): Initialize Node *next_boundary_node = NULL;
 

	
 
	* xmlwrite.cpp (XMLReadSimtime): Removed unused variable cur
 
	(XMLReadWalls): viz_flux need not be declared twice; default value of 0.0.
 
	(XMLReadCells): Removed unused count variable.
 
	(XMLReadSimtime): Removed unused cur variable.
 
	(XMLRead): Removed unused v_str variable.
 

	
 
	* simitembase.cpp (userMove): Use assignment merely to obviate compilation warning.
 
	(SimItemBase) Ditto.
 

	
 
	* qcanvasarrow.h (QGraphicsLineItem): Use assignment merely to obviate compilation warning.
 

	
 
	* output.cpp (OpenWriteFile): Removed unused par variable.
 

	
 
	* nodeitem.cpp (paint): Use assignment merely to obviate compilation warning.
 

	
 
	* forwardeuler.cpp (odeint): Use assignment merely to obviate compilation warning.
 

	
 
	* cell.cpp (DivideOverGivenLine): Use assignment merely to obviate compilation warning.
 

	
 
	* canvas.cpp (FigureEditor): Use assignments merely to obviate compilation errors.
 
	(mousePressEvent): Removed unused item variable.
 

	
 
	* apoplastitem.cpp
 
	(ApoplastItem): Removed unused par variable.
 
	(OnClick): Use NULL assignment merely to obviate compilation warning.
 

	
 
	* mainbase.h (MainBase): Use assignment merely to obviate compilation warning.
 

	
 
	* cellbase.h (CellsStaticDatamembers): Use assignment merely to obviate compilation warning.
 

	
 

	
 
	* cell.cpp: Wrapped diagnostic output in QDEBUG blocks.
 
	* VirtualLeaf.cpp ditto.
 
	* canvas.cpp ditto.
 
	* cell.cpp ditto.
 
	* data_plot.cpp ditto.
 
	* forwardeuler.cpp ditto.
 
	* mesh.cpp ditto.
 
	* mesh.h
 
	* random.cpp ditto.
 
	* wall.cpp ditto.
 
	* wallbase.cpp ditto.
 
	* wallitem.cpp ditto.
 

	
 

	
 
2010-06-07    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed explicit perl invocation to regerenerate parameter files.
 
	* libplugin.pro: ditto.
 

	
 
2010-06-03    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* pardialog.h: Added default versions of this automatically generated file.
 
	* pardialog.cpp: ditto.
 
	* parameter.h: ditto.
 
	* parameter.cpp: ditto.
 

	
 
	* VirtualLeaf.pro: delete/generate  parameter.{h,cpp}and pardialog.{h,cpp} only if perl is installed.
 
 	* libplugin.pro: dito.
 

	
 
	* Makefile: Added top-level Makefile
 

	
 
2010-05-10    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Added -fPIC option to QMAKE_CXXFLAGS.
 

	
src/VirtualLeafpar.tmpl
Show inline comments
 
title = Parameter values for The Virtual Leaf / title
 
label = <b>Visualization</b> / label
 
arrowcolor = white / string
 
arrowsize = 100 / double
 
textcolor = red / string
 
cellnumsize = 1 / int
 
nodenumsize = 1 / int
 
node_mag = 1.0 / double 
 
outlinewidth = 1.0 / double
 
cell_outline_color = forestgreen / string
 
resize_stride = 0 / int
 
label = / label
 
label = <b>Cell mechanics</b> / label
 
T = 1.0 / double
 
lambda_length = 100. / double
 
yielding_threshold = 4. / double
 
lambda_celllength = 0. / double
 
target_length = 60. / double 
 
cell_expansion_rate = 1. / double
 
cell_div_expansion_rate = 0. / double
 
auxin_dependent_growth = true / bool
 
ode_accuracy = 1e-4 / double
 
mc_stepsize = 0.4 / double
 
mc_cell_stepsize = 0.2 / double
 
energy_threshold = 1000. / double
 
bend_lambda = 0. / double
 
alignment_lambda = 0. / double
 
rel_cell_div_threshold = 2. / double
 
rel_perimeter_stiffness = 2 / double
 
collapse_node_threshold = 0.05 / double
 
morphogen_div_threshold = 0.2 / double
 
morphogen_expansion_threshold = 0.01 / double
 
copy_wall = true / bool
 
label = / label
 
label = <b>Auxin transport and PIN1 dynamics</b> / label
 
source = 0. / double
 
D = 0., 0.0, 0.0, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. / doublelist
 
initval = 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. / doublelist
 
k1 = 1. / double
 
k2 = 0.3 / double
 
r = 1. / double
 
kr = 1. / double
 
#k3 = 1 / double
 
#k4 = 0.3 / double
 
km = 1. / double
 
Pi_tot = 1. / double
 
transport = 0.036 / double
 
ka = 1 / double
 
# d = 1e-06 / double
 
# e = 0.01 / double
 
# f = 10 / double
 
pin_prod = 0.001 / double
 
pin_prod_in_epidermis = 0.1 / double
 
pin_breakdown = 0.001 / double
 
pin_breakdown_internal = 0.001 / double
 
aux1prod = 0.001 / double
 
aux1prodmeso = 0. / double
 
aux1decay = 0.001 / double
 
aux1decaymeso = 0.1 / double
 
aux1transport = 0.036 / double
 
aux_cons = 0. / double
 
aux_breakdown = 0. / double
 
kaux1 = 1 / double
 
kap = 1 / double
 
leaf_tip_source = 0.001 / double
 
sam_efflux = 0.0001 / double
 
sam_auxin = 10. / double
 
# gf_prod = 1e-3 / double
 
# gf_decay = 1e-3 / double
 
sam_auxin_breakdown = 0 / double
 
#label = / label
 
#label = <b>miscellaneous</b> / label
 
van3prod = 0.002 / double
 
van3autokat = 0.1 / double
 
van3sat = 10 / double
 
k2van3 = 0.3 / double
 
#glvprod = 0.0 / double
 
#glvbreakdown = 0. / double
 
label = / label
 
label = <b>Integration parameters</b> / label
 
dt = 0.1 / double 
 
rd_dt = 1.0 / double
 
datadir = . / directory 
 
movie = false / bool
 
nit = 100000 / int
 
maxt = 1000. / double
 
storage_stride = 10 / int
 
xml_storage_stride = 500 / int
 
rseed = -1 / int
 
#label = / label
 
#label = <b>Parameters for new chemical</b> / label
 
#glvproduction = 0. / double
 
#glvdecay = 0. / double
 
#glvdiffthreshold = 0. / double
 
label = / label
 
label = <b>Meinhardt leaf venation model</b> / label
 
constituous_expansion_limit = 16 / int
 
vessel_inh_level = 1 / double
 
vessel_expansion_rate = 0.25 / double
 
d = 0. / double
 
e = 0. / double
 
f = 0. / double
 
c = 0. / double
 
mu = 0. / double
 
nu = 0. / double
 
rho0 = 0. / double
 
rho1 = 0. / double
 
c0 = 0. / double
 
gamma = 0. / double
 
eps = 0. / double
 
label = / label
 
label = <b>User-defined parameters</b> / label
 
k = 0., 0.0, 0.0, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. / doublelist
 
i1 = 0 / int
 
i2 = 0 / int
 
i3 = 0 / int
 
i4 = 0 / int
 
i5 = 0 / int
 
s1 =  / string
 
s2 =  / string
 
s3 =  / string
 
b1 = false / bool
 
b2 = false / bool
 
b3 = false / bool
 
b4 = false / bool
 
dir1 = . / directory
 
dir2 = . / directory
 
export_interval = 0 / int
 
export_fn_prefix = cell. / string
src/mesh.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include <algorithm>
 
#include <vector>
 
#include <sstream>
 
#include <cstdlib>
 
//#include <cerrno>
 
#include <cstring>
 
#include <numeric>
 
#include <functional>
 
#include <fstream>
 
#include <QPair>
 
#include "mesh.h"
 
#include "tiny.h"
 
#include "parameter.h"
 
#include "random.h"
 
#include "pi.h"
 
#include "parse.h"
 
#include "matrix.h"
 
#include "sqr.h"
 
#include "nodeset.h"
 
#include "nodeitem.h"
 
#include "simplugin.h"
 

	
 
#include <QDebug>
 
#include <set>
 
#include <iostream>
 
#include <iterator>
 
#include <QTextStream>
 

	
 
static const std::string _module_id("$Id$");
 

	
 
extern Parameter par;
 

	
 
void Mesh::AddNodeToCellAtIndex(Cell *c, Node *n, Node *nb1, Node *nb2, list<Node *>::iterator ins_pos) {
 
  c->nodes.insert(ins_pos, n);        
 
  n->owners.push_back( Neighbor(c, nb1, nb2 ) );
 
}
 

	
 

	
 
void Mesh::AddNodeToCell(Cell *c, Node *n, Node *nb1, Node *nb2) {
 

	
 
  c->nodes.push_back( n );
 
  n->owners.push_back( Neighbor(c, nb1, nb2 ) );
 
}
 

	
 
void Mesh::PerturbChem(int chemnum, double range) {
 

	
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    (*i)->chem[chemnum] += range*(RANDOM()-0.5);
 
    if ((*i)->chem[chemnum]<0.) (*i)->chem[chemnum]=0.;
 
  }
 
}
 

	
 
void Mesh::CellFiles(const Vector ll, const Vector ur) {
 

	
 
  Cell *cell = RectangularCell(ll,ur,0.001); 
 

	
 
  for (int c=0;c<Cell::NChem();c++) {
 
    cell->SetChemical(c,par.initval[c]);
 
  }
 

	
 
  cell->SetTargetArea(cell->CalcArea());
 

	
 
  Vector axis(1,0,0);
 

	
 
  // divide rectangle a number of times
 
  for (int i=0;i<6;i++) {
 
    IncreaseCellCapacityIfNecessary();
 

	
 
    vector <Cell *> current_cells = cells;
 
    for (vector<Cell *>::iterator j=current_cells.begin(); j!=current_cells.end();j++) {
 
      (*j)->DivideOverAxis(axis);
 
    }
 
    axis=axis.Perp2D();
 

	
 
  }
 

	
 
  IncreaseCellCapacityIfNecessary();
 

	
 
  axis=axis.Perp2D();
 

	
 
  vector <Cell *> current_cells = cells;
 
  for (vector<Cell *>::iterator j=current_cells.begin(); j!=current_cells.end();j++) {
 
    (*j)->DivideOverAxis(axis);
 
  }
 

	
 

	
 
  double sum_l=0; int n_l=0;
 
  for (list<Node *>::const_iterator i=cell->nodes.begin(); i!=cell->nodes.end(); i++) {
 
    list<Node *>::const_iterator nb=i; nb++; 
 
    if (nb==cell->nodes.end()) 
 
      nb=cell->nodes.begin();
 

	
 
    double l = (**nb-**i).Norm();
 

	
 
    sum_l += l;
 
    n_l++;
 

	
 
  }
 

	
 

	
 
  Node::target_length = sum_l/(double)n_l;
 
  // a bit more tension
 
  Node::target_length/=4.;
 

	
 
  SetBaseArea();
 
}
 

	
 
Cell *Mesh::RectangularCell(const Vector ll, const Vector ur, double rotation) {
 

	
 
  Cell *cell=AddCell(new Cell());
 
  cell->m=this;
 

	
 
  Matrix rotmat;
 
  rotmat.Rot2D(rotation); // rotation over 0,0
 

	
 
  Node *n1=AddNode(new Node(rotmat * ll));
 
  Node *n2=AddNode(new Node(rotmat * Vector(ll.x, ur.y,0)));
 
  Node *n3=AddNode(new Node(rotmat * ur));
 
  Node *n4=AddNode(new Node(rotmat * Vector(ur.x, ll.y,0)));
 

	
 
  n1->boundary=true;
 
  n2->boundary=true;
 
  n3->boundary=true;
 
  n4->boundary=true;
 

	
 
  //n1.fixed=n2.fixed=n3.fixed=n4.fixed=true;
 

	
 
  AddNodeToCell(cell, n4, 
 
		n1,
 
		n3);
 

	
 
  AddNodeToCell(cell, n3, 
 
		n4,
 
		n2);
 

	
 
  AddNodeToCell(cell, n2, 
 
		n3,
 
		n1);
 

	
 
  AddNodeToCell(cell, n1, 
 
		n2,
 
		n4);
 

	
 

	
 
  AddNodeToCell(boundary_polygon, n4, 
 
		n1,
 
		n3);
 
  AddNodeToCell(boundary_polygon, n3, 
 
		n4,
 
		n2);
 
  AddNodeToCell(boundary_polygon, n2, 
 
		n3,
 
		n1);
 
  AddNodeToCell(boundary_polygon, n1, 
 
		n2,
 
		n4);
 

	
 
  cell->setCellVec(Vector(0,1,0));
 

	
 
  boundary_polygon->m = this;
 
  boundary_polygon->area = 0;
 

	
 
  cell->area = cell->CalcArea();
 
  // target length is the length of the elements
 

	
 
  Node::target_length = ur.y-ll.y;
 
  // a bit more tension
 
  Node::target_length/=2;
 

	
 
  cell->SetIntegrals(); 
 
  cell->ConstructNeighborList();
 

	
 
  return cell;
 
}
 

	
 
Cell &Mesh::EllipticCell(double xc, double yc, double ra, double rb,  int nnodes, double rotation) {
 

	
 
  int first_node=Node::nnodes;
 
  //  nodes.reserve(nodes.size()+nnodes);
 

	
 

	
 
  //cells.push_back(Cell(xc,yc));
 
  Cell *c=AddCell(new Cell(xc,yc));
 
  c->m=this;
 

	
 
  for (int i=0;i<nnodes;i++) {
 

	
 
    double angle=2*Pi*(i/(double)nnodes);
 
    double x=xc+ra*cos(angle)*cos(rotation) - rb*sin(angle)*sin(rotation);
 
    double y=yc+ra*cos(angle)*sin(rotation) + rb*sin(angle)*cos(rotation);
 

	
 

	
 
    Node *n=AddNode(new Node(x,y,0));
 
    n->boundary = true;
 

	
 
  } 
 

	
 
  for (int i=0;i<nnodes;i++) {
 

	
 
    AddNodeToCell(c,
 
		  nodes[first_node + i],
 
		  nodes[first_node+ (nnodes+i-1)%nnodes],
 
		  nodes[first_node+ (i + 1)%nnodes]);
 
    AddNodeToCell(boundary_polygon,
 
		  nodes[first_node + i],
 
		  nodes[first_node+ (nnodes+i-1)%nnodes],
 
		  nodes[first_node+ (i + 1)%nnodes]);
 
  }
 

	
 
  boundary_polygon->m = this;
 
  boundary_polygon->area = 0;
 

	
 
  c->area = c->CalcArea();
 
  // target length is the length of the elements
 

	
 
  Node::target_length = (2 * ((ra +rb)/2.) * sin (Pi/nnodes));
 
  // a bit more tension
 
  Node::target_length/=2;
 

	
 
  c->SetIntegrals(); 
 
  c->at_boundary=true;
 

	
 
  return *c;
 
}
 

	
 
Cell &Mesh::LeafPrimordium(int nnodes, double pet_length) {
 

	
 
  // first leaf cell
 

	
 
  int first_node=Node::nnodes;
 

	
 
  Cell *circle=AddCell(new Cell(0,0));
 
  circle->m=this;
 
  const double ra=10, rb=10;
 
  const double xc=0,yc=0;
 
  const double rotation=0;
 
  for (int i=0;i<nnodes;i++) {
 

	
 
    double angle=2*Pi*(i/(double)nnodes);
 
    double x=xc+ra*cos(angle)*cos(rotation) - rb*sin(angle)*sin(rotation);
 
    double y=yc+ra*cos(angle)*sin(rotation) + rb*sin(angle)*cos(rotation);
 

	
 

	
 
    Node *n=AddNode(new Node(x,y,0));
 

	
 
    /* if (angle > 1.25*Pi && angle < 1.75*Pi ) {
 
       n.sam = true;
 
       }*/
 

	
 
    AddNodeToCell(circle,
 
		  n,
 
		  nodes[first_node+ (nnodes+i-1)%nnodes],
 
		  nodes[first_node+ (i + 1)%nnodes]);
 

	
 
  }
 

	
 
  boundary_polygon->m = this;
 
  boundary_polygon->area = 0;
 

	
 
  circle->area = circle->CalcArea();
 
  // target length is the length of the elements
 

	
 
  Node::target_length = (2 * ((ra +rb)/2.) * sin (Pi/nnodes));
 
  // a bit more tension
 
  Node::target_length/=2;
 

	
 
  circle->SetIntegrals(); 
 

	
 
  //return c;
 

	
 
  circle->SetTargetArea(2*circle->Area());
 

	
 
  // Petiole: starts at both sides of the circular cell
 
  // get position of the (n/4)'th and (3*(n/4))'th node.
 

	
 
  list<Node *>::reverse_iterator it_n1=circle->nodes.rbegin();
 
  for (int i=0; i<nnodes/2; i++) 
 
    it_n1++;
 
  it_n1--;
 

	
 
  list<Node *>::reverse_iterator it_n2=--circle->nodes.rend();
 

	
 
  Cell *petiole=AddCell(new Cell());
 

	
 
  Node *n1 = *it_n1;
 
  Node *n2 = *it_n2;
 

	
 
  Node *n3=AddNode( new Node ( *n2 + Vector( 0, pet_length, 0) ) );
 
  Node *n4=AddNode( new Node ( *n1 + Vector( 0, pet_length, 0) ) );
 

	
 
  n3->boundary=true;
 
  n4->boundary=true;
 

	
 
  AddNodeToCell(petiole, *it_n1, 
 
		n4,
 
		nodes[(*it_n2)->Index() 
 
		      + (( (*it_n1)->Index() - (*it_n2)->Index() )-1+nnodes)%nnodes]);
 

	
 

	
 

	
 
  list<Node *>::reverse_iterator i=it_n1; i++;
 
  for (; i!=it_n2; ++i) {
 
    AddNodeToCell(petiole, *i,
 
		  nodes[(*it_n2)->Index() + (((*i)->Index()-(*it_n2)->Index()) + 1)%nnodes],
 
		  nodes[(*it_n2)->Index() + (((*i)->Index()-(*it_n2)->Index())-1+nnodes)%nnodes]);
 
  }
 

	
 
  AddNodeToCell(petiole, *it_n2, *it_n2 + 1, n3);
 

	
 
  (*it_n2)->boundary=true;
 

	
 
  AddNodeToCell(petiole, n3, n2, n4);
 
  AddNodeToCell(petiole, n4, n3, n1);
 

	
 

	
 
#ifdef QDEBUG  
 
  qDebug() << circle << endl;
 
  qDebug() << petiole << endl;
 
#endif
 

	
 
  AddNodeToCell(boundary_polygon, *it_n1, n4, *it_n2 + ((*it_n1-*it_n2)+1)%nnodes); // is this gonna work?
 

	
 
  (*it_n1)->boundary=true;
 

	
 
  for (int i=0;i<nnodes;i++) {
 

	
 
    if (nodes[(first_node + i)]->owners.size()==1) {
 
      AddNodeToCell(boundary_polygon,
 
		    nodes[first_node +i],
 
		    nodes[first_node+ (nnodes+i-1)%nnodes],
 
		    nodes[first_node+ (i + 1)%nnodes]);
 

	
 
      nodes[first_node+i]->boundary=true;
 
    }
 
  }
 

	
 
  AddNodeToCell(boundary_polygon, *it_n2, nodes[(nnodes+(*it_n2)->Index() - 1)%nnodes], n3);
 
  AddNodeToCell(boundary_polygon, n3, n2, n4);
 
  AddNodeToCell(boundary_polygon, n4, n3, n1);
 

	
 
  // make petiole solid
 
  for (list<Node *>::iterator i=petiole->nodes.begin(); i!=petiole->nodes.end(); i++) {
 
    (*i)->Fix();
 
  }
 
  petiole->Fix();
 

	
 
  petiole->area=petiole->CalcArea();
 
  petiole->target_area=petiole->area;  
 
  petiole->ConstructNeighborList();
 
  circle->ConstructNeighborList();
 
  boundary_polygon->ConstructConnections();
 
  boundary_polygon->ConstructNeighborList();
 

	
 
  circle->setCellVec(Vector(0,1,0));
 

	
 
  return *circle;
 
}
 

	
 
/*Cell &Mesh::Box() {
 
  }*/
 

	
 

	
 
// return bounding box of mesh
 
void Mesh::BoundingBox(Vector &LowerLeft, Vector &UpperRight) {
 

	
 
  LowerLeft = **nodes.begin();
 
  UpperRight = **nodes.begin();
 
  for (vector<Node *>::iterator c=nodes.begin(); c!=nodes.end(); c++) {
 
    if ((*c)->x < LowerLeft.x)
 
      LowerLeft.x = (*c)->x;
 
    if ((*c)->y < LowerLeft.y)
 
      LowerLeft.y = (*c)->y;
 
    if ((*c)->z < LowerLeft.z)
 
      LowerLeft.z = (*c)->z;
 
    if ((*c)->x > UpperRight.x) 
 
      UpperRight.x = (*c)->x;
 
    if ((*c)->y > UpperRight.y) 
 
      UpperRight.y = (*c)->y;
 
    if ((*c)->z > UpperRight.z)
 
      UpperRight.z = (*c)->z;
 
  }
 
}
 

	
 

	
 
double Mesh::Area(void) {
 

	
 
  double area=0;
 
  vector<Cell *>::iterator i=cells.begin();
 
  while (i != cells.end()) {
 
    area += (*(i++))->Area();
 
  }
 
  return area;
 
}
 

	
 
void Mesh::SetBaseArea(void) {
 

	
 
  // Set base area to mean area. 
 
  // This method is typically called during initiation, after
 
  // defining the first cell
 
  Cell::BaseArea() = Area()/cells.size();
 
}
 

	
 
// for optimization, we moved Displace to Mesh
 

	
 
class DeltaIntgrl {
 

	
 
public:
 
  double area;
 
  double ix, iy;
 
  double ixx,ixy,iyy;
 
  DeltaIntgrl(double sarea,double six,double siy,double sixx,double sixy,double siyy) {
 
    area=sarea;
 
    ix=six;
 
    iy=siy;
 
    ixx=sixx;
 
    ixy=sixy;
 
    iyy=siyy;
 
  }
 
};
 

	
 
void Mesh::Clear(void) {
 

	
 
  // clear nodes
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  nodes.clear();
 
  Node::nnodes=0;
 

	
 
  node_insertion_queue.clear();
 
  // Clear NodeSets
 
  for (vector<NodeSet *>::iterator i=node_sets.begin(); i!=node_sets.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  node_sets.clear();
 
  time = 0;
 

	
 
  // clear cells
 

	
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  cells.clear();
 
  Cell::NCells() = 0;
 

	
 
  if (boundary_polygon) {
 
    delete boundary_polygon;
 
    boundary_polygon=0;
 
  }
 

	
 
  // Clear walls
 
  for (list<Wall *>::iterator i=walls.begin(); i!=walls.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  walls.clear();
 
  WallBase::nwalls = 0;
 
  //tmp_walls->clear();
 

	
 
  shuffled_cells.clear();
 
  shuffled_nodes.clear();
 
 
 
#ifdef QDEBUG
 
  qDebug() << "cells.size() = " << cells.size() << endl;
 
  qDebug() << "walls.size() = " << walls.size() << endl;
 
  qDebug() << "nodes.size() = " << nodes.size() << endl;
 
#endif
 
}
 

	
 
double Mesh::DisplaceNodes(void) {
 

	
 
  MyUrand r(shuffled_nodes.size());
 
  random_shuffle(shuffled_nodes.begin(),shuffled_nodes.end(),r);
 

	
 
  double sum_dh=0;
 

	
 
  list<DeltaIntgrl> delta_intgrl_list;
 

	
 
  for_each( node_sets.begin(), node_sets.end(), mem_fun( &NodeSet::ResetDone ) );
 

	
 
  for (vector<Node *>::const_iterator i=shuffled_nodes.begin(); i!=shuffled_nodes.end(); i++) {
 

	
 
    //int n=shuffled_nodes[*i];
 
    Node &node(**i);
 

	
 
    // Do not allow displacement if fixed
 
    //if (node.fixed) continue;
 

	
 
    if (node.DeadP()) continue;
 

	
 
    // Attempt to move this cell in a random direction
 
    double rx=par.mc_stepsize*(RANDOM()-0.5); // was 100.
 
    double ry=par.mc_stepsize*(RANDOM()-0.5);
 

	
 
    // Uniform with a circle of radius par.mc_stepsize
 
    /* double r = RANDOM() * par.mc_stepsize;
 
       double th = RANDOM()*2*Pi;
 

	
 
       double rx = r * cos(th);
 
       double ry = r * sin(th);
 
    */
 
    Vector new_p(node.x+rx,node.y+ry,0);
 
    Vector old_p(node.x,node.y,0);
 

	
 
    /* if (node.boundary  && boundary_polygon->MoveSelfIntersectsP(n,  new_p )) {
 
    // reject if move of boundary results in self intersection
 
    continue;
 
    }*/
 

	
 

	
 
    if (node.node_set) {
 
      // move each node set only once
 
      if (!node.node_set->DoneP()) 
 
	node.node_set->AttemptMove(rx,ry);
 

	
 
    } else {
 

	
 
      // for all cells to which this node belongs:
 
      //   calculate energy difference
 

	
 
      double area_dh=0.;
 
      double length_dh=0.;
 
      double bending_dh=0.;
 
      double cell_length_dh=0.;
 
      double alignment_dh=0.;
 

	
 
      double old_l1=0.,old_l2=0.,new_l1=0.,new_l2=0.;
 

	
 
      double sum_stiff=0.;
 
      double dh=0.;
 

	
 
      for (list<Neighbor>::const_iterator cit=node.owners.begin(); cit!=node.owners.end(); cit++) {
 

	
 
	
 
	Cell &c=*((Cell *)(cit->cell));
 

	
 
	if (c.MoveSelfIntersectsP(&node,  new_p )) {
 
		
 
	  // reject if move results in self intersection
 
	  //
 
	  // I know: using goto's is bad practice... except when jumping out
 
	  // of deeply nested loops :-)
 
	  //cerr << "Rejecting due to self-intersection\n";
 
	  goto next_node;
 
	}
 

	
 
	// summing stiffnesses of cells. Move has to overcome this minimum required energy.
 
	sum_stiff += c.stiffness;
 
	// area - (area after displacement): see notes for derivation
 
	
 
	Vector i_min_1 = *(cit->nb1);
 
	//Vector i_plus_1 = m->getNode(cit->nb2);
 
	Vector i_plus_1 = *(cit->nb2);
 

	
 

	
 
	// We must double the weights for the perimeter (otherwise they start bulging...)
 
	double w1, w2;
 
	if (node.boundary && cit->nb1->boundary) 
 
#ifdef FLEMING
 
	  w1 = par.rel_perimeter_stiffness;
 
#else
 
	w1=2;
 
#endif
 
	else
 
	  w1 = 1;
 

	
 
	if (node.boundary && cit->nb2->boundary) 
 
#ifdef FLEMING
 
	  w2 = par.rel_perimeter_stiffness;
 
#else
 
	w2 = 2;
 
#endif
 
	else 
 
	  w2 = 1;
 

	
 
	//if (cit->cell>=0) {
 
	if (!cit->cell->BoundaryPolP()) {
 
	  double delta_A = 0.5 * ( ( new_p.x - old_p.x ) * (i_min_1.y - i_plus_1.y) +
 
				   ( new_p.y - old_p.y ) * ( i_plus_1.x - i_min_1.x ) );
 

	
 
	  area_dh +=  delta_A * (2 * c.target_area - 2 * c.area + delta_A);
 

	
 

	
 
	  // cell length constraint
 
	  // expensive and not always needed
 
	  // so we check the value of lambda_celllength
 

	
 
	  if (/* par.lambda_celllength */  cit->cell->lambda_celllength) {
 

	
 
	    double delta_ix = 
 
	      (i_min_1.x + new_p.x)
 
	      * (new_p.x * i_min_1.y- i_min_1.x * new_p.y) +
 
	      (new_p.x + i_plus_1.x)
 
	      * (i_plus_1.x * new_p.y- new_p.x * i_plus_1.y) -
 

	
 
	      (i_min_1.x + old_p.x)
 
	      * (old_p.x * i_min_1.y- i_min_1.x * old_p.y) -
 
	      (old_p.x + i_plus_1.x)
 
	      * (i_plus_1.x * old_p.y - old_p.x * i_plus_1.y);
 

	
 

	
 
	    double delta_iy =
 
	      (i_min_1.y + new_p.y)
 
	      * (new_p.x * i_min_1.y- i_min_1.x * new_p.y) +
 
	      (new_p.y + i_plus_1.y)
 
	      * (i_plus_1.x * new_p.y- new_p.x * i_plus_1.y) -
 

	
 
	      (i_min_1.y + old_p.y)
 
	      * (old_p.x * i_min_1.y- i_min_1.x * old_p.y) -
 
	      (old_p.y + i_plus_1.y)
 
	      * (i_plus_1.x * old_p.y - old_p.x * i_plus_1.y);
 

	
 

	
 
	    double delta_ixx = 
 
	      (new_p.x*new_p.x+
 
	       i_min_1.x*new_p.x+
 
	       i_min_1.x*i_min_1.x ) *
 
	      (new_p.x*i_min_1.y - i_min_1.x*new_p.y) +
 

	
 
	      (i_plus_1.x*i_plus_1.x+
 
	       new_p.x*i_plus_1.x+
 
	       new_p.x*new_p.x ) *
 
	      (i_plus_1.x*new_p.y - new_p.x*i_plus_1.y) -
 

	
 
	      (old_p.x*old_p.x+
 
	       i_min_1.x*old_p.x+
 
	       i_min_1.x*i_min_1.x ) *
 
	      (old_p.x*i_min_1.y - i_min_1.x*old_p.y) -
 

	
 
	      (i_plus_1.x*i_plus_1.x+
 
	       old_p.x*i_plus_1.x+
 
	       old_p.x*old_p.x ) *
 
	      (i_plus_1.x*old_p.y - old_p.x*i_plus_1.y);
 

	
 

	
 
	    double delta_ixy =
 
	      (i_min_1.x*new_p.y-
 
	       new_p.x*i_min_1.y)*
 
	      (new_p.x*(2*new_p.y+i_min_1.y)+
 
	       i_min_1.x*(new_p.y+2*i_min_1.y)) +
 

	
 
	      (new_p.x*i_plus_1.y-
 
	       i_plus_1.x*new_p.y)*
 
	      (i_plus_1.x*(2*i_plus_1.y+new_p.y)+
 
	       new_p.x*(i_plus_1.y+2*new_p.y)) -
 

	
 
	      (i_min_1.x*old_p.y-
 
	       old_p.x*i_min_1.y)*
 
	      (old_p.x*(2*old_p.y+i_min_1.y)+
 
	       i_min_1.x*(old_p.y+2*i_min_1.y)) -
 

	
 
	      (old_p.x*i_plus_1.y-
 
	       i_plus_1.x*old_p.y)*
 
	      (i_plus_1.x*(2*i_plus_1.y+old_p.y)+
 
	       old_p.x*(i_plus_1.y+2*old_p.y));
 

	
 

	
 
	    double delta_iyy = 
 
	      (new_p.x*i_min_1.y-
 
	       i_min_1.x*new_p.y)*
 
	      (new_p.y*new_p.y+
 
	       i_min_1.y*new_p.y+
 
	       i_min_1.y*i_min_1.y ) + 
 

	
 
	      (i_plus_1.x*new_p.y-
 
	       new_p.x*i_plus_1.y)*
 
	      (i_plus_1.y*i_plus_1.y+
 
	       new_p.y*i_plus_1.y+
 
	       new_p.y*new_p.y ) -
 

	
 
	      (old_p.x*i_min_1.y-
 
	       i_min_1.x*old_p.y)*
 
	      (old_p.y*old_p.y+
 
	       i_min_1.y*old_p.y+
 
	       i_min_1.y*i_min_1.y ) -
 

	
 
	      (i_plus_1.x*old_p.y-
 
	       old_p.x*i_plus_1.y)*
 
	      (i_plus_1.y*i_plus_1.y+
 
	       old_p.y*i_plus_1.y+
 
	       old_p.y*old_p.y );
 

	
 
	    delta_intgrl_list.push_back(DeltaIntgrl(delta_A,delta_ix,delta_iy,delta_ixx,delta_ixy,delta_iyy));
 

	
 
	    Vector old_axis;
 
	    double old_celllength = c.Length(&old_axis);
 
	    old_axis=old_axis.Normalised().Perp2D();
 

	
 
	    // calculate length after proposed update
 
	    double intrx=(c.intgrl_x-delta_ix)/6.;
 
	    double intry=(c.intgrl_y-delta_iy)/6.;
 
	    double ixx=((c.intgrl_xx-delta_ixx)/12.)-(intrx*intrx)/(c.area-delta_A);
 
	    double ixy=((c.intgrl_xy-delta_ixy)/24.)+(intrx*intry)/(c.area-delta_A);
 
	    double iyy=((c.intgrl_yy-delta_iyy)/12.)-(intry*intry)/(c.area-delta_A);
 

	
 
	    double rhs1=(ixx+iyy)/2., rhs2=sqrt( (ixx-iyy)*(ixx-iyy)+4*ixy*ixy )/2.;
 

	
 
	    double lambda_b=rhs1+rhs2;
 

	
 

	
 
	    double new_celllength=4*sqrt(lambda_b/(c.area-delta_A));
 
	    //cerr << "new_celllength = "  << new_celllength << endl;
 
	    //cerr << "target_length = "  << c.target_length << endl;
 

	
 
	    cell_length_dh += c.lambda_celllength * ( DSQR(c.target_length - new_celllength) - DSQR(c.target_length-old_celllength) );
 

	
 
	    Vector norm_long_axis(lambda_b - ixx, ixy, 0);
 
	    norm_long_axis.Normalise();
 

	
 
	    double alignment_before = InnerProduct(old_axis, c.cellvec);
 
	    double alignment_after = InnerProduct(norm_long_axis, c.cellvec);
 

	
 
	    /* cerr << "Delta alignment = " << alignment_before - alignment_after << endl;
 
	       cerr << "Old alignment is " << alignment_before << ", new alignment is " << alignment_after << endl;
 
	       cerr << "Old axis is " << old_axis << ", new axis is " << norm_long_axis << endl; 
 
	    */
 
	    alignment_dh += alignment_before - alignment_after;
 

	
 
	    /* cerr << "alignment_dh  = " << alignment_dh << endl;
 
	       cerr << "cellvec = " << c.cellvec << endl;*/
 

	
 
	  } else {
 
	    // if we have no length constraint, still need to update area
 
	    delta_intgrl_list.push_back(DeltaIntgrl(delta_A,0,0,0,0,0));
 

	
 
	  }
 

	
 
	  old_l1=(old_p-i_min_1).Norm();
 
	  old_l2=(old_p-i_plus_1).Norm();
 
	  new_l1=(new_p-i_min_1).Norm();
 
	  new_l2=(new_p-i_plus_1).Norm();
 

	
 

	
 

	
 

	
 
	  static int count=0;
 
	  // Insertion of nodes (cell wall yielding)
 
	  if (!node.fixed) {
 
	    if (old_l1 > 4*Node::target_length && !cit->nb1->fixed) {
 
	    if (old_l1 > par.yielding_threshold*Node::target_length && !cit->nb1->fixed) {
 
	      node_insertion_queue.push( Edge(cit->nb1, &node) );
 
	    }
 
	    if (old_l2 > 4*Node::target_length && !cit->nb2->fixed) {
 
	    if (old_l2 > par.yielding_threshold*Node::target_length && !cit->nb2->fixed) {
 
	      node_insertion_queue.push( Edge(&node, cit->nb2 ) );
 
	    }
 
	    count++;
 

	
 
	  }
 

	
 

	
 
	
 
	  length_dh += 2*Node::target_length * ( w1*(old_l1 - new_l1) + 
 
						 w2*(old_l2 - new_l2) ) +
 
	    w1*(DSQR(new_l1) 
 
		- DSQR(old_l1)) 
 
	    + w2*(DSQR(new_l2) 
 
		  - DSQR(old_l2));
 

	
 

	
 
	 
 

	
 

	
 
	}
 

	
 
	// bending energy also holds for outer boundary
 
	// first implementation. Can probably be done more efficiently
 
	// calculate circumcenter radius (gives local curvature)
 
	// the ideal bending state is flat... (K=0)
 
		  {
 
	  // strong bending energy to resist "cleaving" by division planes
 
	  double r1, r2, xc, yc;
 
	  CircumCircle(i_min_1.x, i_min_1.y, old_p.x, old_p.y, i_plus_1.x, i_plus_1.y,
 
		       &xc,&yc,&r1);
 
	  CircumCircle(i_min_1.x, i_min_1.y, new_p.x, new_p.y, i_plus_1.x, i_plus_1.y,
 
		       &xc,&yc, &r2);
 

	
 
	  if (r1<0 || r2<0) {
 
	    MyWarning::warning("r1 = %f, r2 = %f",r1,r2);
 
	  }
 
	  bending_dh += DSQR(1/r2 - 1/r1);
 

	
 
	}
 

	
 

	
 
      }
 

	
 
     
 
		
 

	
 
      dh = 	area_dh + cell_length_dh +
 
	par.lambda_length * length_dh + par.bend_lambda * bending_dh + par.alignment_lambda * alignment_dh;
 

	
 
         //(length_constraint_after - length_constraint_before);
 

	
 
      if (node.fixed) {
 

	
 
	// search the fixed cell to which this node belongs
 
	// and displace these cells as a whole
 
	// WARNING: undefined things will happen for connected fixed cells...
 
	for (list<Neighbor>::iterator c=node.owners.begin(); c!=node.owners.end(); c++) {
 
	  if (!c->cell->BoundaryPolP() && c->cell->FixedP()) {
 
	    sum_dh+=c->cell->Displace(rx,ry,0);
 
	  }
 
	}
 
      } else {
 

	
 

	
 
	if (dh<-sum_stiff || RANDOM()<exp((-dh-sum_stiff)/par.T)) {
 

	
 
	  // update areas of cells
 
	  list<DeltaIntgrl>::const_iterator di_it = delta_intgrl_list.begin();
 
	  for (list<Neighbor>::iterator cit=node.owners.begin(); cit!=node.owners.end(); ( cit++) ) {
 
	    if (!cit->cell->BoundaryPolP()) {
 
	      cit->cell->area -= di_it->area;
 
	      if (par.lambda_celllength) {
 
		cit->cell->intgrl_x -= di_it->ix;
 
		cit->cell->intgrl_y -= di_it->iy;
 
		cit->cell->intgrl_xx -= di_it->ixx;
 
		cit->cell->intgrl_xy -= di_it->ixy;
 
		cit->cell->intgrl_yy -= di_it->iyy;
 
	      }
 
	      di_it++;
 
	    }
 
	  }
 

	
 
	  double old_nodex, old_nodey;
 

	
 
	  old_nodex=node.x;
 
	  old_nodey=node.y;
 

	
 
	  node.x = new_p.x;
 
	  node.y = new_p.y;
 

	
 
	  for (list<Neighbor>::iterator cit=node.owners.begin();
 
	       cit!=node.owners.end();
 
	       ( cit++) ) {
 

	
 
	    /*   if (cit->cell >= 0 && cells[cit->cell].SelfIntersect()) {
 
		 node.x = old_nodex;		       
 
		 node.y = old_nodey;
 
		 goto next_node;
 
		 }*/
 
	  }
 
	  sum_dh += dh;
 
	}  
 
      }
 
    } 
 
  next_node:
 
    delta_intgrl_list.clear();//dA_list.clear();
 

	
 
  }
 

	
 
  return sum_dh;
 
}
 

	
 

	
 
void Mesh::InsertNode(Edge &e) {
 

	
 

	
 
  // Construct a new node in the middle of the edge
 
  Node *new_node = AddNode( new Node ( ( *e.first + *e.second )/2 ) );
 

	
 
  // if new node is inserted into the boundary
 
  // it will be part of the boundary, fixed, and source, too
 

	
 
  // The new node is part of the boundary only if both its neighbors are boundary nodes and the boundray proceeds from first to second.
 
  new_node->boundary = (e.first->BoundaryP() && e.first->BoundaryP()) && ((findNextBoundaryNode(e.first))->Index() == e.second->Index());
 
  new_node->fixed = e.first->fixed && e.second->fixed;
 
  new_node->sam = new_node->boundary && (e.first->sam || e.second->sam);
 

	
 
  // insert it into the boundary polygon;
 
  /* if (new_node->boundary) {
 

	
 
  // find the position of the first node in the boundary
 
  list<Node *>::iterator ins_pos = find
 
  (boundary_polygon->nodes.begin(),
 
  boundary_polygon->nodes.end(),
 
  e.first);
 
  // ... second node comes before or after it ...
 
  if (*(++ins_pos!=boundary_polygon->nodes.end()?
 
  ins_pos:boundary_polygon->nodes.begin())!=e.second) {
 

	
 
  boundary_polygon->nodes.insert(((ins_pos--)!=boundary_polygon->nodes.begin()?ins_pos:(--boundary_polygon->nodes.end())), new_node);
 

	
 
  // .. set the neighbors of the new node ...
 
  // in this case e.second and e.first are inverted
 
  new_node->owners.push_back( Neighbor(boundary_polygon, e.second, e.first ) );
 
  //cerr << "pushing back " << Neighbor(boundary_polygon->index, e.second, e.first ) << endl;
 
  } else {
 
  // insert before second node, so leave ins_pos as it is,
 
  // that is incremented
 
  boundary_polygon->nodes.insert(ins_pos, new_node);
 

	
 
  // .. set the neighbors of the new node ...
 
  new_node->owners.push_back( Neighbor(boundary_polygon, e.first, e.second ) );
 
  // cerr << "pushing back " << Neighbor(boundary_polygon->index, e.second, e.first ) << endl;
 
  }
 

	
 
  }*/
 

	
 

	
 
  list<Neighbor> owners;
 

	
 
  // push all cells owning the two nodes of the divided edges
 
  // onto a list
 
  copy(e.first->owners.begin(),
 
       e.first->owners.end(),
 
       back_inserter(owners));
 
  copy(e.second->owners.begin(),
 
       e.second->owners.end(),
 
       back_inserter(owners));
 

	
 
  //copy(owners.begin(), owners.end(), ostream_iterator<Neighbor>(cerr, " "));
 
  //cerr << endl;
 

	
 
  // sort the nodes
 
  owners.sort( mem_fun_ref( &Neighbor::Cmp ) );
 

	
 
  //  extern ofstream debug_stream;
 

	
 
  //  debug_stream << "Nodes " << e.first << " and " << e.second << endl;
 
  //  copy(owners.begin(), owners.end(), ostream_iterator<Neighbor>(debug_stream, " "));
 
  //  debug_stream << endl;
 

	
 
  // the duplicates in this list indicate cells owning this edge  
 
  list<Neighbor>::iterator c=owners.begin();
 
  while (c!=owners.end()) {
 
    c=adjacent_find(c,owners.end(),  neighbor_cell_eq);
 

	
 

	
 
    if (c!=owners.end()) { // else break;
 

	
 
      //      debug_stream << "Cell " << c->cell << " owns Edge " << e << endl;
 

	
 
 
 
      // find the position of the edge's first node in cell c...
 
      list<Node *>::iterator ins_pos = find
 
	(c->cell->nodes.begin(),
 
	 c->cell->nodes.end(),
 
	 e.first);
 
      // ... second node comes before or after it ...
 

	
 
      // XXXX probably this test is always false XXXX: No, works okay.
 
      if (*(++ins_pos!=c->cell->nodes.end()?
 
	    ins_pos:c->cell->nodes.begin())!=e.second) {
 
	c->cell->nodes.insert(((ins_pos--)!=c->cell->nodes.begin()?ins_pos:(--c->cell->nodes.end())), new_node);
 
	//cells[c->cell].nodes.insert(--ins_pos, new_node->index);
 
	// .. set the neighbors of the new node ...
 
	// in this case e.second and e.first are inverted
 
	//  cerr << "Inverted\n";
 
	new_node->owners.push_back( Neighbor(c->cell, e.second, e.first ) );
 
      } else {
 
	// insert before second node, so leave ins_pos as it is,
 
	// that is incremented
 
	c->cell->nodes.insert(ins_pos, new_node);	
 
	// .. set the neighbors of the new node ...
 
	// cerr << "Not inverted\n";
 
	new_node->owners.push_back( Neighbor(c->cell, e.first, e.second ) );
 
      }
 

	
 
      // redo the neighbors:
 
      //}
 

	
 

	
 
      // - find cell c among owners of Node e.first
 
      list<Neighbor>::iterator cpos=
 
	find_if( e.first->owners.begin(),
 
		 e.first->owners.end(),
 
		 bind2nd( mem_fun_ref(&Neighbor::CellEquals), c->cell->Index()) );
 

	
 
      // - correct the record
 
      if (cpos->nb1 == e.second) {
 
	cpos->nb1 = new_node;
 
      } else 
 
	if (cpos->nb2 == e.second) {
 
	  cpos->nb2 = new_node;
 
	}
 

	
 
      // - same for Node e.second
 
      cpos=
 
	find_if( e.second->owners.begin(),
 
		 e.second->owners.end(),
 
		 bind2nd( mem_fun_ref(&Neighbor::CellEquals), c->cell->Index()) );
 

	
 
      // - correct the record
 
      if (cpos->nb1 == e.first) {
 
	cpos->nb1 = new_node;
 
      } else 
 
	if (cpos->nb2 == e.first) {
 
	  cpos->nb2 = new_node;
 
	}
 

	
 

	
 
    } else break;
 
    c++; 
 
  }
 

	
 
  // Repair neighborhood lists in a second loop, to make sure all
 
  // `administration' is up to date
 
  while (c!=owners.end()) {
 
    c=adjacent_find(c,owners.end(),  neighbor_cell_eq);
 
    // repair neighborhood lists of cell and Wall lists
 

	
 
    if (!c->cell->BoundaryPolP()) {
 
      c->cell->ConstructNeighborList();
 
    
 
    }
 
    c++;
 
  }
 

	
 
}
 

	
 

	
 
/*
 
  Calculate circumcircle of triangle (x1,y1), (x2,y2), (x3,y3)
 
  The circumcircle centre is returned in (xc,yc) and the radius in r
 
  NOTE: A point on the edge is inside the circumcircle
 
*/
 
void Mesh::CircumCircle(double x1,double y1,double x2,double y2,double x3,double y3,
 
			double *xc,double *yc,double *r)
 
{
 
  double m1,m2,mx1,mx2,my1,my2;
 
  double dx,dy,rsqr;
 

	
 
  /* Check for coincident points */
 
  /*if (abs(y1-y2) < TINY && abs(y2-y3) < TINY)
 
    return(false);*/
 

	
 
  if (abs(y2-y1) < TINY) {
 
    m2 = - (x3-x2) / (y3-y2);
 
    mx2 = (x2 + x3) / 2.0;
 
    my2 = (y2 + y3) / 2.0;
 
    *xc = (x2 + x1) / 2.0;
 
    *yc = m2 * (*xc - mx2) + my2;
 
  } else if (abs(y3-y2) < TINY) {
 
    m1 = - (x2-x1) / (y2-y1);
 
    mx1 = (x1 + x2) / 2.0;
 
    my1 = (y1 + y2) / 2.0;
 
    *xc = (x3 + x2) / 2.0;
 
    *yc = m1 * (*xc - mx1) + my1;
 
  } else {
 
    m1 = - (x2-x1) / (y2-y1);
 
    m2 = - (x3-x2) / (y3-y2);
 
    mx1 = (x1 + x2) / 2.0;
 
    mx2 = (x2 + x3) / 2.0;
 
    my1 = (y1 + y2) / 2.0;
 
    my2 = (y2 + y3) / 2.0;
 
    *xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
 
    *yc = m1 * (*xc - mx1) + my1;
 
  }
 

	
 
  dx = x2 - *xc;
 
  dy = y2 - *yc;
 
  rsqr = dx*dx + dy*dy;
 
  *r = sqrt(rsqr);
 

	
 
  return;
 
  // Suggested
 
  // return((drsqr <= rsqr + EPSILON) ? TRUE : FALSE);
 
}
 

	
 
//
 

	
 
// return the total amount of chemical "ch" in the leaf
 
double Mesh::SumChemical(int ch) {
 

	
 
  double sum=0.;
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    sum+=(*i)->chem[ch];
 
  }
 
  return sum;
 
}
 

	
 

	
 

	
 
void Mesh::CleanUpCellNodeLists(void) {
 

	
 
  typedef vector <vector<Cell *>::iterator> CellItVect;
 

	
 
  CellItVect cellstoberemoved;
 
  vector<int> cellind;
 

	
 
  // Start of by removing all stale walls.
 
  //DeleteLooseWalls();
 
  // collect all dead cells that need to be removed from the simulation
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    if ((*i)->DeadP()) {
 
      // collect the iterators
 
      cellstoberemoved.push_back(i);
 

	
 
      // collect the indices
 
      cellind.push_back((*i)->index);
 
    } else {
 
      // Remove pointers to dead Walls
 
      for (list<Wall *>::iterator w=(*i)->walls.begin(); w!=(*i)->walls.end(); w++) {
 
	if ((*w)->DeadP()) {
 
	  (*w)=0;
 
	}
 
      }
 
      (*i)->walls.remove(0);
 
    }
 
  }
 

	
 
  // Remove pointers to dead Walls from BoundaryPolygon
 
  for (list<Wall *>::iterator w=boundary_polygon->walls.begin(); w!=boundary_polygon->walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      (*w)=0;
 
    }
 
  }
 
  boundary_polygon->walls.remove(0);
 

	
 

	
 
  // Renumber cells; this is most efficient if the list of dead cell indices is sorted
 
  sort(cellind.begin(),cellind.end());
 

	
 

	
 
  // Reindexing of Cells
 
  for (vector<int>::reverse_iterator j=cellind.rbegin(); j!=cellind.rend(); j++) {
 
    for (vector<Cell *>::reverse_iterator i=cells.rbegin(); i!=cells.rend(); i++) {
 
      if (*j < (*i)->index) (*i)->index--;
 
    }
 
  }
 

	
 

	
 
  // Actual deleting of Cells
 
  // We must delete in reverse order, otherwise the iterators become redefined
 
  for ( CellItVect::reverse_iterator i=cellstoberemoved.rbegin(); i!=cellstoberemoved.rend(); i++) {
 
    Cell::NCells()--;
 
    cells.erase(*i);
 
  }
 

	
 

	
 
  // same for nodes
 
  typedef vector <vector<Node *>::iterator> NodeItVect;
 

	
 
  NodeItVect nodestoberemoved;
 
  vector<int> nodeindlist;
 

	
 
  // collect iterators and indices of dead nodes
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    if ((*i)->DeadP()) {
 
      nodestoberemoved.push_back( i );
 
      nodeindlist.push_back((*i)->index);
 
    }
 
  }
 

	
 
  // sort the list of dead nodes for renumbering
 
  sort(nodeindlist.begin(),nodeindlist.end());
 

	
 

	
 
  // Reindicing of Nodes
 
  for (vector<int>::reverse_iterator j=nodeindlist.rbegin(); j!=nodeindlist.rend(); j++) {
 
    for (vector<Node *>::reverse_iterator i=nodes.rbegin(); i!=nodes.rend(); i++) {
 
      if (*j < (*i)->index) { 
 
	(*i)->index--;
 
      } 
 
    }
 
  }
 

	
 
  // Actual deleting of nodes
 
  // We must delete in reverse order, otherwise the iterators become redefined
 
  for ( NodeItVect::reverse_iterator i=nodestoberemoved.rbegin(); i!=nodestoberemoved.rend(); i++) {
 
    Node::nnodes--;
 
    nodes.erase(*i);
 
  }
 

	
 

	
 

	
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      Wall::nwalls--;
 
      delete *w;
 
      *w = 0;
 
    }
 
  }
 

	
 
  walls.remove( 0 );
 

	
 

	
 

	
 
  // Clean up all intercellular connections and redo everything
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    (*i)->owners.clear();
 
  }
 

	
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    (*i)->ConstructConnections();
 
  }
 

	
 
  boundary_polygon->ConstructConnections();
 

	
 
  // remake shuffled_nodes and shuffled cells
 
  shuffled_nodes.clear();
 
  shuffled_nodes = nodes;
 

	
 
  shuffled_cells.clear();
 
  shuffled_cells = cells;
 
}
 

	
 
void Mesh::CutAwayBelowLine( Vector startpoint, Vector endpoint) {
 

	
 
  // Kills all cells below the line startpoint -> endpoint
 

	
 
  Vector perp = (endpoint-startpoint).Perp2D().Normalised();
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Before Apoptose" << endl;
 
#endif
 

	
 
  TestIllegalWalls();
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 

	
 
    // do some vector geometry to check whether the cell is below the cutting line
 
    Vector cellvec = ((*i)->Centroid()-startpoint);
 

	
 
    if ( InnerProduct(perp, cellvec) < 0 ) {
 
      // remove those cells
 
      (*i)->Apoptose();
 
    }
 
  }
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Before CleanUpCellNodeLists" << endl;
 
#endif
 
  TestIllegalWalls();
 

	
 
  CleanUpCellNodeLists();
 
}
 

	
 
void Mesh::CutAwaySAM(void) {
 

	
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    if( (*i)->Boundary() == Cell::SAM ) {
 
      (*i)->Apoptose();
 
    }
 
  }
 
  TestIllegalWalls();
 
  CleanUpCellNodeLists();
 
}
 

	
 
void Mesh::TestIllegalWalls(void) {
 

	
 
  for (list<Wall *>::iterator w = walls.begin(); w!=walls.end(); w++) {
 
    if ((*w)->IllegalP() ) {
 
#ifdef QDEBUG
 
      cerr << "Wall " << **w << " is illegal." << endl;
 
#endif
 
    }
 
  }
 
}
 

	
 

	
 

	
 
class node_owners_eq : public unary_function<Node, bool> {
 
  int no;
 
public:
 

	
 
  explicit node_owners_eq(int nn) { no=nn; }
 

	
 
  bool operator() (const Node &n) const {
 
    if (n.CellsSize()==1) 
 
      return true;
 
    else 
 
      return false;
 
  }
 
};
 

	
 

	
 
void Mesh::RepairBoundaryPolygon(void) {
 

	
 
  // After serious manipulations (e.g. after cutting part off the
 
  // leaf) repair the boundary polygon. It assumes the cut line has
 
  // already been marked "boundary" and the original boundary marks
 
  // were not removed. 
 
  //
 
  // So, this function just puts boundary nodes into the boundary
 
  // polygon in the right order; it cannot detect boundaries from
 
  // scratch.
 

	
 
  Node *boundary_node=0, *next_boundary_node=0, *internal_node;
 
  set<int> original_boundary_nodes, repaired_boundary_nodes;
 
  vector<int> difference; // set difference result
 

	
 
  // Step 0: print out current boundary polygon
 
#ifdef QDEBUG
 
  qDebug() << endl << "Original Boundary Polygon node indices: ";
 
  foreach (Node* node, boundary_polygon->nodes) {
 
    qDebug() << node->Index() << " " ;
 
  }    
 
  qDebug() << endl << endl;
 
#endif
 

	
 
  // Step 1a: Create a set containing the current boundary polygon nodes' Indices.
 
  foreach (Node* node, boundary_polygon->nodes) {
 
    original_boundary_nodes.insert(node->Index());
 
  }
 

	
 
  // Step 1b: remove all nodes from boundary polygon
 
  boundary_polygon->nodes.clear();
 

	
 
  // Step 2: Remove all references to the boundary polygon from the Mesh's current list of nodes
 
  foreach (Node* node, nodes) {
 
    node->Unmark(); // remove marks, we need them to determine if we have closed the circle
 
    list<Neighbor>::iterator boundary_ref_pos;
 
    if ((boundary_ref_pos = find_if (node->owners.begin(), node->owners.end(), 
 
				     bind2nd(mem_fun_ref(&Neighbor::CellEquals), -1))) != node->owners.end()) {
 
      // i.e. if one of the node's owners is the boundary polygon 
 
      node->owners.erase(boundary_ref_pos); // remove the reference
 
    }
 
  }
 

	
 
  // Step 3: Search for the first boundary node.  We reconstruct the
 
  // boundary polygon by moving along the boundary nodes until we've
 
  // encircled the polygon. Since manually adding nodes may have
 
  // turned nodes previously along the boundary into internal nodes,
 
  // we search through all the node until we find first boundary node
 
  // and proceed from there. If findNextBoundaryNode() returns a node
 
  // other than the one passed to it, the original node is the first
 
  // boundary node.
 
  foreach (Node* node, nodes) {
 
    if ((findNextBoundaryNode(node))->index != node->index){
 
      next_boundary_node = node;
 
      break;
 
    }
 
  }
 

	
 
  // We have a problem if we arrive here without having found a boundary node.
 
  if (!next_boundary_node) throw("Cannot find a boundary node!.");
 

	
 
  // Reconstruct the list of boundary polygon nodes.
 
  do {
 
    boundary_node = next_boundary_node;
 
    boundary_node->Mark();
 
    boundary_polygon->nodes.push_back(boundary_node);
 
    next_boundary_node = findNextBoundaryNode(boundary_node);
 
  } while ( !next_boundary_node->Marked() );
 

	
 

	
 
  // Create a set containing the reconstructed boundary polygon nodes' Indices.
 
  for (list<Node *>::iterator it = boundary_polygon->nodes.begin(); it!=boundary_polygon->nodes.end(); ++it) {
 
    repaired_boundary_nodes.insert((*it)->Index());
 
  }
 

	
 
  // Calculate the difference between the original and repaired sets of boundary nodes
 
  // yielding the set of nodes that are no longer part of the boundary polygon.
 
  set_difference(original_boundary_nodes.begin(), original_boundary_nodes.end(),
 
                 repaired_boundary_nodes.begin(), repaired_boundary_nodes.end(), back_inserter(difference));
 

	
 
  // Tell each node in the difference that it's no longer part of the boundary polygon
 
  vector<Node *>::iterator internal_node_it;
 
  foreach (int i, difference){
 
    internal_node_it = find_if (nodes.begin(), nodes.end(), bind2nd(mem_fun(&Node::IndexEquals), i));
 
    internal_node = *internal_node_it; // dereference the itterator to get to the node pointer
 
    if (!internal_node) throw("Found a null Node pointer.");
 
    internal_node->UnsetBoundary();
 
  }
 

	
 
  boundary_polygon->ConstructConnections();
 
  for (list<Wall *>::iterator w=boundary_polygon->walls.begin(); w!=boundary_polygon->walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      (*w)=0;
 
    }
 
  }
 
  boundary_polygon->walls.remove(0);
 
  boundary_polygon->ConstructNeighborList();
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Repaired Boundary Polygon node indices: ";
 
  foreach (Node* node, boundary_polygon->nodes){
 
    qDebug() << node->Index() << " " ;
 
  }
 
  qDebug() << endl ;
 

	
 
#ifdef _undefined_
 
  qDebug() << "NODES:" << endl;
 
  foreach(Node* node, nodes) {
 
    qDebug() << *node;
 
  }
 
  qDebug() << endl;
 

	
 
  qDebug() << "WALLS:" << endl;
 
  foreach(Wall* wall, walls) {
 
    qDebug() << *wall;
 
  }
 
  qDebug() << endl;
 

	
 
  qDebug() << "CELLS:" << endl;
 
  foreach(Cell* cell, cells) {
 
    qDebug() << *cell;
 
  }
 
  qDebug() << endl;
 
#endif
 
#endif
 
}
 

	
 

	
 
Node* Mesh::findNextBoundaryNode(Node* boundary_node) {
 
  bool found_next_boundary_node = false;
 
  Node *next_boundary_node = 0;
 
  set<int> boundary_node_owners; // This is a list of the current boundary node's owners' Ids
 
  vector<int> neighborIds; // A list of the current boundary node's owners' 2nd neighbor Ids
 
  vector<set<int> *>  nodeOwners; // A vector of set pointers where each set contains the owner Ids of the nodes in the neighborIds list.
 
  vector<int> intersection; // set intersection result
 

	
 
  // The next boundary node is that which has only one owner in common with the current boundary node
 
  for (list<Neighbor>::iterator it=boundary_node->owners.begin(); it!=boundary_node->owners.end(); ++it) {
 
    if (it->cell->Index() != -1) boundary_node_owners.insert(it->cell->Index()); // Save each of the current boundary node's owners' Ids - except the boundary polygon 
 
    set<int> *owners = new set<int>; // create a set to hold a 2nd neighbor's owners' Ids
 
    nodeOwners.push_back(owners);
 
    neighborIds.push_back(it->nb2->Index());
 
    foreach(Neighbor neighbor, it->nb2->owners){
 
      if (neighbor.cell->Index() != -1) owners->insert(neighbor.cell->Index()); // Save second neighbors' owners' Ids - except the boundary polygon 
 
    }
 
  }
 
  vector<int>::iterator itt = neighborIds.begin();
 
  vector<set<int> *>::iterator it = nodeOwners.begin();
 

	
 
#ifdef QDEBUG  
 
  qDebug() << "Boundary node: " <<  boundary_node->Index() << " is owned by the following cells: ";
 
  foreach (int i, boundary_node_owners){
 
    qDebug() << i << "  ";
 
  }
 
  qDebug() << endl;
 
#endif
 

	
 
  for (; it < nodeOwners.end(); it++, itt++) {
 
    intersection.clear();
 
    set_intersection(boundary_node_owners.begin(), boundary_node_owners.end(), (*it)->begin(), (*it)->end(), back_inserter(intersection));
 

	
 
#ifdef QDEBUG  
 
    qDebug() << "The intersection of the boundary node(" << boundary_node->Index() << ") owners and its 2nd neighbor(" <<  *itt << ") owners is: ";
 
    foreach (int i, intersection){
 
      qDebug() << i << "  ";
 
    }
 
    qDebug() << endl;
 
#endif
 

	
 
    if (intersection.size() == 1){
 
      found_next_boundary_node = true;
 
      vector<Node *>::iterator next_boundary_node_it = find_if (nodes.begin(), nodes.end(), bind2nd(mem_fun(&Node::IndexEquals), *itt));
 
      next_boundary_node = *next_boundary_node_it; // defeference the itterator to get to the node pointer
 

	
 
#ifdef QDEBUG  
 
      qDebug() << "The Current boundary node is: " << boundary_node->Index()
 
	       << ". The Next boundary node is: " << *itt << ((next_boundary_node->Marked()) ? " Marked" : " Unmarked") << endl << endl;
 
#endif
 

	
 
      break;
 
    }
 
  }
 

	
 
#ifdef QDEBUG  
 
  if (!found_next_boundary_node) {
 
    qDebug() << "OOPS! Didn't find the next boundrary node!" << endl;
 
  }
 
#endif
 

	
 
  return next_boundary_node;
 
}
 

	
 

	
 
void Mesh::CleanUpWalls(void) {
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      delete *w;
 
      (*w)=0;      
 
    }
 
  }
 
  walls.remove(0);
 
}
 

	
 
void Mesh::Rotate(double angle, Vector center) {
 

	
 
  // Rotate the mesh over the angle "angle", relative to center point "center".
 

	
 
  Matrix rotmat;
 

	
 
  rotmat.Rot2D(angle);
 

	
 
  for (vector<Node *>::iterator n=nodes.begin(); n!=nodes.end(); n++) {
 
    (*n)->setPos ( rotmat * ( *(*n) - center ) + center );  
 
  }
 
}
 

	
 

	
 
void Mesh::PrintWallList( void ) {
 

	
 
  transform ( walls.begin(), walls.end(), ostream_iterator<Wall>(cerr, "\n"), deref_ptr<Wall> );
 
}
 

	
 
#include <QString>
 
//#include "forwardeuler.h"
 
#include "rungekutta.h"
 

	
 
class SolveMesh : public RungeKutta {
 

	
 
private:
 
  SolveMesh(void);
 

	
 
public:
 
  SolveMesh(Mesh *m_) {
 

	
 
    m = m_;
 

	
 
    kmax=0;
 
    kount=0;
 
    xp=0; yp=0; dxsav=0;
 

	
 

	
 
  }
 

	
 
protected:
 
  virtual void derivs(double x, double *y, double *dydx) {
 

	
 
    // set mesh with new values given by ODESolver
 
    // (we must do this, because only mesh knows the connections
 
    // between the variables)
 

	
 
    m->setValues(x,y);
 
    m->Derivatives(dydx);
 

	
 
    //cerr << "Calculated derivatives at " << x << "\n";    
 
  }
 

	
 
private:
 
  Mesh *m;
 
  int kmax,kount;
 
  double *xp,**yp,dxsav;
 
  bool monitor_window;
 
};
 

	
 

	
 

	
 
void Mesh::ReactDiffuse(double delta_t) {
 

	
 
  // Set Lengths of Walls
 
  for_each ( walls.begin(), walls.end(), 
 
	     mem_fun( &Wall::SetLength ) );
 

	
 
  static SolveMesh *solver = new SolveMesh(this);
 

	
 
  int nok, nbad, nvar;
 
  double *ystart = getValues(&nvar);
 

	
 
  solver->odeint(ystart, nvar, getTime(), getTime() + delta_t, 
 
		 par.ode_accuracy, par.dt, 1e-10, &nok, &nbad);
 

	
 
  setTime(getTime()+delta_t);
 
  setValues(getTime(),ystart);
 
}
 

	
 

	
 
Vector Mesh::FirstConcMoment(int chem) {
 

	
 
  Vector moment;
 
  for (vector<Cell *>::const_iterator c=cells.begin(); c!=cells.end(); c++) {
 
    moment += (*c)->Chemical(chem) * (*c)->Centroid();
 
  }
 
  return moment / (double)cells.size();
 
}
 

	
 
/*! This member function deletes all walls connected to two dead cells from the mesh.
 
  It should be called before the Cells are actually removed.
 
  If the cell is connect to one dead cell only, that reference is substituted for a reference 
 
  to the boundary polygon.
 
*/
 
void Mesh::DeleteLooseWalls(void) {
 

	
 
  list<Wall *>::iterator w=walls.begin();
 

	
 
  while (w!=walls.end()) {
 

	
 
    // if both cells of the wall are dead, remove the wall
 
    if ((*w)->C1()->DeadP() || (*w)->C2()->DeadP()) {
 
      if ((*w)->C1()->DeadP() && (*w)->C2()->DeadP()) {
 
	delete *w;
 
	w=walls.erase(w);
 
      } else {
 
	if ((*w)->C1()->DeadP())
 
	  (*w)->c1 = boundary_polygon;
 
	else
 
	  (*w)->c2 = boundary_polygon;
 
	w++;
 
      }
 
    } else {
 
      w++;
 
    }
 

	
 
  }
 
}
 

	
 
/*void Mesh::FitLeafToCanvas(double width, double height) {
 

	
 
  Vector bbll,bbur;
 
  BoundingBox(bbll,bbur);
 

	
 
  double scale_x = width/(bbur.x-bbll.x);
 
  double scale_y = height/(bbur.y-bbll.y);
 

	
 
  double factor = scale_x<scale_y ? scale_x:scale_y;
 

	
 
  Cell::SetMagnification(factor); // smallest of scale_x and scale_y
 

	
 
  double offset_x = (width/Cell::Magnification()-(bbur.x-bbll.x))/2.;  
 
  double offset_y = (height/Cell::Magnification()-(bbur.y-bbll.y))/2.;
 

	
 
  Cell::setOffset(offset_x, offset_y);
 

	
 
  }*/
 

	
 

	
 

	
 
void Mesh::CleanChemicals(const vector<double> &clean_chem) {
 

	
 
  if (clean_chem.size()!=(unsigned)Cell::NChem()) {
 
    throw "Run time error in Mesh::CleanChemicals: size of clean_chem should be equal to Cell::NChem()";
 
  }
 
  for (vector<Cell *>::iterator c=cells.begin(); c!=cells.end(); c++) {
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*c)->SetChemical(i,clean_chem[i]);
 
    }
 
    (*c)->SetNewChemToChem();
 
  }
 
}
 

	
 

	
 
void Mesh::CleanTransporters(const vector<double> &clean_transporters) {
 

	
 
  if (clean_transporters.size()!=(unsigned)Cell::NChem()) {
 
    throw "Run time error in Mesh::CleanTransporters: size ofclean_transporters should be equal to Cell::NChem()";
 
  }
 

	
 

	
 
  // clean transporters
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*w)->setTransporters1(i,clean_transporters[i]); (*w)->setNewTransporters1(i,clean_transporters[i]);
 
      (*w)->setTransporters2(i,clean_transporters[i]); (*w)->setNewTransporters2(i,clean_transporters[i]);
 
    }
 
  }
 
}
 

	
 

	
 
void Mesh::RandomizeChemicals(const vector<double> &max_chem, const vector<double> &max_transporters) {
 

	
 
  if (max_chem.size()!=(unsigned)Cell::NChem() || max_transporters.size()!=(unsigned)Cell::NChem()) {
 
    throw "Run time error in Mesh::CleanChemicals: size of max_chem and max_transporters should be equal to Cell::NChem()";
 
  }
 

	
 
  for (vector<Cell *>::iterator c=cells.begin(); c!=cells.end(); c++) {
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*c)->SetChemical(i,max_chem[i]*RANDOM());
 
    }
 
    (*c)->SetNewChemToChem();
 
  }
 

	
 
  // randomize transporters
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*w)->setTransporters1(i,max_transporters[i] * RANDOM()); (*w)->setNewTransporters1(i, (*w)->Transporters1(i) );
 
      (*w)->setTransporters2(i,max_transporters[i] * RANDOM()); (*w)->setNewTransporters2(i, (*w)->Transporters1(i) );
 
    }
 
  }
 
}
 

	
 
//!\brief Calculates a vector with derivatives of all variables, which
 
// we can pass to an ODESolver. 
 
void Mesh::Derivatives(double *derivs) {
 

	
 
  int nwalls = walls.size();
 
  int ncells = cells.size();
 
  int nchems = Cell::NChem();
 

	
 
  // two eqs per chemical for each walls, and one eq per chemical for each cell
 
  // This is for generality. For a specific model you may optimize
 
  // this by removing superfluous (empty) equations.
 
  int neqs = 2 * nwalls * nchems + ncells * nchems;
 

	
 
  //static double *derivs = 0; 
 
  // derivs is allocated by RungeKutta class.
 

	
 
  for (int i=0;i<neqs;i++) {
 
    derivs[i]=0.;
 
  }
 

	
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  int i=0;
 

	
 
  for (vector<Cell *>::iterator c=cells.begin(); c!=cells.end(); c++) {
 
    plugin->CellDynamics(*c, &(derivs[i]));
 
    i+=nchems;
 
  }
 

	
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    // (*wr)(*w, &(derivs[i]), &(derivs[i+nchems]));
 
    plugin->WallDynamics(*w,  &(derivs[i]), &(derivs[i+nchems]));
 
    // Transport function adds to derivatives of cell chemicals
 
    double *dchem_c1 = &(derivs[(*w)->c1->Index() * nchems]);
 
    double *dchem_c2 = &(derivs[(*w)->c2->Index() * nchems]);
 
    //plugin->CelltoCellTransport(*w, &(derivs[(*w)->c1->Index() * nchems]),
 
    //	  &(derivs[(*w)->c2->Index() * nchems]));
 
    // quick fix: dummy values to prevent end user from writing into outer space and causing a crash :-)
 
    // start here if you want to implement chemical input/output into environment over boundaries
 
    double dummy1, dummy2;
 
    if ((*w)->c1->Index()<0) { // tests if c1 is the boundary pol
 
      dchem_c1 = &dummy1;
 
    }
 
    if ((*w)->c2->Index()<0) {
 
      dchem_c2 = &dummy2;
 
    }
 
    plugin->CelltoCellTransport(*w, dchem_c1, dchem_c2); 
 

	
 
    //(*tf)(*w, &(derivs[(*w)->c1->Index() * nchems]),
 
    //&(derivs[(*w)->c2->Index() * nchems] ) );
 
    i+=2*nchems;
 
  }
 
}
 

	
 
void Mesh::setValues(double x, double *y) {
 

	
 
  //int nwalls = walls.size();
 
  //int ncells = cells.size();
 
  int nchems = Cell::NChem();
 

	
 
  // two eqs per chemical for each walls, and one eq per chemical for each cell
 
  // This is for generality. For a specific model you may optimize
 
  // this by removing superfluous (empty) equations.
 
  //int neqs = 2 * nwalls * nchems + ncells * nchems;
 

	
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  int i=0;
 
  static int emit_count=0;
 
  const int stride = 100;
 
  for (vector<Cell *>::iterator c=cells.begin(); c!=cells.end(); c++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*c)->SetChemical(ch, y[i+ch]);
 
    }
 
    if ( !(emit_count%stride)) {
 
      (*c)->EmitValues(x);
 
    }
 
    i+=nchems;
 
  }
 

	
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*w)->setTransporters1(ch,y[i+ch]);
 
    }
 
    i+=nchems;
 

	
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*w)->setTransporters2(ch,y[i+ch]);
 
    }
 
    i+=nchems;
 
  }
 
  emit_count++;
 
}
 

	
 
double *Mesh::getValues(int *neqs) {
 

	
 
  int nwalls = walls.size();
 
  int ncells = cells.size();
 
  int nchems = Cell::NChem();
 

	
 
  // two eqs per chemical for each wall, and one eq per chemical for each cell
 
  // This is for generality. For a specific model you may optimize
 
  // this by removing superfluous (empty) equations.
 
  (*neqs) = 2 * nwalls * nchems + ncells * nchems;
 

	
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  static double *values = 0;
 
  if (values!=0) { delete[] values; }
 

	
 
  values = new double[*neqs];
 

	
 
  int i=0;
 
  for (vector<Cell *>::iterator c=cells.begin(); c!=cells.end(); c++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*c)->Chemical(ch);
 
    }
 
    i+=nchems;
 
  }
 

	
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*w)->Transporters1(ch);
 
    }
 
    i+=nchems;
 

	
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*w)->Transporters2(ch);
 
    }
 
    i+=nchems;
 
  }
 
  return values;
 
}
 

	
 
void Mesh::DrawNodes(QGraphicsScene *c) const {
 

	
 
  for (vector<Node *>::const_iterator n=nodes.begin(); n!=nodes.end(); n++) {
 
    Node *i=*n;
 

	
 
    NodeItem *item = new NodeItem ( &(*i), c );
 
    item->setColor();
 

	
 
    item->setZValue(5);
 
    item->show();
 
    item ->setPos(((Cell::offset[0]+i->x)*Cell::factor),
 
		  ((Cell::offset[1]+i->y)*Cell::factor) );
 
  }
 
}
 

	
 
/*! Returns the sum of protein "ch" of a cycling protein in cells and walls */
 
double Mesh::CalcProtCellsWalls(int ch) const {
 

	
 

	
 
  double sum_prot=0.;
 

	
 
  // At membranes
 
  for (list<Wall *>::const_iterator w=walls.begin(); w!=walls.end(); w++) {
 
    sum_prot += (*w)->Transporters1(ch);
 
    sum_prot += (*w)->Transporters2(ch);
 
  }
 

	
 
  // At cells
 
  for (vector<Cell *>::const_iterator c=cells.begin(); c!=cells.end(); c++) {
 
    sum_prot += (*c)->Chemical(ch);
 
  }
 
  return sum_prot;
 
}
 

	
 
void Mesh::SettoInitVals(void) {
 

	
 
  vector<double> clean_chem(Cell::NChem());
 
  vector<double> clean_transporters(Cell::NChem());
 

	
 
  for (int i=0;i<Cell::NChem();i++) {
 
    clean_transporters[i]=0.;
 
    clean_chem[i]=par.initval[i];
 
  }
 

	
 
  CleanChemicals(clean_chem);
 
  CleanTransporters(clean_transporters);
 
}
 

	
 
string Mesh::getTimeHours(void) const {
 
  int hours = (int)(time / 3600);
 
  int mins = (int)((time - hours * 3600)/60);
 
  int secs = (int)((time - hours * 3600 - mins * 60));
 
  ostringstream tstr;
 
  tstr << hours << " h " << mins << " m " << secs << " s";
 
  return tstr.str();
 
}
 

	
 
QVector<qreal> Mesh::VertexAngles(void) {
 
  QVector<qreal> angles;
 
  for (vector<Node *>::const_iterator n=nodes.begin(); n!=nodes.end(); n++) {
 
    if ((*n)->Value()>2 && !(*n)->BoundaryP() ) {
 
      angles+=(*n)->NeighbourAngles();
 
    }
 
  }
 
  return angles;
 
}
 

	
 
QVector< QPair<qreal,int> > Mesh::VertexAnglesValues(void) {
 

	
 
  QVector< QPair<qreal,int> > anglesvalues;
 
  for (vector<Node *>::const_iterator n=nodes.begin(); n!=nodes.end(); n++) {
 
    if ((*n)->Value()>2 && !(*n)->BoundaryP() ) {
 
      QVector<qreal> angles = (*n)->NeighbourAngles();
 
      int value_vertex = angles.size();
 
      for (QVector<qreal>::ConstIterator i=angles.begin(); i!=angles.end(); i++) {
 
	anglesvalues += QPair< qreal, int > (*i, value_vertex);
 
      }
 
    }
 
  }
 
  return anglesvalues;
 
}
 

	
 
void Mesh::Clean(void) {
 
#ifdef QDEBUG
 
  qDebug() << "Freeing nodes" << endl;
 
#endif
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    delete *i;
 
  }
 
  nodes.clear();
 
  Node::nnodes=0;
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Freeing node sets" << endl;
 
#endif
 
  for (vector<NodeSet *>::iterator i=node_sets.begin(); i!=node_sets.end(); i++) {
 
    delete *i;
 
  }
 
  node_sets.clear();
 

	
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Freeing cells" << endl;
 
#endif	
 
  //CellsStaticDatamembers *old_static_data_mem = Cell::GetStaticDataMemberPointer();
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    delete *i;
 
  }
 
  //Cell::static_data_members = old_static_data_mem;
 

	
 
  cells.clear();
 
  Cell::NCells()=0;
 

	
 
  if (boundary_polygon) {
 
    delete boundary_polygon; // (already deleted during cleaning of cells?)
 
    boundary_polygon=0;
 
  }
 
#ifdef QDEBUG
 
  qDebug() << "Freeing walls" << endl;
 
#endif
 
  for (list<Wall *>::iterator i=walls.begin(); i!=walls.end(); i++) {
 
    delete *i;
 
  }
 
  walls.clear();
 
  Wall::nwalls=0;
 

	
 
  node_insertion_queue.clear();
 
  shuffled_nodes.clear();
 
  shuffled_cells.clear();
 
  time = 0.0;
 
}
 

	
 
void Mesh::StandardInit(void) {
 

	
 
  boundary_polygon = new BoundaryPolygon();
 
  Cell &circle=CircularCell(0,0,10,10);
 

	
 
  circle.SetTargetArea(circle.CalcArea());
 
  circle.SetTargetLength(par.target_length);
 
  circle.SetLambdaLength(par.lambda_celllength);
 
  SetBaseArea();
 
  // clean up chemicals 
 
  for (int c=0; c<Cell::NChem(); c++) {
 
    circle.SetChemical(c, 0.);
 
  }
 
}
 

	
 
#include "hull.h"
 

	
 

	
 
double Mesh::Compactness(double *res_compactness, double *res_area, double *res_cell_area, double *res_circumference) {
 
  
 
  // Calculate compactness using the convex hull of the cells
 
  // We use Andrew's Monotone Chain Algorithm (see hull.cpp)
 

	
 
  // Step 1. Prepare data for 2D hull code - get boundary polygon
 
  int pc=0;
 
  Point *p=new Point[boundary_polygon->nodes.size()+1];
 
  for (list<Node *>::const_iterator i = boundary_polygon->nodes.begin(); 
 
       i!=boundary_polygon->nodes.end(); i++) {
 
    p[pc++]=Point((*i)->x,(*i)->y);
 
  }
 
  
 
  // chainHull algorithm requires sorted points
 
  qSort( p, p+pc );
 

	
 
 
 
  // Step 2: call 2D Hull code
 
  int np=boundary_polygon->nodes.size();
 
  Point *hull=new Point[np+1];
 
  int nph=chainHull_2D(p,np,hull);
 
  
 
  
 
  // Step 3: calculate area and circumference of convex hull
 
  double hull_area=0.;
 
  double hull_circumference=0.;
 

	
 
  for (int i=0;i<nph-1;i++) {
 
    hull_area+=hull[i].x * hull[i+1].y - hull[i+1].x * hull[i].y;
 
    double s_dx=(hull[i+1].x-hull[i].x);
 
    double s_dy=(hull[i+1].y-hull[i].y);
 
    double l=sqrt(s_dx*s_dx+s_dy*s_dy);
 
    //    f << hull[i].x << " " << hull[i].y << " " << hull[i+1].x << " " << hull[i+1].y << " " << l << endl;
 
    hull_circumference+=l;
 
      
 
  }
 
  hull_area/=2.;
 

	
 
  // Step 4: get area of bounary polygon
 
  double boundary_pol_area = boundary_polygon->CalcArea();
 
  
 

	
 
  /*  ofstream datastr("hull.dat");
 
  for (int i=0;i<nph<i++) {
 
    datastr << hull.x << " " << hull.y << endl;
 
  }
 
  ofstream polstr("pol.dat");
 
  for (int i=0;i<np;h*/
 
  delete[] p;
 
  delete[] hull;
 

	
 

	
 
  // put intermediate results into optional pointers
 
  if (res_compactness) {
 
    *res_compactness = boundary_pol_area/hull_area;
 
  }
 
  if (res_area) {
 
    *res_area = hull_area;
 
  }
 
  if (res_cell_area) {
 
    *res_cell_area = boundary_pol_area;
 
  }
 
  if (res_circumference) {
 
    *res_circumference = hull_circumference;
 
  }
 
  
 
  // return compactness
 
  return boundary_pol_area/hull_area;
 

	
 
}
 

	
 
// DataExport
 
void Mesh::CSVExportCellData(QTextStream &csv_stream) const {
 

	
 
  csv_stream << "\"Cell Index\",\"Center of mass (x)\",\"Center of mass (y)\",\"Cell area\",\"Cell length\"";
 
  
 
  for (int c=0;c<Cell::NChem(); c++) {
 
    csv_stream << ",\"Chemical " << c << "\"";
 
  }
 
  csv_stream << endl;
 
  for (vector<Cell *>::const_iterator i=cells.begin();
 
       i!=cells.end();
 
       i++) {
 
    Vector centroid = (*i)->Centroid();
 
    csv_stream << (*i)->Index() << ", "
 
	       << centroid.x << ", "
 
	       << centroid.y << ", " 
 
	       <<  (*i)->Area() << ", "
 
	       <<(*i)->Length();
 
    for (int c=0;c<Cell::NChem(); c++) {
 
      csv_stream << ", " << (*i)->Chemical(c);
 
    }
 
    csv_stream << endl;
 
  }
 
}
 

	
 

	
 
void Mesh::CSVExportMeshData(QTextStream &csv_stream) { 
 
  
 
  csv_stream << "\"Morph area\",\"Number of cells\",\"Number of nodes\",\"Compactness\",\"Hull area\",\"Morph circumference\",\"Hull circumference\"" << endl;
 
  
 
  double res_compactness, res_area, res_cell_area, hull_circumference;
 
  Compactness(&res_compactness, &res_area, &res_cell_area, &hull_circumference);
 
  double morph_circumference = boundary_polygon->ExactCircumference();
 
  csv_stream << Area() << ", " << NCells() << ", " << NNodes() << ", " << res_compactness << ", " << res_area << ", " << morph_circumference << ", " << hull_circumference << endl;
 
  
 
}
 
/* finis */
src/parameter.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
// WARNING: This file is automatically generated by make_parameter_source.pl.
 
// Do not edit. All edits will be discarded.
 

	
 
#include "parameter.h"
 
#include <cstdio>
 
#include <cstring>
 
#include <cstdlib>
 
#include <cerrno>
 
#include <iostream>
 
#include <sstream>
 
#include "output.h"
 
#include "parse.h"
 
#include "xmlwrite.h"
 
#include "warning.h"
 
#include <QLocale>
 
#include <QDir>
 
#include <QStringList>
 

	
 
using namespace std;
 

	
 
static const std::string _module_id("$Id$");
 

	
 
Parameter::Parameter() {
 
  arrowcolor = strdup("white");
 
  arrowsize = 100;
 
  textcolor = strdup("red");
 
  cellnumsize = 1;
 
  nodenumsize = 1;
 
  node_mag = 1.0;
 
  outlinewidth = 1.0;
 
  cell_outline_color = strdup("forestgreen");
 
  resize_stride = 0;
 
  T = 1.0;
 
  lambda_length = 100.;
 
  yielding_threshold = 4.;
 
  lambda_celllength = 0.;
 
  target_length = 60.;
 
  cell_expansion_rate = 1.;
 
  cell_div_expansion_rate = 0.;
 
  auxin_dependent_growth = true;
 
  ode_accuracy = 1e-4;
 
  mc_stepsize = 0.4;
 
  mc_cell_stepsize = 0.2;
 
  energy_threshold = 1000.;
 
  bend_lambda = 0.;
 
  alignment_lambda = 0.;
 
  rel_cell_div_threshold = 2.;
 
  rel_perimeter_stiffness = 2;
 
  collapse_node_threshold = 0.05;
 
  morphogen_div_threshold = 0.2;
 
  morphogen_expansion_threshold = 0.01;
 
  copy_wall = true;
 
  source = 0.;
 
  D = new double[15];
 
  D[0] = 0.;
 
  D[1] = 0.0;
 
  D[2] = 0.0;
 
  D[3] = 0.;
 
  D[4] = 0.;
 
  D[5] = 0.;
 
  D[6] = 0.;
 
  D[7] = 0.;
 
  D[8] = 0.;
 
  D[9] = 0.;
 
  D[10] = 0.;
 
  D[11] = 0.;
 
  D[12] = 0.;
 
  D[13] = 0.;
 
  D[14] = 0.;
 
  initval = new double[15];
 
  initval[0] = 0.;
 
  initval[1] = 0.;
 
  initval[2] = 0.;
 
  initval[3] = 0.;
 
  initval[4] = 0.;
 
  initval[5] = 0.;
 
  initval[6] = 0.;
 
  initval[7] = 0.;
 
  initval[8] = 0.;
 
  initval[9] = 0.;
 
  initval[10] = 0.;
 
  initval[11] = 0.;
 
  initval[12] = 0.;
 
  initval[13] = 0.;
 
  initval[14] = 0.;
 
  k1 = 1.;
 
  k2 = 0.3;
 
  r = 1.;
 
  kr = 1.;
 
  km = 1.;
 
  Pi_tot = 1.;
 
  transport = 0.036;
 
  ka = 1;
 
  pin_prod = 0.001;
 
  pin_prod_in_epidermis = 0.1;
 
  pin_breakdown = 0.001;
 
  pin_breakdown_internal = 0.001;
 
  aux1prod = 0.001;
 
  aux1prodmeso = 0.;
 
  aux1decay = 0.001;
 
  aux1decaymeso = 0.1;
 
  aux1transport = 0.036;
 
  aux_cons = 0.;
 
  aux_breakdown = 0.;
 
  kaux1 = 1;
 
  kap = 1;
 
  leaf_tip_source = 0.001;
 
  sam_efflux = 0.0001;
 
  sam_auxin = 10.;
 
  sam_auxin_breakdown = 0;
 
  van3prod = 0.002;
 
  van3autokat = 0.1;
 
  van3sat = 10;
 
  k2van3 = 0.3;
 
  dt = 0.1;
 
  rd_dt = 1.0;
 
  datadir = strdup(".");
 
  datadir = AppendHomeDirIfPathRelative(datadir);
 
  movie = false;
 
  nit = 100000;
 
  maxt = 1000.;
 
  storage_stride = 10;
 
  xml_storage_stride = 500;
 
  rseed = -1;
 
  constituous_expansion_limit = 16;
 
  vessel_inh_level = 1;
 
  vessel_expansion_rate = 0.25;
 
  d = 0.;
 
  e = 0.;
 
  f = 0.;
 
  c = 0.;
 
  mu = 0.;
 
  nu = 0.;
 
  rho0 = 0.;
 
  rho1 = 0.;
 
  c0 = 0.;
 
  gamma = 0.;
 
  eps = 0.;
 
  k = new double[15];
 
  k[0] = 0.;
 
  k[1] = 0.0;
 
  k[2] = 0.0;
 
  k[3] = 0.;
 
  k[4] = 0.;
 
  k[5] = 0.;
 
  k[6] = 0.;
 
  k[7] = 0.;
 
  k[8] = 0.;
 
  k[9] = 0.;
 
  k[10] = 0.;
 
  k[11] = 0.;
 
  k[12] = 0.;
 
  k[13] = 0.;
 
  k[14] = 0.;
 
  i1 = 0;
 
  i2 = 0;
 
  i3 = 0;
 
  i4 = 0;
 
  i5 = 0;
 
  s1 = strdup("");
 
  s2 = strdup("");
 
  s3 = strdup("");
 
  b1 = false;
 
  b2 = false;
 
  b3 = false;
 
  b4 = false;
 
  dir1 = strdup(".");
 
  dir2 = strdup(".");
 
  export_interval = 0;
 
  export_fn_prefix = strdup("cell.");
 
}
 

	
 
Parameter::~Parameter() {
 
    
 
// destruct parameter object
 
// free string parameter
 
CleanUp();
 
}
 

	
 
void Parameter::CleanUp(void) {
 
  if (arrowcolor) 
 
     free(arrowcolor);
 
  if (textcolor) 
 
     free(textcolor);
 
  if (cell_outline_color) 
 
     free(cell_outline_color);
 
  if (D) 
 
     free(D);
 
  if (initval) 
 
     free(initval);
 
  if (datadir) 
 
     free(datadir);
 
  if (k) 
 
     free(k);
 
  if (s1) 
 
     free(s1);
 
  if (s2) 
 
     free(s2);
 
  if (s3) 
 
     free(s3);
 
  if (dir1) 
 
     free(dir1);
 
  if (dir2) 
 
     free(dir2);
 
  if (export_fn_prefix) 
 
     free(export_fn_prefix);
 

	
 
}
 

	
 
void Parameter::Read(const char *filename) {
 
    
 
  static bool ReadP=false;
 

	
 
  if (ReadP) {
 

	
 
    //throw "Run Time Error in parameter.cpp: Please Read parameter file only once!!";
 
    CleanUp();
 
	
 
  } else
 
    ReadP=true;
 

	
 
  FILE *fp=OpenReadFile(filename);
 

	
 

	
 
  arrowcolor = sgetpar(fp, "arrowcolor", "white", true);
 
  arrowsize = fgetpar(fp, "arrowsize", 100, true);
 
  textcolor = sgetpar(fp, "textcolor", "red", true);
 
  cellnumsize = igetpar(fp, "cellnumsize", 1, true);
 
  nodenumsize = igetpar(fp, "nodenumsize", 1, true);
 
  node_mag = fgetpar(fp, "node_mag", 1.0, true);
 
  outlinewidth = fgetpar(fp, "outlinewidth", 1.0, true);
 
  cell_outline_color = sgetpar(fp, "cell_outline_color", "forestgreen", true);
 
  resize_stride = igetpar(fp, "resize_stride", 0, true);
 
  T = fgetpar(fp, "T", 1.0, true);
 
  lambda_length = fgetpar(fp, "lambda_length", 100., true);
 
  yielding_threshold = fgetpar(fp, "yielding_threshold", 4., true);
 
  lambda_celllength = fgetpar(fp, "lambda_celllength", 0., true);
 
  target_length = fgetpar(fp, "target_length", 60., true);
 
  cell_expansion_rate = fgetpar(fp, "cell_expansion_rate", 1., true);
 
  cell_div_expansion_rate = fgetpar(fp, "cell_div_expansion_rate", 0., true);
 
  auxin_dependent_growth = bgetpar(fp, "auxin_dependent_growth", true, true);
 
  ode_accuracy = fgetpar(fp, "ode_accuracy", 1e-4, true);
 
  mc_stepsize = fgetpar(fp, "mc_stepsize", 0.4, true);
 
  mc_cell_stepsize = fgetpar(fp, "mc_cell_stepsize", 0.2, true);
 
  energy_threshold = fgetpar(fp, "energy_threshold", 1000., true);
 
  bend_lambda = fgetpar(fp, "bend_lambda", 0., true);
 
  alignment_lambda = fgetpar(fp, "alignment_lambda", 0., true);
 
  rel_cell_div_threshold = fgetpar(fp, "rel_cell_div_threshold", 2., true);
 
  rel_perimeter_stiffness = fgetpar(fp, "rel_perimeter_stiffness", 2, true);
 
  collapse_node_threshold = fgetpar(fp, "collapse_node_threshold", 0.05, true);
 
  morphogen_div_threshold = fgetpar(fp, "morphogen_div_threshold", 0.2, true);
 
  morphogen_expansion_threshold = fgetpar(fp, "morphogen_expansion_threshold", 0.01, true);
 
  copy_wall = bgetpar(fp, "copy_wall", true, true);
 
  source = fgetpar(fp, "source", 0., true);
 
  D = dgetparlist(fp, "D", 15, true);
 
  initval = dgetparlist(fp, "initval", 15, true);
 
  k1 = fgetpar(fp, "k1", 1., true);
 
  k2 = fgetpar(fp, "k2", 0.3, true);
 
  r = fgetpar(fp, "r", 1., true);
 
  kr = fgetpar(fp, "kr", 1., true);
 
  km = fgetpar(fp, "km", 1., true);
 
  Pi_tot = fgetpar(fp, "Pi_tot", 1., true);
 
  transport = fgetpar(fp, "transport", 0.036, true);
 
  ka = fgetpar(fp, "ka", 1, true);
 
  pin_prod = fgetpar(fp, "pin_prod", 0.001, true);
 
  pin_prod_in_epidermis = fgetpar(fp, "pin_prod_in_epidermis", 0.1, true);
 
  pin_breakdown = fgetpar(fp, "pin_breakdown", 0.001, true);
 
  pin_breakdown_internal = fgetpar(fp, "pin_breakdown_internal", 0.001, true);
 
  aux1prod = fgetpar(fp, "aux1prod", 0.001, true);
 
  aux1prodmeso = fgetpar(fp, "aux1prodmeso", 0., true);
 
  aux1decay = fgetpar(fp, "aux1decay", 0.001, true);
 
  aux1decaymeso = fgetpar(fp, "aux1decaymeso", 0.1, true);
 
  aux1transport = fgetpar(fp, "aux1transport", 0.036, true);
 
  aux_cons = fgetpar(fp, "aux_cons", 0., true);
 
  aux_breakdown = fgetpar(fp, "aux_breakdown", 0., true);
 
  kaux1 = fgetpar(fp, "kaux1", 1, true);
 
  kap = fgetpar(fp, "kap", 1, true);
 
  leaf_tip_source = fgetpar(fp, "leaf_tip_source", 0.001, true);
 
  sam_efflux = fgetpar(fp, "sam_efflux", 0.0001, true);
 
  sam_auxin = fgetpar(fp, "sam_auxin", 10., true);
 
  sam_auxin_breakdown = fgetpar(fp, "sam_auxin_breakdown", 0, true);
 
  van3prod = fgetpar(fp, "van3prod", 0.002, true);
 
  van3autokat = fgetpar(fp, "van3autokat", 0.1, true);
 
  van3sat = fgetpar(fp, "van3sat", 10, true);
 
  k2van3 = fgetpar(fp, "k2van3", 0.3, true);
 
  dt = fgetpar(fp, "dt", 0.1, true);
 
  rd_dt = fgetpar(fp, "rd_dt", 1.0, true);
 
  datadir = sgetpar(fp, "datadir", ".", true);
 
  datadir = AppendHomeDirIfPathRelative(datadir);
 
  if (strcmp(datadir, "."))
 
    MakeDir(datadir);
 
  movie = bgetpar(fp, "movie", false, true);
 
  nit = igetpar(fp, "nit", 100000, true);
 
  maxt = fgetpar(fp, "maxt", 1000., true);
 
  storage_stride = igetpar(fp, "storage_stride", 10, true);
 
  xml_storage_stride = igetpar(fp, "xml_storage_stride", 500, true);
 
  rseed = igetpar(fp, "rseed", -1, true);
 
  constituous_expansion_limit = igetpar(fp, "constituous_expansion_limit", 16, true);
 
  vessel_inh_level = fgetpar(fp, "vessel_inh_level", 1, true);
 
  vessel_expansion_rate = fgetpar(fp, "vessel_expansion_rate", 0.25, true);
 
  d = fgetpar(fp, "d", 0., true);
 
  e = fgetpar(fp, "e", 0., true);
 
  f = fgetpar(fp, "f", 0., true);
 
  c = fgetpar(fp, "c", 0., true);
 
  mu = fgetpar(fp, "mu", 0., true);
 
  nu = fgetpar(fp, "nu", 0., true);
 
  rho0 = fgetpar(fp, "rho0", 0., true);
 
  rho1 = fgetpar(fp, "rho1", 0., true);
 
  c0 = fgetpar(fp, "c0", 0., true);
 
  gamma = fgetpar(fp, "gamma", 0., true);
 
  eps = fgetpar(fp, "eps", 0., true);
 
  k = dgetparlist(fp, "k", 15, true);
 
  i1 = igetpar(fp, "i1", 0, true);
 
  i2 = igetpar(fp, "i2", 0, true);
 
  i3 = igetpar(fp, "i3", 0, true);
 
  i4 = igetpar(fp, "i4", 0, true);
 
  i5 = igetpar(fp, "i5", 0, true);
 
  s1 = sgetpar(fp, "s1", "", true);
 
  s2 = sgetpar(fp, "s2", "", true);
 
  s3 = sgetpar(fp, "s3", "", true);
 
  b1 = bgetpar(fp, "b1", false, true);
 
  b2 = bgetpar(fp, "b2", false, true);
 
  b3 = bgetpar(fp, "b3", false, true);
 
  b4 = bgetpar(fp, "b4", false, true);
 
  dir1 = sgetpar(fp, "dir1", ".", true);
 
  if (strcmp(dir1, "."))
 
    MakeDir(dir1);
 
  dir2 = sgetpar(fp, "dir2", ".", true);
 
  if (strcmp(dir2, "."))
 
    MakeDir(dir2);
 
  export_interval = igetpar(fp, "export_interval", 0, true);
 
  export_fn_prefix = sgetpar(fp, "export_fn_prefix", "cell.", true);
 
}
 

	
 
const char *sbool(const bool &p) {
 

	
 
  const char *true_str="true";
 
  const char *false_str="false";
 
  if (p)
 
    return true_str;
 
  else
 
    return false_str;
 
}
 

	
 
void Parameter::Write(ostream &os) const {
 

	
 

	
 
  if (arrowcolor) 
 
  os << " arrowcolor = " << arrowcolor << endl;
 
  os << " arrowsize = " << arrowsize << endl;
 

	
 
  if (textcolor) 
 
  os << " textcolor = " << textcolor << endl;
 
  os << " cellnumsize = " << cellnumsize << endl;
 
  os << " nodenumsize = " << nodenumsize << endl;
 
  os << " node_mag = " << node_mag << endl;
 
  os << " outlinewidth = " << outlinewidth << endl;
 

	
 
  if (cell_outline_color) 
 
  os << " cell_outline_color = " << cell_outline_color << endl;
 
  os << " resize_stride = " << resize_stride << endl;
 
  os << " T = " << T << endl;
 
  os << " lambda_length = " << lambda_length << endl;
 
  os << " yielding_threshold = " << yielding_threshold << endl;
 
  os << " lambda_celllength = " << lambda_celllength << endl;
 
  os << " target_length = " << target_length << endl;
 
  os << " cell_expansion_rate = " << cell_expansion_rate << endl;
 
  os << " cell_div_expansion_rate = " << cell_div_expansion_rate << endl;
 
  os << " auxin_dependent_growth = " << sbool(auxin_dependent_growth) << endl;
 
  os << " ode_accuracy = " << ode_accuracy << endl;
 
  os << " mc_stepsize = " << mc_stepsize << endl;
 
  os << " mc_cell_stepsize = " << mc_cell_stepsize << endl;
 
  os << " energy_threshold = " << energy_threshold << endl;
 
  os << " bend_lambda = " << bend_lambda << endl;
 
  os << " alignment_lambda = " << alignment_lambda << endl;
 
  os << " rel_cell_div_threshold = " << rel_cell_div_threshold << endl;
 
  os << " rel_perimeter_stiffness = " << rel_perimeter_stiffness << endl;
 
  os << " collapse_node_threshold = " << collapse_node_threshold << endl;
 
  os << " morphogen_div_threshold = " << morphogen_div_threshold << endl;
 
  os << " morphogen_expansion_threshold = " << morphogen_expansion_threshold << endl;
 
  os << " copy_wall = " << sbool(copy_wall) << endl;
 
  os << " source = " << source << endl;
 
  os << " D = "<< D[0] << ", " << D[1] << ", " << D[2] << ", " << D[3] << ", " << D[4] << ", " << D[5] << ", " << D[6] << ", " << D[7] << ", " << D[8] << ", " << D[9] << ", " << D[10] << ", " << D[11] << ", " << D[12] << ", " << D[13] << ", " << D[14] << endl;
 
  os << " initval = "<< initval[0] << ", " << initval[1] << ", " << initval[2] << ", " << initval[3] << ", " << initval[4] << ", " << initval[5] << ", " << initval[6] << ", " << initval[7] << ", " << initval[8] << ", " << initval[9] << ", " << initval[10] << ", " << initval[11] << ", " << initval[12] << ", " << initval[13] << ", " << initval[14] << endl;
 
  os << " k1 = " << k1 << endl;
 
  os << " k2 = " << k2 << endl;
 
  os << " r = " << r << endl;
 
  os << " kr = " << kr << endl;
 
  os << " km = " << km << endl;
 
  os << " Pi_tot = " << Pi_tot << endl;
 
  os << " transport = " << transport << endl;
 
  os << " ka = " << ka << endl;
 
  os << " pin_prod = " << pin_prod << endl;
 
  os << " pin_prod_in_epidermis = " << pin_prod_in_epidermis << endl;
 
  os << " pin_breakdown = " << pin_breakdown << endl;
 
  os << " pin_breakdown_internal = " << pin_breakdown_internal << endl;
 
  os << " aux1prod = " << aux1prod << endl;
 
  os << " aux1prodmeso = " << aux1prodmeso << endl;
 
  os << " aux1decay = " << aux1decay << endl;
 
  os << " aux1decaymeso = " << aux1decaymeso << endl;
 
  os << " aux1transport = " << aux1transport << endl;
 
  os << " aux_cons = " << aux_cons << endl;
 
  os << " aux_breakdown = " << aux_breakdown << endl;
 
  os << " kaux1 = " << kaux1 << endl;
 
  os << " kap = " << kap << endl;
 
  os << " leaf_tip_source = " << leaf_tip_source << endl;
 
  os << " sam_efflux = " << sam_efflux << endl;
 
  os << " sam_auxin = " << sam_auxin << endl;
 
  os << " sam_auxin_breakdown = " << sam_auxin_breakdown << endl;
 
  os << " van3prod = " << van3prod << endl;
 
  os << " van3autokat = " << van3autokat << endl;
 
  os << " van3sat = " << van3sat << endl;
 
  os << " k2van3 = " << k2van3 << endl;
 
  os << " dt = " << dt << endl;
 
  os << " rd_dt = " << rd_dt << endl;
 
  if (datadir) {
 
                                     QDir dataDir = QDir::home().relativeFilePath(datadir);
 
                                     os << " datadir = " << dataDir.dirName().toStdString() << endl;
 
                                 }
 
                                 else {
 
                                     os << "datadir = ." << endl;
 
                                 }
 
  os << " movie = " << sbool(movie) << endl;
 
  os << " nit = " << nit << endl;
 
  os << " maxt = " << maxt << endl;
 
  os << " storage_stride = " << storage_stride << endl;
 
  os << " xml_storage_stride = " << xml_storage_stride << endl;
 
  os << " rseed = " << rseed << endl;
 
  os << " constituous_expansion_limit = " << constituous_expansion_limit << endl;
 
  os << " vessel_inh_level = " << vessel_inh_level << endl;
 
  os << " vessel_expansion_rate = " << vessel_expansion_rate << endl;
 
  os << " d = " << d << endl;
 
  os << " e = " << e << endl;
 
  os << " f = " << f << endl;
 
  os << " c = " << c << endl;
 
  os << " mu = " << mu << endl;
 
  os << " nu = " << nu << endl;
 
  os << " rho0 = " << rho0 << endl;
 
  os << " rho1 = " << rho1 << endl;
 
  os << " c0 = " << c0 << endl;
 
  os << " gamma = " << gamma << endl;
 
  os << " eps = " << eps << endl;
 
  os << " k = "<< k[0] << ", " << k[1] << ", " << k[2] << ", " << k[3] << ", " << k[4] << ", " << k[5] << ", " << k[6] << ", " << k[7] << ", " << k[8] << ", " << k[9] << ", " << k[10] << ", " << k[11] << ", " << k[12] << ", " << k[13] << ", " << k[14] << endl;
 
  os << " i1 = " << i1 << endl;
 
  os << " i2 = " << i2 << endl;
 
  os << " i3 = " << i3 << endl;
 
  os << " i4 = " << i4 << endl;
 
  os << " i5 = " << i5 << endl;
 

	
 
  if (s1) 
 
  os << " s1 = " << s1 << endl;
 

	
 
  if (s2) 
 
  os << " s2 = " << s2 << endl;
 

	
 
  if (s3) 
 
  os << " s3 = " << s3 << endl;
 
  os << " b1 = " << sbool(b1) << endl;
 
  os << " b2 = " << sbool(b2) << endl;
 
  os << " b3 = " << sbool(b3) << endl;
 
  os << " b4 = " << sbool(b4) << endl;
 

	
 
  if (dir1) 
 
  os << " dir1 = " << dir1 << endl;
 

	
 
  if (dir2) 
 
  os << " dir2 = " << dir2 << endl;
 
  os << " export_interval = " << export_interval << endl;
 

	
 
  if (export_fn_prefix) 
 
  os << " export_fn_prefix = " << export_fn_prefix << endl;
 
}
 

	
 
void Parameter::XMLAdd(xmlNode *root) const {
 
    xmlNode *xmlparameter = xmlNewChild(root, NULL, BAD_CAST "parameter", NULL);
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "arrowcolor" );
 
  ostringstream text;
 

	
 
  if (arrowcolor) 
 
    text << arrowcolor;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "arrowsize" );
 
  ostringstream text;
 
    text << arrowsize;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "textcolor" );
 
  ostringstream text;
 

	
 
  if (textcolor) 
 
    text << textcolor;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "cellnumsize" );
 
  ostringstream text;
 
    text << cellnumsize;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "nodenumsize" );
 
  ostringstream text;
 
    text << nodenumsize;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "node_mag" );
 
  ostringstream text;
 
    text << node_mag;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "outlinewidth" );
 
  ostringstream text;
 
    text << outlinewidth;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "cell_outline_color" );
 
  ostringstream text;
 

	
 
  if (cell_outline_color) 
 
    text << cell_outline_color;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "resize_stride" );
 
  ostringstream text;
 
    text << resize_stride;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "T" );
 
  ostringstream text;
 
    text << T;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "lambda_length" );
 
  ostringstream text;
 
    text << lambda_length;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "yielding_threshold" );
 
  ostringstream text;
 
    text << yielding_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "lambda_celllength" );
 
  ostringstream text;
 
    text << lambda_celllength;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "target_length" );
 
  ostringstream text;
 
    text << target_length;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "cell_expansion_rate" );
 
  ostringstream text;
 
    text << cell_expansion_rate;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "cell_div_expansion_rate" );
 
  ostringstream text;
 
    text << cell_div_expansion_rate;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "auxin_dependent_growth" );
 
  ostringstream text;
 
text << sbool(auxin_dependent_growth);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "ode_accuracy" );
 
  ostringstream text;
 
    text << ode_accuracy;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "mc_stepsize" );
 
  ostringstream text;
 
    text << mc_stepsize;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "mc_cell_stepsize" );
 
  ostringstream text;
 
    text << mc_cell_stepsize;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "energy_threshold" );
 
  ostringstream text;
 
    text << energy_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "bend_lambda" );
 
  ostringstream text;
 
    text << bend_lambda;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "alignment_lambda" );
 
  ostringstream text;
 
    text << alignment_lambda;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rel_cell_div_threshold" );
 
  ostringstream text;
 
    text << rel_cell_div_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rel_perimeter_stiffness" );
 
  ostringstream text;
 
    text << rel_perimeter_stiffness;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "collapse_node_threshold" );
 
  ostringstream text;
 
    text << collapse_node_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "morphogen_div_threshold" );
 
  ostringstream text;
 
    text << morphogen_div_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "morphogen_expansion_threshold" );
 
  ostringstream text;
 
    text << morphogen_expansion_threshold;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "copy_wall" );
 
  ostringstream text;
 
text << sbool(copy_wall);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "source" );
 
  ostringstream text;
 
    text << source;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "D" );
 
  xmlNode *xmlvalarray = xmlNewChild(xmlpar, NULL, BAD_CAST "valarray", NULL);
 
  {
 
    ostringstream text;
 
    text << D[0];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[1];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[2];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[3];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[4];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[5];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[6];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[7];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[8];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[9];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[10];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[11];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[12];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[13];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << D[14];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "initval" );
 
  xmlNode *xmlvalarray = xmlNewChild(xmlpar, NULL, BAD_CAST "valarray", NULL);
 
  {
 
    ostringstream text;
 
    text << initval[0];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[1];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[2];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[3];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[4];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[5];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[6];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[7];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[8];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[9];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[10];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[11];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[12];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[13];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << initval[14];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "k1" );
 
  ostringstream text;
 
    text << k1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "k2" );
 
  ostringstream text;
 
    text << k2;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "r" );
 
  ostringstream text;
 
    text << r;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "kr" );
 
  ostringstream text;
 
    text << kr;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "km" );
 
  ostringstream text;
 
    text << km;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "Pi_tot" );
 
  ostringstream text;
 
    text << Pi_tot;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "transport" );
 
  ostringstream text;
 
    text << transport;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "ka" );
 
  ostringstream text;
 
    text << ka;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "pin_prod" );
 
  ostringstream text;
 
    text << pin_prod;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "pin_prod_in_epidermis" );
 
  ostringstream text;
 
    text << pin_prod_in_epidermis;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "pin_breakdown" );
 
  ostringstream text;
 
    text << pin_breakdown;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "pin_breakdown_internal" );
 
  ostringstream text;
 
    text << pin_breakdown_internal;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux1prod" );
 
  ostringstream text;
 
    text << aux1prod;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux1prodmeso" );
 
  ostringstream text;
 
    text << aux1prodmeso;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux1decay" );
 
  ostringstream text;
 
    text << aux1decay;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux1decaymeso" );
 
  ostringstream text;
 
    text << aux1decaymeso;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux1transport" );
 
  ostringstream text;
 
    text << aux1transport;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux_cons" );
 
  ostringstream text;
 
    text << aux_cons;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "aux_breakdown" );
 
  ostringstream text;
 
    text << aux_breakdown;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "kaux1" );
 
  ostringstream text;
 
    text << kaux1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "kap" );
 
  ostringstream text;
 
    text << kap;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "leaf_tip_source" );
 
  ostringstream text;
 
    text << leaf_tip_source;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "sam_efflux" );
 
  ostringstream text;
 
    text << sam_efflux;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "sam_auxin" );
 
  ostringstream text;
 
    text << sam_auxin;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "sam_auxin_breakdown" );
 
  ostringstream text;
 
    text << sam_auxin_breakdown;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "van3prod" );
 
  ostringstream text;
 
    text << van3prod;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "van3autokat" );
 
  ostringstream text;
 
    text << van3autokat;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "van3sat" );
 
  ostringstream text;
 
    text << van3sat;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "k2van3" );
 
  ostringstream text;
 
    text << k2van3;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "dt" );
 
  ostringstream text;
 
    text << dt;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rd_dt" );
 
  ostringstream text;
 
    text << rd_dt;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "datadir" );
 
  ostringstream text;
 

	
 
  if (datadir) {
 
                                     QDir dataDir = QDir::home().relativeFilePath(datadir);
 
                                     text << dataDir.dirName().toStdString();
 
                                   }
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "movie" );
 
  ostringstream text;
 
text << sbool(movie);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "nit" );
 
  ostringstream text;
 
    text << nit;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "maxt" );
 
  ostringstream text;
 
    text << maxt;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "storage_stride" );
 
  ostringstream text;
 
    text << storage_stride;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "xml_storage_stride" );
 
  ostringstream text;
 
    text << xml_storage_stride;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rseed" );
 
  ostringstream text;
 
    text << rseed;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "constituous_expansion_limit" );
 
  ostringstream text;
 
    text << constituous_expansion_limit;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "vessel_inh_level" );
 
  ostringstream text;
 
    text << vessel_inh_level;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "vessel_expansion_rate" );
 
  ostringstream text;
 
    text << vessel_expansion_rate;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "d" );
 
  ostringstream text;
 
    text << d;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "e" );
 
  ostringstream text;
 
    text << e;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "f" );
 
  ostringstream text;
 
    text << f;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "c" );
 
  ostringstream text;
 
    text << c;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "mu" );
 
  ostringstream text;
 
    text << mu;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "nu" );
 
  ostringstream text;
 
    text << nu;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rho0" );
 
  ostringstream text;
 
    text << rho0;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "rho1" );
 
  ostringstream text;
 
    text << rho1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "c0" );
 
  ostringstream text;
 
    text << c0;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "gamma" );
 
  ostringstream text;
 
    text << gamma;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "eps" );
 
  ostringstream text;
 
    text << eps;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "k" );
 
  xmlNode *xmlvalarray = xmlNewChild(xmlpar, NULL, BAD_CAST "valarray", NULL);
 
  {
 
    ostringstream text;
 
    text << k[0];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[1];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[2];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[3];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[4];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[5];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[6];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[7];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[8];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[9];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[10];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[11];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[12];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[13];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
  {
 
    ostringstream text;
 
    text << k[14];
 
    xmlNode *xmlval = xmlNewChild(xmlvalarray, NULL, BAD_CAST "val", NULL);
 
    xmlNewProp(xmlval, BAD_CAST "v", BAD_CAST text.str().c_str());
 
  }
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "i1" );
 
  ostringstream text;
 
    text << i1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "i2" );
 
  ostringstream text;
 
    text << i2;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "i3" );
 
  ostringstream text;
 
    text << i3;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "i4" );
 
  ostringstream text;
 
    text << i4;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "i5" );
 
  ostringstream text;
 
    text << i5;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "s1" );
 
  ostringstream text;
 

	
 
  if (s1) 
 
    text << s1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "s2" );
 
  ostringstream text;
 

	
 
  if (s2) 
 
    text << s2;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "s3" );
 
  ostringstream text;
 

	
 
  if (s3) 
 
    text << s3;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "b1" );
 
  ostringstream text;
 
text << sbool(b1);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "b2" );
 
  ostringstream text;
 
text << sbool(b2);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "b3" );
 
  ostringstream text;
 
text << sbool(b3);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "b4" );
 
  ostringstream text;
 
text << sbool(b4);
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "dir1" );
 
  ostringstream text;
 

	
 
  if (dir1) 
 
    text << dir1;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "dir2" );
 
  ostringstream text;
 

	
 
  if (dir2) 
 
    text << dir2;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "export_interval" );
 
  ostringstream text;
 
    text << export_interval;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
{
 
  xmlNode *xmlpar = xmlNewChild(xmlparameter, NULL, BAD_CAST "par", NULL);
 
  xmlNewProp(xmlpar, BAD_CAST "name", BAD_CAST "export_fn_prefix" );
 
  ostringstream text;
 

	
 
  if (export_fn_prefix) 
 
    text << export_fn_prefix;
 
xmlNewProp(xmlpar, BAD_CAST "val", BAD_CAST text.str().c_str());
 
}
 
}
 
void Parameter::AssignValToPar(const char *namec, const char *valc) {
 
  QLocale standardlocale(QLocale::C);
 
  bool ok;
 
if (!strcmp(namec, "arrowcolor")) {
 
  if (arrowcolor) { free(arrowcolor); }
 
  arrowcolor=strdup(valc);
 
}
 
if (!strcmp(namec, "arrowsize")) {
 
  arrowsize = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'arrowsize' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "textcolor")) {
 
  if (textcolor) { free(textcolor); }
 
  textcolor=strdup(valc);
 
}
 
if (!strcmp(namec, "cellnumsize")) {
 
  cellnumsize = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'cellnumsize' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "nodenumsize")) {
 
  nodenumsize = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'nodenumsize' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "node_mag")) {
 
  node_mag = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'node_mag' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "outlinewidth")) {
 
  outlinewidth = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'outlinewidth' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "cell_outline_color")) {
 
  if (cell_outline_color) { free(cell_outline_color); }
 
  cell_outline_color=strdup(valc);
 
}
 
if (!strcmp(namec, "resize_stride")) {
 
  resize_stride = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'resize_stride' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "T")) {
 
  T = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'T' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "lambda_length")) {
 
  lambda_length = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'lambda_length' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "yielding_threshold")) {
 
  yielding_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'yielding_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "lambda_celllength")) {
 
  lambda_celllength = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'lambda_celllength' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "target_length")) {
 
  target_length = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'target_length' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "cell_expansion_rate")) {
 
  cell_expansion_rate = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'cell_expansion_rate' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "cell_div_expansion_rate")) {
 
  cell_div_expansion_rate = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'cell_div_expansion_rate' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "auxin_dependent_growth")) {
 
auxin_dependent_growth = strtobool(valc);
 
}
 
if (!strcmp(namec, "ode_accuracy")) {
 
  ode_accuracy = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'ode_accuracy' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "mc_stepsize")) {
 
  mc_stepsize = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'mc_stepsize' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "mc_cell_stepsize")) {
 
  mc_cell_stepsize = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'mc_cell_stepsize' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "energy_threshold")) {
 
  energy_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'energy_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "bend_lambda")) {
 
  bend_lambda = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'bend_lambda' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "alignment_lambda")) {
 
  alignment_lambda = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'alignment_lambda' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rel_cell_div_threshold")) {
 
  rel_cell_div_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'rel_cell_div_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rel_perimeter_stiffness")) {
 
  rel_perimeter_stiffness = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'rel_perimeter_stiffness' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "collapse_node_threshold")) {
 
  collapse_node_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'collapse_node_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "morphogen_div_threshold")) {
 
  morphogen_div_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'morphogen_div_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "morphogen_expansion_threshold")) {
 
  morphogen_expansion_threshold = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'morphogen_expansion_threshold' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "copy_wall")) {
 
copy_wall = strtobool(valc);
 
}
 
if (!strcmp(namec, "source")) {
 
  source = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'source' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "k1")) {
 
  k1 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'k1' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "k2")) {
 
  k2 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'k2' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "r")) {
 
  r = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'r' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "kr")) {
 
  kr = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'kr' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "km")) {
 
  km = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'km' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "Pi_tot")) {
 
  Pi_tot = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'Pi_tot' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "transport")) {
 
  transport = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'transport' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "ka")) {
 
  ka = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'ka' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "pin_prod")) {
 
  pin_prod = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'pin_prod' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "pin_prod_in_epidermis")) {
 
  pin_prod_in_epidermis = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'pin_prod_in_epidermis' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "pin_breakdown")) {
 
  pin_breakdown = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'pin_breakdown' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "pin_breakdown_internal")) {
 
  pin_breakdown_internal = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'pin_breakdown_internal' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux1prod")) {
 
  aux1prod = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux1prod' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux1prodmeso")) {
 
  aux1prodmeso = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux1prodmeso' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux1decay")) {
 
  aux1decay = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux1decay' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux1decaymeso")) {
 
  aux1decaymeso = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux1decaymeso' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux1transport")) {
 
  aux1transport = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux1transport' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux_cons")) {
 
  aux_cons = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux_cons' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "aux_breakdown")) {
 
  aux_breakdown = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'aux_breakdown' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "kaux1")) {
 
  kaux1 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'kaux1' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "kap")) {
 
  kap = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'kap' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "leaf_tip_source")) {
 
  leaf_tip_source = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'leaf_tip_source' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "sam_efflux")) {
 
  sam_efflux = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'sam_efflux' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "sam_auxin")) {
 
  sam_auxin = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'sam_auxin' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "sam_auxin_breakdown")) {
 
  sam_auxin_breakdown = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'sam_auxin_breakdown' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "van3prod")) {
 
  van3prod = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'van3prod' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "van3autokat")) {
 
  van3autokat = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'van3autokat' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "van3sat")) {
 
  van3sat = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'van3sat' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "k2van3")) {
 
  k2van3 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'k2van3' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "dt")) {
 
  dt = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'dt' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rd_dt")) {
 
  rd_dt = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'rd_dt' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "datadir")) {
 
  if (datadir) { free(datadir); }
 
  datadir=strdup(valc);
 
  datadir = AppendHomeDirIfPathRelative(datadir);
 
}
 
if (!strcmp(namec, "movie")) {
 
movie = strtobool(valc);
 
}
 
if (!strcmp(namec, "nit")) {
 
  nit = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'nit' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "maxt")) {
 
  maxt = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'maxt' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "storage_stride")) {
 
  storage_stride = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'storage_stride' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "xml_storage_stride")) {
 
  xml_storage_stride = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'xml_storage_stride' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rseed")) {
 
  rseed = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'rseed' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "constituous_expansion_limit")) {
 
  constituous_expansion_limit = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'constituous_expansion_limit' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "vessel_inh_level")) {
 
  vessel_inh_level = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'vessel_inh_level' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "vessel_expansion_rate")) {
 
  vessel_expansion_rate = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'vessel_expansion_rate' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "d")) {
 
  d = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'd' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "e")) {
 
  e = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'e' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "f")) {
 
  f = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'f' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "c")) {
 
  c = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'c' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "mu")) {
 
  mu = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'mu' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "nu")) {
 
  nu = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'nu' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rho0")) {
 
  rho0 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'rho0' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "rho1")) {
 
  rho1 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'rho1' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "c0")) {
 
  c0 = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'c0' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "gamma")) {
 
  gamma = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'gamma' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "eps")) {
 
  eps = standardlocale.toDouble(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to double while reading parameter 'eps' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "i1")) {
 
  i1 = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'i1' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "i2")) {
 
  i2 = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'i2' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "i3")) {
 
  i3 = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'i3' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "i4")) {
 
  i4 = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'i4' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "i5")) {
 
  i5 = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'i5' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "s1")) {
 
  if (s1) { free(s1); }
 
  s1=strdup(valc);
 
}
 
if (!strcmp(namec, "s2")) {
 
  if (s2) { free(s2); }
 
  s2=strdup(valc);
 
}
 
if (!strcmp(namec, "s3")) {
 
  if (s3) { free(s3); }
 
  s3=strdup(valc);
 
}
 
if (!strcmp(namec, "b1")) {
 
b1 = strtobool(valc);
 
}
 
if (!strcmp(namec, "b2")) {
 
b2 = strtobool(valc);
 
}
 
if (!strcmp(namec, "b3")) {
 
b3 = strtobool(valc);
 
}
 
if (!strcmp(namec, "b4")) {
 
b4 = strtobool(valc);
 
}
 
if (!strcmp(namec, "dir1")) {
 
  if (dir1) { free(dir1); }
 
  dir1=strdup(valc);
 
}
 
if (!strcmp(namec, "dir2")) {
 
  if (dir2) { free(dir2); }
 
  dir2=strdup(valc);
 
}
 
if (!strcmp(namec, "export_interval")) {
 
  export_interval = standardlocale.toInt(valc, &ok);
 
  if (!ok) { MyWarning::error("Read error: cannot convert string \"%s\" to integer while reading parameter 'export_interval' from XML file.",valc); }
 
}
 
if (!strcmp(namec, "export_fn_prefix")) {
 
  if (export_fn_prefix) { free(export_fn_prefix); }
 
  export_fn_prefix=strdup(valc);
 
}
 
}
 
void Parameter::AssignValArrayToPar(const char *namec, vector<double> valarray) {
 
if (!strcmp(namec, "D")) {
 
  int i=0;
 
  vector<double>::const_iterator v=valarray.begin();
 
  while (v!=valarray.end() && i <= 14 ) {
 
     D[i++]=*(v++);
 
  }
 
}
 
if (!strcmp(namec, "initval")) {
 
  int i=0;
 
  vector<double>::const_iterator v=valarray.begin();
 
  while (v!=valarray.end() && i <= 14 ) {
 
     initval[i++]=*(v++);
 
  }
 
}
 
if (!strcmp(namec, "k")) {
 
  int i=0;
 
  vector<double>::const_iterator v=valarray.begin();
 
  while (v!=valarray.end() && i <= 14 ) {
 
     k[i++]=*(v++);
 
  }
 
}
 
}
 

	
 
ostream &operator<<(ostream &os, Parameter &p) {
 
    p.Write(os);
 
    return os;
 
}
 

	
src/parameter.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
// WARNING: This file is automatically generated by make_parameter_source.pl. Do not edit.
 
// Do not edit. All edits will be discarded.
 

	
 
#ifndef _PARAMETER_H_
 
#define _PARAMETER_H_
 
#include "vector.h"
 
#include <vector>
 

	
 
#include <libxml/parser.h>
 
#include <libxml/tree.h>
 

	
 
 class Parameter {
 
		
 
 public: 
 
   Parameter();
 
   ~Parameter();
 
   void CleanUp(void);
 
   void Read(const char *filename);
 
   void Write(ostream &os) const;
 
   void XMLAdd(xmlNode *root) const;
 
   void XMLRead(xmlNode *root);
 
   void AssignValToPar(const char *namec, const char *valc);
 
   void AssignValArrayToPar(const char *namec, vector<double> valarray);
 
  char * arrowcolor;
 
  double arrowsize;
 
  char * textcolor;
 
  int cellnumsize;
 
  int nodenumsize;
 
  double node_mag;
 
  double outlinewidth;
 
  char * cell_outline_color;
 
  int resize_stride;
 
  double T;
 
  double lambda_length;
 
  double yielding_threshold;
 
  double lambda_celllength;
 
  double target_length;
 
  double cell_expansion_rate;
 
  double cell_div_expansion_rate;
 
  bool auxin_dependent_growth;
 
  double ode_accuracy;
 
  double mc_stepsize;
 
  double mc_cell_stepsize;
 
  double energy_threshold;
 
  double bend_lambda;
 
  double alignment_lambda;
 
  double rel_cell_div_threshold;
 
  double rel_perimeter_stiffness;
 
  double collapse_node_threshold;
 
  double morphogen_div_threshold;
 
  double morphogen_expansion_threshold;
 
  bool copy_wall;
 
  double source;
 
  double * D;
 
  double * initval;
 
  double k1;
 
  double k2;
 
  double r;
 
  double kr;
 
  double km;
 
  double Pi_tot;
 
  double transport;
 
  double ka;
 
  double pin_prod;
 
  double pin_prod_in_epidermis;
 
  double pin_breakdown;
 
  double pin_breakdown_internal;
 
  double aux1prod;
 
  double aux1prodmeso;
 
  double aux1decay;
 
  double aux1decaymeso;
 
  double aux1transport;
 
  double aux_cons;
 
  double aux_breakdown;
 
  double kaux1;
 
  double kap;
 
  double leaf_tip_source;
 
  double sam_efflux;
 
  double sam_auxin;
 
  double sam_auxin_breakdown;
 
  double van3prod;
 
  double van3autokat;
 
  double van3sat;
 
  double k2van3;
 
  double dt;
 
  double rd_dt;
 
  char * datadir;
 
  bool movie;
 
  int nit;
 
  double maxt;
 
  int storage_stride;
 
  int xml_storage_stride;
 
  int rseed;
 
  int constituous_expansion_limit;
 
  double vessel_inh_level;
 
  double vessel_expansion_rate;
 
  double d;
 
  double e;
 
  double f;
 
  double c;
 
  double mu;
 
  double nu;
 
  double rho0;
 
  double rho1;
 
  double c0;
 
  double gamma;
 
  double eps;
 
  double * k;
 
  int i1;
 
  int i2;
 
  int i3;
 
  int i4;
 
  int i5;
 
  char * s1;
 
  char * s2;
 
  char * s3;
 
  bool b1;
 
  bool b2;
 
  bool b3;
 
  bool b4;
 
  char * dir1;
 
  char * dir2;
 
  int export_interval;
 
  char * export_fn_prefix;
 
 private:
 
 };
 

	
 
 ostream &operator<<(ostream &os, Parameter &p);
 
 const char *sbool(const bool &p);
 

	
 

	
 
#endif
src/pardialog.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
// WARNING: This file is automatically generated by make_parameter_source.pl. Do not edit.
 
// Do not edit. All edits will be discarded.
 

	
 
#include "pardialog.h"
 
#include "parameter.h"
 
#include <cstring>
 
#include <qdialog.h>
 
#include <qlabel.h>
 
#include <qlineedit.h>
 
#include <qmessagebox.h>
 

	
 
static const std::string _module_id("$Id$");
 

	
 
ParameterDialog::ParameterDialog(QWidget *parent, const char *name, Qt::WindowFlags f) : QDialog(parent,name,false,f) {
 
    extern Parameter par;
 
  arrowcolor_edit = new QLineEdit( QString("%1").arg(par.arrowcolor), this, "arrowcolor_edit" );
 
  arrowsize_edit = new QLineEdit( QString("%1").arg(par.arrowsize), this, "arrowsize_edit" );
 
  textcolor_edit = new QLineEdit( QString("%1").arg(par.textcolor), this, "textcolor_edit" );
 
  cellnumsize_edit = new QLineEdit( QString("%1").arg(par.cellnumsize), this, "cellnumsize_edit" );
 
  nodenumsize_edit = new QLineEdit( QString("%1").arg(par.nodenumsize), this, "nodenumsize_edit" );
 
  node_mag_edit = new QLineEdit( QString("%1").arg(par.node_mag), this, "node_mag_edit" );
 
  outlinewidth_edit = new QLineEdit( QString("%1").arg(par.outlinewidth), this, "outlinewidth_edit" );
 
  cell_outline_color_edit = new QLineEdit( QString("%1").arg(par.cell_outline_color), this, "cell_outline_color_edit" );
 
  resize_stride_edit = new QLineEdit( QString("%1").arg(par.resize_stride), this, "resize_stride_edit" );
 
  T_edit = new QLineEdit( QString("%1").arg(par.T), this, "T_edit" );
 
  lambda_length_edit = new QLineEdit( QString("%1").arg(par.lambda_length), this, "lambda_length_edit" );
 
  yielding_threshold_edit = new QLineEdit( QString("%1").arg(par.yielding_threshold), this, "yielding_threshold_edit" );
 
  lambda_celllength_edit = new QLineEdit( QString("%1").arg(par.lambda_celllength), this, "lambda_celllength_edit" );
 
  target_length_edit = new QLineEdit( QString("%1").arg(par.target_length), this, "target_length_edit" );
 
  cell_expansion_rate_edit = new QLineEdit( QString("%1").arg(par.cell_expansion_rate), this, "cell_expansion_rate_edit" );
 
  cell_div_expansion_rate_edit = new QLineEdit( QString("%1").arg(par.cell_div_expansion_rate), this, "cell_div_expansion_rate_edit" );
 
  auxin_dependent_growth_edit = new QLineEdit( QString("%1").arg(sbool(par.auxin_dependent_growth)), this, "auxin_dependent_growth_edit" );
 
  ode_accuracy_edit = new QLineEdit( QString("%1").arg(par.ode_accuracy), this, "ode_accuracy_edit" );
 
  mc_stepsize_edit = new QLineEdit( QString("%1").arg(par.mc_stepsize), this, "mc_stepsize_edit" );
 
  mc_cell_stepsize_edit = new QLineEdit( QString("%1").arg(par.mc_cell_stepsize), this, "mc_cell_stepsize_edit" );
 
  energy_threshold_edit = new QLineEdit( QString("%1").arg(par.energy_threshold), this, "energy_threshold_edit" );
 
  bend_lambda_edit = new QLineEdit( QString("%1").arg(par.bend_lambda), this, "bend_lambda_edit" );
 
  alignment_lambda_edit = new QLineEdit( QString("%1").arg(par.alignment_lambda), this, "alignment_lambda_edit" );
 
  rel_cell_div_threshold_edit = new QLineEdit( QString("%1").arg(par.rel_cell_div_threshold), this, "rel_cell_div_threshold_edit" );
 
  rel_perimeter_stiffness_edit = new QLineEdit( QString("%1").arg(par.rel_perimeter_stiffness), this, "rel_perimeter_stiffness_edit" );
 
  collapse_node_threshold_edit = new QLineEdit( QString("%1").arg(par.collapse_node_threshold), this, "collapse_node_threshold_edit" );
 
  morphogen_div_threshold_edit = new QLineEdit( QString("%1").arg(par.morphogen_div_threshold), this, "morphogen_div_threshold_edit" );
 
  morphogen_expansion_threshold_edit = new QLineEdit( QString("%1").arg(par.morphogen_expansion_threshold), this, "morphogen_expansion_threshold_edit" );
 
  copy_wall_edit = new QLineEdit( QString("%1").arg(sbool(par.copy_wall)), this, "copy_wall_edit" );
 
  source_edit = new QLineEdit( QString("%1").arg(par.source), this, "source_edit" );
 
  QString D_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  D_string = D_string.arg(par.D[0]).arg(par.D[1]).arg(par.D[2]).arg(par.D[3]).arg(par.D[4]).arg(par.D[5]).arg(par.D[6]).arg(par.D[7]).arg(par.D[8]).arg(par.D[9]).arg(par.D[10]).arg(par.D[11]).arg(par.D[12]).arg(par.D[13]).arg(par.D[14]);
 
  D_edit = new QLineEdit( D_string, this, "D_edit" );
 
  QString initval_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  initval_string = initval_string.arg(par.initval[0]).arg(par.initval[1]).arg(par.initval[2]).arg(par.initval[3]).arg(par.initval[4]).arg(par.initval[5]).arg(par.initval[6]).arg(par.initval[7]).arg(par.initval[8]).arg(par.initval[9]).arg(par.initval[10]).arg(par.initval[11]).arg(par.initval[12]).arg(par.initval[13]).arg(par.initval[14]);
 
  initval_edit = new QLineEdit( initval_string, this, "initval_edit" );
 
  k1_edit = new QLineEdit( QString("%1").arg(par.k1), this, "k1_edit" );
 
  k2_edit = new QLineEdit( QString("%1").arg(par.k2), this, "k2_edit" );
 
  r_edit = new QLineEdit( QString("%1").arg(par.r), this, "r_edit" );
 
  kr_edit = new QLineEdit( QString("%1").arg(par.kr), this, "kr_edit" );
 
  km_edit = new QLineEdit( QString("%1").arg(par.km), this, "km_edit" );
 
  Pi_tot_edit = new QLineEdit( QString("%1").arg(par.Pi_tot), this, "Pi_tot_edit" );
 
  transport_edit = new QLineEdit( QString("%1").arg(par.transport), this, "transport_edit" );
 
  ka_edit = new QLineEdit( QString("%1").arg(par.ka), this, "ka_edit" );
 
  pin_prod_edit = new QLineEdit( QString("%1").arg(par.pin_prod), this, "pin_prod_edit" );
 
  pin_prod_in_epidermis_edit = new QLineEdit( QString("%1").arg(par.pin_prod_in_epidermis), this, "pin_prod_in_epidermis_edit" );
 
  pin_breakdown_edit = new QLineEdit( QString("%1").arg(par.pin_breakdown), this, "pin_breakdown_edit" );
 
  pin_breakdown_internal_edit = new QLineEdit( QString("%1").arg(par.pin_breakdown_internal), this, "pin_breakdown_internal_edit" );
 
  aux1prod_edit = new QLineEdit( QString("%1").arg(par.aux1prod), this, "aux1prod_edit" );
 
  aux1prodmeso_edit = new QLineEdit( QString("%1").arg(par.aux1prodmeso), this, "aux1prodmeso_edit" );
 
  aux1decay_edit = new QLineEdit( QString("%1").arg(par.aux1decay), this, "aux1decay_edit" );
 
  aux1decaymeso_edit = new QLineEdit( QString("%1").arg(par.aux1decaymeso), this, "aux1decaymeso_edit" );
 
  aux1transport_edit = new QLineEdit( QString("%1").arg(par.aux1transport), this, "aux1transport_edit" );
 
  aux_cons_edit = new QLineEdit( QString("%1").arg(par.aux_cons), this, "aux_cons_edit" );
 
  aux_breakdown_edit = new QLineEdit( QString("%1").arg(par.aux_breakdown), this, "aux_breakdown_edit" );
 
  kaux1_edit = new QLineEdit( QString("%1").arg(par.kaux1), this, "kaux1_edit" );
 
  kap_edit = new QLineEdit( QString("%1").arg(par.kap), this, "kap_edit" );
 
  leaf_tip_source_edit = new QLineEdit( QString("%1").arg(par.leaf_tip_source), this, "leaf_tip_source_edit" );
 
  sam_efflux_edit = new QLineEdit( QString("%1").arg(par.sam_efflux), this, "sam_efflux_edit" );
 
  sam_auxin_edit = new QLineEdit( QString("%1").arg(par.sam_auxin), this, "sam_auxin_edit" );
 
  sam_auxin_breakdown_edit = new QLineEdit( QString("%1").arg(par.sam_auxin_breakdown), this, "sam_auxin_breakdown_edit" );
 
  van3prod_edit = new QLineEdit( QString("%1").arg(par.van3prod), this, "van3prod_edit" );
 
  van3autokat_edit = new QLineEdit( QString("%1").arg(par.van3autokat), this, "van3autokat_edit" );
 
  van3sat_edit = new QLineEdit( QString("%1").arg(par.van3sat), this, "van3sat_edit" );
 
  k2van3_edit = new QLineEdit( QString("%1").arg(par.k2van3), this, "k2van3_edit" );
 
  dt_edit = new QLineEdit( QString("%1").arg(par.dt), this, "dt_edit" );
 
  rd_dt_edit = new QLineEdit( QString("%1").arg(par.rd_dt), this, "rd_dt_edit" );
 
  datadir_edit = new QLineEdit( QString("%1").arg(par.datadir), this, "datadir_edit" );
 
  movie_edit = new QLineEdit( QString("%1").arg(sbool(par.movie)), this, "movie_edit" );
 
  nit_edit = new QLineEdit( QString("%1").arg(par.nit), this, "nit_edit" );
 
  maxt_edit = new QLineEdit( QString("%1").arg(par.maxt), this, "maxt_edit" );
 
  storage_stride_edit = new QLineEdit( QString("%1").arg(par.storage_stride), this, "storage_stride_edit" );
 
  xml_storage_stride_edit = new QLineEdit( QString("%1").arg(par.xml_storage_stride), this, "xml_storage_stride_edit" );
 
  rseed_edit = new QLineEdit( QString("%1").arg(par.rseed), this, "rseed_edit" );
 
  constituous_expansion_limit_edit = new QLineEdit( QString("%1").arg(par.constituous_expansion_limit), this, "constituous_expansion_limit_edit" );
 
  vessel_inh_level_edit = new QLineEdit( QString("%1").arg(par.vessel_inh_level), this, "vessel_inh_level_edit" );
 
  vessel_expansion_rate_edit = new QLineEdit( QString("%1").arg(par.vessel_expansion_rate), this, "vessel_expansion_rate_edit" );
 
  d_edit = new QLineEdit( QString("%1").arg(par.d), this, "d_edit" );
 
  e_edit = new QLineEdit( QString("%1").arg(par.e), this, "e_edit" );
 
  f_edit = new QLineEdit( QString("%1").arg(par.f), this, "f_edit" );
 
  c_edit = new QLineEdit( QString("%1").arg(par.c), this, "c_edit" );
 
  mu_edit = new QLineEdit( QString("%1").arg(par.mu), this, "mu_edit" );
 
  nu_edit = new QLineEdit( QString("%1").arg(par.nu), this, "nu_edit" );
 
  rho0_edit = new QLineEdit( QString("%1").arg(par.rho0), this, "rho0_edit" );
 
  rho1_edit = new QLineEdit( QString("%1").arg(par.rho1), this, "rho1_edit" );
 
  c0_edit = new QLineEdit( QString("%1").arg(par.c0), this, "c0_edit" );
 
  gamma_edit = new QLineEdit( QString("%1").arg(par.gamma), this, "gamma_edit" );
 
  eps_edit = new QLineEdit( QString("%1").arg(par.eps), this, "eps_edit" );
 
  QString k_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  k_string = k_string.arg(par.k[0]).arg(par.k[1]).arg(par.k[2]).arg(par.k[3]).arg(par.k[4]).arg(par.k[5]).arg(par.k[6]).arg(par.k[7]).arg(par.k[8]).arg(par.k[9]).arg(par.k[10]).arg(par.k[11]).arg(par.k[12]).arg(par.k[13]).arg(par.k[14]);
 
  k_edit = new QLineEdit( k_string, this, "k_edit" );
 
  i1_edit = new QLineEdit( QString("%1").arg(par.i1), this, "i1_edit" );
 
  i2_edit = new QLineEdit( QString("%1").arg(par.i2), this, "i2_edit" );
 
  i3_edit = new QLineEdit( QString("%1").arg(par.i3), this, "i3_edit" );
 
  i4_edit = new QLineEdit( QString("%1").arg(par.i4), this, "i4_edit" );
 
  i5_edit = new QLineEdit( QString("%1").arg(par.i5), this, "i5_edit" );
 
  s1_edit = new QLineEdit( QString("%1").arg(par.s1), this, "s1_edit" );
 
  s2_edit = new QLineEdit( QString("%1").arg(par.s2), this, "s2_edit" );
 
  s3_edit = new QLineEdit( QString("%1").arg(par.s3), this, "s3_edit" );
 
  b1_edit = new QLineEdit( QString("%1").arg(sbool(par.b1)), this, "b1_edit" );
 
  b2_edit = new QLineEdit( QString("%1").arg(sbool(par.b2)), this, "b2_edit" );
 
  b3_edit = new QLineEdit( QString("%1").arg(sbool(par.b3)), this, "b3_edit" );
 
  b4_edit = new QLineEdit( QString("%1").arg(sbool(par.b4)), this, "b4_edit" );
 
  dir1_edit = new QLineEdit( QString("%1").arg(par.dir1), this, "dir1_edit" );
 
  dir2_edit = new QLineEdit( QString("%1").arg(par.dir2), this, "dir2_edit" );
 
  export_interval_edit = new QLineEdit( QString("%1").arg(par.export_interval), this, "export_interval_edit" );
 
  export_fn_prefix_edit = new QLineEdit( QString("%1").arg(par.export_fn_prefix), this, "export_fn_prefix_edit" );
 
// make a 1x1 grid; it will auto-expand
 
QGridLayout *grid = new QGridLayout( this, 1, 1 );
 
    
 
// add the first four widgets with (row, column) addressing
 
  setWindowTitle( QString( " Parameter values for The Virtual Leaf") );
 
  grid->addWidget( new QLabel( "<h3> Parameter values for The Virtual Leaf</h3>",this), 0, 0, 1, -1, Qt::AlignCenter);
 
  grid->addWidget( new QLabel( "", this), 0+1, 0, 1, -1);
 
  grid->addWidget( new QLabel( " <b>Visualization</b>", this), 3, 0, 1, 2 );
 
  grid->addWidget( new QLabel( "arrowcolor", this ),4, 0 );
 
  grid->addWidget( arrowcolor_edit, 4, 0+1  );
 
  grid->addWidget( new QLabel( "arrowsize", this ),5, 0 );
 
  grid->addWidget( arrowsize_edit, 5, 0+1  );
 
  grid->addWidget( new QLabel( "textcolor", this ),6, 0 );
 
  grid->addWidget( textcolor_edit, 6, 0+1  );
 
  grid->addWidget( new QLabel( "cellnumsize", this ),7, 0 );
 
  grid->addWidget( cellnumsize_edit, 7, 0+1  );
 
  grid->addWidget( new QLabel( "nodenumsize", this ),8, 0 );
 
  grid->addWidget( nodenumsize_edit, 8, 0+1  );
 
  grid->addWidget( new QLabel( "node_mag", this ),9, 0 );
 
  grid->addWidget( node_mag_edit, 9, 0+1  );
 
  grid->addWidget( new QLabel( "outlinewidth", this ),10, 0 );
 
  grid->addWidget( outlinewidth_edit, 10, 0+1  );
 
  grid->addWidget( new QLabel( "cell_outline_color", this ),11, 0 );
 
  grid->addWidget( cell_outline_color_edit, 11, 0+1  );
 
  grid->addWidget( new QLabel( "resize_stride", this ),12, 0 );
 
  grid->addWidget( resize_stride_edit, 12, 0+1  );
 
  grid->addWidget( new QLabel( "", this), 13, 0, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Cell mechanics</b>", this), 14, 0, 1, 2 );
 
  grid->addWidget( new QLabel( "T", this ),15, 0 );
 
  grid->addWidget( T_edit, 15, 0+1  );
 
  grid->addWidget( new QLabel( "lambda_length", this ),16, 0 );
 
  grid->addWidget( lambda_length_edit, 16, 0+1  );
 
  grid->addWidget( new QLabel( "lambda_celllength", this ),17, 0 );
 
  grid->addWidget( lambda_celllength_edit, 17, 0+1  );
 
  grid->addWidget( new QLabel( "target_length", this ),18, 0 );
 
  grid->addWidget( target_length_edit, 18, 0+1  );
 
  grid->addWidget( new QLabel( "cell_expansion_rate", this ),19, 0 );
 
  grid->addWidget( cell_expansion_rate_edit, 19, 0+1  );
 
  grid->addWidget( new QLabel( "cell_div_expansion_rate", this ),20, 0 );
 
  grid->addWidget( cell_div_expansion_rate_edit, 20, 0+1  );
 
  grid->addWidget( new QLabel( "auxin_dependent_growth", this ),21, 0 );
 
  grid->addWidget( auxin_dependent_growth_edit, 21, 0+1  );
 
  grid->addWidget( new QLabel( "ode_accuracy", this ),22, 0 );
 
  grid->addWidget( ode_accuracy_edit, 22, 0+1  );
 
  grid->addWidget( new QLabel( "mc_stepsize", this ),23, 0 );
 
  grid->addWidget( mc_stepsize_edit, 23, 0+1  );
 
  grid->addWidget( new QLabel( "mc_cell_stepsize", this ),24, 0 );
 
  grid->addWidget( mc_cell_stepsize_edit, 24, 0+1  );
 
  grid->addWidget( new QLabel( "energy_threshold", this ),25, 0 );
 
  grid->addWidget( energy_threshold_edit, 25, 0+1  );
 
  grid->addWidget( new QLabel( "bend_lambda", this ),26, 0 );
 
  grid->addWidget( bend_lambda_edit, 26, 0+1  );
 
  grid->addWidget( new QLabel( "alignment_lambda", this ),27, 0 );
 
  grid->addWidget( alignment_lambda_edit, 27, 0+1  );
 
  grid->addWidget( new QLabel( "rel_cell_div_threshold", this ),28, 0 );
 
  grid->addWidget( rel_cell_div_threshold_edit, 28, 0+1  );
 
  grid->addWidget( new QLabel( "rel_perimeter_stiffness", this ),29, 0 );
 
  grid->addWidget( rel_perimeter_stiffness_edit, 29, 0+1  );
 
  grid->addWidget( new QLabel( "collapse_node_threshold", this ),3, 2 );
 
  grid->addWidget( collapse_node_threshold_edit, 3, 2+1  );
 
  grid->addWidget( new QLabel( "morphogen_div_threshold", this ),4, 2 );
 
  grid->addWidget( morphogen_div_threshold_edit, 4, 2+1  );
 
  grid->addWidget( new QLabel( "morphogen_expansion_threshold", this ),5, 2 );
 
  grid->addWidget( morphogen_expansion_threshold_edit, 5, 2+1  );
 
  grid->addWidget( new QLabel( "copy_wall", this ),6, 2 );
 
  grid->addWidget( copy_wall_edit, 6, 2+1  );
 
  grid->addWidget( new QLabel( "", this), 7, 2, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Auxin transport and PIN1 dynamics</b>", this), 8, 2, 1, 2 );
 
  grid->addWidget( new QLabel( "source", this ),9, 2 );
 
  grid->addWidget( source_edit, 9, 2+1  );
 
  grid->addWidget( new QLabel( "D", this ),10, 2 );
 
  grid->addWidget( D_edit, 10, 2+1  );
 
  grid->addWidget( new QLabel( "initval", this ),11, 2 );
 
  grid->addWidget( initval_edit, 11, 2+1  );
 
  grid->addWidget( new QLabel( "k1", this ),12, 2 );
 
  grid->addWidget( k1_edit, 12, 2+1  );
 
  grid->addWidget( new QLabel( "k2", this ),13, 2 );
 
  grid->addWidget( k2_edit, 13, 2+1  );
 
  grid->addWidget( new QLabel( "r", this ),14, 2 );
 
  grid->addWidget( r_edit, 14, 2+1  );
 
  grid->addWidget( new QLabel( "kr", this ),15, 2 );
 
  grid->addWidget( kr_edit, 15, 2+1  );
 
  grid->addWidget( new QLabel( "km", this ),16, 2 );
 
  grid->addWidget( km_edit, 16, 2+1  );
 
  grid->addWidget( new QLabel( "Pi_tot", this ),17, 2 );
 
  grid->addWidget( Pi_tot_edit, 17, 2+1  );
 
  grid->addWidget( new QLabel( "transport", this ),18, 2 );
 
  grid->addWidget( transport_edit, 18, 2+1  );
 
  grid->addWidget( new QLabel( "ka", this ),19, 2 );
 
  grid->addWidget( ka_edit, 19, 2+1  );
 
  grid->addWidget( new QLabel( "pin_prod", this ),20, 2 );
 
  grid->addWidget( pin_prod_edit, 20, 2+1  );
 
  grid->addWidget( new QLabel( "pin_prod_in_epidermis", this ),21, 2 );
 
  grid->addWidget( pin_prod_in_epidermis_edit, 21, 2+1  );
 
  grid->addWidget( new QLabel( "pin_breakdown", this ),22, 2 );
 
  grid->addWidget( pin_breakdown_edit, 22, 2+1  );
 
  grid->addWidget( new QLabel( "pin_breakdown_internal", this ),23, 2 );
 
  grid->addWidget( pin_breakdown_internal_edit, 23, 2+1  );
 
  grid->addWidget( new QLabel( "aux1prod", this ),24, 2 );
 
  grid->addWidget( aux1prod_edit, 24, 2+1  );
 
  grid->addWidget( new QLabel( "aux1prodmeso", this ),25, 2 );
 
  grid->addWidget( aux1prodmeso_edit, 25, 2+1  );
 
  grid->addWidget( new QLabel( "aux1decay", this ),26, 2 );
 
  grid->addWidget( aux1decay_edit, 26, 2+1  );
 
  grid->addWidget( new QLabel( "aux1decaymeso", this ),27, 2 );
 
  grid->addWidget( aux1decaymeso_edit, 27, 2+1  );
 
  grid->addWidget( new QLabel( "aux1transport", this ),28, 2 );
 
  grid->addWidget( aux1transport_edit, 28, 2+1  );
 
  grid->addWidget( new QLabel( "aux_cons", this ),29, 2 );
 
  grid->addWidget( aux_cons_edit, 29, 2+1  );
 
  grid->addWidget( new QLabel( "aux_breakdown", this ),3, 4 );
 
  grid->addWidget( aux_breakdown_edit, 3, 4+1  );
 
  grid->addWidget( new QLabel( "kaux1", this ),4, 4 );
 
  grid->addWidget( kaux1_edit, 4, 4+1  );
 
  grid->addWidget( new QLabel( "kap", this ),5, 4 );
 
  grid->addWidget( kap_edit, 5, 4+1  );
 
  grid->addWidget( new QLabel( "leaf_tip_source", this ),6, 4 );
 
  grid->addWidget( leaf_tip_source_edit, 6, 4+1  );
 
  grid->addWidget( new QLabel( "sam_efflux", this ),7, 4 );
 
  grid->addWidget( sam_efflux_edit, 7, 4+1  );
 
  grid->addWidget( new QLabel( "sam_auxin", this ),8, 4 );
 
  grid->addWidget( sam_auxin_edit, 8, 4+1  );
 
  grid->addWidget( new QLabel( "sam_auxin_breakdown", this ),9, 4 );
 
  grid->addWidget( sam_auxin_breakdown_edit, 9, 4+1  );
 
  grid->addWidget( new QLabel( "van3prod", this ),10, 4 );
 
  grid->addWidget( van3prod_edit, 10, 4+1  );
 
  grid->addWidget( new QLabel( "van3autokat", this ),11, 4 );
 
  grid->addWidget( van3autokat_edit, 11, 4+1  );
 
  grid->addWidget( new QLabel( "van3sat", this ),12, 4 );
 
  grid->addWidget( van3sat_edit, 12, 4+1  );
 
  grid->addWidget( new QLabel( "k2van3", this ),13, 4 );
 
  grid->addWidget( k2van3_edit, 13, 4+1  );
 
  grid->addWidget( new QLabel( "", this), 14, 4, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Integration parameters</b>", this), 15, 4, 1, 2 );
 
  grid->addWidget( new QLabel( "dt", this ),16, 4 );
 
  grid->addWidget( dt_edit, 16, 4+1  );
 
  grid->addWidget( new QLabel( "rd_dt", this ),17, 4 );
 
  grid->addWidget( rd_dt_edit, 17, 4+1  );
 
  grid->addWidget( new QLabel( "datadir", this ),18, 4 );
 
  grid->addWidget( datadir_edit, 18, 4+1  );
 
  grid->addWidget( new QLabel( "movie", this ),19, 4 );
 
  grid->addWidget( movie_edit, 19, 4+1  );
 
  grid->addWidget( new QLabel( "nit", this ),20, 4 );
 
  grid->addWidget( nit_edit, 20, 4+1  );
 
  grid->addWidget( new QLabel( "maxt", this ),21, 4 );
 
  grid->addWidget( maxt_edit, 21, 4+1  );
 
  grid->addWidget( new QLabel( "storage_stride", this ),22, 4 );
 
  grid->addWidget( storage_stride_edit, 22, 4+1  );
 
  grid->addWidget( new QLabel( "xml_storage_stride", this ),23, 4 );
 
  grid->addWidget( xml_storage_stride_edit, 23, 4+1  );
 
  grid->addWidget( new QLabel( "rseed", this ),24, 4 );
 
  grid->addWidget( rseed_edit, 24, 4+1  );
 
  grid->addWidget( new QLabel( "", this), 25, 4, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Meinhardt leaf venation model</b>", this), 26, 4, 1, 2 );
 
  grid->addWidget( new QLabel( "constituous_expansion_limit", this ),27, 4 );
 
  grid->addWidget( constituous_expansion_limit_edit, 27, 4+1  );
 
  grid->addWidget( new QLabel( "vessel_inh_level", this ),28, 4 );
 
  grid->addWidget( vessel_inh_level_edit, 28, 4+1  );
 
  grid->addWidget( new QLabel( "vessel_expansion_rate", this ),29, 4 );
 
  grid->addWidget( vessel_expansion_rate_edit, 29, 4+1  );
 
  grid->addWidget( new QLabel( "d", this ),3, 6 );
 
  grid->addWidget( d_edit, 3, 6+1  );
 
  grid->addWidget( new QLabel( "e", this ),4, 6 );
 
  grid->addWidget( e_edit, 4, 6+1  );
 
  grid->addWidget( new QLabel( "f", this ),5, 6 );
 
  grid->addWidget( f_edit, 5, 6+1  );
 
  grid->addWidget( new QLabel( "c", this ),6, 6 );
 
  grid->addWidget( c_edit, 6, 6+1  );
 
  grid->addWidget( new QLabel( "mu", this ),7, 6 );
 
  grid->addWidget( mu_edit, 7, 6+1  );
 
  grid->addWidget( new QLabel( "nu", this ),8, 6 );
 
  grid->addWidget( nu_edit, 8, 6+1  );
 
  grid->addWidget( new QLabel( "rho0", this ),9, 6 );
 
  grid->addWidget( rho0_edit, 9, 6+1  );
 
  grid->addWidget( new QLabel( "rho1", this ),10, 6 );
 
  grid->addWidget( rho1_edit, 10, 6+1  );
 
  grid->addWidget( new QLabel( "c0", this ),11, 6 );
 
  grid->addWidget( c0_edit, 11, 6+1  );
 
  grid->addWidget( new QLabel( "gamma", this ),12, 6 );
 
  grid->addWidget( gamma_edit, 12, 6+1  );
 
  grid->addWidget( new QLabel( "eps", this ),13, 6 );
 
  grid->addWidget( eps_edit, 13, 6+1  );
 
  grid->addWidget( new QLabel( "", this), 14, 6, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>User-defined parameters</b>", this), 15, 6, 1, 2 );
 
  grid->addWidget( new QLabel( "k", this ),16, 6 );
 
  grid->addWidget( k_edit, 16, 6+1  );
 
  grid->addWidget( new QLabel( "i1", this ),17, 6 );
 
  grid->addWidget( i1_edit, 17, 6+1  );
 
  grid->addWidget( new QLabel( "i2", this ),18, 6 );
 
  grid->addWidget( i2_edit, 18, 6+1  );
 
  grid->addWidget( new QLabel( "i3", this ),19, 6 );
 
  grid->addWidget( i3_edit, 19, 6+1  );
 
  grid->addWidget( new QLabel( "i4", this ),20, 6 );
 
  grid->addWidget( i4_edit, 20, 6+1  );
 
  grid->addWidget( new QLabel( "i5", this ),21, 6 );
 
  grid->addWidget( i5_edit, 21, 6+1  );
 
  grid->addWidget( new QLabel( "s1", this ),22, 6 );
 
  grid->addWidget( s1_edit, 22, 6+1  );
 
  grid->addWidget( new QLabel( "s2", this ),23, 6 );
 
  grid->addWidget( s2_edit, 23, 6+1  );
 
  grid->addWidget( new QLabel( "s3", this ),24, 6 );
 
  grid->addWidget( s3_edit, 24, 6+1  );
 
  grid->addWidget( new QLabel( "b1", this ),25, 6 );
 
  grid->addWidget( b1_edit, 25, 6+1  );
 
  grid->addWidget( new QLabel( "b2", this ),26, 6 );
 
  grid->addWidget( b2_edit, 26, 6+1  );
 
  grid->addWidget( new QLabel( "b3", this ),27, 6 );
 
  grid->addWidget( b3_edit, 27, 6+1  );
 
  grid->addWidget( new QLabel( "b4", this ),28, 6 );
 
  grid->addWidget( b4_edit, 28, 6+1  );
 
  grid->addWidget( new QLabel( "dir1", this ),29, 6 );
 
  grid->addWidget( dir1_edit, 29, 6+1  );
 
  grid->addWidget( new QLabel( "dir2", this ),3, 8 );
 
  grid->addWidget( dir2_edit, 3, 8+1  );
 
  grid->addWidget( new QLabel( "export_interval", this ),4, 8 );
 
  grid->addWidget( export_interval_edit, 4, 8+1  );
 
  grid->addWidget( new QLabel( "export_fn_prefix", this ),5, 8 );
 
  grid->addWidget( export_fn_prefix_edit, 5, 8+1  );
 
  grid->addWidget( new QLabel( "yielding_threshold", this ),17, 0 );
 
  grid->addWidget( yielding_threshold_edit, 17, 0+1  );
 
  grid->addWidget( new QLabel( "lambda_celllength", this ),18, 0 );
 
  grid->addWidget( lambda_celllength_edit, 18, 0+1  );
 
  grid->addWidget( new QLabel( "target_length", this ),19, 0 );
 
  grid->addWidget( target_length_edit, 19, 0+1  );
 
  grid->addWidget( new QLabel( "cell_expansion_rate", this ),20, 0 );
 
  grid->addWidget( cell_expansion_rate_edit, 20, 0+1  );
 
  grid->addWidget( new QLabel( "cell_div_expansion_rate", this ),21, 0 );
 
  grid->addWidget( cell_div_expansion_rate_edit, 21, 0+1  );
 
  grid->addWidget( new QLabel( "auxin_dependent_growth", this ),22, 0 );
 
  grid->addWidget( auxin_dependent_growth_edit, 22, 0+1  );
 
  grid->addWidget( new QLabel( "ode_accuracy", this ),23, 0 );
 
  grid->addWidget( ode_accuracy_edit, 23, 0+1  );
 
  grid->addWidget( new QLabel( "mc_stepsize", this ),24, 0 );
 
  grid->addWidget( mc_stepsize_edit, 24, 0+1  );
 
  grid->addWidget( new QLabel( "mc_cell_stepsize", this ),25, 0 );
 
  grid->addWidget( mc_cell_stepsize_edit, 25, 0+1  );
 
  grid->addWidget( new QLabel( "energy_threshold", this ),26, 0 );
 
  grid->addWidget( energy_threshold_edit, 26, 0+1  );
 
  grid->addWidget( new QLabel( "bend_lambda", this ),27, 0 );
 
  grid->addWidget( bend_lambda_edit, 27, 0+1  );
 
  grid->addWidget( new QLabel( "alignment_lambda", this ),28, 0 );
 
  grid->addWidget( alignment_lambda_edit, 28, 0+1  );
 
  grid->addWidget( new QLabel( "rel_cell_div_threshold", this ),29, 0 );
 
  grid->addWidget( rel_cell_div_threshold_edit, 29, 0+1  );
 
  grid->addWidget( new QLabel( "rel_perimeter_stiffness", this ),3, 2 );
 
  grid->addWidget( rel_perimeter_stiffness_edit, 3, 2+1  );
 
  grid->addWidget( new QLabel( "collapse_node_threshold", this ),4, 2 );
 
  grid->addWidget( collapse_node_threshold_edit, 4, 2+1  );
 
  grid->addWidget( new QLabel( "morphogen_div_threshold", this ),5, 2 );
 
  grid->addWidget( morphogen_div_threshold_edit, 5, 2+1  );
 
  grid->addWidget( new QLabel( "morphogen_expansion_threshold", this ),6, 2 );
 
  grid->addWidget( morphogen_expansion_threshold_edit, 6, 2+1  );
 
  grid->addWidget( new QLabel( "copy_wall", this ),7, 2 );
 
  grid->addWidget( copy_wall_edit, 7, 2+1  );
 
  grid->addWidget( new QLabel( "", this), 8, 2, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Auxin transport and PIN1 dynamics</b>", this), 9, 2, 1, 2 );
 
  grid->addWidget( new QLabel( "source", this ),10, 2 );
 
  grid->addWidget( source_edit, 10, 2+1  );
 
  grid->addWidget( new QLabel( "D", this ),11, 2 );
 
  grid->addWidget( D_edit, 11, 2+1  );
 
  grid->addWidget( new QLabel( "initval", this ),12, 2 );
 
  grid->addWidget( initval_edit, 12, 2+1  );
 
  grid->addWidget( new QLabel( "k1", this ),13, 2 );
 
  grid->addWidget( k1_edit, 13, 2+1  );
 
  grid->addWidget( new QLabel( "k2", this ),14, 2 );
 
  grid->addWidget( k2_edit, 14, 2+1  );
 
  grid->addWidget( new QLabel( "r", this ),15, 2 );
 
  grid->addWidget( r_edit, 15, 2+1  );
 
  grid->addWidget( new QLabel( "kr", this ),16, 2 );
 
  grid->addWidget( kr_edit, 16, 2+1  );
 
  grid->addWidget( new QLabel( "km", this ),17, 2 );
 
  grid->addWidget( km_edit, 17, 2+1  );
 
  grid->addWidget( new QLabel( "Pi_tot", this ),18, 2 );
 
  grid->addWidget( Pi_tot_edit, 18, 2+1  );
 
  grid->addWidget( new QLabel( "transport", this ),19, 2 );
 
  grid->addWidget( transport_edit, 19, 2+1  );
 
  grid->addWidget( new QLabel( "ka", this ),20, 2 );
 
  grid->addWidget( ka_edit, 20, 2+1  );
 
  grid->addWidget( new QLabel( "pin_prod", this ),21, 2 );
 
  grid->addWidget( pin_prod_edit, 21, 2+1  );
 
  grid->addWidget( new QLabel( "pin_prod_in_epidermis", this ),22, 2 );
 
  grid->addWidget( pin_prod_in_epidermis_edit, 22, 2+1  );
 
  grid->addWidget( new QLabel( "pin_breakdown", this ),23, 2 );
 
  grid->addWidget( pin_breakdown_edit, 23, 2+1  );
 
  grid->addWidget( new QLabel( "pin_breakdown_internal", this ),24, 2 );
 
  grid->addWidget( pin_breakdown_internal_edit, 24, 2+1  );
 
  grid->addWidget( new QLabel( "aux1prod", this ),25, 2 );
 
  grid->addWidget( aux1prod_edit, 25, 2+1  );
 
  grid->addWidget( new QLabel( "aux1prodmeso", this ),26, 2 );
 
  grid->addWidget( aux1prodmeso_edit, 26, 2+1  );
 
  grid->addWidget( new QLabel( "aux1decay", this ),27, 2 );
 
  grid->addWidget( aux1decay_edit, 27, 2+1  );
 
  grid->addWidget( new QLabel( "aux1decaymeso", this ),28, 2 );
 
  grid->addWidget( aux1decaymeso_edit, 28, 2+1  );
 
  grid->addWidget( new QLabel( "aux1transport", this ),29, 2 );
 
  grid->addWidget( aux1transport_edit, 29, 2+1  );
 
  grid->addWidget( new QLabel( "aux_cons", this ),3, 4 );
 
  grid->addWidget( aux_cons_edit, 3, 4+1  );
 
  grid->addWidget( new QLabel( "aux_breakdown", this ),4, 4 );
 
  grid->addWidget( aux_breakdown_edit, 4, 4+1  );
 
  grid->addWidget( new QLabel( "kaux1", this ),5, 4 );
 
  grid->addWidget( kaux1_edit, 5, 4+1  );
 
  grid->addWidget( new QLabel( "kap", this ),6, 4 );
 
  grid->addWidget( kap_edit, 6, 4+1  );
 
  grid->addWidget( new QLabel( "leaf_tip_source", this ),7, 4 );
 
  grid->addWidget( leaf_tip_source_edit, 7, 4+1  );
 
  grid->addWidget( new QLabel( "sam_efflux", this ),8, 4 );
 
  grid->addWidget( sam_efflux_edit, 8, 4+1  );
 
  grid->addWidget( new QLabel( "sam_auxin", this ),9, 4 );
 
  grid->addWidget( sam_auxin_edit, 9, 4+1  );
 
  grid->addWidget( new QLabel( "sam_auxin_breakdown", this ),10, 4 );
 
  grid->addWidget( sam_auxin_breakdown_edit, 10, 4+1  );
 
  grid->addWidget( new QLabel( "van3prod", this ),11, 4 );
 
  grid->addWidget( van3prod_edit, 11, 4+1  );
 
  grid->addWidget( new QLabel( "van3autokat", this ),12, 4 );
 
  grid->addWidget( van3autokat_edit, 12, 4+1  );
 
  grid->addWidget( new QLabel( "van3sat", this ),13, 4 );
 
  grid->addWidget( van3sat_edit, 13, 4+1  );
 
  grid->addWidget( new QLabel( "k2van3", this ),14, 4 );
 
  grid->addWidget( k2van3_edit, 14, 4+1  );
 
  grid->addWidget( new QLabel( "", this), 15, 4, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Integration parameters</b>", this), 16, 4, 1, 2 );
 
  grid->addWidget( new QLabel( "dt", this ),17, 4 );
 
  grid->addWidget( dt_edit, 17, 4+1  );
 
  grid->addWidget( new QLabel( "rd_dt", this ),18, 4 );
 
  grid->addWidget( rd_dt_edit, 18, 4+1  );
 
  grid->addWidget( new QLabel( "datadir", this ),19, 4 );
 
  grid->addWidget( datadir_edit, 19, 4+1  );
 
  grid->addWidget( new QLabel( "movie", this ),20, 4 );
 
  grid->addWidget( movie_edit, 20, 4+1  );
 
  grid->addWidget( new QLabel( "nit", this ),21, 4 );
 
  grid->addWidget( nit_edit, 21, 4+1  );
 
  grid->addWidget( new QLabel( "maxt", this ),22, 4 );
 
  grid->addWidget( maxt_edit, 22, 4+1  );
 
  grid->addWidget( new QLabel( "storage_stride", this ),23, 4 );
 
  grid->addWidget( storage_stride_edit, 23, 4+1  );
 
  grid->addWidget( new QLabel( "xml_storage_stride", this ),24, 4 );
 
  grid->addWidget( xml_storage_stride_edit, 24, 4+1  );
 
  grid->addWidget( new QLabel( "rseed", this ),25, 4 );
 
  grid->addWidget( rseed_edit, 25, 4+1  );
 
  grid->addWidget( new QLabel( "", this), 26, 4, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>Meinhardt leaf venation model</b>", this), 27, 4, 1, 2 );
 
  grid->addWidget( new QLabel( "constituous_expansion_limit", this ),28, 4 );
 
  grid->addWidget( constituous_expansion_limit_edit, 28, 4+1  );
 
  grid->addWidget( new QLabel( "vessel_inh_level", this ),29, 4 );
 
  grid->addWidget( vessel_inh_level_edit, 29, 4+1  );
 
  grid->addWidget( new QLabel( "vessel_expansion_rate", this ),3, 6 );
 
  grid->addWidget( vessel_expansion_rate_edit, 3, 6+1  );
 
  grid->addWidget( new QLabel( "d", this ),4, 6 );
 
  grid->addWidget( d_edit, 4, 6+1  );
 
  grid->addWidget( new QLabel( "e", this ),5, 6 );
 
  grid->addWidget( e_edit, 5, 6+1  );
 
  grid->addWidget( new QLabel( "f", this ),6, 6 );
 
  grid->addWidget( f_edit, 6, 6+1  );
 
  grid->addWidget( new QLabel( "c", this ),7, 6 );
 
  grid->addWidget( c_edit, 7, 6+1  );
 
  grid->addWidget( new QLabel( "mu", this ),8, 6 );
 
  grid->addWidget( mu_edit, 8, 6+1  );
 
  grid->addWidget( new QLabel( "nu", this ),9, 6 );
 
  grid->addWidget( nu_edit, 9, 6+1  );
 
  grid->addWidget( new QLabel( "rho0", this ),10, 6 );
 
  grid->addWidget( rho0_edit, 10, 6+1  );
 
  grid->addWidget( new QLabel( "rho1", this ),11, 6 );
 
  grid->addWidget( rho1_edit, 11, 6+1  );
 
  grid->addWidget( new QLabel( "c0", this ),12, 6 );
 
  grid->addWidget( c0_edit, 12, 6+1  );
 
  grid->addWidget( new QLabel( "gamma", this ),13, 6 );
 
  grid->addWidget( gamma_edit, 13, 6+1  );
 
  grid->addWidget( new QLabel( "eps", this ),14, 6 );
 
  grid->addWidget( eps_edit, 14, 6+1  );
 
  grid->addWidget( new QLabel( "", this), 15, 6, 1, 2 );
 
  grid->addWidget( new QLabel( " <b>User-defined parameters</b>", this), 16, 6, 1, 2 );
 
  grid->addWidget( new QLabel( "k", this ),17, 6 );
 
  grid->addWidget( k_edit, 17, 6+1  );
 
  grid->addWidget( new QLabel( "i1", this ),18, 6 );
 
  grid->addWidget( i1_edit, 18, 6+1  );
 
  grid->addWidget( new QLabel( "i2", this ),19, 6 );
 
  grid->addWidget( i2_edit, 19, 6+1  );
 
  grid->addWidget( new QLabel( "i3", this ),20, 6 );
 
  grid->addWidget( i3_edit, 20, 6+1  );
 
  grid->addWidget( new QLabel( "i4", this ),21, 6 );
 
  grid->addWidget( i4_edit, 21, 6+1  );
 
  grid->addWidget( new QLabel( "i5", this ),22, 6 );
 
  grid->addWidget( i5_edit, 22, 6+1  );
 
  grid->addWidget( new QLabel( "s1", this ),23, 6 );
 
  grid->addWidget( s1_edit, 23, 6+1  );
 
  grid->addWidget( new QLabel( "s2", this ),24, 6 );
 
  grid->addWidget( s2_edit, 24, 6+1  );
 
  grid->addWidget( new QLabel( "s3", this ),25, 6 );
 
  grid->addWidget( s3_edit, 25, 6+1  );
 
  grid->addWidget( new QLabel( "b1", this ),26, 6 );
 
  grid->addWidget( b1_edit, 26, 6+1  );
 
  grid->addWidget( new QLabel( "b2", this ),27, 6 );
 
  grid->addWidget( b2_edit, 27, 6+1  );
 
  grid->addWidget( new QLabel( "b3", this ),28, 6 );
 
  grid->addWidget( b3_edit, 28, 6+1  );
 
  grid->addWidget( new QLabel( "b4", this ),29, 6 );
 
  grid->addWidget( b4_edit, 29, 6+1  );
 
  grid->addWidget( new QLabel( "dir1", this ),3, 8 );
 
  grid->addWidget( dir1_edit, 3, 8+1  );
 
  grid->addWidget( new QLabel( "dir2", this ),4, 8 );
 
  grid->addWidget( dir2_edit, 4, 8+1  );
 
  grid->addWidget( new QLabel( "export_interval", this ),5, 8 );
 
  grid->addWidget( export_interval_edit, 5, 8+1  );
 
  grid->addWidget( new QLabel( "export_fn_prefix", this ),6, 8 );
 
  grid->addWidget( export_fn_prefix_edit, 6, 8+1  );
 
QPushButton *pb = new QPushButton( "&Write", this );
 
grid->addWidget(pb, 31, 6 );
 
connect( pb, SIGNAL( clicked() ), this, SLOT( write() ) );
 
QPushButton *pb2 = new QPushButton( "&Close", this );
 
grid->addWidget(pb2,31, 6+1 );
 
connect( pb2, SIGNAL( clicked() ), this, SLOT( close() ) );
 
QPushButton *pb3 = new QPushButton( "&Reset", this );
 
grid->addWidget(pb3, 31, 6+2 );
 
connect( pb3, SIGNAL( clicked() ), this, SLOT( Reset() ) );
 
show();
 
};
 

	
 
ParameterDialog::~ParameterDialog(void) {
 
delete arrowcolor_edit;
 
delete arrowsize_edit;
 
delete textcolor_edit;
 
delete cellnumsize_edit;
 
delete nodenumsize_edit;
 
delete node_mag_edit;
 
delete outlinewidth_edit;
 
delete cell_outline_color_edit;
 
delete resize_stride_edit;
 
delete T_edit;
 
delete lambda_length_edit;
 
delete yielding_threshold_edit;
 
delete lambda_celllength_edit;
 
delete target_length_edit;
 
delete cell_expansion_rate_edit;
 
delete cell_div_expansion_rate_edit;
 
delete auxin_dependent_growth_edit;
 
delete ode_accuracy_edit;
 
delete mc_stepsize_edit;
 
delete mc_cell_stepsize_edit;
 
delete energy_threshold_edit;
 
delete bend_lambda_edit;
 
delete alignment_lambda_edit;
 
delete rel_cell_div_threshold_edit;
 
delete rel_perimeter_stiffness_edit;
 
delete collapse_node_threshold_edit;
 
delete morphogen_div_threshold_edit;
 
delete morphogen_expansion_threshold_edit;
 
delete copy_wall_edit;
 
delete source_edit;
 
delete D_edit;
 
delete initval_edit;
 
delete k1_edit;
 
delete k2_edit;
 
delete r_edit;
 
delete kr_edit;
 
delete km_edit;
 
delete Pi_tot_edit;
 
delete transport_edit;
 
delete ka_edit;
 
delete pin_prod_edit;
 
delete pin_prod_in_epidermis_edit;
 
delete pin_breakdown_edit;
 
delete pin_breakdown_internal_edit;
 
delete aux1prod_edit;
 
delete aux1prodmeso_edit;
 
delete aux1decay_edit;
 
delete aux1decaymeso_edit;
 
delete aux1transport_edit;
 
delete aux_cons_edit;
 
delete aux_breakdown_edit;
 
delete kaux1_edit;
 
delete kap_edit;
 
delete leaf_tip_source_edit;
 
delete sam_efflux_edit;
 
delete sam_auxin_edit;
 
delete sam_auxin_breakdown_edit;
 
delete van3prod_edit;
 
delete van3autokat_edit;
 
delete van3sat_edit;
 
delete k2van3_edit;
 
delete dt_edit;
 
delete rd_dt_edit;
 
delete datadir_edit;
 
delete movie_edit;
 
delete nit_edit;
 
delete maxt_edit;
 
delete storage_stride_edit;
 
delete xml_storage_stride_edit;
 
delete rseed_edit;
 
delete constituous_expansion_limit_edit;
 
delete vessel_inh_level_edit;
 
delete vessel_expansion_rate_edit;
 
delete d_edit;
 
delete e_edit;
 
delete f_edit;
 
delete c_edit;
 
delete mu_edit;
 
delete nu_edit;
 
delete rho0_edit;
 
delete rho1_edit;
 
delete c0_edit;
 
delete gamma_edit;
 
delete eps_edit;
 
delete k_edit;
 
delete i1_edit;
 
delete i2_edit;
 
delete i3_edit;
 
delete i4_edit;
 
delete i5_edit;
 
delete s1_edit;
 
delete s2_edit;
 
delete s3_edit;
 
delete b1_edit;
 
delete b2_edit;
 
delete b3_edit;
 
delete b4_edit;
 
delete dir1_edit;
 
delete dir2_edit;
 
delete export_interval_edit;
 
delete export_fn_prefix_edit;
 
}
 

	
 
void ParameterDialog::write(void) {
 
    
 
extern Parameter par;
 
QString tmpval;
 
  par.arrowcolor = strdup((const char *)arrowcolor_edit->text());
 
  par.arrowsize = arrowsize_edit->text().toDouble();
 
  par.textcolor = strdup((const char *)textcolor_edit->text());
 
  par.cellnumsize = cellnumsize_edit->text().toInt();
 
  par.nodenumsize = nodenumsize_edit->text().toInt();
 
  par.node_mag = node_mag_edit->text().toDouble();
 
  par.outlinewidth = outlinewidth_edit->text().toDouble();
 
  par.cell_outline_color = strdup((const char *)cell_outline_color_edit->text());
 
  par.resize_stride = resize_stride_edit->text().toInt();
 
  par.T = T_edit->text().toDouble();
 
  par.lambda_length = lambda_length_edit->text().toDouble();
 
  par.yielding_threshold = yielding_threshold_edit->text().toDouble();
 
  par.lambda_celllength = lambda_celllength_edit->text().toDouble();
 
  par.target_length = target_length_edit->text().toDouble();
 
  par.cell_expansion_rate = cell_expansion_rate_edit->text().toDouble();
 
  par.cell_div_expansion_rate = cell_div_expansion_rate_edit->text().toDouble();
 
  tmpval = auxin_dependent_growth_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.auxin_dependent_growth = true;
 
  else if (tmpval == "false" || tmpval == "no") par.auxin_dependent_growth = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("auxin_dependent_growth"),"True","False", QString::null, 0, 1)==0) par.auxin_dependent_growth=true;
 
      else par.auxin_dependent_growth=false;
 
  }
 
  par.ode_accuracy = ode_accuracy_edit->text().toDouble();
 
  par.mc_stepsize = mc_stepsize_edit->text().toDouble();
 
  par.mc_cell_stepsize = mc_cell_stepsize_edit->text().toDouble();
 
  par.energy_threshold = energy_threshold_edit->text().toDouble();
 
  par.bend_lambda = bend_lambda_edit->text().toDouble();
 
  par.alignment_lambda = alignment_lambda_edit->text().toDouble();
 
  par.rel_cell_div_threshold = rel_cell_div_threshold_edit->text().toDouble();
 
  par.rel_perimeter_stiffness = rel_perimeter_stiffness_edit->text().toDouble();
 
  par.collapse_node_threshold = collapse_node_threshold_edit->text().toDouble();
 
  par.morphogen_div_threshold = morphogen_div_threshold_edit->text().toDouble();
 
  par.morphogen_expansion_threshold = morphogen_expansion_threshold_edit->text().toDouble();
 
  tmpval = copy_wall_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.copy_wall = true;
 
  else if (tmpval == "false" || tmpval == "no") par.copy_wall = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("copy_wall"),"True","False", QString::null, 0, 1)==0) par.copy_wall=true;
 
      else par.copy_wall=false;
 
  }
 
  par.source = source_edit->text().toDouble();
 
  tmpval = D_edit->text().section(',', 0, 0);
 
  par.D[0] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 1, 1);
 
  par.D[1] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 2, 2);
 
  par.D[2] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 3, 3);
 
  par.D[3] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 4, 4);
 
  par.D[4] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 5, 5);
 
  par.D[5] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 6, 6);
 
  par.D[6] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 7, 7);
 
  par.D[7] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 8, 8);
 
  par.D[8] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 9, 9);
 
  par.D[9] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 10, 10);
 
  par.D[10] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 11, 11);
 
  par.D[11] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 12, 12);
 
  par.D[12] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 13, 13);
 
  par.D[13] = tmpval.toDouble();
 
  tmpval = D_edit->text().section(',', 14, 14);
 
  par.D[14] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 0, 0);
 
  par.initval[0] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 1, 1);
 
  par.initval[1] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 2, 2);
 
  par.initval[2] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 3, 3);
 
  par.initval[3] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 4, 4);
 
  par.initval[4] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 5, 5);
 
  par.initval[5] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 6, 6);
 
  par.initval[6] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 7, 7);
 
  par.initval[7] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 8, 8);
 
  par.initval[8] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 9, 9);
 
  par.initval[9] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 10, 10);
 
  par.initval[10] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 11, 11);
 
  par.initval[11] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 12, 12);
 
  par.initval[12] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 13, 13);
 
  par.initval[13] = tmpval.toDouble();
 
  tmpval = initval_edit->text().section(',', 14, 14);
 
  par.initval[14] = tmpval.toDouble();
 
  par.k1 = k1_edit->text().toDouble();
 
  par.k2 = k2_edit->text().toDouble();
 
  par.r = r_edit->text().toDouble();
 
  par.kr = kr_edit->text().toDouble();
 
  par.km = km_edit->text().toDouble();
 
  par.Pi_tot = Pi_tot_edit->text().toDouble();
 
  par.transport = transport_edit->text().toDouble();
 
  par.ka = ka_edit->text().toDouble();
 
  par.pin_prod = pin_prod_edit->text().toDouble();
 
  par.pin_prod_in_epidermis = pin_prod_in_epidermis_edit->text().toDouble();
 
  par.pin_breakdown = pin_breakdown_edit->text().toDouble();
 
  par.pin_breakdown_internal = pin_breakdown_internal_edit->text().toDouble();
 
  par.aux1prod = aux1prod_edit->text().toDouble();
 
  par.aux1prodmeso = aux1prodmeso_edit->text().toDouble();
 
  par.aux1decay = aux1decay_edit->text().toDouble();
 
  par.aux1decaymeso = aux1decaymeso_edit->text().toDouble();
 
  par.aux1transport = aux1transport_edit->text().toDouble();
 
  par.aux_cons = aux_cons_edit->text().toDouble();
 
  par.aux_breakdown = aux_breakdown_edit->text().toDouble();
 
  par.kaux1 = kaux1_edit->text().toDouble();
 
  par.kap = kap_edit->text().toDouble();
 
  par.leaf_tip_source = leaf_tip_source_edit->text().toDouble();
 
  par.sam_efflux = sam_efflux_edit->text().toDouble();
 
  par.sam_auxin = sam_auxin_edit->text().toDouble();
 
  par.sam_auxin_breakdown = sam_auxin_breakdown_edit->text().toDouble();
 
  par.van3prod = van3prod_edit->text().toDouble();
 
  par.van3autokat = van3autokat_edit->text().toDouble();
 
  par.van3sat = van3sat_edit->text().toDouble();
 
  par.k2van3 = k2van3_edit->text().toDouble();
 
  par.dt = dt_edit->text().toDouble();
 
  par.rd_dt = rd_dt_edit->text().toDouble();
 
  par.datadir = strdup((const char *)datadir_edit->text());
 
  tmpval = movie_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.movie = true;
 
  else if (tmpval == "false" || tmpval == "no") par.movie = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("movie"),"True","False", QString::null, 0, 1)==0) par.movie=true;
 
      else par.movie=false;
 
  }
 
  par.nit = nit_edit->text().toInt();
 
  par.maxt = maxt_edit->text().toDouble();
 
  par.storage_stride = storage_stride_edit->text().toInt();
 
  par.xml_storage_stride = xml_storage_stride_edit->text().toInt();
 
  par.rseed = rseed_edit->text().toInt();
 
  par.constituous_expansion_limit = constituous_expansion_limit_edit->text().toInt();
 
  par.vessel_inh_level = vessel_inh_level_edit->text().toDouble();
 
  par.vessel_expansion_rate = vessel_expansion_rate_edit->text().toDouble();
 
  par.d = d_edit->text().toDouble();
 
  par.e = e_edit->text().toDouble();
 
  par.f = f_edit->text().toDouble();
 
  par.c = c_edit->text().toDouble();
 
  par.mu = mu_edit->text().toDouble();
 
  par.nu = nu_edit->text().toDouble();
 
  par.rho0 = rho0_edit->text().toDouble();
 
  par.rho1 = rho1_edit->text().toDouble();
 
  par.c0 = c0_edit->text().toDouble();
 
  par.gamma = gamma_edit->text().toDouble();
 
  par.eps = eps_edit->text().toDouble();
 
  tmpval = k_edit->text().section(',', 0, 0);
 
  par.k[0] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 1, 1);
 
  par.k[1] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 2, 2);
 
  par.k[2] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 3, 3);
 
  par.k[3] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 4, 4);
 
  par.k[4] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 5, 5);
 
  par.k[5] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 6, 6);
 
  par.k[6] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 7, 7);
 
  par.k[7] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 8, 8);
 
  par.k[8] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 9, 9);
 
  par.k[9] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 10, 10);
 
  par.k[10] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 11, 11);
 
  par.k[11] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 12, 12);
 
  par.k[12] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 13, 13);
 
  par.k[13] = tmpval.toDouble();
 
  tmpval = k_edit->text().section(',', 14, 14);
 
  par.k[14] = tmpval.toDouble();
 
  par.i1 = i1_edit->text().toInt();
 
  par.i2 = i2_edit->text().toInt();
 
  par.i3 = i3_edit->text().toInt();
 
  par.i4 = i4_edit->text().toInt();
 
  par.i5 = i5_edit->text().toInt();
 
  par.s1 = strdup((const char *)s1_edit->text());
 
  par.s2 = strdup((const char *)s2_edit->text());
 
  par.s3 = strdup((const char *)s3_edit->text());
 
  tmpval = b1_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.b1 = true;
 
  else if (tmpval == "false" || tmpval == "no") par.b1 = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("b1"),"True","False", QString::null, 0, 1)==0) par.b1=true;
 
      else par.b1=false;
 
  }
 
  tmpval = b2_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.b2 = true;
 
  else if (tmpval == "false" || tmpval == "no") par.b2 = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("b2"),"True","False", QString::null, 0, 1)==0) par.b2=true;
 
      else par.b2=false;
 
  }
 
  tmpval = b3_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.b3 = true;
 
  else if (tmpval == "false" || tmpval == "no") par.b3 = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("b3"),"True","False", QString::null, 0, 1)==0) par.b3=true;
 
      else par.b3=false;
 
  }
 
  tmpval = b4_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.b4 = true;
 
  else if (tmpval == "false" || tmpval == "no") par.b4 = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("b4"),"True","False", QString::null, 0, 1)==0) par.b4=true;
 
      else par.b4=false;
 
  }
 
  par.dir1 = strdup((const char *)dir1_edit->text());
 
  par.dir2 = strdup((const char *)dir2_edit->text());
 
  par.export_interval = export_interval_edit->text().toInt();
 
  par.export_fn_prefix = strdup((const char *)export_fn_prefix_edit->text());
 
Reset();
 

	
 
}
 
void ParameterDialog::Reset(void) {
 
  extern Parameter par;
 
  arrowcolor_edit->setText( QString("%1").arg(par.arrowcolor) );
 
  arrowsize_edit->setText( QString("%1").arg(par.arrowsize) );
 
  textcolor_edit->setText( QString("%1").arg(par.textcolor) );
 
  cellnumsize_edit->setText( QString("%1").arg(par.cellnumsize) );
 
  nodenumsize_edit->setText( QString("%1").arg(par.nodenumsize) );
 
  node_mag_edit->setText( QString("%1").arg(par.node_mag) );
 
  outlinewidth_edit->setText( QString("%1").arg(par.outlinewidth) );
 
  cell_outline_color_edit->setText( QString("%1").arg(par.cell_outline_color) );
 
  resize_stride_edit->setText( QString("%1").arg(par.resize_stride) );
 
  T_edit->setText( QString("%1").arg(par.T) );
 
  lambda_length_edit->setText( QString("%1").arg(par.lambda_length) );
 
  yielding_threshold_edit->setText( QString("%1").arg(par.yielding_threshold) );
 
  lambda_celllength_edit->setText( QString("%1").arg(par.lambda_celllength) );
 
  target_length_edit->setText( QString("%1").arg(par.target_length) );
 
  cell_expansion_rate_edit->setText( QString("%1").arg(par.cell_expansion_rate) );
 
  cell_div_expansion_rate_edit->setText( QString("%1").arg(par.cell_div_expansion_rate) );
 
  auxin_dependent_growth_edit->setText( QString("%1").arg(sbool(par.auxin_dependent_growth)));
 
  ode_accuracy_edit->setText( QString("%1").arg(par.ode_accuracy) );
 
  mc_stepsize_edit->setText( QString("%1").arg(par.mc_stepsize) );
 
  mc_cell_stepsize_edit->setText( QString("%1").arg(par.mc_cell_stepsize) );
 
  energy_threshold_edit->setText( QString("%1").arg(par.energy_threshold) );
 
  bend_lambda_edit->setText( QString("%1").arg(par.bend_lambda) );
 
  alignment_lambda_edit->setText( QString("%1").arg(par.alignment_lambda) );
 
  rel_cell_div_threshold_edit->setText( QString("%1").arg(par.rel_cell_div_threshold) );
 
  rel_perimeter_stiffness_edit->setText( QString("%1").arg(par.rel_perimeter_stiffness) );
 
  collapse_node_threshold_edit->setText( QString("%1").arg(par.collapse_node_threshold) );
 
  morphogen_div_threshold_edit->setText( QString("%1").arg(par.morphogen_div_threshold) );
 
  morphogen_expansion_threshold_edit->setText( QString("%1").arg(par.morphogen_expansion_threshold) );
 
  copy_wall_edit->setText( QString("%1").arg(sbool(par.copy_wall)));
 
  source_edit->setText( QString("%1").arg(par.source) );
 
  QString D_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  D_string = D_string.arg(par.D[0]).arg(par.D[1]).arg(par.D[2]).arg(par.D[3]).arg(par.D[4]).arg(par.D[5]).arg(par.D[6]).arg(par.D[7]).arg(par.D[8]).arg(par.D[9]).arg(par.D[10]).arg(par.D[11]).arg(par.D[12]).arg(par.D[13]).arg(par.D[14]);
 
  D_edit->setText( D_string );
 
  QString initval_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  initval_string = initval_string.arg(par.initval[0]).arg(par.initval[1]).arg(par.initval[2]).arg(par.initval[3]).arg(par.initval[4]).arg(par.initval[5]).arg(par.initval[6]).arg(par.initval[7]).arg(par.initval[8]).arg(par.initval[9]).arg(par.initval[10]).arg(par.initval[11]).arg(par.initval[12]).arg(par.initval[13]).arg(par.initval[14]);
 
  initval_edit->setText( initval_string );
 
  k1_edit->setText( QString("%1").arg(par.k1) );
 
  k2_edit->setText( QString("%1").arg(par.k2) );
 
  r_edit->setText( QString("%1").arg(par.r) );
 
  kr_edit->setText( QString("%1").arg(par.kr) );
 
  km_edit->setText( QString("%1").arg(par.km) );
 
  Pi_tot_edit->setText( QString("%1").arg(par.Pi_tot) );
 
  transport_edit->setText( QString("%1").arg(par.transport) );
 
  ka_edit->setText( QString("%1").arg(par.ka) );
 
  pin_prod_edit->setText( QString("%1").arg(par.pin_prod) );
 
  pin_prod_in_epidermis_edit->setText( QString("%1").arg(par.pin_prod_in_epidermis) );
 
  pin_breakdown_edit->setText( QString("%1").arg(par.pin_breakdown) );
 
  pin_breakdown_internal_edit->setText( QString("%1").arg(par.pin_breakdown_internal) );
 
  aux1prod_edit->setText( QString("%1").arg(par.aux1prod) );
 
  aux1prodmeso_edit->setText( QString("%1").arg(par.aux1prodmeso) );
 
  aux1decay_edit->setText( QString("%1").arg(par.aux1decay) );
 
  aux1decaymeso_edit->setText( QString("%1").arg(par.aux1decaymeso) );
 
  aux1transport_edit->setText( QString("%1").arg(par.aux1transport) );
 
  aux_cons_edit->setText( QString("%1").arg(par.aux_cons) );
 
  aux_breakdown_edit->setText( QString("%1").arg(par.aux_breakdown) );
 
  kaux1_edit->setText( QString("%1").arg(par.kaux1) );
 
  kap_edit->setText( QString("%1").arg(par.kap) );
 
  leaf_tip_source_edit->setText( QString("%1").arg(par.leaf_tip_source) );
 
  sam_efflux_edit->setText( QString("%1").arg(par.sam_efflux) );
 
  sam_auxin_edit->setText( QString("%1").arg(par.sam_auxin) );
 
  sam_auxin_breakdown_edit->setText( QString("%1").arg(par.sam_auxin_breakdown) );
 
  van3prod_edit->setText( QString("%1").arg(par.van3prod) );
 
  van3autokat_edit->setText( QString("%1").arg(par.van3autokat) );
 
  van3sat_edit->setText( QString("%1").arg(par.van3sat) );
 
  k2van3_edit->setText( QString("%1").arg(par.k2van3) );
 
  dt_edit->setText( QString("%1").arg(par.dt) );
 
  rd_dt_edit->setText( QString("%1").arg(par.rd_dt) );
 
  datadir_edit->setText( QString("%1").arg(par.datadir) );
 
  movie_edit->setText( QString("%1").arg(sbool(par.movie)));
 
  nit_edit->setText( QString("%1").arg(par.nit) );
 
  maxt_edit->setText( QString("%1").arg(par.maxt) );
 
  storage_stride_edit->setText( QString("%1").arg(par.storage_stride) );
 
  xml_storage_stride_edit->setText( QString("%1").arg(par.xml_storage_stride) );
 
  rseed_edit->setText( QString("%1").arg(par.rseed) );
 
  constituous_expansion_limit_edit->setText( QString("%1").arg(par.constituous_expansion_limit) );
 
  vessel_inh_level_edit->setText( QString("%1").arg(par.vessel_inh_level) );
 
  vessel_expansion_rate_edit->setText( QString("%1").arg(par.vessel_expansion_rate) );
 
  d_edit->setText( QString("%1").arg(par.d) );
 
  e_edit->setText( QString("%1").arg(par.e) );
 
  f_edit->setText( QString("%1").arg(par.f) );
 
  c_edit->setText( QString("%1").arg(par.c) );
 
  mu_edit->setText( QString("%1").arg(par.mu) );
 
  nu_edit->setText( QString("%1").arg(par.nu) );
 
  rho0_edit->setText( QString("%1").arg(par.rho0) );
 
  rho1_edit->setText( QString("%1").arg(par.rho1) );
 
  c0_edit->setText( QString("%1").arg(par.c0) );
 
  gamma_edit->setText( QString("%1").arg(par.gamma) );
 
  eps_edit->setText( QString("%1").arg(par.eps) );
 
  QString k_string("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15");
 
  k_string = k_string.arg(par.k[0]).arg(par.k[1]).arg(par.k[2]).arg(par.k[3]).arg(par.k[4]).arg(par.k[5]).arg(par.k[6]).arg(par.k[7]).arg(par.k[8]).arg(par.k[9]).arg(par.k[10]).arg(par.k[11]).arg(par.k[12]).arg(par.k[13]).arg(par.k[14]);
 
  k_edit->setText( k_string );
 
  i1_edit->setText( QString("%1").arg(par.i1) );
 
  i2_edit->setText( QString("%1").arg(par.i2) );
 
  i3_edit->setText( QString("%1").arg(par.i3) );
 
  i4_edit->setText( QString("%1").arg(par.i4) );
 
  i5_edit->setText( QString("%1").arg(par.i5) );
 
  s1_edit->setText( QString("%1").arg(par.s1) );
 
  s2_edit->setText( QString("%1").arg(par.s2) );
 
  s3_edit->setText( QString("%1").arg(par.s3) );
 
  b1_edit->setText( QString("%1").arg(sbool(par.b1)));
 
  b2_edit->setText( QString("%1").arg(sbool(par.b2)));
 
  b3_edit->setText( QString("%1").arg(sbool(par.b3)));
 
  b4_edit->setText( QString("%1").arg(sbool(par.b4)));
 
  dir1_edit->setText( QString("%1").arg(par.dir1) );
 
  dir2_edit->setText( QString("%1").arg(par.dir2) );
 
  export_interval_edit->setText( QString("%1").arg(par.export_interval) );
 
  export_fn_prefix_edit->setText( QString("%1").arg(par.export_fn_prefix) );
 
}
 

	
src/pardialog.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
// WARNING: This file is automatically generated by make_parameter_source.pl. Do not edit.
 
// Do not edit. All edits will be discarded.
 

	
 
#ifndef PARAMETER_DIALOG_H
 
#define PARAMETER_DIALOG_H
 
#include <qdialog.h>
 
#include <qspinbox.h>
 
#include <qlineedit.h>
 
#include <qlayout.h>
 
#include <qpushbutton.h>
 
#include <iostream>
 

	
 
class ParameterDialog : public QDialog {
 
    Q_OBJECT
 
	
 
      public:
 
	ParameterDialog(QWidget *parent=0, const char *name = 0, Qt::WindowFlags f = 0);
 
    virtual ~ParameterDialog(void);
 
    public slots:
 
    void Reset(void);
 

	
 
    private slots:
 
    void write(void);
 

	
 
  private:
 
  QLineEdit *arrowcolor_edit;
 
  QLineEdit *arrowsize_edit;
 
  QLineEdit *textcolor_edit;
 
  QLineEdit *cellnumsize_edit;
 
  QLineEdit *nodenumsize_edit;
 
  QLineEdit *node_mag_edit;
 
  QLineEdit *outlinewidth_edit;
 
  QLineEdit *cell_outline_color_edit;
 
  QLineEdit *resize_stride_edit;
 
  QLineEdit *T_edit;
 
  QLineEdit *lambda_length_edit;
 
  QLineEdit *yielding_threshold_edit;
 
  QLineEdit *lambda_celllength_edit;
 
  QLineEdit *target_length_edit;
 
  QLineEdit *cell_expansion_rate_edit;
 
  QLineEdit *cell_div_expansion_rate_edit;
 
  QLineEdit *auxin_dependent_growth_edit;
 
  QLineEdit *ode_accuracy_edit;
 
  QLineEdit *mc_stepsize_edit;
 
  QLineEdit *mc_cell_stepsize_edit;
 
  QLineEdit *energy_threshold_edit;
 
  QLineEdit *bend_lambda_edit;
 
  QLineEdit *alignment_lambda_edit;
 
  QLineEdit *rel_cell_div_threshold_edit;
 
  QLineEdit *rel_perimeter_stiffness_edit;
 
  QLineEdit *collapse_node_threshold_edit;
 
  QLineEdit *morphogen_div_threshold_edit;
 
  QLineEdit *morphogen_expansion_threshold_edit;
 
  QLineEdit *copy_wall_edit;
 
  QLineEdit *source_edit;
 
  QLineEdit *D_edit;
 
  QLineEdit *initval_edit;
 
  QLineEdit *k1_edit;
 
  QLineEdit *k2_edit;
 
  QLineEdit *r_edit;
 
  QLineEdit *kr_edit;
 
  QLineEdit *km_edit;
 
  QLineEdit *Pi_tot_edit;
 
  QLineEdit *transport_edit;
 
  QLineEdit *ka_edit;
 
  QLineEdit *pin_prod_edit;
 
  QLineEdit *pin_prod_in_epidermis_edit;
 
  QLineEdit *pin_breakdown_edit;
 
  QLineEdit *pin_breakdown_internal_edit;
 
  QLineEdit *aux1prod_edit;
 
  QLineEdit *aux1prodmeso_edit;
 
  QLineEdit *aux1decay_edit;
 
  QLineEdit *aux1decaymeso_edit;
 
  QLineEdit *aux1transport_edit;
 
  QLineEdit *aux_cons_edit;
 
  QLineEdit *aux_breakdown_edit;
 
  QLineEdit *kaux1_edit;
 
  QLineEdit *kap_edit;
 
  QLineEdit *leaf_tip_source_edit;
 
  QLineEdit *sam_efflux_edit;
 
  QLineEdit *sam_auxin_edit;
 
  QLineEdit *sam_auxin_breakdown_edit;
 
  QLineEdit *van3prod_edit;
 
  QLineEdit *van3autokat_edit;
 
  QLineEdit *van3sat_edit;
 
  QLineEdit *k2van3_edit;
 
  QLineEdit *dt_edit;
 
  QLineEdit *rd_dt_edit;
 
  QLineEdit *datadir_edit;
 
  QLineEdit *movie_edit;
 
  QLineEdit *nit_edit;
 
  QLineEdit *maxt_edit;
 
  QLineEdit *storage_stride_edit;
 
  QLineEdit *xml_storage_stride_edit;
 
  QLineEdit *rseed_edit;
 
  QLineEdit *constituous_expansion_limit_edit;
 
  QLineEdit *vessel_inh_level_edit;
 
  QLineEdit *vessel_expansion_rate_edit;
 
  QLineEdit *d_edit;
 
  QLineEdit *e_edit;
 
  QLineEdit *f_edit;
 
  QLineEdit *c_edit;
 
  QLineEdit *mu_edit;
 
  QLineEdit *nu_edit;
 
  QLineEdit *rho0_edit;
 
  QLineEdit *rho1_edit;
 
  QLineEdit *c0_edit;
 
  QLineEdit *gamma_edit;
 
  QLineEdit *eps_edit;
 
  QLineEdit *k_edit;
 
  QLineEdit *i1_edit;
 
  QLineEdit *i2_edit;
 
  QLineEdit *i3_edit;
 
  QLineEdit *i4_edit;
 
  QLineEdit *i5_edit;
 
  QLineEdit *s1_edit;
 
  QLineEdit *s2_edit;
 
  QLineEdit *s3_edit;
 
  QLineEdit *b1_edit;
 
  QLineEdit *b2_edit;
 
  QLineEdit *b3_edit;
 
  QLineEdit *b4_edit;
 
  QLineEdit *dir1_edit;
 
  QLineEdit *dir2_edit;
 
  QLineEdit *export_interval_edit;
 
  QLineEdit *export_fn_prefix_edit;
 
};
 
#endif
src/wallitem.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  VirtualLeaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  VirtualLeaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <QDebug>
 
#include <string>
 
#include <QGraphicsScene>
 
#include <QVector>
 
#include "canvas.h"
 
#include "wallitem.h"
 
#include "parameter.h"
 
#include "node.h"
 
#include "transporterdialog.h"
 

	
 
static const std::string _module_id("$Id$");
 

	
 
WallItem::WallItem( Wall *w, int wallnumber, QGraphicsScene *canvas )
 
  : QGraphicsLineItem( 0, canvas ), SimItemBase( w, canvas){
 

	
 
  wn = wallnumber;
 

	
 
  extern Parameter par;
 

	
 
  setColor();
 

	
 
  // line with "PIN1"is a bit inside the cell wall
 
  Vector edgevec = (*(w->N2())) - (*(w->N1()));
 
  Vector perp = edgevec.Normalised().Perp2D();
 

	
 
  Vector offs = Cell::Offset();
 
  double factor = Cell::Factor();
 

	
 
  Vector from = ( offs + *(w->N1()) ) * factor + (wn==1?-1:1) * par.outlinewidth * 0.5 * factor * perp;
 
  Vector to = ( offs + *(w->N2()) ) *factor + (wn==1?-1:1) * par.outlinewidth * 0.5 * factor * perp;
 

	
 

	
 
  Vector tmp_centroid = ( *(w->N2()) + *(w->N1()) )/2.;
 
  Vector centroid = ( offs + tmp_centroid ) * factor;
 

	
 
  QString text=QString("%1").arg(w->Index());
 
  setLine(( from.x ),
 
	  ( from.y ),
 
	  ( to.x ),
 
	  ( to.y ) );
 
  setZValue(12);
 
}
 

	
 

	
 
void WallItem::setColor(void) {
 

	
 
  QColor diffcolor;
 
  static const QColor purple("Purple");
 
  static const QColor blue("blue");
 

	
 
  Wall *w=&getWall();
 
  double tr = wn==1?w->Transporters1(1):w->Transporters2(1);
 
  CellBase *c = wn==1?w->C1():w->C2();
 
  diffcolor.setRgb( (int)( ( tr / (1 + tr) )*255.), 0, 0);
 
  if (w->AuxinSource() && c->BoundaryPolP()) {
 
    setPen( QPen(purple , par.outlinewidth) );
 
  } else {
 
    if (w->AuxinSink() && c->BoundaryPolP()) {
 
      setPen( QPen(blue, par.outlinewidth));
 
    } else {
 
      setPen (QPen(diffcolor, par.outlinewidth) );
 
    }
 
  }
 
}
 

	
 
void WallItem::OnClick(QMouseEvent *e) {
 

	
 

	
 
  Wall *w=&getWall();
 
#ifdef QDEBUG
 
  qDebug() << "Wall ID = " << w->Index() << ", this = " << w << endl;
 
  qDebug() << "Wall item = " << this << endl;
 
  qDebug() << "C1 = " << w->C1()->Index() << ", C2 = " << w->C2()->Index() << endl;
 
  qDebug() << "N1 = " << w->N1()->Index() << ", N2 = " << w->N2()->Index() << endl;
 
#endif
 
  CellBase *c = wn==1?w->C1():w->C2();
 

	
 
  TransporterDialog dialog(w, c, wn);
 
  dialog.exec();
 

	
 
  if (e->button() == Qt::RightButton) {
 
    QString message;
 
    if (wn==1) {
 
      message=QString("Transporter 1 = %1, color = %2, length = %3\n").arg(w->Transporters1(1)).arg(pen().color().red()).arg(getWall().Length());
 
    } else {
 
      message=QString("Transporter 2 = %1, color = %2, length = %3\n").arg(w->Transporters2(1)).arg(pen().color().red()).arg(getWall().Length());
 
    }
 

	
 
    //extern MainBase *main_window;
 

	
 
  } else {
 
    if (e->button() == Qt::LeftButton) {
 
 
 
      if (e->modifiers() == Qt::ControlModifier) {
 
	// let's consider wall type cycling an "easter egg". 
 
	// Ctrl modifier key required 
 

	
 
      if (c->BoundaryPolP()) {
 
	w->cycleWallType();
 
      } else {
 
	if (e->modifiers() == Qt::ShiftModifier) {
 
	  wn==1?w->setTransporters1(1,0):w->setTransporters2(1,0);					
 

	
 
	} else {
 
	  // set high amount of PIN1
 
	  //cerr << "Setting PIN1\n";
 
	  wn==1?w->setTransporters1(1,10):w->setTransporters2(1,10);
 
	}
 
      }
 
      setColor();
 
      update(boundingRect());
 
      } else {
 
	TransporterDialog dialog(w, c, wn);
 
	dialog.exec();
 
      }
 

	
 
    } 
 
 
 
  }
 
  setColor();
 
  update(boundingRect());
 

	
 
}
 

	
 
/* finis */
0 comments (0 inline, 0 general)