Bläddra i källkod

Fixes to code to work with elliptic problems again

iss2
Trevor Irons 8 år sedan
förälder
incheckning
d236b7e4ff

+ 1
- 0
examples/FEM4EllipticPDE_bhmag.cpp Visa fil

@@ -149,6 +149,7 @@ int main(int argc, char**argv) {
149 149
         //Solver->SetSigmaFunction(implSigma);
150 150
         Solver->SetBoundaryStep(.05);
151 151
         Solver->SetGrid(MeshReader->GetOutput());
152
+        Solver->SetupPotential();
152 153
         //Solver->SetGrid(rGrid);
153 154
         Solver->Solve(argv[3]);
154 155
 

+ 32
- 29
examples/borehole/sphere.geo Visa fil

@@ -22,7 +22,7 @@ D0 = 10;          // Top of magnet
22 22
 D1 = 11;          // Bottom of magnet
23 23
 radius = 2.25;     // Radius of the damn thing
24 24
 
25
-lc = radius*10;   //  0.25;   // Target element size
25
+lc = radius;   //  0.25;   // Target element size
26 26
 
27 27
 // Total Solution Space
28 28
 Box = 10*radius; // The down side of potential
@@ -37,6 +37,31 @@ cellSize=lc; //300;
37 37
 dd = 0 ; //  1e-5; //cellSize; // .01;
38 38
 pio2=Pi/2;
39 39
 
40
+
41
+/////////////////////////////////////
42
+// Large Bounding box
43
+pp = newp;
44
+Point(pp)    = {X0, Y0, Z0, lc};
45
+Point(pp+1)  = {X1, Y0, Z0, lc};
46
+Point(pp+2)  = {X1, Y1, Z0, lc};
47
+Point(pp+3)  = {X0, Y1, Z0, lc};
48
+
49
+
50
+lv = newl;
51
+Line(lv) = {pp,pp+1};
52
+Line(lv+1) = {pp+1,pp+2};
53
+Line(lv+2) = {pp+2,pp+3};
54
+Line(lv+3) = {pp+3,pp};
55
+Line Loop(lv+4) = {lv, lv+1, lv+2, lv+3};
56
+
57
+// Hard coded doom
58
+Plane Surface(125) = {lv+4};
59
+
60
+//v = newv;
61
+v[] = Extrude {0, 0, Z1-Z0} { Surface{125}; };
62
+
63
+
64
+
40 65
 // Calculate offset effect
41 66
 theta = Asin(dd/radius);
42 67
 rr = radius * Cos(theta);
@@ -92,28 +117,6 @@ t4[] = Rotate {{0,0,1},{0,0,0},pio2  } {Duplicata{Surface{61};}};
92 117
 t5[] = Rotate {{0,0,1},{0,0,0},pio2*2} {Duplicata{Surface{61};}};
93 118
 t6[] = Rotate {{0,0,1},{0,0,0},pio2*3} {Duplicata{Surface{61};}};
94 119
 
95
-/////////////////////////////////////
96
-// Large Bounding box
97
-pp = newp;
98
-Point(pp)    = {X0, Y0, Z0, lc};
99
-Point(pp+1)  = {X1, Y0, Z0, lc};
100
-Point(pp+2)  = {X1, Y1, Z0, lc};
101
-Point(pp+3)  = {X0, Y1, Z0, lc};
102
-
103
-
104
-lv = newl;
105
-Line(lv) = {pp,pp+1};
106
-Line(lv+1) = {pp+1,pp+2};
107
-Line(lv+2) = {pp+2,pp+3};
108
-Line(lv+3) = {pp+3,pp};
109
-Line Loop(lv+4) = {lv, lv+1, lv+2, lv+3};
110
-
111
-// Hard coded doom
112
-Plane Surface(125) = {lv+4};
113
-
114
-//v = newv;
115
-v[] = Extrude {0, 0, Z1-Z0} { Surface{125}; };
116
-
117 120
 /* This is GOOD */
118 121
 Surface{60} In Volume{v[1]};
119 122
 Surface{t1[0]} In Volume{v[1]};
@@ -128,13 +131,13 @@ Surface{t6[0]} In Volume{v[1]};
128 131
 ///////////////////////////////////////////////
129 132
 // Attractor Field
130 133
 
131
-Field[1] = Attractor;
132
-Field[1].NodesList = {p}; //0, p0+1, p0+2, p0+3, p0+4, p, p+1, p+2, p+3, p+4};
134
+//Field[1] = Attractor;
135
+//Field[1].NodesList = {p}; //0, p0+1, p0+2, p0+3, p0+4, p, p+1, p+2, p+3, p+4};
133 136
 
134
-Field[2] = MathEval;
135
-//Field[2].F = Sprintf("(.25 - F1)^2 + %g", cellSize );  // WORKS
136
-Field[2].F = Sprintf("(%g - F1)^2 + %g", radius, cellSize/2. );
137
-Background Field = 2;
137
+//Field[2] = MathEval;
138
+//Field[2].F = Sprintf("(2.25 - F1)^2 + %g", cellSize*10 );  // WORKS
139
+//Field[2].F = Sprintf("(%g - F1)^2 + %g", radius, 2*cellSize );
140
+//Background Field = 2;
138 141
 
139 142
 // Don't extend the elements sizes from the boundary inside the domain
140 143
 //Mesh.CharacteristicLengthExtendFromBoundary = 0;

+ 5
- 0
examples/borehole/sphere.sh Visa fil

@@ -1,4 +1,9 @@
1 1
 
2
+gmsh  -3 -format vtk -o sphere.vtk  sphere.geo 
3
+gmsh  -2 -format stl -o sphereBox.stl  sphereBox.geo 
4
+
5
+
6
+
2 7
 #gmsh -3 -format vtk -o sphere.vtk  sphere.geo
3 8
 #../utVTKEdgeGsphere sphere.vtk .25 magnet  sphereG.vtu
4 9
 #../utFEM4EllipticPDE_bhmag  sphereG.vtu  sphereG.vtu   sphereOut.vtu 

+ 136
- 0
examples/borehole/sphereBox.geo Visa fil

@@ -0,0 +1,136 @@
1
+/* This file is part of Lemma, a geophysical modelling and inversion API.
2
+ * More information is available at http://lemmasoftware.org
3
+ */
4
+
5
+/* This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ */
9
+
10
+D0 = 10;          // Top of magnet
11
+D1 = 11;          // Bottom of magnet
12
+radius = 2.25;     // Radius of the damn thing
13
+
14
+lc = radius;   //  0.25;   // Target element size
15
+
16
+// Total Solution Space
17
+Box = 10*radius; // The down side of potential
18
+X0 = -Box;
19
+X1 =  Box;
20
+Y0 = -Box;
21
+Y1 =  Box;
22
+Z0 = -Box;
23
+Z1 =  Box;
24
+
25
+cellSize=lc; //300;
26
+dd = 0 ; //  1e-5; //cellSize; // .01;
27
+pio2=Pi/2;
28
+
29
+
30
+/////////////////////////////////////
31
+// Large Bounding box
32
+pp = newp;
33
+Point(pp)    = {X0, Y0, Z0, lc};
34
+Point(pp+1)  = {X1, Y0, Z0, lc};
35
+Point(pp+2)  = {X1, Y1, Z0, lc};
36
+Point(pp+3)  = {X0, Y1, Z0, lc};
37
+
38
+
39
+lv = newl;
40
+Line(lv) = {pp,pp+1};
41
+Line(lv+1) = {pp+1,pp+2};
42
+Line(lv+2) = {pp+2,pp+3};
43
+Line(lv+3) = {pp+3,pp};
44
+Line Loop(lv+4) = {lv, lv+1, lv+2, lv+3};
45
+
46
+// Hard coded doom
47
+Plane Surface(125) = {lv+4};
48
+
49
+//v = newv;
50
+v[] = Extrude {0, 0, Z1-Z0} { Surface{125}; };
51
+
52
+// // Calculate offset effect
53
+// theta = Asin(dd/radius);
54
+// rr = radius * Cos(theta);
55
+//
56
+// ///////////////////////////////////
57
+// // Positive half sphere
58
+// // create inner 1/8 shell
59
+// p0 = newp;
60
+// Point(p0)   = {      0,   0,       0, cellSize}; // origin
61
+// Point(p0+1) = {    -rr,   0,      dd, cellSize};
62
+// Point(p0+2) = {      0,  rr,      dd, cellSize};
63
+// Point(p0+3) = {      0,   0,  radius, cellSize};
64
+// Point(p0+4) = {      0,   0,      dd, cellSize}; // origin
65
+//
66
+// c0 = newc;
67
+// Circle(c0  ) = {p0+1, p0+4, p0+2};       // Tricky, This one needs to be offset!
68
+// Circle(c0+1) = {p0+3, p0, p0+1};
69
+// Circle(c0+2) = {p0+3, p0, p0+2};
70
+//
71
+// Line Loop(10) = {c0, -(c0+2), c0+1} ;
72
+// Ruled Surface (60) = {10};
73
+//
74
+// ////////////////////////////////////////////////////////////
75
+// // Negative half sphere
76
+// p = newp;
77
+// Point(  p) = {      0,      0,            0, cellSize};
78
+// Point(p+1) = {    -rr,      0,          -dd, cellSize};
79
+// Point(p+2) = {      0,     rr,          -dd, cellSize};
80
+// Point(p+3) = {      0,      0,      -radius, cellSize};
81
+// Point(p+4) = {      0,      0,          -dd, cellSize};
82
+//
83
+// cc = newc;
84
+// Circle(cc  ) = {p+1, p+4, p+2};
85
+// Circle(cc+1) = {p+3, p,   p+1};
86
+// Circle(cc+2) = {p+3, p,   p+2};
87
+//
88
+// Circle(cc+3) = {p+3, p, p+2};
89
+// Circle(cc+4) = {p+3, p, p+2};
90
+// Circle(cc+5) = {p+3, p, p+2};
91
+//
92
+// ccl = newl;
93
+// Line(ccl) = { p0+3, p+3 };
94
+//
95
+// Line Loop(11) = {cc, -(cc+2), cc+1} ;
96
+// Ruled Surface (61) = {11};
97
+//
98
+// // create remaining 7/8 inner shells
99
+// t1[] = Rotate {{0,0,1},{0,0,0},pio2  } {Duplicata{Surface{60};}};
100
+// t2[] = Rotate {{0,0,1},{0,0,0},pio2*2} {Duplicata{Surface{60};}};
101
+// t3[] = Rotate {{0,0,1},{0,0,0},pio2*3} {Duplicata{Surface{60};}};
102
+// //
103
+// t4[] = Rotate {{0,0,1},{0,0,0},pio2  } {Duplicata{Surface{61};}};
104
+// t5[] = Rotate {{0,0,1},{0,0,0},pio2*2} {Duplicata{Surface{61};}};
105
+// t6[] = Rotate {{0,0,1},{0,0,0},pio2*3} {Duplicata{Surface{61};}};
106
+//
107
+// /* This is GOOD */
108
+// Surface{60} In Volume{v[1]};
109
+// Surface{t1[0]} In Volume{v[1]};
110
+// Surface{t2[0]} In Volume{v[1]};
111
+// Surface{t3[0]} In Volume{v[1]};
112
+//
113
+// Surface{61} In Volume{v[1]};
114
+// Surface{t4[0]} In Volume{v[1]};
115
+// Surface{t5[0]} In Volume{v[1]};
116
+// Surface{t6[0]} In Volume{v[1]};
117
+//
118
+// ///////////////////////////////////////////////
119
+// // Attractor Field
120
+//
121
+// //Field[1] = Attractor;
122
+// //Field[1].NodesList = {p}; //0, p0+1, p0+2, p0+3, p0+4, p, p+1, p+2, p+3, p+4};
123
+//
124
+// //Field[2] = MathEval;
125
+// //Field[2].F = Sprintf("(2.25 - F1)^2 + %g", cellSize*10 );  // WORKS
126
+// //Field[2].F = Sprintf("(%g - F1)^2 + %g", radius, 2*cellSize );
127
+// //Background Field = 2;
128
+//
129
+// // Don't extend the elements sizes from the boundary inside the domain
130
+// //Mesh.CharacteristicLengthExtendFromBoundary = 0;
131
+//
132
+// Physical Volume(1) = {v[1]};
133
+
134
+// To create the mesh run
135
+// gmsh sphere.gmsh -2 -v 0 -format msh -o sphere.msh
136
+//gmsh -3 -format msh1 -o outfile.msh sphere.geo

+ 4
- 0
include/FEM4EllipticPDE.h Visa fil

@@ -125,6 +125,10 @@ namespace Lemma {
125 125
              */
126 126
             void SetupDC(DCSurvey* Survey, const int& ij);
127 127
 
128
+            /** Sets up the potential problem from the VTK file
129
+             */
130
+            void SetupPotential();
131
+
128 132
             /** Performs solution */
129 133
             void Solve(const std::string& fname);
130 134
 

+ 65
- 9
src/FEM4EllipticPDE.cpp Visa fil

@@ -214,8 +214,9 @@ namespace Lemma {
214 214
 
215 215
         //Eigen::BiCGSTAB<Eigen::SparseMatrix<Real> > cg(A);
216 216
         cg.setMaxIterations(3000);
217
-        //cg.compute(A);
218
-        //std::cout << "Computed     " << std::endl;
217
+
218
+        std::cout << "A: "  << A.rows() << "\t" << A.cols() << std::endl;
219
+        std::cout << "g: "  << g.rows() << "\t" << g.cols() << std::endl;
219 220
 
220 221
         VectorXr u = cg.solve(g);
221 222
         std::cout << "#iterations:     " << cg.iterations() << std::endl;
@@ -257,20 +258,31 @@ namespace Lemma {
257 258
         std::cout << "Building Stiffness Matrix (A) " << std::endl;
258 259
         std::cout << "\tMesh has " << vtkGrid->GetNumberOfCells()  << " cells "  << std::endl;
259 260
 
260
-
261 261
   	    //Eigen::SparseMatrix<Real>
262 262
         A.resize(vtkGrid->GetNumberOfPoints(), vtkGrid->GetNumberOfPoints());
263 263
         std::vector< Eigen::Triplet<Real> > coeffs;
264 264
 
265
+        if ( !vtkGrid->GetPointData()->GetScalars("vtkValidPointMask") ) {
266
+            throw std::runtime_error("No vtkValidPointMask");
267
+        }
268
+
269
+        if ( !vtkGrid->GetCellData()->GetScalars("G") && !vtkGrid->GetPointData()->GetScalars("G") ) {
270
+            throw std::runtime_error("No Cell or Point Data G");
271
+        }
272
+
273
+        bool GCell = false;
274
+        if ( vtkGrid->GetCellData()->GetScalars("G") ) {
275
+            GCell = true;
276
+        }
277
+
278
+
265 279
         // Here we iterate over all of the cells
266 280
         for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
267 281
 
268 282
             assert ( vtkGrid->GetCell(ic)->GetNumberOfPoints() == 4 );
269 283
             // TODO, in production code we might not want to do this check here
270 284
             if ( vtkGrid->GetCell(ic)->GetNumberOfPoints() != 4 ) {
271
-                std::cout << "DOOM FEM4EllipticPDE encountered non-tetrahedral mesh\n";
272
-                std::cout << "Number of points in cell " << vtkGrid->GetCell(ic)->GetNumberOfPoints() << std::endl ;
273
-                exit(1);
285
+                throw std::runtime_error("Non-tetrahedral mesh encountered!");
274 286
             }
275 287
 
276 288
             // construct coordinate matrix C
@@ -292,8 +304,16 @@ namespace Lemma {
292 304
                 ID[1] = Ids->GetId(1);
293 305
                 ID[2] = Ids->GetId(2);
294 306
                 ID[3] = Ids->GetId(3);
295
-            Real sum(0);
296
-            Real sigma_bar = vtkGrid->GetCellData()->GetScalars()->GetTuple1(ic);
307
+            Real sum(0), sigma_bar(0);
308
+            if (GCell) {
309
+                sigma_bar = vtkGrid->GetCellData()->GetScalars("G")->GetTuple1(ic);
310
+            } else {
311
+                sigma_bar  = vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0]);
312
+                sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1]);
313
+                sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2]);
314
+                sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3]);
315
+                sigma_bar /= 4.;
316
+            }
297 317
 
298 318
             for (int ip=0; ip<4; ++ip) {
299 319
                 for (int ip2=0; ip2<4; ++ip2) {
@@ -302,7 +322,6 @@ namespace Lemma {
302 322
                         //   solve for the boundaries? Is one better? This seems to work, which is nice.
303 323
                         //Real bdry = V*(1./(BndryH*BndryH))*BndrySigma*bndryCnt( ID[ip] ); // + sum;
304 324
                         Real bb = vtkGrid->GetPointData()->GetScalars("vtkValidPointMask")->GetTuple(ID[ip])[0];
305
-                        //std::cout << "bb " << bb  << std::endl;
306 325
                         Real bdry = V*(1./(BndryH*BndryH))*BndrySigma*bb; // + sum;
307 326
                         coeffs.push_back( Eigen::Triplet<Real> ( ID[ip], ID[ip2], bdry +  Phi.col(ip).tail<3>().dot(Phi.col(ip2).tail<3>() ) * V * sigma_bar ) );
308 327
                     } else {
@@ -315,6 +334,43 @@ namespace Lemma {
315 334
             std::cout <<  "\r" << (int)(1e2*((float)(ic) / (float)(vtkGrid->GetNumberOfCells()))) << std::flush ;
316 335
         }
317 336
         A.setFromTriplets(coeffs.begin(), coeffs.end());
337
+    }
338
+
339
+    void FEM4EllipticPDE::SetupPotential() {
340
+
341
+        ////////////////////////////////////////////////////////////
342
+	    // Load vector g
343
+        std::cout << "\nBuilding load vector (g)" << std::endl;
344
+        g = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
345
+        std::cout << "made g with "  << vtkGrid->GetNumberOfPoints() << " cells" << std::endl;
346
+
347
+        for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
348
+
349
+                Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
350
+                for (int ip=0; ip<4; ++ip) {
351
+                    double* pts =  vtkGrid->GetCell(ic)->GetPoints()->GetPoint(ip); //[ipc] ;
352
+                    C(ip, 0) = 1;
353
+                    C(ip, 1) =  pts[0];
354
+                    C(ip, 2) =  pts[1];
355
+                    C(ip, 3) =  pts[2];
356
+                }
357
+
358
+                Real V = (1./6.) * C.determinant();          // volume of tetrahedra
359
+                //Real V = C.determinant();          // volume of tetrahedra
360
+
361
+                vtkIdList* Ids = vtkGrid->GetCell(ic)->GetPointIds();
362
+                int ID[4];
363
+                    ID[0] = Ids->GetId(0);
364
+                    ID[1] = Ids->GetId(1);
365
+                    ID[2] = Ids->GetId(2);
366
+                    ID[3] = Ids->GetId(3);
367
+
368
+            for (int ip=0; ip<4; ++ip) {
369
+                 g(ID[ip]) +=  (V/4.) *  ( vtkGrid->GetPointData()->GetScalars()->GetTuple(ID[ip])[0] )  ;
370
+                 //if ( std::abs(vtkGrid->GetPointData()->GetScalars()->GetTuple(ID[ip])[0]) > 1e-3 )
371
+            }
372
+
373
+        }
318 374
 
319 375
     }
320 376
 

Laddar…
Avbryt
Spara