dgfparserblocks.hh

00001 #ifndef DUNE_MACROGRIDPARSERBLOCKS_HH
00002 #define DUNE_MACROGRIDPARSERBLOCKS_HH
00003 
00004 #include <set>
00005 
00006 namespace Dune {
00007 
00008 // *************************************************************
00009 // Read one block with given identifier from disk
00010 // and allows the line-wise extraction from this block
00011 // *************************************************************
00012 namespace {
00013 
00014 inline void makeupcase(std::string &s) 
00015 {
00016   for (size_t i=0;i<s.size();i++) 
00017     s[i]=toupper(s[i]);
00018 }
00019 
00020 class BasicBlock {
00021   int pos;                   // line number
00022   bool active;               // block was found
00023   bool empty;                // block was found but was empty
00024   std::string identifier;    // identifier of this block
00025   int linecount;             // total number of lines in the block
00026   std::stringstream block;   // the block itself
00027   std::string oneline;       // the active line in the block
00028   // get the block (if it exists)
00029   void getblock(std::istream &in) {
00030     std::string id;
00031     getline(in,id);
00032     while (in.good()) {
00033       std::stringstream idstream(id);
00034       std::string upcaseid;
00035       idstream >> upcaseid;
00036       makeupcase(upcaseid);
00037       if (upcaseid==identifier) 
00038       {
00039         active=true;
00040         break;
00041       }
00042       getline(in,id);
00043     }
00044     if (active) {
00045       bool blockend=false;
00046       while (in.good()) {
00047         getline(in,oneline);
00048         if (oneline.size()==0)
00049           continue;
00050         std::stringstream onelinestream(oneline);
00051         std::string test;
00052         onelinestream >> test;
00053         if (test[0] == '#') {
00054           blockend=true;
00055           break;
00056         }
00057         empty=false;
00058         block << oneline << "\n"; 
00059       }
00060       if (!blockend) {
00061         DUNE_THROW(DGFException,
00062                    "Error: block must end with a #-line");
00063       }
00064     }
00065     else {
00066       // std::cerr << "Warning: Block " << identifier << " not found" << std::endl;
00067     }
00068   }
00069   // count the number of lines in the block
00070   int countlines() {
00071     if (empty) 
00072       return 0;
00073     int ret=0;
00074     while (1) {
00075       getnextline();
00076       if (oneline.size()==0)
00077         break;
00078       ret++;
00079     } 
00080     return ret;
00081   }
00082  protected:
00083   std::stringstream line; // the active line as string buffer 
00084                           // for use in the derived classes
00085   // go back to beginning of block
00086   void reset() {
00087     pos=-1;
00088     block.clear();
00089     block.seekg(0);
00090     linecount=countlines();
00091     pos=-1;
00092     block.clear();
00093     block.seekg(0);
00094   }
00095   // get next line and store in string stream
00096   void getnextline() {
00097     line.clear();
00098     oneline.clear();
00099     getline(block,oneline);
00100     if (oneline.size()>0) {
00101       std::size_t comment=oneline.find("%");
00102       if (comment!=std::string::npos) {
00103         oneline.erase(comment);
00104         if (oneline.size()==0) {
00105           getnextline();
00106           return;
00107         }
00108       }
00109     }
00110     line.str(oneline); 
00111     pos++;
00112   }
00113   // get next entry in line
00114   template <class ENTRY>
00115   bool getnextentry(ENTRY &entry) {
00116     line >> entry;
00117     return line;
00118   }
00119   bool gettokenparam(std::string token,std::string& entry) {
00120     makeupcase(token);
00121     std::string ltoken;
00122     reset();
00123     do {
00124       getnextline();
00125       if (oneline.size()==0)
00126         return false;
00127       line >> ltoken;
00128       makeupcase(ltoken);
00129     } while (ltoken!=token);
00130     getline(line,entry);
00131     return true;
00132   }
00133   bool findtoken(std::string token) {
00134     makeupcase(token);
00135     std::string ltoken;
00136     reset();
00137     do {
00138       getnextline();
00139       if (oneline.size()==0)
00140         return false;
00141       line >> ltoken;
00142       makeupcase(ltoken);
00143     } while (ltoken!=token);
00144     return true;
00145   }
00146  public:
00147   // search for block in file and store in buffer
00148   BasicBlock(std::istream& in, const char* id) :
00149     pos(-1),
00150     active(false),
00151     empty(true),
00152     identifier(id),
00153     linecount(0)
00154   {
00155     makeupcase(identifier);
00156     in.clear();
00157     in.seekg(0);
00158     if (!in) {
00159       DUNE_THROW(DGFException,
00160                  "file not found in BasicBlock::BasicBlock");
00161     }
00162     getblock(in);
00163     if (active && !empty) {
00164       linecount=countlines();
00165       reset();
00166     }
00167     in.clear();
00168     in.seekg(0);
00169   }
00170   // some information on this block
00171   bool isactive() {
00172     return active;
00173   }
00174   bool isempty() {
00175     return empty;
00176   }
00177   int& noflines() {
00178     return linecount;
00179   }
00180   int linenumber() {
00181     return pos;
00182   }
00183   // for error messages
00184   friend std::ostream& operator<<(std::ostream& os, const BasicBlock &b) {
00185     return os 
00186       << "block " << b.identifier 
00187       << " on line " << b.pos << std::endl;
00188   }
00189 };
00190 // *************************************************************
00191 // derived classes for each block in grid file
00192 // *************************************************************
00193 class VertexBlock : public BasicBlock {
00194   int dimworld;          // the dimesnsion of the vertices (is given from user)
00195   bool goodline;         // active line describes a vertex
00196   std::vector<double> p; // active vertex
00197   int vtxoffset;
00198   int nofParam;
00199   std::vector<double> vtxparam;
00200  public:
00201   static const char* ID;
00202   // initialize vertex block and get first vertex
00203   VertexBlock(std::istream& in,int &pdimworld) :
00204     BasicBlock(in,ID),
00205     dimworld(pdimworld),
00206     goodline(true),
00207     p(0),
00208     vtxoffset(0),
00209     nofParam(0),
00210     vtxparam(0)
00211   {
00212     if (!isactive())
00213       return;
00214     if (dimworld<0) 
00215       dimworld=0;
00216     { 
00217       int x;
00218       if (findtoken("firstindex")) {
00219         if (getnextentry(x)) {
00220           vtxoffset=x;
00221         }
00222       }
00223     }
00224     { 
00225       int x;
00226       if (findtoken("parameters")) {
00227         if (getnextentry(x)) {
00228           nofParam=x;
00229           vtxparam.resize(nofParam);
00230         }
00231       }
00232     }
00233     dimworld=getDimW();
00234     if (dimworld>0) {
00235       p.resize(dimworld);
00236     } else {
00237       DUNE_THROW(DGFException,
00238                  "ERROR in " << *this
00239                  << "      no line with enough entries found");
00240     }
00241     reset();
00242     next();
00243     pdimworld=dimworld;
00244   }
00245   ~VertexBlock() {
00246   }
00247   int offset() {
00248     return vtxoffset;
00249   }
00250   int get(std::vector<std::vector<double> >& vtx,
00251           std::vector<std::vector<double> >& param,int& nofp) {
00252     nofp=nofParam;
00253     size_t nofvtx;
00254     size_t old_size = vtx.size();
00255     // vtx.resize(old_size+nofvertex());
00256     for (nofvtx=old_size;ok();next(),nofvtx++) {
00257       vtx.push_back(p);
00258       if (nofParam>0)
00259         param.push_back(vtxparam);
00260     }
00261     return nofvtx;
00262   }
00263   // some information
00264   bool ok() {
00265     return goodline;
00266   }
00267  private:
00268   // get dimworld
00269   int getDimW() {
00270     reset();
00271     int dimworld=0;
00272     getnextline();
00273     while (dimworld<1 && linenumber()<noflines()) {
00274       dimworld = 0;
00275       double x;
00276       while (getnextentry(x)) {
00277         dimworld++;
00278       }
00279       dimworld-=nofParam;
00280       getnextline();
00281     }
00282     return dimworld;
00283   }
00284   // get next vertex
00285   bool next() {
00286     assert(ok());
00287     int n=0;
00288     getnextline();
00289     if (linenumber()==noflines()) {
00290       goodline=false;
00291       return goodline;
00292     }
00293     double x;
00294     while (getnextentry(x)){
00295       if (n<dimworld) 
00296         p[n]=x;
00297       else if (n-dimworld<nofParam) {
00298         vtxparam[n-dimworld]=x;
00299       }
00300       n++;
00301     }
00302     if (n>0 && n!=dimworld+nofParam) {
00303       return next();
00304       /*
00305       DUNE_THROW(DGFException,
00306                  "ERROR in " << *this
00307                  << "      wrong number of coordinates and parameters: "
00308                  << n << " read but expected " << dimworld+nofParam);
00309       */
00310     }
00311     if (n==0) {
00312       return next();
00313     }
00314     goodline=true;
00315     if (!goodline) {
00316       DUNE_THROW(DGFException,
00317                  "ERROR in " << *this
00318                  << "      wrong number of coordinates: "
00319                  << n << " read but expected " << dimworld);
00320     }
00321     return goodline;
00322   }
00323   // get coordinates of active vertex
00324   double operator[](int i) {
00325     assert(ok());
00326     assert(linenumber()>=0);
00327     assert(0<=i && i<dimworld);
00328     return p[i];
00329   }
00330 };
00331 const char *VertexBlock::ID = "Vertex";
00332 // *************************************************************
00333 class SimplexGenerationBlock : public BasicBlock {
00334   double area_;
00335   double angle_;
00336   bool display_;
00337   std::string path_;
00338   bool haspath_;
00339   std::string filename_;
00340   std::string filetype_;
00341   std::string parameter_;
00342   bool hasfile_;
00343   int dimension_;
00344  public:
00345   const static char* ID;
00346   SimplexGenerationBlock(std::istream& in) :
00347     BasicBlock(in,ID),
00348     area_(-1),
00349     angle_(-1),
00350     display_(false),
00351     haspath_(false),
00352     filetype_(),
00353     parameter_(),
00354     hasfile_(false),
00355     dimension_(-1)
00356   {
00357     double x;
00358     bool b;
00359     int i;
00360     std::string p;
00361     if (findtoken("max-area"))
00362       if (getnextentry(x))
00363         area_=x;
00364     if (findtoken("min-angle"))
00365       if (getnextentry(x))
00366         angle_=x;
00367     if (findtoken("display")) 
00368       if (getnextentry(b))
00369         display_=b;
00370     if (findtoken("path")) 
00371       if (getnextentry(p)) {
00372         path_=p;
00373         haspath_=true;
00374       }
00375     if (findtoken("file")) {
00376       if (getnextentry(p)) {
00377         filename_=p;
00378         hasfile_=true;
00379       }
00380       if (getnextentry(p)) {
00381         filetype_=p;
00382       }
00383       if (findtoken("dimension"))
00384         if (getnextentry(i)) {
00385           dimension_=i;
00386         }
00387       gettokenparam("parameter",parameter_);
00388     }
00389   }
00390   double maxArea() {
00391     return area_;
00392   }
00393   double minAngle() {
00394     return angle_;
00395   }
00396   bool display() {
00397     return display_;
00398   }
00399   bool haspath() {
00400     return haspath_;
00401   }
00402   std::string path() {
00403     return path_;
00404   }
00405   bool hasfile() {
00406     return hasfile_;
00407   }
00408   std::string filename() {
00409     return filename_;
00410   }
00411   std::string filetype() {
00412     return filetype_;
00413   }
00414   int dimension() {
00415     return dimension_;
00416   }
00417   std::string parameter() {
00418     return parameter_;
00419   }
00420 };
00421 const char* SimplexGenerationBlock::ID = "Simplexgenerator";
00422 // *************************************************************
00423 class SimplexBlock : public BasicBlock {
00424   int nofvtx;        
00425   int vtxoffset;
00426   int dimworld;  
00427   bool goodline;      // active line describes a vertex
00428   std::vector<int> p; // active vertex
00429   int nofparams;      // nof parameters
00430   std::vector<double> psimpl; // active parameters
00431 public:
00432   const static char* ID;
00433   SimplexBlock(std::istream& in,int pnofvtx, int pvtxoffset, int adimworld) :
00434     BasicBlock(in,ID),
00435     nofvtx(pnofvtx),
00436     vtxoffset(pvtxoffset),
00437     dimworld(adimworld),
00438     goodline(true),
00439     p(adimworld+1),
00440     nofparams(0),
00441     psimpl(0)
00442   {
00443     if (!isactive()) return;
00444     assert((dimworld+1)>0);
00445     if (findtoken("parameters")) {
00446       int x=0;
00447       if (getnextentry(x)) {
00448         if (x>0) {
00449           nofparams = x;
00450           psimpl.resize(nofparams);
00451         }
00452       }
00453       if (x<=0) {
00454         DUNE_THROW(DGFException,
00455                    "ERROR in " << *this
00456                    << "      parameter key found with no or non-positive value "
00457                    << x);
00458       }
00459     }
00460     reset();
00461     next();
00462   }
00463   ~SimplexBlock() {
00464   }
00465   int get(std::vector<std::vector<int> >& simplex,
00466           std::vector<std::vector<double> >&params,int& nofp) {
00467     nofp=nofparams;
00468     int nofsimpl;
00469     for (nofsimpl=0; ok(); next(), nofsimpl++) {
00470       simplex.push_back(p); 
00471       for (size_t j=0;j<p.size();j++) {
00472         simplex[nofsimpl][j] = p[j];
00473       }
00474       if (nofparams>0) {
00475         params.push_back(psimpl);
00476       }
00477     }
00478     /*
00479     // make numbering starting from zero 
00480     // not matter whether offset is positive or negative 
00481     offset = vtxoffset;
00482     if(offset != 0) {
00483       for (int i=0; i<nofsimpl; ++i) {
00484         for (size_t j=0;j<simplex[i].size();++j) {
00485           simplex[i][j] -= offset; 
00486         }
00487       }
00488     }
00489     */
00490     return nofsimpl;
00491   }
00492   // cubes -> simplex
00493   static int cube2simplex(std::vector<std::vector<double> >& vtx,
00494                           std::vector<std::vector<int> >& elements,
00495                           std::vector<std::vector<double> >& params) {
00496     static int offset3[6][4][3] = {{{0,0,0},{1,1,1},{1,0,0},{1,1,0}},
00497                                    {{0,0,0},{1,1,1},{1,0,1},{1,0,0}},
00498                                    {{0,0,0},{1,1,1},{0,0,1},{1,0,1}},
00499                                    {{0,0,0},{1,1,1},{1,1,0},{0,1,0}},
00500                                    {{0,0,0},{1,1,1},{0,1,0},{0,1,1}},
00501                                    {{0,0,0},{1,1,1},{0,1,1},{0,0,1}} };
00502     static int offset2[2][3][2] = {{{0,0},{1,0},{0,1}},
00503                                    {{1,1},{0,1},{1,0}}};
00504     if (vtx.size()==0)
00505       DUNE_THROW(DGFException, "Converting Cune- to Simplexgrid with no vertices given");
00506     int dimworld = vtx[0].size();
00507     dverb << "generating simplices...";
00508     dverb.flush();
00509     std::vector<std::vector<int> > cubes = elements;
00510     std::vector<std::vector<double> > cubeparams = params;
00511     if(dimworld == 3) {
00512       elements.resize(6*cubes.size()); 
00513       if (cubeparams.size()>0)
00514         params.resize(6*cubes.size());
00515       for(size_t countsimpl=0;countsimpl < elements.size(); countsimpl++) 
00516         elements[countsimpl].resize(4);
00517       for (size_t c=0;c<cubes.size();c++)  {
00518         for(int tetra=0; tetra < 6 ; tetra++) {
00519           for (int v=0;v<4;v++) {
00520             elements[c*6+tetra][v]=
00521               cubes[c][offset3[tetra][v][0]+
00522                        offset3[tetra][v][1]*2+
00523                        offset3[tetra][v][2]*4];
00524           }
00525           if (cubeparams.size()>0)
00526             params[c*6+tetra] = cubeparams[c];
00527         }
00528       }
00529     }
00530     else {
00531       elements.resize(2*cubes.size() ); 
00532       if (cubeparams.size()>0)
00533         params.resize(2*cubes.size());
00534       for(size_t countsimpl=0;countsimpl < elements.size(); countsimpl++)
00535         elements[countsimpl].resize(3);
00536       for (size_t c=0;c<cubes.size();c++) {
00537         int diag = 0;
00538         double mind = 0;
00539         for (int d=0;d<2;d++) {
00540           double diaglen = 
00541             pow(vtx[cubes[c][d]][0]-vtx[cubes[c][2+((d+1)%2)]][0],2) +
00542             pow(vtx[cubes[c][d]][1]-vtx[cubes[c][2+((d+1)%2)]][1],2);
00543           if (diaglen<mind) {
00544             mind=diaglen;
00545             diag = d;
00546           }
00547         }
00548         
00549         if (diag == 0) {
00550           int tmp0 = cubes[c][0];
00551           cubes[c][0] = cubes[c][1];
00552           cubes[c][1] = cubes[c][3];
00553           cubes[c][3] = cubes[c][2];
00554           cubes[c][2] = tmp0;
00555         }
00556         for(int tetra=0; tetra < 2 ; tetra++) {
00557           for (int v=0;v<3;v++) {
00558             elements[c*2+tetra][v]=
00559               cubes[c][offset2[tetra][v][0]+
00560                        offset2[tetra][v][1]*2];
00561           }
00562           if (cubeparams.size()>0)
00563             params[c*2+tetra] = cubeparams[c];
00564         }
00565       }
00566     }
00567     return elements.size();
00568   }
00569   // some information
00570   bool ok() {
00571     return goodline;
00572   }
00573   int nofsimplex() {
00574     return noflines();
00575   }
00576 private:
00577   // get next simplex
00578   bool next() {
00579     assert(ok());
00580     int n=0;
00581     getnextline();
00582     if (linenumber()==noflines()) {
00583       goodline=false;
00584       return goodline;
00585     }
00586     double x;
00587     while (getnextentry(x)){
00588       if (n<(int)p.size()) { 
00589         p[n]=int(x)-vtxoffset;
00590         if (p[n]<0 || p[n]>=nofvtx) {
00591           DUNE_THROW(DGFException,
00592                      "ERROR in " << *this
00593                      << "      wrong index of vertices: "
00594                      << x << " read but expected value between "
00595                      << vtxoffset << " and "
00596                      << nofvtx+vtxoffset);
00597         }
00598       } 
00599       else if (n-int(p.size())<nofparams) {
00600         psimpl[n-p.size()]=x;
00601       }
00602       n++;
00603     }
00604     // tests if the written block is ok in its size
00605     if (n!=(int)p.size()+nofparams) {
00606       return next();
00607     }
00608     // tests if the written block is ok in its size
00609     goodline=(n==(int)p.size()+nofparams);
00610     return goodline;
00611   }
00612   // get coordinates of active simplex
00613   int operator[](int i) {
00614     assert(ok());
00615     assert(linenumber()>=0);
00616     assert(0<=i && i<(dimworld+1));
00617     return p[i];
00618   }
00619 };
00620 const char* SimplexBlock::ID = "Simplex";
00622 class CubeBlock : public BasicBlock {
00623   int nofvtx;        
00624   int dimworld;  
00625   bool goodline;        // active line describes a vertex
00626   std::vector<int> p;   // active vertex
00627   std::vector<int> map; // active vertex
00628   int nofparams;
00629   int vtxoffset;
00630   std::vector<double> psimpl; // active parameters
00631  public:
00632   static const char* ID;
00633   CubeBlock(std::istream& in,int pnofvtx, int pvtxoffset, int adimworld) :
00634     BasicBlock(in,ID),
00635     nofvtx(pnofvtx),
00636     dimworld(adimworld),
00637     goodline(true),
00638     p(0),
00639     map(0),
00640     nofparams(0),
00641     vtxoffset(pvtxoffset),
00642     psimpl(0)
00643   {
00644     if (!isactive()) return;
00645     assert((dimworld+1)>0);
00646     p.resize(1<<dimworld);
00647     map.resize(1<<dimworld);
00648     int x;
00649     if (findtoken("map")) {
00650       for (size_t i=0;i<map.size();i++) {
00651         if (getnextentry(x)) {
00652           map[i]=x;
00653         } else {
00654           DUNE_THROW(DGFException,
00655                      "ERROR in " << *this
00656                      << "      reference maping not complete "
00657                      << i
00658                      << " entries read but expected " 
00659                      << map.size());
00660         }
00661       }
00662     } else {
00663       for (size_t i=0;i<map.size();i++) {
00664         map[i]=i;
00665       }
00666     }
00667     if (findtoken("parameters")) {
00668       int x=0;
00669       if (getnextentry(x)) {
00670         if (x>0) {
00671           nofparams = x;
00672           psimpl.resize(nofparams);
00673         }
00674       }
00675       if (x<=0){
00676         DUNE_THROW(DGFException,
00677                    "ERROR in " << *this
00678                    << "      parameter key found with no or non-positive value "
00679                    << x);
00680       }
00681     }
00682     reset();
00683     next();
00684   }
00685   ~CubeBlock() {
00686   }
00687   int get(std::vector<std::vector<int> >& simplex,
00688           std::vector<std::vector<double> >&params,int& nofp) {
00689     nofp=nofparams;
00690     int nofsimpl;
00691     // simplex.resize(nofsimplex());
00692     for (nofsimpl=0; ok(); next(), nofsimpl++) {
00693       simplex.push_back(p); 
00694       for (size_t j=0;j<p.size();j++) {
00695         simplex[nofsimpl][map[j]] = p[j];
00696       }
00697       if (nofparams>0) {
00698         params.push_back(psimpl);
00699       }
00700     }
00701     /*
00702     int offset = vtxoffset;
00703     if(offset != 0) 
00704     {
00705       for (int i=0; i<nofsimpl; ++i) 
00706       {
00707         for (size_t j=0;j<simplex[i].size();++j) 
00708         {
00709           simplex[i][j] -= offset; 
00710         }
00711       }
00712     }
00713     */
00714     return nofsimpl;
00715   }
00716   // some information
00717   bool ok() {
00718     return goodline;
00719   }
00720   int nofsimplex() {
00721     return noflines();
00722   }
00723  private:
00724   // get next simplex
00725   bool next() {
00726     assert(ok());
00727     int n=0;
00728     getnextline();
00729     if (linenumber()==noflines()) {
00730       goodline=false;
00731       return goodline;
00732     }
00733     double x;
00734     while (getnextentry(x))
00735     {
00736       if (n<(int)p.size())
00737       { 
00738         p[n]=int(x)-vtxoffset;
00739         if (p[n]<0 || p[n]>=nofvtx)
00740         {
00741           DUNE_THROW(DGFException,
00742                      "ERROR in " << *this
00743                      << "      wrong index of vertices: "
00744                      << x << " read but expected value between "
00745                      << vtxoffset << " and "
00746                      << nofvtx+vtxoffset);
00747         }
00748       } else if (n-int(p.size())<nofparams) {
00749         psimpl[n-p.size()]=x;
00750       }
00751       n++;
00752     }
00753     // tests if the written block is ok in its size
00754     if (n!=(int)p.size()+nofparams) {
00755       return next();
00756     }
00757     goodline=(n==(int)p.size()+nofparams);
00758     return goodline;
00759   }
00760   // get coordinates of active simplex
00761   int operator[](int i) {
00762     assert(ok());
00763     assert(linenumber()>=0);
00764     assert(0<=i && i< (int)p.size());
00765     return p[i];
00766   }
00767 };
00768 const char* CubeBlock::ID = "Cube";
00769 // *************************************************************
00770 // the block BoundaryDomBlock looks for a domain which is characterized by two points in R^dimworld
00771 class BoundaryDomBlock : public BasicBlock {
00772   int dimworld;        // the dimesnsion of the vertices (is given  from user)
00773   bool goodline;       // active line describes a vertex
00774   std::vector<double> p1,p2;    // active vertex
00775   int bndid;
00776   bool withdefault;
00777   int defaultvalue;
00778  public:
00779   static const char* ID;
00780   // initialize vertex block and get first vertex
00781   BoundaryDomBlock(std::istream& in,int cdimworld ) :
00782     BasicBlock(in,ID),
00783     dimworld(cdimworld),
00784     goodline(true),
00785     p1(cdimworld),
00786     p2(cdimworld),
00787     bndid(0),
00788     withdefault(false),
00789     defaultvalue(0)
00790   {
00791     if (!isactive())
00792       return;
00793     assert(cdimworld>0);
00794     { 
00795       int x;
00796       if (findtoken("default"))
00797       {
00798         if (getnextentry(x)) 
00799         {
00800           if( x <= 0 )
00801           {
00802             DUNE_THROW(DGFException,
00803                            "ERROR in " << *this
00804                           << "      non-positive boundary id (" << x << ") read!");
00805           }
00806           defaultvalue=x;
00807           withdefault = true;
00808               }
00809       }
00810     }
00811     reset();
00812     next();
00813   }
00814   ~BoundaryDomBlock() {
00815   }
00816   bool next() {
00817     assert(ok());
00818     getnextline();
00819     if (linenumber()==noflines()) {
00820       goodline=false;
00821       return goodline;
00822     }
00823     int id;
00824     if (getnextentry(id)) 
00825     {
00826       if( id <= 0 )
00827       {
00828         DUNE_THROW(DGFException,
00829                       "ERROR in " << *this
00830                     << "      non-positive boundary id (" << id << ") read!");
00831       }
00832       bndid = id;
00833       double x;
00834       int n=0;
00835       while (getnextentry(x))
00836       {
00837         if (0<=n && n<dimworld) 
00838           p1.at(n)=x;
00839         else if (dimworld<=n && n<2*dimworld) 
00840         {
00841           p2.at(n-dimworld)=x;
00842           if (p2.at(n-dimworld)<p1.at(n-dimworld)) 
00843         {
00844             DUNE_THROW(DGFException,
00845                    "ERROR in " << *this
00846                    << "      second coordinate smaller than first coordinate: "
00847                    << p2.at(n-dimworld) 
00848                    << " read but expected value larger or equal to " 
00849                    << p1.at(n-dimworld));
00850               }
00851             }
00852             n++;
00853     }
00854 
00855     goodline=(n==dimworld*2);
00856     if (!goodline) 
00857     {
00858       DUNE_THROW(DGFException,
00859                    "ERROR in " << *this
00860                    << "      wrong number of coordinates: "
00861                    << n << " read but expected " << dimworld);
00862       }
00863     }
00864     else 
00865       next();
00866     return goodline;
00867   }
00868   bool inside(const std::vector<double>& v) const {
00869     assert(v.size()==(size_t)dimworld);
00870     for (int i=0;i<dimworld;i++) 
00871       if (v[i]<p1[i] || v[i]>p2[i]) 
00872         return false;
00873     return true;
00874   }
00875   int id() const {
00876     return bndid;
00877   }
00878   bool defaultValueGiven() {
00879     return withdefault;
00880   }
00881   int defaultValue() {
00882     return defaultvalue;
00883   }
00884   // some information
00885   bool ok() {
00886     return goodline;
00887   }
00888   int nofdombound() {
00889     return noflines();
00890   }
00891     
00892 };
00893 const char *BoundaryDomBlock::ID = "boundarydomain";
00894 // *************************************************************
00895 // the BoundarySegBlock looks for given boundary values unless they aren't given they got the value zero 
00896 class BoundarySegBlock : public BasicBlock {
00897   int dimworld;          // the dimesnsion of the vertices (is given  from user)
00898   bool goodline;         // active line describes a vertex
00899   std::vector<int> p; // active vertex
00900   int bndid;
00901   bool simplexgrid;
00902  public:
00903   static const char* ID;
00904   // initialize vertex block and get first vertex
00905   BoundarySegBlock(std::istream& in,int pnofvtx, 
00906                    int pdimworld,bool psimplexgrid ) :
00907     BasicBlock(in,ID),
00908     dimworld(pdimworld),
00909     goodline(true),
00910     p(),
00911     bndid(-1),
00912     simplexgrid(psimplexgrid)
00913   {
00914     if (!isactive())
00915       return;
00916     assert(dimworld>0);
00917     next();
00918   }
00919 
00920   ~BoundarySegBlock() {
00921   }
00922 
00923   // some information
00924   int get(std::map<DGFEntityKey<int>,int>& facemap,bool fixedsize,int vtxoffset) {
00925     static int cube2simplex[3][3] = { 
00926       {0,1,3},
00927       {0,2,3},
00928       {1,2,3} 
00929     };
00930 
00931     int lnofbound;
00932     int face = ElementFaceUtil::faceSize(dimworld,simplexgrid);
00933     for (lnofbound=0; ok(); next()) 
00934     {
00935       for (size_t i=0;i<p.size();i++) 
00936       {
00937         p[i] -= vtxoffset;
00938       }
00939       if (fixedsize) 
00940       {
00941               if ((dimworld==2 && size()< 2) ||
00942                   (dimworld==3 && simplexgrid && size()!=3 && size()!=4) ||
00943                 (dimworld==3 && !simplexgrid && size()!=4)) 
00944               continue;
00945         std::vector<int> bound(face);
00946         for (int j=0;j<face;j++) {
00947           bound[j] = p[j];
00948         }
00949 
00950         DGFEntityKey<int> key(bound,false); 
00951 
00952               facemap[key] = bndid;
00953               ++lnofbound;
00954         
00955         if (size()>face) 
00956         {
00957           assert(dimworld==2 || face==3);
00958             if (dimworld==3) {
00959                 for (int i=0; i<3;i++) 
00960           {
00961                   for (int j=0;j<face;j++) 
00962             {
00963                     bound[j] = p[cube2simplex[i][j]];
00964                   }
00965             
00966                   DGFEntityKey<int> key(bound,false); 
00967                   facemap[key] = bndid;
00968                   ++lnofbound;
00969                 }
00970               } 
00971         else 
00972         {
00973                 for (int i=2; i<=size();i++) 
00974           {
00975                   bound[0] = p[i-1];
00976                   bound[1] = p[i%size()];
00977                   DGFEntityKey<int> key(bound,false); 
00978                   facemap[key] = bndid;
00979                   ++lnofbound;
00980                 }
00981               }
00982             }
00983     }
00984     else {
00985         if (dimworld==3) {
00986           DGFEntityKey<int> key(p,false); 
00987           facemap[key] = bndid;
00988           ++lnofbound;
00989         } else {
00990           std::vector<int> k(2);
00991           for (size_t i=0;i<p.size()-1;i++) {
00992             k[0]=p[i];
00993             k[1]=p[(i+1)%p.size()];
00994             DGFEntityKey<int> key(k,false); 
00995             facemap[key] = bndid;
00996             ++lnofbound;
00997           }
00998         }
00999       }
01000     }
01001     return lnofbound;
01002   }
01003   bool ok() {
01004     return goodline;
01005   }
01006   int nofbound() {
01007     return noflines();
01008   }
01009   private:
01010   bool next() {
01011     assert(ok());
01012     int n=0;
01013     getnextline();
01014     if (linenumber()==noflines()) {
01015       goodline=false;
01016       return goodline;
01017     }
01018     p.clear();
01019     int x;
01020     if (getnextentry(x)) {
01021       bndid = x;
01022       if (bndid<=0) 
01023       {
01024         DUNE_THROW(DGFException,
01025                        "ERROR in " << *this
01026                       << "      non-positive boundary id (" << bndid << ") read!");
01027       }
01028       while (getnextentry(x))
01029       {
01030         p.push_back(x);
01031               n++;
01032       }
01033       // goodline=(n==dimworld+1);
01034       goodline=true;
01035       return goodline;
01036     } else return next();
01037   }
01038   // get coordinates of active vertex
01039   int operator[](int i) {
01040     assert(ok());
01041     assert(linenumber()>=0);
01042     assert(0<=i && i<dimworld+1);
01043     return p[i];
01044   }
01045   int size() {
01046     return p.size();
01047   }
01048 };
01049 const char *BoundarySegBlock::ID = "boundarysegments";
01050 // *************************************************************
01051 class DimBlock : public BasicBlock {
01052   int _dimworld;     // dimension of world
01053   int _dim;          // dimension of grid
01054  public:
01055   const static char* ID;
01056   // initialize block and get dimension of world
01057   DimBlock(std::istream& in) :
01058   BasicBlock(in,ID)
01059   {
01060     if (isempty()) {
01061       DUNE_THROW(DGFException,
01062                  "no dimension of world specified!");
01063     } else {
01064       getnextline();
01065       line >> _dim;
01066       if (_dim<1) {
01067         DUNE_THROW(DGFException,
01068                    "negative dimension of world specified!");
01069       }
01070       else {
01071         if (noflines()==1)
01072           _dimworld=_dim;
01073         else {
01074           getnextline();
01075           line >> _dimworld;
01076           if (_dimworld < _dim) {
01077             DUNE_THROW(DGFException,
01078                        "negative dimension of world smaller than dim!");
01079           }
01080         }
01081       }
01082     }
01083   }
01084   // get dimension of world found in block
01085   int dim() {
01086     return _dim;
01087   }
01088   int dimworld() {
01089     return _dimworld;
01090   }
01091   // some information 
01092   bool ok() {
01093     return true;
01094   }
01095 };
01096 const char* DimBlock::ID = "Dimensions";
01097 
01098 // *************************************************************
01099 class GridParameterBlock : public BasicBlock 
01100 {
01101  protected:  
01102   std::set<int> _periodic; // periodic grid 
01103   int _overlap;     // overlap for YaspGrid
01104   bool _noClosure;  // no closure for UGGrid 
01105  private:
01106   // copy not implemented
01107   GridParameterBlock(const GridParameterBlock&);
01108  public:
01109   const static char* ID;
01110   // initialize block and get dimension of world
01111   GridParameterBlock(std::istream& in, 
01112                      const bool readOverlapAndBnd)
01113     : BasicBlock(in,ID) 
01114     , _periodic()
01115     , _overlap(0) // default value
01116     , _noClosure(false) // default value 
01117   {
01118     if (! isempty() ) 
01119     {
01120       if( readOverlapAndBnd  )
01121       {
01122         // check overlap 
01123         if (findtoken("overlap"))
01124         {
01125           int x;
01126           if( getnextentry(x) ) _overlap = x;
01127           else 
01128           {
01129             dwarn << "GridParameterBlock: found keyword `overlap' but no value, defaulting to `" <<  _overlap  <<"' !\n";
01130           }
01131 
01132           if (_overlap < 0) 
01133           {
01134             DUNE_THROW(DGFException,"Negative overlap specified!");
01135           }
01136         }
01137         else 
01138         {
01139           dwarn << "GridParameterBlock: could not find keyword `overlap' in DGF file, defaulting to `"<<_overlap<<"' !\n";
01140         }
01141         
01142         // check periodic grid 
01143         if (findtoken("periodic"))
01144         {
01145           int x;
01146           while (getnextentry(x)) 
01147           {
01148             _periodic.insert(x);
01149           }
01150         }
01151         else 
01152         {
01153           dwarn << "GridParameterBlock: could not find keyword `periodic' in DGF file, defaulting to no periodic boundary! \n";
01154         }
01155       }
01156       else 
01157       {
01158         // check closure 
01159         if (findtoken("closure"))
01160         {
01161           std::string clo;
01162           if(getnextentry(clo)) 
01163           {
01164             makeupcase(clo);
01165             if(clo == "NONE")
01166             {
01167               _noClosure = true; 
01168             }
01169           }
01170         }
01171         else 
01172         {
01173           dwarn << "GridParameterBlock: could not find keyword `closure' in DGF file, defaulting to `GREEN' !\n";
01174         }
01175       }
01176     }
01177   }
01178   
01179   // get dimension of world found in block
01180   int overlap() const { return _overlap;  }
01181 
01182   // returns true if no closure should be used for UGGrid 
01183   bool noClosure() const { return _noClosure; }
01184 
01185   // returns true if dimension is periodic 
01186   bool isPeriodic(const int dim) const 
01187   {
01188     return (_periodic.find(dim) != _periodic.end());
01189   }
01190   
01191   // some information 
01192   bool ok() 
01193   {
01194     return true;
01195   }
01196 };
01197 const char* GridParameterBlock::ID = "GridParameter";
01198 
01199 // *************************************************************
01200 class IntervalBlock : public BasicBlock {
01201   std::vector<double> p0_,p1_;     //lower and upper boundary points
01202   std::vector<double> h_;          // width of the cells in every direction 
01203   std::vector<int> nofcells_;      // number of cells in every direction
01204   bool good_;                      //data read correctly
01205   int dimw_;                       //dimension of world
01206  public:
01207   const static char* ID;
01208   IntervalBlock(std::istream& in) :
01209     BasicBlock(in,ID),
01210     p0_(0),
01211     p1_(0),
01212     h_(0),
01213     nofcells_(0),
01214     good_(false),
01215     dimw_(0)
01216   {
01217     if(isactive()) {
01218       getnextline();
01219       double x;
01220       while (getnextentry(x)) {
01221               dimw_++;
01222       }
01223       if (dimw_==0) {
01224               DUNE_THROW(DGFException,
01225                     "Too few coordinates for point p0 in IntervalBlock");
01226       } else if (dimw_>3) {
01227               DUNE_THROW(DGFException,
01228                     "Interval block only implemented for dimension 1,2, and 3");
01229       }
01230       p0_.resize(dimw_);
01231       p1_.resize(dimw_);
01232       h_.resize(dimw_);
01233       nofcells_.resize(dimw_);
01234       reset();
01235       next();
01236     }
01237   }
01238   void get(std::vector<std::vector<double> >& vtx,int& nofvtx,
01239            std::vector<std::vector<int> >& simplex,int& nofsimpl) {
01240     do {
01241       int oldvtx = nofvtx;
01242       nofvtx  +=getVtx(vtx);
01243       nofsimpl+=getHexa(simplex,oldvtx);
01244     } while (next());
01245   }
01246   void get(std::vector<std::vector<double> >& vtx,int& nofvtx) {
01247     do {
01248       // int oldvtx = nofvtx;
01249       nofvtx  +=getVtx(vtx);
01250     } while (next());
01251   }
01252   int getVtx(std::vector<std::vector<double> >& vtx) {
01253     size_t countvtx;
01254     size_t old_size = vtx.size();
01255     //fill vtx 
01256     dverb << "reading vertices..."; 
01257     vtx.resize(vtx.size()+nofvtx());
01258     for (countvtx=old_size;countvtx < vtx.size(); countvtx++)
01259       vtx[countvtx].resize(dimw_);
01260     int m = old_size;
01261     if(dimw_ == 3) {
01262             for(int k=0; k < nofcells_[2]+1; k++)  // z-dir 
01263               for(int j=0; j < nofcells_[1]+1; j++) // y-dir
01264           for(int i =0; i < nofcells_[0]+1; i++) // x-dir 
01265           {
01266                   vtx[m][0] = p0_[0] + i*h_[0];
01267                   vtx[m][1] = p0_[1] + j*h_[1];
01268                   vtx[m][2] = p0_[2] + k*h_[2];
01269                   m++;
01270                 }
01271     }
01272     else if (dimw_==2) 
01273     {
01274             for(int j=0; j < nofcells_[1]+1; j++) 
01275         for(int i =0; i < nofcells_[0]+1; i++)
01276         {
01277                 vtx[m][0] = p0_[0] + i*h_[0];
01278                 vtx[m][1] = p0_[1] + j*h_[1];
01279                 m++;
01280               }
01281     } else {
01282             for(int j=0; j < nofcells_[0]+1; j++) {
01283               vtx[m][0] = p0_[0] + j*h_[0];
01284               m++;
01285             }
01286     }
01287     dverb << "done" << std::endl;
01288     return  nofvtx();
01289   }
01290   int getHexa(std::vector<std::vector<int> >& simplex,
01291               int offset=0) {
01292     int oldsize=simplex.size();
01293     //fill simplex with Hexaeder
01294     size_t counthexa;
01295     int verticesPerCube = -1;
01296     int m=oldsize;  
01297     if(dimw_ == 3)
01298       verticesPerCube = 8;
01299     else if (dimw_ == 2)
01300       verticesPerCube = 4;
01301     else if (dimw_ == 1)
01302       verticesPerCube = 2;
01303     else 
01304             DUNE_THROW(DGFException,
01305                              "Invalid dimension world "<< dimw_ << " in IntervalBlock::getHexa!");
01306 
01307     dverb << "generating hexaeder...";
01308     simplex.resize(oldsize+nofhexa());
01309     for (counthexa=m;counthexa < simplex.size();counthexa++)
01310       simplex[counthexa].resize(verticesPerCube);
01311       if(dimw_ == 3) {
01312               for(int k=0; k < nofcells_[2]; k++) 
01313                 for(int j=0; j < nofcells_[1]; j++)
01314             for(int i =0; i < nofcells_[0]; i++)
01315             {
01316                     simplex[m][0] = offset+getIndex(i,j,k);
01317                     simplex[m][1] = offset+getIndex(i+1,j,k);
01318                     simplex[m][2] = offset+getIndex(i,j+1,k);
01319                     simplex[m][3] = offset+getIndex(i+1,j+1,k);
01320                     simplex[m][4] = offset+getIndex(i,j,k+1);
01321                     simplex[m][5] = offset+getIndex(i+1,j,k+1);
01322                     simplex[m][6] = offset+getIndex(i,j+1,k+1);
01323                     simplex[m][7] = offset+getIndex(i+1,j+1,k+1);
01324                     m++;
01325                   }
01326     }
01327     else if (dimw_==2) 
01328     {
01329             for(int j=0; j < nofcells_[1]; j++) 
01330       {
01331         for(int i =0; i < nofcells_[0]; i++)
01332         {
01333                 simplex[m][0] = offset+getIndex(i,j);
01334                 simplex[m][1] = offset+getIndex(i+1,j);
01335                 simplex[m][2] = offset+getIndex(i,j+1);
01336                 simplex[m][3] = offset+getIndex(i+1,j+1);
01337                 m++;
01338               }
01339       }
01340     } 
01341     else 
01342     {
01343       for(int i =0; i < nofcells_[0]; i++) 
01344       {
01345               simplex[m][0] = offset+getIndex(i);
01346               simplex[m][1] = offset+getIndex(i+1);
01347               m++;
01348             }
01349     }
01350     dverb << "done" << std::endl;
01351     assert((size_t)m==simplex.size());
01352     return nofhexa();
01353   }
01354 
01355   int nofvtx() {
01356     if(dimw_ == 3)
01357       return (nofcells_[0]+1)*(nofcells_[1]+1)*(nofcells_[2]+1);
01358     else if (dimw_ == 2)
01359       return (nofcells_[0]+1)*(nofcells_[1]+1);
01360     else
01361       return nofcells_[0]+1;
01362   }
01363 
01364   int nofhexa() {
01365     if(dimw_ == 3)
01366       return (nofcells_[0])*(nofcells_[1])*(nofcells_[2]);
01367     else if (dimw_ == 2)
01368       return (nofcells_[0])*(nofcells_[1]);
01369     else
01370       return nofcells_[0];
01371   }
01372   int segments(int i) {
01373     return nofcells_[i];
01374   }
01375   double length(int i) {
01376     return p1_[i]-p0_[i]; 
01377   }
01378   double start(int i) {
01379     return p0_[i];
01380   }
01381   double end(int i) {
01382     return p1_[i];
01383   }
01384   /*
01385   bool ok() {
01386     return good_;
01387   }
01388   */
01389   int dimw() {
01390     return dimw_;
01391   }
01392 
01393   int getIndex(int i,int j = 0, int k = 0) 
01394   {
01395     if(dimw_ == 3)
01396       return  k*(nofcells_[1]+1)*(nofcells_[0]+1) + j*(nofcells_[0]+1) + i;
01397     else if (dimw_ == 2)
01398       return  j * (nofcells_[0]+1) + i;
01399     else 
01400       return i;
01401   }
01402  private:
01403   bool next() {
01404     if (linenumber()==noflines()-1) {
01405       good_=false;
01406       return good_;
01407     }
01408     //read p0_ 
01409     getnextline();
01410     double x;
01411     for(int i = 0;i<dimw_;i++) 
01412       if(getnextentry(x))
01413               p0_[i] = x;
01414       else  {
01415         DUNE_THROW(DGFException,
01416                    "ERROR in " << *this
01417                    << "Too few coordinates for point p0");
01418       }
01419     //read p1_
01420     getnextline();
01421     for(int i = 0;i<dimw_;i++) 
01422       if(getnextentry(x))
01423               p1_[i] = x;
01424       else  {
01425         DUNE_THROW(DGFException,
01426                    "ERROR in " << *this
01427                    << "Too few coordinates for point p1");
01428       }
01429     
01430     //find real upper and lower edge
01431     std::vector<double> p0h(dimw_),p1h(dimw_);  //help variables
01432     for(int i = 0; i<dimw_;i++) {
01433       p0h[i] = p0_[i] < p1_[i] ? p0_[i] : p1_[i];
01434       p1h[i] = p0_[i] > p1_[i] ? p0_[i] : p1_[i];       
01435     }
01436     p0_ = p0h;
01437     p1_ = p1h;
01438     //get numbers of cells for every direction
01439     getnextline();
01440     int number;
01441     for(int i = 0;i<dimw_;i++) 
01442       if(getnextentry(number))
01443               nofcells_[i] = number;
01444       else {
01445         DUNE_THROW(DGFException,
01446                    "ERROR in " << *this            
01447                    << "Couldn't detect a number of cells for every direction");
01448       }
01449     good_ = true;
01450     for(int i =0; i < dimw_; i++)
01451       h_[i] = (p1_[i] - p0_[i])/double(nofcells_[i]);
01452     //Printing Data on screen
01453     dverb << "p0 = ("; 
01454     for(int i = 0;i<dimw_-1;i++)
01455       dverb << p0_[i]  <<",";
01456     dverb << p0_[dimw_-1] <<") \n";
01457     dverb << "p1 = ("; 
01458     for(int i = 0;i<dimw_-1;i++)
01459       dverb << p1_[i]  <<",";
01460     dverb << p1_[dimw_-1] <<") \n";             
01461     dverb << "n = ("; 
01462     for(int i = 0;i<dimw_-1;i++)
01463       dverb << nofcells_[i]  <<",";
01464     dverb << nofcells_[dimw_-1] <<") \n";               
01465     dverb << std::endl;
01466     return good_;
01467   }
01468 };
01469 const char* IntervalBlock::ID = "Interval";
01470 }
01471 }
01472 #endif

Generated on 6 Nov 2008 with Doxygen (ver 1.5.6) [logfile].