40 #ifndef LEVELSETSOLVER_H 41 #define LEVELSETSOLVER_H 1
44 #include <Epetra_ConfigDefs.h> 47 #include <Epetra_MpiComm.h> 49 #include <Epetra_SerialComm.h> 54 #include <lifev/core/algorithm/SolverAztecOO.hpp> 56 #include <lifev/core/LifeV.hpp> 58 #include <lifev/core/fem/TimeAdvanceBDF.hpp> 60 #include <lifev/core/solver/ADRAssembler.hpp> 61 #include <lifev/core/solver/ADRAssemblerIP.hpp> 63 #include <lifev/level_set/solver/LevelSetData.hpp> 68 #include <boost/shared_ptr.hpp> 164 template<
typename mesh_type,
typename solver_type = LifeV::SolverAztecOO>
174 typedef FESpace<mesh_type, map_Type> fespace_type;
175 typedef std::shared_ptr<fespace_type> fespace_ptrType;
177 typedef typename solver_type::vector_type vector_type;
179 typedef typename solver_type::matrix_type matrix_type;
180 typedef std::shared_ptr<matrix_type> matrix_ptrType;
182 typedef DataLevelSet data_type;
183 typedef std::shared_ptr<data_type> data_ptrType;
186 typedef std::shared_ptr<bdf_type> bdf_ptrType;
195 LevelSetSolver ( fespace_ptrType fespace, fespace_ptrType betaFESpace );
198 ~LevelSetSolver() {};
206 void setup (
const data_ptrType& data);
212 void initialize (
const vector_type& init);
218 void updateSystem (
const vector_type& beta,
BCHandler& bch,
const Real& time);
221 void setupLinearSolver (
const GetPot& dataFile,
const std::string& section =
"level-set");
227 void reinitializationDirect();
241 inline map_Type map()
const 243 return M_fespace->map();
247 inline vector_type solution()
const 253 inline data_ptrType data()
const 265 typedef ADRAssembler<mesh_type, matrix_type, vector_type> adrAssembler_type;
266 typedef ADRAssemblerIP<mesh_type, matrix_type, vector_type> ipAssembler_type;
269 typedef std::vector<Real> point_type;
270 typedef std::vector<point_type> face_type;
276 void updateFacesNormalsRadius();
277 Real computeUnsignedDistance (
const std::vector< Real >& point);
278 void cleanFacesData();
279 inline Real distanceBetweenPoints (
const point_type& P1,
const point_type& P2)
const 281 return std::sqrt ( (P1[0] - P2[0]) * (P1[0] - P2[0]) + (P1[1] - P2[1]) * (P1[1] - P2[1]) + (P1[2] - P2[2]) * (P1[2] - P2[2]) );
283 inline point_type crossProd (
const point_type& P1,
const point_type& P2)
const 287 n[0] = P1[1] * P2[2] - P1[2] * P2[1];
288 n[1] = P1[2] * P2[0] - P1[0] * P2[2];
289 n[2] = P1[0] * P2[1] - P1[1] * P2[0];
293 inline Real scalProd (
const point_type& P1,
const point_type& P2)
const 295 return P1[0] * P2[0] + P1[1] * P2[1] + P1[2] * P2[2];
297 inline Real norm (
const point_type& V)
const 299 return std::sqrt (V[0] * V[0] + V[1] * V[1] + V[2] * V[2]);
306 fespace_ptrType M_fespace;
307 fespace_ptrType M_betaFESpace;
309 vector_type M_solution;
311 adrAssembler_type M_adrAssembler;
312 ipAssembler_type M_ipAssembler;
314 matrix_ptrType M_systemMatrix;
315 matrix_ptrType M_massMatrix;
316 matrix_ptrType M_rhsMatrix;
324 solver_type M_linearSolver;
326 std::vector<face_type> M_faces;
327 std::vector<point_type> M_normals;
328 std::vector<Real> M_radius;
336 template<
typename mesh_type,
typename solver_type>
337 LevelSetSolver<mesh_type, solver_type>::
338 LevelSetSolver ( fespace_ptrType fespace, fespace_ptrType betaFESpace )
341 M_betaFESpace (betaFESpace),
343 M_solution (fespace->map() ),
352 M_rhs (fespace->map() ),
360 M_adrAssembler.setup (fespace, betaFESpace);
361 M_ipAssembler.setup (fespace, betaFESpace);
362 M_linearSolver.setCommunicator (fespace->map().commPtr() );
369 template<
typename mesh_type,
typename solver_type>
371 LevelSetSolver<mesh_type, solver_type>::
372 setup (
const data_ptrType& data)
375 M_bdf.reset (
new bdf_type() );
376 M_bdf->setup (data->dataTimeAdvance()->orderBDF() );
380 template<
typename mesh_type,
typename solver_type>
382 LevelSetSolver<mesh_type, solver_type>::
383 initialize (
const vector_type& init)
385 ASSERT (M_bdf != 0,
"Bdf structure not initialized. Use the setup method before initialize.");
387 M_bdf->setInitialCondition (init);
390 template<
typename mesh_type,
typename solver_type>
392 LevelSetSolver<mesh_type, solver_type>::
393 updateSystem (
const vector_type& beta,
BCHandler& bcHandler,
const Real& time)
395 ASSERT (M_bdf != 0,
"Bdf structure not initialized. Use the setup method before updateSystem.");
396 ASSERT (M_data != 0,
"No data available. Use the setup method before updateSystem.");
399 if (M_massMatrix == 0)
401 M_massMatrix.reset (
new matrix_type (M_fespace->map() ) );
402 M_adrAssembler.addMass (M_massMatrix, 1.0);
403 M_massMatrix->globalAssemble();
406 M_systemMatrix.reset (
new matrix_type (M_fespace->map() ) );
407 M_rhsMatrix.reset (
new matrix_type (M_fespace->map() ) );
410 *M_systemMatrix *= 0.0;
415 *M_systemMatrix += (*M_massMatrix) * ( M_bdf->coefficientFirstDerivative (0) / M_data->dataTime()->timeStep() );
418 M_adrAssembler.addAdvection (M_systemMatrix, beta);
421 if (M_data->stabilization() == DataLevelSet::IP)
423 if (M_data->IPTreatment() == DataLevelSet::IMPLICIT)
425 M_ipAssembler.addIPStabilization (M_systemMatrix, beta, M_data->IPCoef() );
427 else if (M_data->IPTreatment() == DataLevelSet::SEMI_IMPLICIT)
429 M_ipAssembler.addIPStabilizationStencil (M_systemMatrix, M_rhsMatrix, beta, M_data->IPCoef() );
431 else if (M_data->IPTreatment() == DataLevelSet::EXPLICIT)
433 M_ipAssembler.addIPStabilization (M_rhsMatrix, beta, M_data->IPCoef() );
439 M_systemMatrix->globalAssemble();
440 M_rhsMatrix->globalAssemble();
447 M_bdf->updateRHSContribution (M_data->dataTime()->timeStep() );
448 M_rhs += *M_massMatrix * M_bdf->rhsContributionFirstDerivative();
451 M_rhs += *M_rhsMatrix * M_solution;
455 bcHandler.bcUpdate (*M_fespace->mesh(), M_fespace->feBd(), M_fespace->dof() );
456 bcManage (*M_systemMatrix, M_rhs, *M_fespace->mesh(), M_fespace->dof(), bcHandler, M_fespace->feBd(), 1.0, time);
460 template<
typename mesh_type,
typename solver_type>
462 LevelSetSolver<mesh_type, solver_type>::
463 setupLinearSolver (
const GetPot& dataFile,
const std::string& section)
465 M_linearSolver.setDataFromGetPot ( dataFile, (section +
"/solver").data() );
466 M_linearSolver.setupPreconditioner ( dataFile, (section +
"/prec").data() );
469 template<
typename mesh_type,
typename solver_type>
471 LevelSetSolver<mesh_type, solver_type>::
474 ASSERT (M_systemMatrix != 0,
"No system matrix for the linear system! Build it before.");
475 ASSERT (M_bdf != 0,
"No bdf structure. Use the setup method before the iterate.");
477 M_linearSolver.setMatrix (*M_systemMatrix);
479 M_linearSolver.solveSystem (M_rhs, M_solution, M_systemMatrix);
481 M_bdf->shiftRight (M_solution);
486 template<
typename mesh_type,
typename solver_type>
488 LevelSetSolver<mesh_type, solver_type>::
489 reinitializationDirect()
491 updateFacesNormalsRadius();
498 const Epetra_MpiComm* my_comm =
dynamic_cast<Epetra_MpiComm
const*> (& (M_fespace->map().comm() ) );
500 unsigned int dim (3);
501 int nPt (M_fespace->mesh()->storedPoints() );
503 nb_proc = my_comm->NumProc();
504 my_rank = my_comm->MyPID();
507 std::vector< std::vector< Real > > my_points (nPt, std::vector<Real> (dim) );
508 for (
int iter_pt (0); iter_pt < nPt; ++iter_pt)
510 my_points[iter_pt][0] = M_fespace->mesh()->point (iter_pt).x();
511 my_points[iter_pt][1] = M_fespace->mesh()->point (iter_pt).y();
512 my_points[iter_pt][2] = M_fespace->mesh()->point (iter_pt).z();
518 std::vector < std::vector < Real > > temp_distances (nb_proc, std::vector< Real> (nPt, 0.0) );
526 for (
int i (0); i < nb_proc; ++i)
533 for (
int j (0); j < nb_proc; ++j)
537 MPI_Send (&nPt, 1, MPI_INT, j, 1, my_comm->Comm() );
542 for (
int d (0); d < nPt; ++d)
544 for (
int j (0); j < nb_proc; ++j)
551 MPI_Ssend (&my_points[d][0], dim, MPI_DOUBLE, j, 1, my_comm->Comm() );
557 for (
int iter_pt (0); iter_pt < nPt; ++iter_pt)
559 std::vector<Real> dof_coord;
560 dof_coord.push_back (my_points[iter_pt][0]);
561 dof_coord.push_back (my_points[iter_pt][1]);
562 dof_coord.push_back (my_points[iter_pt][2]);
563 temp_distances[i][iter_pt] = computeUnsignedDistance (dof_coord);
567 for (
int distToRecieve (0); distToRecieve < nPt; ++distToRecieve)
569 for (
int j (0); j < nb_proc; ++j)
576 MPI_Recv (& (temp_distances[j][distToRecieve]), 1, MPI_DOUBLE, j, 1, my_comm->Comm(), &status);
587 int n_pt_to_recieve (0);
588 MPI_Recv (&n_pt_to_recieve, 1, MPI_INT, i, 1, my_comm->Comm(), &status);
591 std::vector< std::vector< Real > > current_points (n_pt_to_recieve, std::vector< Real> (dim, 0) );
592 std::vector< Real> current_distances (n_pt_to_recieve, 0);
594 for (
int d (0); d < n_pt_to_recieve; ++d)
599 MPI_Recv (¤t_points[d][0], dim, MPI_DOUBLE, i, 1, my_comm->Comm(), &status);
602 for (
int iter_pt (0); iter_pt < n_pt_to_recieve; ++iter_pt)
604 std::vector< Real > current_pt (dim, 0);
605 current_pt[0] = current_points[iter_pt][0];
606 current_pt[1] = current_points[iter_pt][1];
607 current_pt[2] = current_points[iter_pt][2];
609 current_distances[iter_pt] = computeUnsignedDistance (current_pt);
612 for (
int iter_pt (0); iter_pt < n_pt_to_recieve; ++iter_pt)
617 MPI_Ssend (¤t_distances[iter_pt], 1, MPI_DOUBLE, i, 1, my_comm->Comm() );
630 vector_type repSol (M_solution,
Repeated);
632 for (
int iter_pt (0); iter_pt < nPt; ++iter_pt)
635 Real abs_dist (temp_distances[0][iter_pt]);
637 for (
int j (1); j < nb_proc; ++j)
639 if (temp_distances[j][iter_pt] < abs_dist)
641 abs_dist = temp_distances[j][iter_pt];
645 ID my_id (M_fespace->mesh()->point (iter_pt).id() );
647 if (repSol (my_id) < 0)
651 repSol (my_id) = abs_dist * sign;
656 M_solution = vector_type (repSol, Unique, Zero);
664 template<
typename mesh_type,
typename solver_type>
666 LevelSetSolver<mesh_type, solver_type>::
667 updateFacesNormalsRadius()
671 vector_type rep_solution (M_solution,
Repeated);
675 UInt n_el (M_fespace->mesh()->numElements() );
676 UInt n_dof (M_fespace->dof().numLocalDof() );
677 for (
ID iter_el (0); iter_el < n_el; ++iter_el)
681 std::vector< point_type> intersection_points;
685 for (
UInt iter_dof_1 (0); iter_dof_1 < n_dof; ++iter_dof_1)
687 ID id_dof_1 ( M_fespace->dof().localToGlobalMap (iter_el, iter_dof_1) );
688 Real val1 (rep_solution (id_dof_1) );
690 for (
UInt iter_dof_2 (iter_dof_1 + 1); iter_dof_2 < n_dof ; ++iter_dof_2)
692 ID id_dof_2 ( M_fespace->dof().localToGlobalMap (iter_el, iter_dof_2) );
693 Real val2 (rep_solution (id_dof_2) );
697 if ( (val1 * val2 <= 0) && ( (val1 != 0) || (val2 != 0) ) )
699 Real lambda (-val1 / (val2 - val1) );
701 point_type inter (3, 0);
703 inter[0] = (1 - lambda) * M_fespace->mesh()->element (iter_el).point (iter_dof_1).x()
704 + lambda * M_fespace->mesh()->element (iter_el).point (iter_dof_2).x() ;
705 inter[1] = (1 - lambda) * M_fespace->mesh()->element (iter_el).point (iter_dof_1).y()
706 + lambda * M_fespace->mesh()->element (iter_el).point (iter_dof_2).y() ;
707 inter[2] = (1 - lambda) * M_fespace->mesh()->element (iter_el).point (iter_dof_1).z()
708 + lambda * M_fespace->mesh()->element (iter_el).point (iter_dof_2).z() ;
710 intersection_points.push_back (inter);
720 if (intersection_points.size() == 3)
725 my_face.push_back (intersection_points[0]);
726 my_face.push_back (intersection_points[1]);
727 my_face.push_back (intersection_points[2]);
729 M_faces.push_back (my_face);
734 Real current_dist (0);
735 current_dist = distanceBetweenPoints (intersection_points[0], intersection_points[1]);
736 if (current_dist > radius)
738 radius = current_dist;
740 current_dist = distanceBetweenPoints (intersection_points[0], intersection_points[2]);
741 if (current_dist > radius)
743 radius = current_dist;
745 current_dist = distanceBetweenPoints (intersection_points[1], intersection_points[2]);
746 if (current_dist > radius)
748 radius = current_dist;
751 M_radius.push_back (radius);
755 point_type v1 (3, 0);
756 v1[0] = intersection_points[1][0] - intersection_points[0][0];
757 v1[1] = intersection_points[1][1] - intersection_points[0][1];
758 v1[2] = intersection_points[1][2] - intersection_points[0][2];
760 point_type v2 (3, 0);
761 v2[0] = intersection_points[2][0] - intersection_points[0][0];
762 v2[1] = intersection_points[2][1] - intersection_points[0][1];
763 v2[2] = intersection_points[2][2] - intersection_points[0][2];
765 point_type normal_face (crossProd (v1, v2) );
766 Real my_norm (norm (normal_face) );
767 normal_face[0] = normal_face[0] / my_norm;
768 normal_face[1] = normal_face[1] / my_norm;
769 normal_face[2] = normal_face[2] / my_norm;
771 M_normals.push_back (normal_face);
775 else if (intersection_points.size() == 4)
781 my_face.push_back (intersection_points[0]);
782 my_face.push_back (intersection_points[1]);
783 my_face.push_back (intersection_points[2]);
785 M_faces.push_back (my_face);
790 Real current_dist (0);
791 current_dist = distanceBetweenPoints (intersection_points[0], intersection_points[1]);
792 if (current_dist > radius)
794 radius = current_dist;
796 current_dist = distanceBetweenPoints (intersection_points[0], intersection_points[2]);
797 if (current_dist > radius)
799 radius = current_dist;
801 current_dist = distanceBetweenPoints (intersection_points[1], intersection_points[2]);
802 if (current_dist > radius)
804 radius = current_dist;
807 M_radius.push_back (radius);
809 point_type v1 (3, 0);
810 v1[0] = intersection_points[1][0] - intersection_points[0][0];
811 v1[1] = intersection_points[1][1] - intersection_points[0][1];
812 v1[2] = intersection_points[1][2] - intersection_points[0][2];
814 point_type v2 (3, 0);
815 v2[0] = intersection_points[2][0] - intersection_points[0][0];
816 v2[1] = intersection_points[2][1] - intersection_points[0][1];
817 v2[2] = intersection_points[2][2] - intersection_points[0][2];
819 point_type normal_face (crossProd (v1, v2) );
820 Real my_norm (norm (normal_face) );
821 normal_face[0] = normal_face[0] / my_norm;
822 normal_face[1] = normal_face[1] / my_norm;
823 normal_face[2] = normal_face[2] / my_norm;
825 M_normals.push_back (normal_face);
829 face_type my_second_face;
831 my_second_face.push_back (intersection_points[3]);
833 for (
int i (0); i < 3; ++i)
835 int other_1 ( (i + 1) % 3);
836 int other_2 ( (i + 2) % 3);
839 v[0] = intersection_points[other_2][0] - intersection_points[other_1][0];
840 v[1] = intersection_points[other_2][1] - intersection_points[other_1][1];
841 v[2] = intersection_points[other_2][2] - intersection_points[other_1][2];
843 point_type normal_v (crossProd (v, normal_face) );
845 point_type o1_to_i (3, 0);
846 o1_to_i[0] = intersection_points[i][0] - intersection_points[other_1][0];
847 o1_to_i[1] = intersection_points[i][1] - intersection_points[other_1][1];
848 o1_to_i[2] = intersection_points[i][2] - intersection_points[other_1][2];
850 point_type o1_to_inter3 (3, 0);
851 o1_to_inter3[0] = intersection_points[3][0] - intersection_points[other_1][0];
852 o1_to_inter3[1] = intersection_points[3][1] - intersection_points[other_1][1];
853 o1_to_inter3[2] = intersection_points[3][2] - intersection_points[other_1][2];
855 if ( scalProd (normal_v, o1_to_i) * scalProd (normal_v, o1_to_inter3) > 0)
857 my_second_face.push_back (intersection_points[i]);
862 ASSERT (my_second_face.size() == 3,
"Internal error while computing the faces");
863 M_faces.push_back (my_second_face);
868 current_dist = distanceBetweenPoints (my_second_face[0], my_second_face[1]);
869 if (current_dist > radius)
871 radius = current_dist;
873 current_dist = distanceBetweenPoints (my_second_face[0], my_second_face[2]);
874 if (current_dist > radius)
876 radius = current_dist;
878 current_dist = distanceBetweenPoints (my_second_face[1], my_second_face[2]);
879 if (current_dist > radius)
881 radius = current_dist;
884 M_radius.push_back (radius);
888 M_normals.push_back (normal_face);
893 else if (intersection_points.size() > 0)
895 std::cout << intersection_points.size() << std::endl;
896 ERROR_MSG (
"Internal error in the localization of the interface");
900 ASSERT (M_faces.size() == M_radius.size(),
"Internal non coerance");
901 ASSERT (M_faces.size() == M_normals.size(),
"Internal non coerance");
905 template<
typename mesh_type,
typename solver_type>
907 LevelSetSolver<mesh_type, solver_type>::
908 computeUnsignedDistance (
const std::vector< Real >& point)
917 Real absdist (std::numeric_limits<
double>::max() );
920 int nbFaces (
this->M_faces.size() );
923 std::vector<Real> dist_lower_bound (nbFaces);
931 for (
int iter_face (0); iter_face < nbFaces; ++iter_face)
933 Real current_dist (distanceBetweenPoints (point, M_faces[iter_face][0]) );
934 dist_lower_bound[iter_face] = current_dist - M_radius[iter_face];
936 if (current_dist < absdist)
938 absdist = current_dist;
947 for (
int iter_face (0); iter_face < nbFaces; ++iter_face)
950 if (dist_lower_bound[iter_face] <= absdist)
953 Real current_abs_dist (std::numeric_limits<
double>::max() );
959 point_type point_to_face (3, 0);
960 point_to_face[0] = point[0] - M_faces[iter_face][0][0];
961 point_to_face[1] = point[1] - M_faces[iter_face][0][1];
962 point_to_face[2] = point[2] - M_faces[iter_face][0][2];
964 Real lambda = scalProd (point_to_face, M_normals[iter_face]);
965 point_type projected_point (3, 0);
966 projected_point[0] = point[0] - lambda * M_normals[iter_face][0];
967 projected_point[1] = point[1] - lambda * M_normals[iter_face][1];
968 projected_point[2] = point[2] - lambda * M_normals[iter_face][2];
972 current_abs_dist = distanceBetweenPoints (point, projected_point);
977 for (
int iter_edge (0); iter_edge < 3 ; ++iter_edge)
979 int vertex1 (iter_edge), vertex2 ( (iter_edge + 1) % 3), vertex_out ( (iter_edge + 2) % 3);
982 point_type edge_vector (3, 0);
983 edge_vector[0] = M_faces[iter_face][vertex2][0] - M_faces[iter_face][vertex1][0];
984 edge_vector[1] = M_faces[iter_face][vertex2][1] - M_faces[iter_face][vertex1][1];
985 edge_vector[2] = M_faces[iter_face][vertex2][2] - M_faces[iter_face][vertex1][2];
989 point_type edge_normal (crossProd (M_normals[iter_face], edge_vector) );
991 Real edge_normal_norm (norm (edge_normal) );
992 edge_normal[0] = edge_normal[0] / edge_normal_norm;
993 edge_normal[1] = edge_normal[1] / edge_normal_norm;
994 edge_normal[2] = edge_normal[2] / edge_normal_norm;
998 point_type projpoint_to_edge (3, 0);
999 projpoint_to_edge[0] = projected_point[0] - M_faces[iter_face][vertex1][0];
1000 projpoint_to_edge[1] = projected_point[1] - M_faces[iter_face][vertex1][1];
1001 projpoint_to_edge[2] = projected_point[2] - M_faces[iter_face][vertex1][2];
1003 point_type vertex_out_to_edge (3, 0);
1004 vertex_out_to_edge[0] = M_faces[iter_face][vertex_out][0] - M_faces[iter_face][vertex1][0];
1005 vertex_out_to_edge[1] = M_faces[iter_face][vertex_out][1] - M_faces[iter_face][vertex1][1];
1006 vertex_out_to_edge[2] = M_faces[iter_face][vertex_out][2] - M_faces[iter_face][vertex1][2];
1010 if (scalProd (edge_normal, projpoint_to_edge) * scalProd (edge_normal, vertex_out_to_edge) < 0)
1018 Real lambda_2 (scalProd (edge_normal, projpoint_to_edge) );
1019 point_type projproj_point (3, 0);
1020 projproj_point[0] = projected_point[0] - lambda_2 * edge_normal[0];
1021 projproj_point[1] = projected_point[1] - lambda_2 * edge_normal[1];
1022 projproj_point[2] = projected_point[2] - lambda_2 * edge_normal[2];
1024 point_type projprojpoint_to_edge (3, 0);
1025 projprojpoint_to_edge[0] = projproj_point[0] - M_faces[iter_face][vertex1][0];
1026 projprojpoint_to_edge[1] = projproj_point[1] - M_faces[iter_face][vertex1][1];
1027 projprojpoint_to_edge[2] = projproj_point[2] - M_faces[iter_face][vertex1][2];
1029 Real report (scalProd (projprojpoint_to_edge, edge_vector) / scalProd (edge_vector, edge_vector) );
1033 current_abs_dist = distanceBetweenPoints (point, M_faces[iter_face][vertex1]);
1035 else if (report <= 1)
1037 current_abs_dist = distanceBetweenPoints (point, projproj_point);
1041 current_abs_dist = distanceBetweenPoints (point, M_faces[iter_face][vertex2]);
1053 if (current_abs_dist <= absdist)
1055 absdist = current_abs_dist;
1063 template<
typename mesh_type,
typename solver_type>
1065 LevelSetSolver<mesh_type, solver_type>::
BCHandler - class for handling boundary conditions.
Epetra_Import const & importer()
Getter for the Epetra_Import.
class TimeAdvanceBDF - Backward differencing formula time discretization for the first and the second...
double Real
Generic real data.
ADRAssembler - This class add into given matrices terms corresponding to the space discretization of ...
uint32_type UInt
generic unsigned integer (used mainly for addressing)