|
@@ -205,30 +205,38 @@ namespace Lemma {
|
205
|
205
|
//ConstructLoadVector();
|
206
|
206
|
|
207
|
207
|
std::cout << "\nSolving" << std::endl;
|
208
|
|
- std::cout << " rows\tcols\n";
|
209
|
|
- std::cout << "A: " << A.rows() << "\t" << A.cols() << std::endl;
|
210
|
|
- std::cout << "g: " << g.rows() << "\t" << g.cols() << std::endl;
|
|
208
|
+
|
|
209
|
+ std::cout << std::setw(5) << " " << std::setw(14) << "rows" << std::setw(14) << "cols" << std::endl;
|
|
210
|
+ std::cout << std::setw(5) << " " << std::setw(14) << "--------" << std::setw(14) << "--------" << std::endl;
|
|
211
|
+ std::cout << std::setw(5) << "A:" << std::setw(14) << A.rows() << std::setw(14) << A.cols() << std::endl;
|
|
212
|
+ std::cout << std::setw(5) << "g:" << std::setw(14) << g.rows() << std::setw(14) << g.cols() << std::endl;
|
211
|
213
|
|
212
|
214
|
////////////////////////////////////////////////////////////
|
213
|
215
|
// Solving:
|
214
|
216
|
//Eigen::SimplicialCholesky<Eigen::SparseMatrix<Real>, Eigen::Lower > chol(A); // performs a Cholesky factorization of A
|
215
|
217
|
//VectorXr u = chol.solve(g);
|
216
|
|
-
|
217
|
|
- //Eigen::SparseLU<Eigen::SparseMatrix<Real, Eigen::ColMajor>, Eigen::COLAMDOrdering<int> > solver;
|
218
|
|
- //solver.analyzePattern(A);
|
219
|
|
- //solver.factorize(A);
|
220
|
|
- //VectorXr u = solver.solve(g);
|
221
|
|
-
|
222
|
|
- //#ifdef CGSOLVE
|
223
|
|
- //Eigen::ConjugateGradient<Eigen::SparseMatrix<Real, Eigen::Lower > Eigen::DiagonalPreconditioner > cg;
|
224
|
|
- //Eigen::ConjugateGradient< Eigen::SparseMatrix<Real> > cg(A);
|
|
218
|
+ //#define LUSOLVE
|
|
219
|
+ #ifdef LUSOLVE
|
|
220
|
+ Eigen::SparseLU<Eigen::SparseMatrix<Real, Eigen::ColMajor>, Eigen::COLAMDOrdering<int> > solver;
|
|
221
|
+ std::cout << "LU analyze pattern" << std::endl;
|
|
222
|
+ solver.analyzePattern(A);
|
|
223
|
+ std::cout << "LU factorizing" << std::endl;
|
|
224
|
+ solver.factorize(A);
|
|
225
|
+ std::cout << "LU solving" << std::endl;
|
|
226
|
+ solver.factorize(A);
|
|
227
|
+ VectorXr u = solver.solve(g);
|
|
228
|
+ #endif
|
|
229
|
+
|
|
230
|
+ #define CGSOLVE
|
|
231
|
+ #ifdef CGSOLVE
|
|
232
|
+ // TODO try IncompleteLUT preconditioner
|
225
|
233
|
Eigen::BiCGSTAB<Eigen::SparseMatrix<Real> > cg(A);
|
226
|
234
|
//cg.setMaxIterations(3000);
|
227
|
235
|
//cg.setTolerance(1e-28);
|
228
|
236
|
VectorXr u = cg.solve(g);
|
229
|
237
|
std::cout << "#iterations: " << cg.iterations() << std::endl;
|
230
|
238
|
std::cout << "estimated error: " << cg.error() << std::endl;
|
231
|
|
- //#endif
|
|
239
|
+ #endif
|
232
|
240
|
|
233
|
241
|
vtkDoubleArray *gArray = vtkDoubleArray::New();
|
234
|
242
|
vtkDoubleArray *uArray = vtkDoubleArray::New();
|
|
@@ -284,7 +292,6 @@ namespace Lemma {
|
284
|
292
|
GCell = true;
|
285
|
293
|
}
|
286
|
294
|
|
287
|
|
-
|
288
|
295
|
// Here we iterate over all of the cells
|
289
|
296
|
for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
|
290
|
297
|
|
|
@@ -315,19 +322,8 @@ namespace Lemma {
|
315
|
322
|
ID[3] = Ids->GetId(3);
|
316
|
323
|
|
317
|
324
|
Real sigma_bar(0);
|
318
|
|
- /*
|
319
|
|
- if (GCell) {
|
320
|
|
- sigma_bar = vtkGrid->GetCellData()->GetScalars("G")->GetTuple1(ic);
|
321
|
|
- } else {
|
322
|
|
- sigma_bar = vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0]);
|
323
|
|
- sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1]);
|
324
|
|
- sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2]);
|
325
|
|
- sigma_bar += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3]);
|
326
|
|
- sigma_bar /= 4.;
|
327
|
|
- }
|
328
|
|
- */
|
329
|
|
-
|
330
|
325
|
// TEST VOID IN SIGMA!! TODO DON"T KEEP THIS
|
|
326
|
+ /*
|
331
|
327
|
Real xc = C.col(1).array().mean();
|
332
|
328
|
Real yc = C.col(2).array().mean();
|
333
|
329
|
Real zc = C.col(3).array().mean();
|
|
@@ -336,40 +332,26 @@ namespace Lemma {
|
336
|
332
|
} else {
|
337
|
333
|
sigma_bar = 1.;
|
338
|
334
|
}
|
|
335
|
+ */
|
339
|
336
|
sigma_bar = 1.;
|
340
|
337
|
|
341
|
338
|
|
342
|
339
|
for (int ii=0; ii<4; ++ii) {
|
343
|
340
|
int bbi = vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0];
|
344
|
341
|
if (bbi) {
|
|
342
|
+ /* Dirichlet boundary */
|
345
|
343
|
coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[ii], 1));
|
346
|
344
|
} else {
|
347
|
345
|
for (int jj=0; jj<4; ++jj) {
|
348
|
|
- /* homogeneous Dirichlet boundary */
|
349
|
|
- //if (jj==ii && C(ii,3)==13.5) {
|
350
|
|
- //if (jj==ii && ((bb-1.)<1e-8) ) {
|
351
|
|
- // Apply Homogeneous Dirichlet Boundary conditions
|
352
|
|
- // Real bb = vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0];
|
353
|
|
- // Real bdry = (1./(BndryH*BndryH))*BndrySigma*bb; // + sum;
|
354
|
|
- //Real bdry = GradPhi.col(ii).tail<3>().dot(GradPhi.col(ii).tail<3>())*BndrySigma*bb; // + sum;
|
355
|
|
- // coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[jj], bdry + GradPhi.col(ii).tail<3>().dot(GradPhi.col(jj).tail<3>() ) * V * sigma_bar ) );
|
356
|
|
- //coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[jj], 1));
|
357
|
|
- //break;
|
358
|
|
- //} else {
|
359
|
346
|
coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[jj], GradPhi.col(ii).tail<3>().dot(GradPhi.col(jj).tail<3>() ) * V * sigma_bar ) );
|
360
|
|
- //}
|
361
|
|
- /* */
|
362
|
|
- /* Inhomogeneous Dirichlet */
|
363
|
|
- //coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[jj], GradPhi.col(ii).tail<3>().dot(GradPhi.col(jj).tail<3>())*V*sigma_bar ));
|
364
|
|
- // Stiffness matrix no longer contains boundary conditions...
|
365
|
|
- //coeffs.push_back( Eigen::Triplet<Real> ( ID[ii], ID[jj], GradPhi.col(ii).tail<3>().dot(GradPhi.col(jj).tail<3>() ) * V * sigma_bar ) );
|
|
347
|
+ }
|
366
|
348
|
}
|
367
|
349
|
}
|
368
|
|
- }
|
369
|
|
- //std::cout << "\r" << (int)(1e2*((float)(ic) / (float)(vtkGrid->GetNumberOfCells()))) << std::flush ;
|
|
350
|
+ std::cout << "\r" << (int)(1e2*((float)(ic) / (float)(vtkGrid->GetNumberOfCells()))) << std::flush ;
|
370
|
351
|
}
|
371
|
352
|
A.setFromTriplets(coeffs.begin(), coeffs.end());
|
372
|
|
- //std::cout << "A\n" << A << std::endl;
|
|
353
|
+ A.finalize();
|
|
354
|
+ A.makeCompressed();
|
373
|
355
|
}
|
374
|
356
|
|
375
|
357
|
void FEM4EllipticPDE::SetupPotential() {
|
|
@@ -379,7 +361,7 @@ namespace Lemma {
|
379
|
361
|
std::cout << "\nBuilding load vector (g)" << std::endl;
|
380
|
362
|
g = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
|
381
|
363
|
std::cout << "made g with " << vtkGrid->GetNumberOfPoints() << " points" << std::endl;
|
382
|
|
- VectorXr DB = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
|
|
364
|
+
|
383
|
365
|
for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
|
384
|
366
|
|
385
|
367
|
Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
|
|
@@ -392,8 +374,9 @@ namespace Lemma {
|
392
|
374
|
}
|
393
|
375
|
|
394
|
376
|
Real V = (1./6.) * C.determinant(); // volume of tetrahedra
|
395
|
|
- Eigen::Matrix<Real, 4, 4> GradPhi = C.inverse(); // nabla \phi
|
|
377
|
+ //Eigen::Matrix<Real, 4, 4> GradPhi = C.inverse(); // nabla \phi
|
396
|
378
|
|
|
379
|
+ /* The indices */
|
397
|
380
|
vtkIdList* Ids = vtkGrid->GetCell(ic)->GetPointIds();
|
398
|
381
|
int ID[4];
|
399
|
382
|
ID[0] = Ids->GetId(0);
|
|
@@ -401,56 +384,19 @@ namespace Lemma {
|
401
|
384
|
ID[2] = Ids->GetId(2);
|
402
|
385
|
ID[3] = Ids->GetId(3);
|
403
|
386
|
|
404
|
|
- /*
|
405
|
|
- Real avg(0);
|
406
|
|
- Real GG[4];
|
407
|
|
- for (int ii=0; ii<4; ++ii) {
|
408
|
|
- GG[ii] = vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[ii])[0];
|
409
|
|
- //avg /= 4.;
|
410
|
|
- }
|
411
|
|
- if ( std::abs( (GG[0]+GG[1]+GG[2]+GG[3])/4. - GG[0]) < 1e-5) {
|
412
|
|
- avg = GG[0];
|
413
|
|
- }
|
414
|
|
- */
|
415
|
|
-
|
416
|
|
- /*
|
417
|
|
- VectorXr W = VectorXr::Zero(4);
|
|
387
|
+ /* Fill the RHS vector with Dirichlet conditions or fuction value */
|
418
|
388
|
for (int ii=0; ii<4; ++ii) {
|
419
|
|
- W[ii] = vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0] *
|
420
|
|
- vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
421
|
|
- DB[ID[ii]] = vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0] *
|
422
|
|
- vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
423
|
|
- }
|
424
|
|
- //auto G = GradPhi.block<3,4>(1,0).transpose()*GradPhi.block<3,4>(1,0)*W;
|
425
|
|
- VectorXr G = GradPhi.block<3,4>(1,0).transpose()*GradPhi.block<3,4>(1,0)*W;
|
426
|
|
- Real sigma_bar(1.);
|
427
|
|
- */
|
428
|
|
-
|
429
|
|
- for (int ii=0; ii<4; ++ii) {
|
430
|
|
- // avg += vtkGrid->GetPointData()->GetScalars()->GetTuple(ID[ii])[0];
|
431
|
|
- // //if ( std::abs(vtkGrid->GetPointData()->GetScalars()->GetTuple(ID[ii])[0]) > 1e-3 )
|
432
|
|
- //}
|
433
|
|
- //TODO this seems wrong!
|
434
|
|
- //avg /= 4.;
|
435
|
|
- // TODO test code remove
|
436
|
389
|
if (vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
|
437
|
390
|
g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
438
|
391
|
} else {
|
439
|
|
- g(ID[ii]) += (PI*V)*(vtkGrid->GetCellData()->GetScalars("G")->GetTuple(ic)[0]); // Why 3.0??
|
|
392
|
+ g(ID[ii]) += (V/4.)*(vtkGrid->GetCellData()->GetScalars("G")->GetTuple(ic)[0]); // Why 3.0??
|
440
|
393
|
}
|
441
|
|
- //if (std::abs(C(ii,3)-13.5) > 1e-5) {
|
442
|
|
- // g(ID[ii]) -= G[ii]*(V)*sigma_bar;
|
443
|
|
- //}
|
444
|
|
- //g(ID[ii]) += V/4*avg;
|
445
|
|
- //g(ID[ii]) += 6.67 *(V/4.) * avg;
|
446
|
394
|
}
|
447
|
|
- //g(ID[0]) += (V/4.) * avg;
|
448
|
|
- }
|
449
|
|
- //g -= A*DB;
|
450
|
395
|
|
|
396
|
+ }
|
451
|
397
|
}
|
452
|
398
|
|
453
|
|
- void FEM4EllipticPDE::SolveOLD(const std::string& fname) {
|
|
399
|
+ void FEM4EllipticPDE::SolveOLD2(const std::string& fname) {
|
454
|
400
|
|
455
|
401
|
Real r0[3];
|
456
|
402
|
Real r1[3];
|