Browse Source

More work on the Linear Mag problem. Seems to be close.

master
Trevor Irons 8 years ago
parent
commit
7f1f288a33

+ 4
- 1
examples/LinearMag/Sphere.cpp View File

@@ -31,6 +31,9 @@ int main( int argc, char** argv ) {
31 31
     std::cout << "# This program solves for the secondary magnetic  #\n";
32 32
     std::cout << "# field from a low susceptibily model in the      #\n";
33 33
     std::cout << "# presence of a homogeneous static inducing field #\n";
34
+    std::cout << "#                                                 #\n";
35
+    std::cout << "# (C) University of Utah, 2016                    #\n";
36
+    std::cout << "#                                                 #\n";
34 37
     std::cout << "###################################################\n\n";
35 38
 
36 39
     if (argc < 3) {
@@ -40,7 +43,7 @@ int main( int argc, char** argv ) {
40 43
     }
41 44
 
42 45
     LinearMag* Mag = LinearMag::New();
43
-        Mag->SetInducingMagField( 55234., 60, 14, NANOTESLA );
46
+        Mag->SetInducingMagField( 55234., 0, 0, NANOTESLA );
44 47
         Mag->SetVTUGridFile( argv[1] );
45 48
         Mag->CalculateRHS( "kappa" );
46 49
         Mag->Solve( argv[2] );

+ 148
- 0
examples/LinearMag/sphere.geo View File

@@ -0,0 +1,148 @@
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
+radius = 3.25;     // Radius of the damn thing
11
+lc = radius/5;     //  0.25;   // Target element size
12
+
13
+// Total Solution Space
14
+Box = 3*radius; // The down side of potential
15
+X0 = -Box;
16
+X1 =  Box;
17
+Y0 = -Box;
18
+Y1 =  Box;
19
+Z0 = -Box;
20
+Z1 =  Box;
21
+
22
+cellSize=radius/10; ///10;
23
+dd = 0 ; //  1e-5; //cellSize; // .01;
24
+pio2=Pi/2;
25
+
26
+
27
+/////////////////////////////////////
28
+// Large Bounding box
29
+pp = newp;
30
+Point(pp)    = {X0, Y0, Z0, lc};
31
+Point(pp+1)  = {X1, Y0, Z0, lc};
32
+Point(pp+2)  = {X1, Y1, Z0, lc};
33
+Point(pp+3)  = {X0, Y1, Z0, lc};
34
+
35
+
36
+lv = newl;
37
+Line(lv) = {pp,pp+1};
38
+Line(lv+1) = {pp+1,pp+2};
39
+Line(lv+2) = {pp+2,pp+3};
40
+Line(lv+3) = {pp+3,pp};
41
+Line Loop(lv+4) = {lv, lv+1, lv+2, lv+3};
42
+
43
+// Hard coded doom
44
+Plane Surface(125) = {lv+4};
45
+
46
+//v = newv;
47
+v[] = Extrude {0, 0, Z1-Z0} { Surface{125}; };
48
+
49
+// Calculate offset effect
50
+theta = Asin(dd/radius);
51
+rr = radius * Cos(theta);
52
+
53
+///////////////////////////////////
54
+// Positive half sphere
55
+// create inner 1/8 shell
56
+p0 = newp;
57
+Point(p0)   = {      0,   0,       0, cellSize}; // origin
58
+Point(p0+1) = {    -rr,   0,      dd, cellSize};
59
+Point(p0+2) = {      0,  rr,      dd, cellSize};
60
+Point(p0+3) = {      0,   0,  radius, cellSize};
61
+Point(p0+4) = {      0,   0,      dd, cellSize}; // origin
62
+
63
+c0 = newc;
64
+Circle(c0  ) = {p0+1, p0+4, p0+2};       // Tricky, This one needs to be offset!
65
+Circle(c0+1) = {p0+3, p0, p0+1};
66
+Circle(c0+2) = {p0+3, p0, p0+2};
67
+
68
+Line Loop(10) = {c0, -(c0+2), c0+1} ;
69
+Ruled Surface (60) = {10};
70
+
71
+////////////////////////////////////////////////////////////
72
+// Negative half sphere
73
+p = newp;
74
+Point(  p) = {      0,      0,            0, cellSize};
75
+Point(p+1) = {    -rr,      0,          -dd, cellSize};
76
+Point(p+2) = {      0,     rr,          -dd, cellSize};
77
+Point(p+3) = {      0,      0,      -radius, cellSize};
78
+Point(p+4) = {      0,      0,          -dd, cellSize};
79
+
80
+cc = newc;
81
+Circle(cc  ) = {p+1, p+4, p+2};
82
+Circle(cc+1) = {p+3, p,   p+1};
83
+Circle(cc+2) = {p+3, p,   p+2};
84
+
85
+Circle(cc+3) = {p+3, p, p+2};
86
+Circle(cc+4) = {p+3, p, p+2};
87
+Circle(cc+5) = {p+3, p, p+2};
88
+
89
+ccl = newl;
90
+Line(ccl) = { p0+3, p+3 };
91
+
92
+Line Loop(11) = {cc, -(cc+2), cc+1} ;
93
+Ruled Surface (61) = {11};
94
+
95
+// create remaining 7/8 inner shells
96
+t1[] = Rotate {{0,0,1},{0,0,0},pio2  } {Duplicata{Surface{60};}};
97
+t2[] = Rotate {{0,0,1},{0,0,0},pio2*2} {Duplicata{Surface{60};}};
98
+t3[] = Rotate {{0,0,1},{0,0,0},pio2*3} {Duplicata{Surface{60};}};
99
+//
100
+t4[] = Rotate {{0,0,1},{0,0,0},pio2  } {Duplicata{Surface{61};}};
101
+t5[] = Rotate {{0,0,1},{0,0,0},pio2*2} {Duplicata{Surface{61};}};
102
+t6[] = Rotate {{0,0,1},{0,0,0},pio2*3} {Duplicata{Surface{61};}};
103
+
104
+/* This is GOOD */
105
+Surface{60} In Volume{v[1]};
106
+Surface{t1[0]} In Volume{v[1]};
107
+Surface{t2[0]} In Volume{v[1]};
108
+Surface{t3[0]} In Volume{v[1]};
109
+
110
+Surface{61} In Volume{v[1]};
111
+Surface{t4[0]} In Volume{v[1]};
112
+Surface{t5[0]} In Volume{v[1]};
113
+Surface{t6[0]} In Volume{v[1]};
114
+
115
+///////////////////////////////////////////////
116
+// Attractor Field
117
+
118
+// Field[1] = Attractor;
119
+// Field[1].NodesList = {p}; //0, p0+1, p0+2, p0+3, p0+4, p, p+1, p+2, p+3, p+4};
120
+//
121
+// Field[2] = MathEval;
122
+// Field[2].F = Sprintf("(2.25 - F1)^1.01 + %g", radius/10 );  // WORKS
123
+//
124
+// Field[3] = MathEval;
125
+// Field[3].F = Sprintf("(12.25 - F1)^1.01 + %g", radius/5 );  // WORKS
126
+//
127
+// Field[4] = MathEval;
128
+// Field[4].F = Sprintf("(22.25 - F1)^1.01 + %g", radius );  // WORKS
129
+//
130
+// Field[5] = MathEval;
131
+// Field[5].F = Sprintf("(42.25 - F1)^1.01 + %g", radius*5 );  // WORKS
132
+//
133
+// //Field[2].F = Sprintf("(%g - F1)^2 + %g", radius, 2*cellSize );
134
+// //Background Field = 2;
135
+//
136
+// // Finally, let's use the minimum of all the fields as the background mesh field
137
+// Field[7] = Min;
138
+// Field[7].FieldsList = {2, 3, 4, 5};
139
+// Background Field = 7;
140
+
141
+// Don't extend the elements sizes from the boundary inside the domain
142
+//Mesh.CharacteristicLengthExtendFromBoundary = 0;
143
+
144
+Physical Volume(1) = {v[1]};
145
+
146
+// To create the mesh run
147
+// gmsh sphere.gmsh -2 -v 0 -format msh -o sphere.msh
148
+//gmsh -3 -format msh1 -o outfile.msh sphere.geo

+ 8
- 0
examples/LinearMag/sphere.sh View File

@@ -0,0 +1,8 @@
1
+#!/usr/bin/env bash
2
+gmsh  -3 -format vtk -o sphere.vtk  sphere.geo 
3
+gmsh  -2 -format stl -o sphereBox.stl  sphereBox.geo 
4
+../ResampleWithDataset  sphere.vtk  sphereBox.stl  MergedSphere.vtu 
5
+../VTKEdgeGsphere MergedSphere.vtu   3.25  mag  sphereMag.vtu
6
+./Sphere  sphereMag.vtu     sphereOutMag.vtu 
7
+
8
+#paraview --data=sphereOutGrav.vtu 

+ 136
- 0
examples/LinearMag/sphereBox.geo View File

@@ -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 = 3.25;     // Radius of the damn thing
13
+
14
+lc = radius;   //  0.25;   // Target element size
15
+
16
+// Total Solution Space
17
+Box = 3*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

+ 82
- 57
examples/VTKEdgeGsphere.cpp View File

@@ -28,6 +28,8 @@
28 28
 #include <vtkXMLUnstructuredGridWriter.h>
29 29
 #include <vtkDoubleArray.h>
30 30
 #include <vtkPointData.h>
31
+#include <vtkCellData.h>
32
+#include <vtkCell.h>
31 33
 
32 34
 #include <cmath>
33 35
 #include <Eigen/Core>
@@ -42,7 +44,7 @@ int main(int argc, char**argv) {
42 44
         exit(EXIT_SUCCESS);
43 45
     }
44 46
 
45
-    vtkUnstructuredGrid* uGrid = vtkUnstructuredGrid::New();
47
+    vtkUnstructuredGrid* uGrid;// = vtkUnstructuredGrid::New();
46 48
 
47 49
     std::string fn = argv[1];
48 50
     if(fn.substr(fn.find_last_of(".") + 1) == "vtk") {
@@ -67,8 +69,8 @@ int main(int argc, char**argv) {
67 69
     }
68 70
 
69 71
 
70
-        int nc = uGrid->GetNumberOfCells()  ;
71
-        int nn = uGrid->GetNumberOfPoints()  ;
72
+    int nc = uGrid->GetNumberOfCells()  ;
73
+    int nn = uGrid->GetNumberOfPoints()  ;
72 74
 
73 75
     std::cout << "Processing grid with nodes=" << nn << "\t cells=" << nc << "\n";
74 76
 
@@ -84,80 +86,103 @@ int main(int argc, char**argv) {
84 86
         //G->SetName("G");
85 87
         if ( std::string(argv[3]) == "mag") {
86 88
             G->SetName("kappa");
89
+            G->SetNumberOfTuples(nc);
87 90
         }
88 91
         else {
89 92
             G->SetName("G");
93
+            G->SetNumberOfTuples(nn);
90 94
         }
91 95
     vtkDoubleArray* phi = vtkDoubleArray::New();
92 96
         phi->SetNumberOfComponents(1);
93 97
         phi->SetNumberOfTuples(nn);
94 98
         phi->SetName("analytic_phi");
95 99
 
96
-    // Loop over nodes, look at position, set with G if on boundary
97 100
     double point[3];
98
-    Eigen::Vector3d M; M << 0,0,1;
99
-    for (int in=0; in<nn; ++in) {
100
-        uGrid->GetPoint(in, &point[0]);
101
-        //std::cout << point[0] << "\t" <<point[1] << "\t" << point[2] << std::endl;
102
-        double raddist = sqrt( point[0]*point[0] + point[1]*point[1] + point[2]*point[2] );
103
-
104
-        //double rho = sqrt( point[1]*point[1] + point[2]*point[2] );
105
-        // Calculate RHS
106
-        if ( std::string(argv[3]) == "gravity") {
107
-            if ( raddist < R + eps) {
108
-                G->InsertTuple1( in, 1 );
109
-            } else {
110
-                G->InsertTuple1( in, 0 );
101
+
102
+
103
+    if ( std::string(argv[3]) == "mag") {
104
+        // Loop over cells and decide if all of them lie within sphere
105
+        for (int ic=0; ic<nc; ++ic) {
106
+            assert ( uGrid->GetCell(ic)->GetNumberOfPoints() == 4 );
107
+            // TODO, in production code we might not want to do this check here
108
+            if ( uGrid->GetCell(ic)->GetNumberOfPoints() != 4 ) {
109
+                throw std::runtime_error("Non-tetrahedral mesh encountered!");
111 110
             }
112
-        }
113
-        if ( std::string(argv[3]) == "magnet") {
114
-            if ( raddist > R - eps && raddist < R + eps ) {
115
-                // \rho = \nabla \cdot \mathbf{M}
116
-                // Use divergence theorm --> \mahtbf{M} \cdot \hat{n}
117
-                Eigen::Vector3d n;
118
-                n << point[0],point[1],point[2];
119
-                n.array() /= raddist;
120
-                G->InsertTuple1(in, n.dot(M) );
121
-            } else {
122
-                G->InsertTuple1( in, 0 );
111
+            // construct coordinate matrix C
112
+            //Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
113
+            bool cellin(true);
114
+            for (int ii=0; ii<4; ++ii) {
115
+                double* point =  uGrid->GetCell(ic)->GetPoints()->GetPoint(ii); //[ipc] ;
116
+                if ( sqrt( point[0]*point[0] + point[1]*point[1] + point[2]*point[2] ) > R+eps ) {
117
+                    cellin = false;
118
+                }
123 119
             }
124
-        }
125
-        if ( std::string(argv[3]) == "mag") {
126
-            if ( raddist < R + eps) {
127
-                G->InsertTuple1( in, 1 );
120
+            if (cellin) {
121
+                G->InsertTuple1( ic, 1 );
128 122
             } else {
129
-                G->InsertTuple1( in, 0 );
123
+                G->InsertTuple1( ic, 0 );
130 124
             }
131 125
         }
126
+        uGrid->GetCellData()->AddArray( G );
132 127
 
133
-        // Insert analytic phi part
134
-        /* magnetics problem p. 198 Jackson */
135
-        if (std::string(argv[3]) == "magnet") {
136
-            if (raddist < R) {
137
-                phi->InsertTuple1( in, (1./3.)*point[2] );
138
-            } else {
139
-                phi->InsertTuple1( in, 0);
140
-                double costheta = point[2]/raddist ;
141
-                //phi->InsertTuple1( in, -(1./3.)*(R*R*R) * ( costheta / (rho*rho) )  );
142
-                phi->InsertTuple1( in, (1./3.) * (R*R*R) * (costheta / (raddist*raddist))  );
128
+    } else {
129
+        // Loop over nodes, look at position, set with G if on boundary
130
+        Eigen::Vector3d M; M << 0,0,1;
131
+        for (int in=0; in<nn; ++in) {
132
+            uGrid->GetPoint(in, &point[0]);
133
+            //std::cout << point[0] << "\t" <<point[1] << "\t" << point[2] << std::endl;
134
+            double raddist = sqrt( point[0]*point[0] + point[1]*point[1] + point[2]*point[2] );
135
+
136
+            //double rho = sqrt( point[1]*point[1] + point[2]*point[2] );
137
+            // Calculate RHS
138
+            if ( std::string(argv[3]) == "gravity") {
139
+                if ( raddist < R + eps) {
140
+                    G->InsertTuple1( in, 1 );
141
+                } else {
142
+                    G->InsertTuple1( in, 0 );
143
+                }
143 144
             }
144
-        } else if (std::string(argv[3]) == "gravity") {
145
-            double mass = 4./3. * PI * (R*R*R); // volume * density (1)
146
-            if (raddist < R) {
147
-                phi->InsertTuple1( in, mass * (( 3*(R*R) - raddist*raddist )/(2*(R*R*R))) ); // (1./3.)*point[2] );
148
-                //phi->InsertTuple1( in,  (2*PI/3)*(3*R*R-raddist*raddist)  ); // (1./3.)*point[2] );
149
-            } else {
150
-                //phi->InsertTuple1( in, 0);
151
-                //double costheta = point[2]/raddist ;
152
-                //phi->InsertTuple1( in, -(1./3.)*(R*R*R) * ( costheta / (rho*rho) )  );
153
-                phi->InsertTuple1( in, mass/raddist );
145
+            if ( std::string(argv[3]) == "magnet") {
146
+                if ( raddist > R - eps && raddist < R + eps ) {
147
+                    // \rho = \nabla \cdot \mathbf{M}
148
+                    // Use divergence theorm --> \mahtbf{M} \cdot \hat{n}
149
+                    Eigen::Vector3d n;
150
+                    n << point[0],point[1],point[2];
151
+                    n.array() /= raddist;
152
+                    G->InsertTuple1(in, n.dot(M) );
153
+                } else {
154
+                    G->InsertTuple1( in, 0 );
155
+                }
156
+            }
157
+            // Insert analytic phi part
158
+            /* magnetics problem p. 198 Jackson */
159
+            if (std::string(argv[3]) == "magnet") {
160
+                if (raddist < R) {
161
+                    phi->InsertTuple1( in, (1./3.)*point[2] );
162
+                } else {
163
+                    phi->InsertTuple1( in, 0);
164
+                    double costheta = point[2]/raddist ;
165
+                    //phi->InsertTuple1( in, -(1./3.)*(R*R*R) * ( costheta / (rho*rho) )  );
166
+                    phi->InsertTuple1( in, (1./3.) * (R*R*R) * (costheta / (raddist*raddist))  );
167
+                }
168
+            } else if (std::string(argv[3]) == "gravity") {
169
+                double mass = 4./3. * PI * (R*R*R); // volume * density (1)
170
+                if (raddist < R) {
171
+                    phi->InsertTuple1( in, mass * (( 3*(R*R) - raddist*raddist )/(2*(R*R*R))) ); // (1./3.)*point[2] );
172
+                    //phi->InsertTuple1( in,  (2*PI/3)*(3*R*R-raddist*raddist)  ); // (1./3.)*point[2] );
173
+                } else {
174
+                    //phi->InsertTuple1( in, 0);
175
+                    //double costheta = point[2]/raddist ;
176
+                    //phi->InsertTuple1( in, -(1./3.)*(R*R*R) * ( costheta / (rho*rho) )  );
177
+                    phi->InsertTuple1( in, mass/raddist );
178
+                }
154 179
             }
155 180
         }
156
-    }
157 181
 
158
-    // Add new data
159
-    uGrid->GetPointData()->AddArray( phi );
160
-    uGrid->GetPointData()->SetScalars( G );
182
+        // Add new data
183
+        uGrid->GetPointData()->AddArray( phi );
184
+        uGrid->GetPointData()->SetScalars( G );
185
+    }
161 186
 
162 187
     // Write out new file
163 188
     vtkXMLUnstructuredGridWriter* Writer = vtkXMLUnstructuredGridWriter::New();

+ 8
- 7
src/FEM4EllipticPDE.cpp View File

@@ -145,11 +145,13 @@ namespace Lemma {
145 145
     //      Method:  SetVTUGridFile
146 146
     //--------------------------------------------------------------------------------------
147 147
     void FEM4EllipticPDE::SetVTUGridFile ( std::string& fname  ) {
148
+        std::cout  << "Loading VTK .vtu file " << fname << std::endl;
148 149
         vtkXMLUnstructuredGridReader* MeshReader = vtkXMLUnstructuredGridReader::New();
149 150
         MeshReader->SetFileName(fname.c_str());
150 151
         MeshReader->Update();
151 152
         //vtkGrid->DeepCopy( MeshReader->GetOutput() );
152
-        vtkGrid->ShallowCopy( MeshReader->GetOutput() );
153
+        //vtkGrid->ShallowCopy( MeshReader->GetOutput() );
154
+        vtkGrid = MeshReader->GetOutput();
153 155
         MeshReader->Delete();
154 156
         return ;
155 157
     }		// -----  end of method FEM4EllipticPDE::SetVTKGridFile  -----
@@ -164,8 +166,8 @@ namespace Lemma {
164 166
         MeshReader->SetFileName(fname);
165 167
         MeshReader->Update();
166 168
         //vtkGrid->DeepCopy( MeshReader->GetOutput() );
167
-        vtkGrid = MeshReader->GetOutput();
168 169
         //vtkGrid->ShallowCopy( MeshReader->GetOutput() );
170
+        vtkGrid = MeshReader->GetOutput();
169 171
         MeshReader->Delete();
170 172
         return ;
171 173
     }		// -----  end of method FEM4EllipticPDE::SetVTKGridFile  -----
@@ -547,10 +549,8 @@ namespace Lemma {
547 549
 	    // Load vector g
548 550
         std::cout << "\nBuilding load vector (g)" << std::endl;
549 551
         g = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
550
-        std::cout << "made g with "  << vtkGrid->GetNumberOfPoints() << " points" << std::endl;
551 552
 
552 553
         for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
553
-
554 554
             Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
555 555
             for (int ii=0; ii<4; ++ii) {
556 556
                 double* pts =  vtkGrid->GetCell(ic)->GetPoints()->GetPoint(ii); //[ipc] ;
@@ -573,9 +573,9 @@ namespace Lemma {
573 573
 
574 574
             // Apply Dirichlet conditions
575 575
             for (int ii=0; ii<4; ++ii) {
576
-                if (vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
577
-                    g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
578
-                }
576
+                //if (vtkGrid->GetPointData()->GetScalars("InHomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
577
+                //    g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
578
+                //}
579 579
             }
580 580
 
581 581
             /* the 4 faces of the tetrahedra
@@ -632,6 +632,7 @@ namespace Lemma {
632 632
                 g(ID[3]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])*TA/3. * i4pi ;
633 633
             }
634 634
         }
635
+        std::cout << "made g with "  << vtkGrid->GetNumberOfPoints() << " points" << std::endl;
635 636
     }
636 637
 
637 638
     #if 0

+ 55
- 6
src/LinearMag.cpp View File

@@ -173,14 +173,27 @@ void LinearMag::ScaleB0 ( const MAGUNITS& U ) {
173 173
 //      Method:  CalculateRHS
174 174
 //--------------------------------------------------------------------------------------
175 175
 void LinearMag::CalculateRHS ( const std::string& susName ) {
176
+
177
+    if ( !vtkGrid->GetCellData()->GetScalars(susName.c_str()) ) {
178
+        std::string err("No cell data by name ");
179
+        err.append(susName);
180
+        throw std::runtime_error(err.c_str());
181
+    }
182
+
176 183
     vtkDoubleArray* G = vtkDoubleArray::New();
177 184
     G->SetNumberOfComponents(1);
178 185
     G->SetNumberOfTuples( vtkGrid->GetNumberOfPoints() );
179 186
     G->SetName("G");
187
+    //g.resize(vtkGrid->GetNumberOfPoints());
188
+    VectorXr GG = VectorXr::Zero( vtkGrid->GetNumberOfPoints() );
180 189
 
181 190
     // Iterate over all the points or all of the cells?
182 191
     for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
183 192
 
193
+        if ( vtkGrid->GetCell(ic)->GetNumberOfPoints() != 4 ) {
194
+            throw std::runtime_error("Non-tetrahedral mesh encountered!");
195
+        }
196
+
184 197
         Real cellSus = vtkGrid->GetCellData()->GetScalars(susName.c_str())->GetTuple(ic)[0];
185 198
 
186 199
         Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
@@ -207,23 +220,59 @@ void LinearMag::CalculateRHS ( const std::string& susName ) {
207 220
             ID[1] ID[2] ID[3]
208 221
         */
209 222
         // Face 0, ID 0,1,2
210
-        /*
211 223
         Eigen::Matrix<Real, 3, 2> CC = Eigen::Matrix<Real, 3, 2>::Ones() ;
212 224
         {
225
+
213 226
             CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
214 227
             CC.col(2) = C.row(0).tail<3>() - C.row(2).tail<3>();
215 228
             Vector3r nhat = CC.col(1).cross(CC.col(2));
216 229
             nhat.array() /= nhat.norm();
217 230
             Real flux = cellSus*nhat.dot(B0);
218
-            g(ID[0]) += flux;
219
-            g(ID[1]) += flux;
220
-            g(ID[2]) += flux;
221
-                    //  vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])*TA/3. * i4pi ;
231
+            GG(ID[0]) += flux;
232
+            GG(ID[1]) += flux;
233
+            GG(ID[2]) += flux;
222 234
         }
223
-        */
235
+        // Face 1, ID 0,1,3
236
+        {
237
+            CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
238
+            CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
239
+            Vector3r nhat = CC.col(1).cross(CC.col(2));
240
+            nhat.array() /= nhat.norm();
241
+            Real flux = cellSus*nhat.dot(B0);
242
+            GG(ID[0]) += flux;
243
+            GG(ID[1]) += flux;
244
+            GG(ID[3]) += flux;
245
+        }
246
+        // Face 1, ID 0,2,3
247
+        {
248
+            CC.col(1) = C.row(0).tail<3>() - C.row(2).tail<3>();
249
+            CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
250
+            Vector3r nhat = CC.col(1).cross(CC.col(2));
251
+            nhat.array() /= nhat.norm();
252
+            Real flux = cellSus*nhat.dot(B0);
253
+            GG(ID[0]) += flux;
254
+            GG(ID[2]) += flux;
255
+            GG(ID[3]) += flux;
256
+        }
257
+        // Face 1, ID 1,2,3
258
+        {
259
+            CC.col(1) = C.row(1).tail<3>() - C.row(2).tail<3>();
260
+            CC.col(2) = C.row(1).tail<3>() - C.row(3).tail<3>();
261
+            Vector3r nhat = CC.col(1).cross(CC.col(2));
262
+            nhat.array() /= nhat.norm();
263
+            Real flux = cellSus*nhat.dot(B0);
264
+            GG(ID[1]) += flux;
265
+            GG(ID[2]) += flux;
266
+            GG(ID[3]) += flux;
267
+        }
268
+
269
+    }
270
+    for (int ip=0; ip<vtkGrid->GetNumberOfPoints(); ++ip) {
271
+        G->InsertTuple1( ip, GG(ip) );
224 272
     }
225 273
 
226 274
     vtkGrid->GetPointData()->AddArray( G );
275
+    vtkGrid->GetPointData()->SetScalars( G );
227 276
     return ;
228 277
 }		// -----  end of method LinearMag::CalculateRHS  -----
229 278
 

Loading…
Cancel
Save