42
28
CELL_PREDICATE(RightPointTest, {return fabs(x[0]-1.0) < 1.0e-10;})
43
29
CELL_PREDICATE(TopPointTest, {return fabs(x[1]-1.0) < 1.0e-10;})
48
33
int main(int argc, char** argv)
55
string meshFile="builtin";
56
string solverFile = "aztec-ml.xml";
57
Sundance::setOption("meshFile", meshFile, "mesh file");
58
Sundance::setOption("nx", nx, "number of elements in x");
59
Sundance::setOption("ny", ny, "number of elements in y");
60
Sundance::setOption("solver", solverFile, "name of XML file for solver");
62
Sundance::init(&argc, &argv);
63
int np = MPIComm::world().getNProc();
65
/* We will do our linear algebra using Epetra */
66
VectorType<double> vecType = new EpetraVectorType();
68
/* Create a mesh. It will be of type BasisSimplicialMesh, and will
69
* be built using a PartitionedRectangleMesher. */
70
MeshType meshType = new BasicSimplicialMeshType();
73
if (meshFile != "builtin")
75
mesher = new ExodusMeshReader("../../../examples-tutorial/meshes/"+meshFile, meshType);
79
mesher = new PartitionedRectangleMesher(0.0, 1.0, nx, np,
80
0.0, 1.0, ny, 1, meshType);
82
Mesh mesh = mesher.getMesh();
85
bool meshOK = mesh.checkConsistency(meshFile+"-check");
88
cout << "mesh is OK" << endl;
92
cout << "mesh is INCONSISTENT" << endl;
94
mesh.dump(meshFile+"-dump");
96
/* Create a cell filter that will identify the maximal cells
97
* in the interior of the domain */
98
CellFilter interior = new MaximalCellFilter();
99
CellFilter edges = new DimensionalCellFilter(1);
106
if (meshFile != "builtin")
108
left = edges.labeledSubset(1);
109
right = edges.labeledSubset(2);
110
top = edges.labeledSubset(3);
111
bottom = edges.labeledSubset(4);
115
left = edges.subset(new LeftPointTest());
116
right = edges.subset(new RightPointTest());
117
top = edges.subset(new TopPointTest());
118
bottom = edges.subset(new BottomPointTest());
121
/* Create unknown and test functions, discretized using second-order
122
* Lagrange interpolants */
123
BasisFamily basis = new Lagrange(1);
124
Expr u = new UnknownFunction(basis, "u");
125
Expr v = new TestFunction(basis, "v");
127
/* Create differential operator and coordinate functions */
128
Expr dx = new Derivative(0);
129
Expr dy = new Derivative(1);
130
Expr grad = List(dx, dy);
131
Expr x = new CoordExpr(0);
132
Expr y = new CoordExpr(1);
134
/* We need a quadrature rule for doing the integrations */
135
QuadratureFamily quad2 = new GaussianQuadrature(2);
136
QuadratureFamily quad4 = new GaussianQuadrature(4);
138
/* Define the weak form */
139
//Expr eqn = Integral(interior, (grad*v)*(grad*u) + v, quad);
140
Expr one = new SundanceCore::Parameter(1.0);
141
Expr exactSoln = x+2.0*y;//0.5*x*x + (1.0/3.0)*y;
142
Expr eqn = Integral(interior, (grad*u)*(grad*v) /* + one*v */, quad2);
143
/* Define the Dirichlet BC */
144
Expr h = new CellDiameterExpr();
145
Expr bc = EssentialBC(bottom+top+left+right, v*(u-exactSoln)/h, quad4);
147
Assembler::defaultVerbParams()->set<int>("global", 2);
148
Assembler::defaultVerbParams()->set<int>("evaluation", 4);
149
Assembler::defaultVerbParams()->set<int>("assembly loop", 2);
151
/* We can now set up the linear problem! */
152
LinearProblem prob(mesh, eqn, bc, v, u, vecType);
154
ParameterXMLFileReader reader(searchForFile("SolverParameters/" + solverFile));
155
ParameterList solverParams = reader.getParameters();
156
LinearSolver<double> solver
157
= LinearSolverBuilder::createSolver(solverParams);
159
// cout << "map = " << endl;
160
//prob.rowMap()->print(cout);
162
Expr soln = prob.solve(solver);
164
DiscreteSpace discSpace2(mesh, new Lagrange(2), vecType);
165
DiscreteSpace discSpace0(mesh, new Lagrange(0), vecType);
166
L2Projector proj1(discSpace2, soln-exactSoln);
167
double pid = MPIComm::world().getRank();
168
L2Projector proj2(discSpace0, pid);
169
Expr errorDisc = proj1.project();
170
Expr pidDisc = proj2.project();
175
/* Write the field in VTK format */
176
FieldWriter w = new VTKWriter("Poisson2d");
178
w.addField("soln", new ExprFieldWrapper(soln[0]));
179
w.addField("error", new ExprFieldWrapper(errorDisc));
180
w.addField("rank", new ExprFieldWrapper(pidDisc));
183
Expr err = exactSoln - soln;
184
Expr errExpr = Integral(interior,
188
Expr derivErr = dx*(exactSoln-soln);
189
Expr derivErrExpr = Integral(interior,
195
Expr fluxErrExpr = Integral(top,
196
pow(dy*(soln-exactSoln), 2),
197
new GaussianQuadrature(2));
201
Expr exactFluxExpr = Integral(top,
203
new GaussianQuadrature(2));
205
Expr numFluxExpr = Integral(top,
207
new GaussianQuadrature(2));
208
// + Integral(top+bottom,
209
// pow(dy*(soln-exactSoln), 2),
210
// new GaussianQuadrature(2));
213
FunctionalEvaluator errInt(mesh, errExpr);
214
FunctionalEvaluator derivErrInt(mesh, derivErrExpr);
216
double errorSq = errInt.evaluate();
217
cout << "error norm = " << sqrt(errorSq) << endl << endl;
219
double derivErrorSq = derivErrInt.evaluate();
220
cout << "deriv error norm = " << sqrt(derivErrorSq) << endl << endl;
222
Assembler::defaultVerbParams()->set<int>("global", 2);
223
Assembler::defaultVerbParams()->set<int>("assembly loop", 2);
224
double fluxErrorSq = evaluateIntegral(mesh, fluxErrExpr);
225
cout << "flux error norm = " << sqrt(fluxErrorSq) << endl << endl;
227
cout << "exact flux = " << evaluateIntegral(mesh, exactFluxExpr) << endl;
228
cout << "numerical flux = " << evaluateIntegral(mesh, numFluxExpr) << endl;
230
Sundance::passFailTest(sqrt(errorSq + derivErrorSq + fluxErrorSq), 1.0e-9);
39
string meshFile="builtin";
40
string solverFile = "aztec-ml.xml";
41
Sundance::setOption("meshFile", meshFile, "mesh file");
42
Sundance::setOption("nx", nx, "number of elements in x");
43
Sundance::setOption("ny", ny, "number of elements in y");
44
Sundance::setOption("solver", solverFile, "name of XML file for solver");
46
Sundance::init(&argc, &argv);
47
int np = MPIComm::world().getNProc();
53
* <Header level="subsubsection" name="vector_type">
54
* Creation of vector type
57
* Next we create a \verb+VectorType+ object. A \verb+VectorType+
58
* is an abstract factory which produces \verb+VectorSpace+ objects.
59
* A \verb+VectorSpace+ is itself a factory which can produce
60
* \verb+Vector+ objects which are, logically enough, vectors.
62
* Why this heirarchy of factorys? Vectors may need to be created
63
* inside code far below the user level, and the \verb+VectorSpace+
64
* encapsulates the information needed to build a vector of a
65
* given type, size, and distribution over processors. The
66
* \verb+VectorType+ is needed because we might need to select a
67
* particular {\it software representation} for a vector, {\it e.g.},
68
* Trilinos, Petsc, or some other library.
70
* By using an \verb+EpetraVectorType+, we will be creating
71
* \verb+EpetraVectorSpace+ vector spaces, which in turn
72
* create \verb+EpetraVector+ vectors.
74
VectorType<double> vecType = new EpetraVectorType();
77
* <Header level="subsubsection" name="mesh">
81
* The creation of a mesh object involves several intermediate
82
* objects: a \verb+MeshType+ and a \verb+MeshSource+. The
83
* \verb+MeshType+ specifies what mesh data structure will be used,
84
* and the \verb+MeshSource+ builds that data structure. How it is
85
* built will depend on the \verb+MeshSource+ subtype used. An
86
* \verb+ExodusMeshReader+, for instance, reads from an Exodus II file,
87
* while a \verb+PartitionedRectangleMesher+ builds a uniform
88
* triangulation of a rectangle.
90
* Once the \verb+MeshType+ and \verb+MeshSource+ objects have been
91
* defined, the mesh is created (read, built, whatever) by a call
92
* to the \verb+getMesh()+ method of \verb+MeshSource+.
94
MeshType meshType = new BasicSimplicialMeshType();
97
if (meshFile != "builtin")
99
mesher = new ExodusMeshReader("../../../examples-tutorial/meshes/"+meshFile, meshType);
105
PartitionedRectangleMesher::balanceXY(np, &npx, &npy);
106
TEST_FOR_EXCEPT(npx < 1);
107
TEST_FOR_EXCEPT(npy < 1);
108
TEST_FOR_EXCEPT(npx * npy != np);
109
mesher = new PartitionedRectangleMesher(0.0, 1.0, nx, npx,
110
0.0, 1.0, ny, npy, meshType);
112
Mesh mesh = mesher.getMesh();
115
bool meshOK = mesh.checkConsistency(meshFile+"-check");
118
cout << "mesh is OK" << endl;
122
cout << "mesh is INCONSISTENT" << endl;
124
mesh.dump(meshFile+"-dump");
126
WatchFlag watchMe("watch eqn");
127
watchMe.deactivate();
129
WatchFlag watchBC("watch BCs");
130
watchBC.setParam("integration setup", 0);
131
watchBC.setParam("integration", 0);
132
watchBC.setParam("fill", 0);
133
watchBC.setParam("evaluation", 0);
134
watchBC.deactivate();
139
* <Header level="subsubsection" name="cell_filter">
140
* Specification of geometric regions
143
* We'll need to specify subsets of the mesh on which equations
144
* or boundary conditions are defined. In many FEA codes this is
145
* done by explicit definition of element blocks, node sets, and
146
* side sets. Rather than working with sets explicitly at the user
147
* level, we instead work with filtering rules that produce
148
* sets of cells. These rules are represented by \verb+CellFilter+
151
* \verb+MaximalCellFilter+
152
* selects all cells having dimension equal to the spatial dimension
155
CellFilter interior = new MaximalCellFilter();
159
* \verb+DimensionalCellFilter+
160
* selects all cells of a specified dimension.
162
CellFilter edges = new DimensionalCellFilter(1);
169
if (meshFile != "builtin")
171
left = edges.labeledSubset(1);
172
right = edges.labeledSubset(2);
173
top = edges.labeledSubset(3);
174
bottom = edges.labeledSubset(4);
178
left = edges.subset(new LeftPointTest());
179
right = edges.subset(new RightPointTest());
180
top = edges.subset(new TopPointTest());
181
bottom = edges.subset(new BottomPointTest());
184
/* Create unknown and test functions, discretized using second-order
185
* Lagrange interpolants */
186
BasisFamily basis = new Lagrange(1);
187
Expr u = new UnknownFunction(basis, "u");
188
Expr v = new TestFunction(basis, "v");
190
/* Create differential operator and coordinate functions */
191
Expr dx = new Derivative(0);
192
Expr dy = new Derivative(1);
193
Expr grad = List(dx, dy);
194
Expr x = new CoordExpr(0);
195
Expr y = new CoordExpr(1);
197
/* We need a quadrature rule for doing the integrations */
198
QuadratureFamily quad2 = new GaussianQuadrature(2);
199
QuadratureFamily quad4 = new GaussianQuadrature(4);
201
/* Define the weak form */
202
//Expr eqn = Integral(interior, (grad*v)*(grad*u) + v, quad);
203
Expr one = new SundanceCore::Parameter(1.0);
204
Expr exactSoln = 2.0*x+y;
205
Expr eqn = Integral(interior, (grad*u)*(grad*v), quad2, watchMe);
206
/* Define the Dirichlet BC */
207
Expr h = new CellDiameterExpr();
208
Expr bc = EssentialBC(bottom+top+left+right, v*(u-exactSoln), quad4, watchBC);
210
/* We can now set up the linear problem! */
211
LinearProblem prob(mesh, eqn, bc, v, u, vecType);
214
ParameterXMLFileReader reader(solverFile);
215
ParameterList solverParams = reader.getParameters();
216
LinearSolver<double> solver
217
= LinearSolverBuilder::createSolver(solverParams);
219
Expr soln = prob.solve(solver);
221
DiscreteSpace discSpace2(mesh, new Lagrange(2), vecType);
222
DiscreteSpace discSpace0(mesh, new Lagrange(0), vecType);
223
L2Projector proj1(discSpace2, soln-exactSoln);
224
double pid = MPIComm::world().getRank();
225
L2Projector proj2(discSpace0, pid);
226
Expr errorDisc = proj1.project();
227
Expr pidDisc = proj2.project();
232
/* Write the field in VTK format */
233
FieldWriter w = new VTKWriter("Poisson2d");
235
w.addField("soln", new ExprFieldWrapper(soln[0]));
236
w.addField("error", new ExprFieldWrapper(errorDisc));
237
w.addField("rank", new ExprFieldWrapper(pidDisc));
240
FieldWriter w2 = new VerboseFieldWriter("mesh");
244
Expr err = exactSoln - soln;
245
Expr errExpr = Integral(interior,
249
Expr derivErr = dx*(exactSoln-soln);
250
Expr derivErrExpr = Integral(interior,
256
Expr fluxErrExpr = Integral(top,
257
pow(dy*(soln-exactSoln), 2),
258
new GaussianQuadrature(2));
261
watchBC.deactivate();
262
Expr exactFluxExpr = Integral(top,
264
new GaussianQuadrature(2), watchBC);
266
Expr numFluxExpr = Integral(top,
268
new GaussianQuadrature(2));
271
FunctionalEvaluator errInt(mesh, errExpr);
272
FunctionalEvaluator derivErrInt(mesh, derivErrExpr);
274
double errorSq = errInt.evaluate();
275
cout << "error norm = " << sqrt(errorSq) << endl << endl;
277
double derivErrorSq = derivErrInt.evaluate();
278
cout << "deriv error norm = " << sqrt(derivErrorSq) << endl << endl;
281
double fluxErrorSq = evaluateIntegral(mesh, fluxErrExpr);
282
cout << "flux error norm = " << sqrt(fluxErrorSq) << endl << endl;
285
cout << "exact flux = " << evaluateIntegral(mesh, exactFluxExpr) << endl;
286
cout << "numerical flux = " << evaluateIntegral(mesh, numFluxExpr) << endl;
288
Sundance::passFailTest(sqrt(errorSq + derivErrorSq + fluxErrorSq), 1.0e-9);
233
291
catch(exception& e)
235
Sundance::handleException(e);
293
Sundance::handleException(e);
237
295
Sundance::finalize(); return Sundance::testStatus();
239
297
return Sundance::testStatus();
245
305
int main(int argc, char** argv)
307
Sundance::init(&argc, &argv);
247
308
std::cout << "dummy Poisson2D PASSED. Enable exodus to run the actual test" << std::endl;
309
Sundance::finalize();