dgfparserblocks.hh

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

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)