diff --git a/src/cellbase.h b/src/cellbase.h new file mode 100644 --- /dev/null +++ b/src/cellbase.h @@ -0,0 +1,473 @@ +/* + * + * $Id$ + * + * This file is part of the Virtual Leaf. + * + * The Virtual Leaf 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. + * + * The Virtual Leaf 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 . + * + * Copyright 2010 Roeland Merks. + * + */ + +// CellBase derives from Vector, where Vector is simply used as a Vertex + +#ifndef _CELLBASE_H_ +#define _CELLBASE_H_ + +#include +#include +#include +#include +#include "vector.h" +#include "parameter.h" +#include "wall.h" +#include "warning.h" + +extern Parameter par; +using namespace std; + +class Mesh; +class Node; +class CellBase; +class NodeSet; + +struct ParentInfo { + + Vector polarization; + double PINmembrane; + double PINendosome; + +}; + +// We need a little trick here, to make sure the plugin and the main application will see the same static datamembers +// otherwise each have their own instantation. +// My solution is as follow. I collect all original statics in a class. The main application instantiates it and +// has a static pointer to it. After loading the plugin I set a static pointer to the same class +class CellsStaticDatamembers { + +public: + CellsStaticDatamembers(void) { + ncells = 0; + nchem = 0; + base_area = 0.; + cerr << "Constructor of CellsStaticDatamembers\n"; + } + ~CellsStaticDatamembers() { + cerr << "Oops! Desctructor of CellsStaticDatamembers called\n"; + } + int ncells; + int nchem; + double base_area; + + +}; + +class CellBase : public QObject, public Vector +{ + + Q_OBJECT + + + friend class Mesh; + friend class CellInfo; + friend class Node; + friend class WallBase; + friend class SimPluginInterface; + + public: + CellBase(QObject *parent=0); + CellBase(double x,double y,double z=0); // constructor + + virtual ~CellBase() { + delete[] chem; + delete[] new_chem; + //cerr << "CellBase " << index << " is dying. " << endl; + } + + CellBase(const CellBase &src); // copy constructor + virtual bool BoundaryPolP(void) const { return false; } + + + // CellBase(const Vector &src); // not allowed (we cannot know to which mesh + /// the CellBase will belong...) + CellBase operator=(const CellBase &src); // assignment operator + CellBase operator=(const Vector &src); + + void SetChemical(int chem, double conc); + inline void SetNewChem(int chem, double conc) { + new_chem[chem] = conc; + } + void SetSource(int chem, double conc) { + source=true; + source_chem = chem; + source_conc = conc; + } + + void UnfixNodes(void); + void FixNodes(void); + void UnsetSource(void) { + source = false; + } + + inline bool Source(void) { return source; } + enum boundary_type {None, Noflux, SourceSink, SAM}; + static const char * boundary_type_names[4]; + + inline const char *BoundaryStr(void) { return boundary_type_names[boundary]; } + + ostream &print(ostream &os) const; + inline double Chemical(int c) const { // returns the value of chemical c + return chem[c]; + } + + + //void print_nblist(void) const; + + boundary_type SetBoundary(boundary_type bound) { + if (bound!=None) { + //area=0.; + //length=0.; + } + return boundary=bound; + } + + boundary_type ResetBoundary(void) { + return boundary=None; + } + boundary_type Boundary(void) const { + return boundary; + } + static int &NChem(void) { + return static_data_members->nchem; + } + + double CalcArea(void) const; + double RecalcArea(void) { + return area = CalcArea(); + } + + Vector Centroid(void) const; + + void SetIntegrals(void) const; + + double Length(Vector *long_axis = 0, double *width = 0) const; + double CalcLength(Vector *long_axis = 0, double *width = 0) const; + + + inline int Index(void) const { + return index; + } + + + void SetTargetArea(double tar_ar) { + target_area=tar_ar; + } + inline void SetTargetLength(double tar_l) { + target_length=tar_l; + } + inline void SetLambdaLength(double lambda_length) { + lambda_celllength = lambda_length; + } + inline double TargetArea(void) { + return target_area; + } + + inline void SetStiffness(double stiff) { + stiffness = stiff; + } + + inline double Stiffness(void) { + return stiffness; + } + inline double EnlargeTargetArea(double da) { + return target_area+=da; + } + + inline double Area(void) const { + return area; + } + + inline void Divide(void) { + flag_for_divide = true; + } + //Vector Strain(void) const; + + inline double Circumference(void) const { + double sum=0.; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->Length(); + } + + return sum; + } + + QList getWalls(void) { + QList wall_list; + for (list::iterator i=walls.begin(); + i!=walls.end(); + i++) { + wall_list << *i; + } + return wall_list; + } + // void XFigPrint(std::ostream &os) const; + + void Dump(ostream &os) const; + + QString printednodelist(void); + + // void OnDivide(ParentInfo &parent_info, CellBase &daughter); + + + inline bool DeadP(void) { return dead; } + inline void MarkDead(void) { dead = true; } + + static double &BaseArea(void) { + return static_data_members->base_area; + } + + void CheckForDivision(void); + + + // write flux from neighboring cells into "flux" + void Flux(double *flux, double *D); + inline bool FixedP(void) { return fixed; } + inline bool Fix(void) { FixNodes(); return (fixed=true); } + inline bool Unfix(void) { UnfixNodes(); return (fixed=false);} + inline void setCellVec(Vector cv) { cellvec = cv; } + + bool AtBoundaryP(void) const; + + static inline int &NCells(void) { + return static_data_members->ncells; + } + + + + inline void Mark(void) { + marked=true; + } + inline void Unmark(void) { + marked=false; + } + inline bool Marked(void) const { + return marked; + } + + //! Returns the sum of chemical "chem" of this CellBase's neighbors + double SumChemicalsOfNeighbors(int chem) { + double sum=0.; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->Length() * ( (*w)->c1!=this ? (*w)->c1->Chemical(chem) : (*w)->c2->Chemical(chem) ); + } + return sum; + } + + //! Generalization of the previous member function + template P ReduceNeighbors(Op f) { + P sum=0; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->c1 != this ? f( *((*w)->c1) ) : f ( *((*w)->c2) ); + } + return sum; + } + + //! The same, but now for the walls + template P ReduceWalls(Op f, P sum) { + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += f( **w ); + } + return sum; + } + + + + + //! The same, but now for the walls AND neighbors + template P ReduceCellAndWalls(Op f) { + P sum = 0; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->c1 == this ? + f( *((*w)->c1), *((*w)->c2), **w ) : + f( *((*w)->c2), *((*w)->c1), **w ); + } + return sum; + } + + /* template void LoopWalls(Op f) { + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + ( **w)->f; + } + }*/ + + //! Sum transporters at this CellBase's side of the walls + double SumTransporters(int ch) { + double sum=0.; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->getTransporter(this, ch); + + } + + return sum; + } + + inline int NumberOfDivisions(void) { return div_counter; } + + //! Sum transporters at this CellBase's side of the walls + double SumLengthTransporters(int ch) { + double sum=0.; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->getTransporter(this, ch) * (*w)->Length(); + + } + + return sum; + } + + + + double SumLengthTransportersChemical(int trch, int ch) { + double sum=0.; + for (list::const_iterator w=walls.begin(); + w!=walls.end(); + w++) { + sum += (*w)->getTransporter(this, trch) * ( (*w)->c1!=this ? (*w)->c1->Chemical(ch) : (*w)->c2->Chemical(ch) ); + + } + + return sum; + } + inline int CellType(void) const { return cell_type; } + inline void SetCellType(int ct) { cell_type = ct; } + + + static void SetNChem(int new_nchem) { + if (NCells()) { + MyWarning::error("CellBase::SetNChem says: not permitted, call SetNChem after deleting all cells."); + } else { + NChem() = new_nchem; + } + } + + inline double TargetLength() const { return target_length; } + + static inline CellsStaticDatamembers *GetStaticDataMemberPointer(void) { return static_data_members; } + +protected: + // (define a list of Node* iterators) + typedef list < list::iterator > ItList; + + int index; + + inline void SetChemToNewchem(void) { + for (int c=0;c nodes; + void ConstructNeighborList(void); + long wall_list_index (Wall *elem) const; + + // DATA MEMBERS + + // list of nodes, in clockwise order + + // a (non-ordered) list of neighboring cells (actually I think the + // introduction of ConstructWalls() has made these + // lists ordered (clockwise), but I am not yet 100% sure...). + list neighbors; + + list walls; + + double *chem; + double *new_chem; + + boundary_type boundary; + mutable double area; + double target_area; + double target_length; + double lambda_celllength; + + double stiffness; // stiffness like in Hogeweg (2000) + + bool fixed; + bool pin_fixed; + bool at_boundary; + bool dead; + bool flag_for_divide; + + int cell_type; + + //double length; + //Vector meanflux; + //int valence; + + // for length constraint + mutable double intgrl_xx, intgrl_xy, intgrl_yy, intgrl_x, intgrl_y; + + bool source; + Vector cellvec; + + // STATIC DATAMEMBERS MOVED TO CLASS + static CellsStaticDatamembers *static_data_members; + double source_conc; + int source_chem; + + // PRIVATE MEMBER FUNCTIONS + inline static void ClearNCells(void) { + NCells()=0; + } + + bool marked; + int div_counter; +}; + +ostream &operator<<(ostream &os, const CellBase &v); + +inline Vector PINdir(CellBase &here, CellBase &nb, Wall &w) { + return w.getTransporter( &here, 1) * w.getInfluxVector(&here); +} + + +#endif + + + + +