00001 #ifndef DUNE_MACROGRIDPARSERBLOCKS_HH
00002 #define DUNE_MACROGRIDPARSERBLOCKS_HH
00003
00004 #include <set>
00005
00006 namespace Dune {
00007
00008
00009
00010
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;
00022 bool active;
00023 bool empty;
00024 std::string identifier;
00025 int linecount;
00026 std::stringstream block;
00027 std::string oneline;
00028
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
00067 }
00068 }
00069
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;
00084
00085
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
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
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
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
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
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
00192
00193 class VertexBlock : public BasicBlock {
00194 int dimworld;
00195 bool goodline;
00196 std::vector<double> p;
00197 int vtxoffset;
00198 int nofParam;
00199 std::vector<double> vtxparam;
00200 public:
00201 static const char* ID;
00202
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
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
00264 bool ok() {
00265 return goodline;
00266 }
00267 private:
00268
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
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
00306
00307
00308
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
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;
00428 std::vector<int> p;
00429 int nofparams;
00430 std::vector<double> psimpl;
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> >¶ms,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
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 return nofsimpl;
00491 }
00492
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
00570 bool ok() {
00571 return goodline;
00572 }
00573 int nofsimplex() {
00574 return noflines();
00575 }
00576 private:
00577
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
00605 if (n!=(int)p.size()+nofparams) {
00606 return next();
00607 }
00608
00609 goodline=(n==(int)p.size()+nofparams);
00610 return goodline;
00611 }
00612
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;
00626 std::vector<int> p;
00627 std::vector<int> map;
00628 int nofparams;
00629 int vtxoffset;
00630 std::vector<double> psimpl;
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> >¶ms,int& nofp) {
00689 nofp=nofparams;
00690 int nofsimpl;
00691
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
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 return nofsimpl;
00715 }
00716
00717 bool ok() {
00718 return goodline;
00719 }
00720 int nofsimplex() {
00721 return noflines();
00722 }
00723 private:
00724
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
00754 if (n!=(int)p.size()+nofparams) {
00755 return next();
00756 }
00757 goodline=(n==(int)p.size()+nofparams);
00758 return goodline;
00759 }
00760
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
00771 class BoundaryDomBlock : public BasicBlock {
00772 int dimworld;
00773 bool goodline;
00774 std::vector<double> p1,p2;
00775 int bndid;
00776 bool withdefault;
00777 int defaultvalue;
00778 public:
00779 static const char* ID;
00780
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
00885 bool ok() {
00886 return goodline;
00887 }
00888 int nofdombound() {
00889 return noflines();
00890 }
00891
00892 };
00893 const char *BoundaryDomBlock::ID = "boundarydomain";
00894
00895
00896 class BoundarySegBlock : public BasicBlock {
00897 int dimworld;
00898 bool goodline;
00899 std::vector<int> p;
00900 int bndid;
00901 bool simplexgrid;
00902 public:
00903 static const char* ID;
00904
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
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
01034 goodline=true;
01035 return goodline;
01036 } else return next();
01037 }
01038
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;
01053 int _dim;
01054 public:
01055 const static char* ID;
01056
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
01085 int dim() {
01086 return _dim;
01087 }
01088 int dimworld() {
01089 return _dimworld;
01090 }
01091
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;
01103 int _overlap;
01104 bool _noClosure;
01105 private:
01106
01107 GridParameterBlock(const GridParameterBlock&);
01108 public:
01109 const static char* ID;
01110
01111 GridParameterBlock(std::istream& in,
01112 const bool readOverlapAndBnd)
01113 : BasicBlock(in,ID)
01114 , _periodic()
01115 , _overlap(0)
01116 , _noClosure(false)
01117 {
01118 if (! isempty() )
01119 {
01120 if( readOverlapAndBnd )
01121 {
01122
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
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
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
01180 int overlap() const { return _overlap; }
01181
01182
01183 bool noClosure() const { return _noClosure; }
01184
01185
01186 bool isPeriodic(const int dim) const
01187 {
01188 return (_periodic.find(dim) != _periodic.end());
01189 }
01190
01191
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_;
01202 std::vector<double> h_;
01203 std::vector<int> nofcells_;
01204 bool good_;
01205 int dimw_;
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
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
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++)
01263 for(int j=0; j < nofcells_[1]+1; j++)
01264 for(int i =0; i < nofcells_[0]+1; i++)
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
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
01386
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
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
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
01431 std::vector<double> p0h(dimw_),p1h(dimw_);
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
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
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