|
@@ -201,7 +201,9 @@ namespace Lemma {
|
201
|
201
|
|
202
|
202
|
void FEM4EllipticPDE::Solve( const std::string& resfile ) {
|
203
|
203
|
ConstructAMatrix();
|
204
|
|
- SetupPotential();
|
|
204
|
+ //SetupLineSourcePotential();
|
|
205
|
+ SetupSurfaceSourcePotential();
|
|
206
|
+ //SetupPotential();
|
205
|
207
|
//ConstructLoadVector();
|
206
|
208
|
|
207
|
209
|
std::cout << "\nSolving" << std::endl;
|
|
@@ -389,10 +391,164 @@ namespace Lemma {
|
389
|
391
|
if (vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
|
390
|
392
|
g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
391
|
393
|
} else {
|
392
|
|
- g(ID[ii]) += (V/4.)*(vtkGrid->GetCellData()->GetScalars("G")->GetTuple(ic)[0]); // Why 3.0??
|
|
394
|
+ g(ID[ii]) += (V/4.)*(vtkGrid->GetCellData()->GetScalars("G")->GetTuple(ic)[0]); // Cell data
|
|
395
|
+ /* for point data, determine if it is a point or line source */
|
|
396
|
+ //g(ID[ii]) = (vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[ii])[0]); // Point source
|
|
397
|
+ //g(ID[ii]) = (vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[ii])[0]); // Point source
|
393
|
398
|
}
|
394
|
399
|
}
|
395
|
400
|
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+ }
|
|
404
|
+ }
|
|
405
|
+
|
|
406
|
+ void FEM4EllipticPDE::SetupLineSourcePotential() {
|
|
407
|
+
|
|
408
|
+ std::cerr << " FEM4EllipticPDE::SetupLineSourcePotential is not completed\n";
|
|
409
|
+ exit(1);
|
|
410
|
+
|
|
411
|
+ ////////////////////////////////////////////////////////////
|
|
412
|
+ // Load vector g
|
|
413
|
+ std::cout << "\nBuilding load vector (g)" << std::endl;
|
|
414
|
+ g = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
|
|
415
|
+ std::cout << "made g with " << vtkGrid->GetNumberOfPoints() << " points" << std::endl;
|
|
416
|
+
|
|
417
|
+ for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
|
|
418
|
+
|
|
419
|
+ Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
|
|
420
|
+ for (int ii=0; ii<4; ++ii) {
|
|
421
|
+ double* pts = vtkGrid->GetCell(ic)->GetPoints()->GetPoint(ii); //[ipc] ;
|
|
422
|
+ C(ii, 0) = 1;
|
|
423
|
+ C(ii, 1) = pts[0];
|
|
424
|
+ C(ii, 2) = pts[1];
|
|
425
|
+ C(ii, 3) = pts[2];
|
|
426
|
+ }
|
|
427
|
+
|
|
428
|
+ Real V = (1./6.) * C.determinant(); // volume of tetrahedra
|
|
429
|
+ //Eigen::Matrix<Real, 4, 4> GradPhi = C.inverse(); // nabla \phi
|
|
430
|
+
|
|
431
|
+ /* The indices */
|
|
432
|
+ vtkIdList* Ids = vtkGrid->GetCell(ic)->GetPointIds();
|
|
433
|
+ int ID[4];
|
|
434
|
+ ID[0] = Ids->GetId(0);
|
|
435
|
+ ID[1] = Ids->GetId(1);
|
|
436
|
+ ID[2] = Ids->GetId(2);
|
|
437
|
+ ID[3] = Ids->GetId(3);
|
|
438
|
+
|
|
439
|
+ /* Line source between nodes */
|
|
440
|
+ for (int ii=0; ii<4; ++ii) {
|
|
441
|
+ if (vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
|
|
442
|
+ g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
|
443
|
+ } else {
|
|
444
|
+ Real nv1 = vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[ii])[0];
|
|
445
|
+ for (int jj=ii+1; jj<4; ++jj) {
|
|
446
|
+ Real nv2 = vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[jj])[0];
|
|
447
|
+ if ( std::abs(nv1) > 1e-12 && std::abs(nv2) > 1e-12) {
|
|
448
|
+ Real length = ( C.row(ii).tail<3>()-C.row(jj).tail<3>() ).norm();
|
|
449
|
+
|
|
450
|
+ g(ID[ii]) += ((nv1+nv2)/2.)/(length);//*(V/4.);// * (vtkGrid->GetPointData()->GetScalars("G")->GetTuple(ID[ii])[0]); // Point source
|
|
451
|
+ }
|
|
452
|
+ }
|
|
453
|
+ }
|
|
454
|
+ }
|
|
455
|
+ }
|
|
456
|
+
|
|
457
|
+ }
|
|
458
|
+
|
|
459
|
+ void FEM4EllipticPDE::SetupSurfaceSourcePotential() {
|
|
460
|
+
|
|
461
|
+ ////////////////////////////////////////////////////////////
|
|
462
|
+ // Load vector g
|
|
463
|
+ std::cout << "\nBuilding load vector (g)" << std::endl;
|
|
464
|
+ g = VectorXr::Zero(vtkGrid->GetNumberOfPoints());
|
|
465
|
+ std::cout << "made g with " << vtkGrid->GetNumberOfPoints() << " points" << std::endl;
|
|
466
|
+
|
|
467
|
+ for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
|
|
468
|
+
|
|
469
|
+ Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
|
|
470
|
+ for (int ii=0; ii<4; ++ii) {
|
|
471
|
+ double* pts = vtkGrid->GetCell(ic)->GetPoints()->GetPoint(ii); //[ipc] ;
|
|
472
|
+ C(ii, 0) = 1;
|
|
473
|
+ C(ii, 1) = pts[0];
|
|
474
|
+ C(ii, 2) = pts[1];
|
|
475
|
+ C(ii, 3) = pts[2];
|
|
476
|
+ }
|
|
477
|
+
|
|
478
|
+ Real V = (1./6.) * C.determinant(); // volume of tetrahedra
|
|
479
|
+ //Eigen::Matrix<Real, 4, 4> GradPhi = C.inverse(); // nabla \phi
|
|
480
|
+
|
|
481
|
+ /* The indices */
|
|
482
|
+ vtkIdList* Ids = vtkGrid->GetCell(ic)->GetPointIds();
|
|
483
|
+ int ID[4];
|
|
484
|
+ ID[0] = Ids->GetId(0);
|
|
485
|
+ ID[1] = Ids->GetId(1);
|
|
486
|
+ ID[2] = Ids->GetId(2);
|
|
487
|
+ ID[3] = Ids->GetId(3);
|
|
488
|
+
|
|
489
|
+ // Apply Dirichlet conditions
|
|
490
|
+ for (int ii=0; ii<4; ++ii) {
|
|
491
|
+ if (vtkGrid->GetPointData()->GetScalars("HomogeneousDirichlet")->GetTuple(ID[ii])[0]) {
|
|
492
|
+ g(ID[ii]) += vtkGrid->GetPointData()->GetScalars("analytic_phi")->GetTuple(ID[ii])[0];
|
|
493
|
+ }
|
|
494
|
+ }
|
|
495
|
+
|
|
496
|
+ /* the 4 faces of the tetrahedra
|
|
497
|
+ ID[0] ID[1] ID[2]
|
|
498
|
+ ID[0] ID[1] ID[3]
|
|
499
|
+ ID[0] ID[2] ID[3]
|
|
500
|
+ ID[1] ID[2] ID[3]
|
|
501
|
+ */
|
|
502
|
+ //Real i4pi = .99738684646226885559*.961*PI/6.;//(4.*PI);// * V/4.;
|
|
503
|
+ //Real i4pi = .99738684646226885559*.961*PI/6.;//(4.*PI);// * V/4.;
|
|
504
|
+ //Real i4pi = 0.9584887594502403*PI/6.;//(4.*PI);// * V/4.;
|
|
505
|
+ Real i4pi = .5;// 0.1597132348845018*PI; // very nearly .5
|
|
506
|
+ /* surfaces of tetrahedra */
|
|
507
|
+ // Face 0, ID 0,1,2
|
|
508
|
+ Eigen::Matrix<Real, 3, 3> CC = Eigen::Matrix<Real, 3, 3>::Ones() ;
|
|
509
|
+ if ( std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])) > 1e-12 &&
|
|
510
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])) > 1e-12 &&
|
|
511
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])) > 1e-12 ) {
|
|
512
|
+ CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
|
|
513
|
+ CC.col(2) = C.row(0).tail<3>() - C.row(2).tail<3>();
|
|
514
|
+ Real TA = .5*CC.col(1).cross(CC.col(2)).norm();
|
|
515
|
+ g(ID[0]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])*TA/3. * i4pi ;
|
|
516
|
+ g(ID[1]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])*TA/3. * i4pi ;
|
|
517
|
+ g(ID[2]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])*TA/3. * i4pi ;
|
|
518
|
+ }
|
|
519
|
+ // Face 1, ID 0,1,3
|
|
520
|
+ if ( std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])) > 1e-12 &&
|
|
521
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])) > 1e-12 &&
|
|
522
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])) > 1e-12 ) {
|
|
523
|
+ CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
|
|
524
|
+ CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
|
|
525
|
+ Real TA = .5*CC.col(1).cross(CC.col(2)).norm();
|
|
526
|
+ g(ID[0]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])*TA/3. * i4pi ;
|
|
527
|
+ g(ID[1]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])*TA/3. * i4pi ;
|
|
528
|
+ g(ID[3]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])*TA/3. * i4pi ;
|
|
529
|
+ }
|
|
530
|
+ // Face 2, ID 0,2,3
|
|
531
|
+ if ( std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])) > 1e-12 &&
|
|
532
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])) > 1e-12 &&
|
|
533
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])) > 1e-12 ) {
|
|
534
|
+ CC.col(1) = C.row(0).tail<3>() - C.row(2).tail<3>();
|
|
535
|
+ CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
|
|
536
|
+ Real TA = .5*CC.col(1).cross(CC.col(2)).norm();
|
|
537
|
+ g(ID[0]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[0])*TA/3. * i4pi ;
|
|
538
|
+ g(ID[2]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])*TA/3. * i4pi ;
|
|
539
|
+ g(ID[3]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])*TA/3. * i4pi ;
|
|
540
|
+ }
|
|
541
|
+ // Face 3, ID 1,2,3
|
|
542
|
+ if ( std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])) > 1e-12 &&
|
|
543
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])) > 1e-12 &&
|
|
544
|
+ std::abs(vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])) > 1e-12 ) {
|
|
545
|
+ CC.col(1) = C.row(1).tail<3>() - C.row(2).tail<3>();
|
|
546
|
+ CC.col(2) = C.row(1).tail<3>() - C.row(3).tail<3>();
|
|
547
|
+ Real TA = .5*CC.col(1).cross(CC.col(2)).norm();
|
|
548
|
+ g(ID[1]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[1])*TA/3. * i4pi ;
|
|
549
|
+ g(ID[2]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[2])*TA/3. * i4pi ;
|
|
550
|
+ g(ID[3]) += vtkGrid->GetPointData()->GetScalars("G")->GetTuple1(ID[3])*TA/3. * i4pi ;
|
|
551
|
+ }
|
396
|
552
|
}
|
397
|
553
|
}
|
398
|
554
|
|