26 #include <QApplication>
28 #include "DECExamplesCommon.h"
31 #include "DGtal/math/linalg/EigenSupport.h"
32 #include "DGtal/dec/DiscreteExteriorCalculus.h"
33 #include "DGtal/dec/DiscreteExteriorCalculusSolver.h"
34 #include "DGtal/dec/DiscreteExteriorCalculusFactory.h"
36 #include "DGtal/io/viewers/Viewer3D.h"
37 #include "DGtal/io/boards/Board2D.h"
38 #include "DGtal/io/readers/GenericReader.h"
40 using namespace DGtal;
43 void solve2d_laplace()
53 Calculus
calculus = CalculusFactory::createFromDigitalSet(generateRingSet(
domain));
60 trace.
info() <<
"laplace = " << laplace << endl;
71 board.
saveSVG(
"solve_laplace_calculus.svg");
83 Calculus::DualForm0 solution = solver.
solve(dirac);
85 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
93 board.
saveSVG(
"solve_laplace_simplicial_llt.svg");
105 Calculus::DualForm0 solution = solver.
solve(dirac);
107 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
115 board.
saveSVG(
"solve_laplace_simplicial_ldlt.svg");
127 Calculus::DualForm0 solution = solver.
solve(dirac);
130 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
137 board.
saveSVG(
"solve_laplace_conjugate_gradient.svg");
149 Calculus::DualForm0 solution = solver.
solve(dirac);
152 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
159 board.
saveSVG(
"solve_laplace_bicgstab.svg");
171 Calculus::DualForm0 solution = solver.
solve(dirac);
174 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
181 board.
saveSVG(
"solve_laplace_sparse_lu.svg");
193 Calculus::DualForm0 solution = -solver.
solve(dirac);
196 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
203 board.
saveSVG(
"solve_laplace_sparse_qr.svg");
209 void solve2d_dual_decomposition()
211 trace.
beginBlock(
"2d discrete exterior calculus solve dual helmoltz decomposition");
218 Calculus
calculus = CalculusFactory::createFromDigitalSet(generateDoubleRingSet(
domain));
225 const Calculus::DualDerivative0 d0 =
calculus.derivative<0,
DUAL>();
226 const Calculus::DualDerivative1 d1 =
calculus.derivative<1,
DUAL>();
227 const Calculus::PrimalDerivative0 d0p =
calculus.derivative<0,
PRIMAL>();
228 const Calculus::PrimalDerivative1 d1p =
calculus.derivative<1,
PRIMAL>();
229 const Calculus::DualHodge1 h1 =
calculus.hodge<1,
DUAL>();
230 const Calculus::DualHodge2 h2 =
calculus.hodge<2,
DUAL>();
238 Calculus::DualVectorField input_vector_field(
calculus);
242 input_vector_field.myCoordinates(ii, 0) = cos(-.5*cell_center[0]+ .3*cell_center[1]);
243 input_vector_field.myCoordinates(ii, 1) = cos(.4*cell_center[0]+ .8*cell_center[1]);
245 trace.
info() << input_vector_field << endl;
247 const Calculus::DualForm1 input_one_form =
calculus.
flat(input_vector_field);
248 const Calculus::DualForm0 input_one_form_anti_derivated = ad1 * input_one_form;
249 const Calculus::DualForm2 input_one_form_derivated = d1 * input_one_form;
256 board <<
CustomStyle(
"KForm",
new KFormStyle2D(-1, 1));
257 board << input_one_form;
258 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(.75));
259 board << input_vector_field;
260 board.
saveSVG(
"solve_2d_dual_decomposition_calculus.svg");
264 Calculus::DualForm0 solution_curl_free(
calculus);
272 solution_curl_free = solver.
solve(input_one_form_anti_derivated);
275 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
276 trace.
info() <<
"min=" << solution_curl_free.myContainer.minCoeff() <<
" max=" << solution_curl_free.myContainer.maxCoeff() << endl;
284 board << solution_curl_free;
285 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(.75));
287 board.
saveSVG(
"solve_2d_dual_decomposition_curl_free.svg");
290 Calculus::DualForm2 solution_div_free(
calculus);
298 solution_div_free = solver.
solve(input_one_form_derivated);
301 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
302 trace.
info() <<
"min=" << solution_div_free.myContainer.minCoeff() <<
" max=" << solution_div_free.myContainer.maxCoeff() << endl;
310 board << solution_div_free;
311 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(1.5));
313 board.
saveSVG(
"solve_2d_dual_decomposition_div_free.svg");
317 const Calculus::DualForm1 solution_harmonic = input_one_form - d0*solution_curl_free - ad2*solution_div_free;
319 trace.
info() <<
"min=" << solution_harmonic.myContainer.minCoeff() <<
" max=" << solution_harmonic.myContainer.maxCoeff() << endl;
325 board << solution_harmonic;
326 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(20));
328 board.
saveSVG(
"solve_2d_dual_decomposition_harmonic.svg");
334 void solve2d_primal_decomposition()
336 trace.
beginBlock(
"2d discrete exterior calculus solve primal helmoltz decomposition");
343 Calculus
calculus = CalculusFactory::createFromDigitalSet(generateDoubleRingSet(
domain));
350 const Calculus::PrimalDerivative0 d0 =
calculus.derivative<0,
PRIMAL>();
351 const Calculus::PrimalDerivative1 d1 =
calculus.derivative<1,
PRIMAL>();
352 const Calculus::DualDerivative0 d0p =
calculus.derivative<0,
DUAL>();
353 const Calculus::DualDerivative1 d1p =
calculus.derivative<1,
DUAL>();
356 const Calculus::DualHodge1 h1p =
calculus.hodge<1,
DUAL>();
357 const Calculus::DualHodge2 h2p =
calculus.hodge<2,
DUAL>();
363 Calculus::PrimalVectorField input_vector_field(
calculus);
367 input_vector_field.myCoordinates(ii, 0) = cos(-.5*cell_center[0]+ .3*cell_center[1]);
368 input_vector_field.myCoordinates(ii, 1) = cos(.4*cell_center[0]+ .8*cell_center[1]);
370 trace.
info() << input_vector_field << endl;
372 const Calculus::PrimalForm1 input_one_form =
calculus.
flat(input_vector_field);
373 const Calculus::PrimalForm0 input_one_form_anti_derivated = ad1 * input_one_form;
374 const Calculus::PrimalForm2 input_one_form_derivated = d1 * input_one_form;
381 board << input_one_form;
382 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(.75));
383 board << input_vector_field;
384 board.
saveSVG(
"solve_2d_primal_decomposition_calculus.svg");
388 Calculus::PrimalForm0 solution_curl_free(
calculus);
396 solution_curl_free = solver.
solve(input_one_form_anti_derivated);
399 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
400 trace.
info() <<
"min=" << solution_curl_free.myContainer.minCoeff() <<
" max=" << solution_curl_free.myContainer.maxCoeff() << endl;
408 board << solution_curl_free;
409 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(.75));
411 board.
saveSVG(
"solve_2d_primal_decomposition_curl_free.svg");
414 Calculus::PrimalForm2 solution_div_free(
calculus);
422 solution_div_free = solver.
solve(input_one_form_derivated);
425 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
426 trace.
info() <<
"min=" << solution_div_free.myContainer.minCoeff() <<
" max=" << solution_div_free.myContainer.maxCoeff() << endl;
434 board << solution_div_free;
435 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(1.5));
437 board.
saveSVG(
"solve_2d_primal_decomposition_div_free.svg");
441 const Calculus::PrimalForm1 solution_harmonic = input_one_form - d0*solution_curl_free - ad2*solution_div_free;
443 trace.
info() <<
"min=" << solution_harmonic.myContainer.minCoeff() <<
" max=" << solution_harmonic.myContainer.maxCoeff() << endl;
449 board << solution_harmonic;
450 board <<
CustomStyle(
"VectorField",
new VectorFieldStyle2D(30));
452 board.
saveSVG(
"solve_2d_primal_decomposition_harmonic.svg");
458 void solve3d_decomposition()
460 trace.
beginBlock(
"3d discrete exterior calculus solve helmoltz decomposition");
474 for (
int kk=2; kk<=18; kk++)
475 for (
int ll=4; ll<=36; ll++)
480 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
484 sign = Calculus::KSpace::POS;
487 sign = Calculus::KSpace::NEG;
490 sign = Calculus::KSpace::NEG;
501 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
505 sign = Calculus::KSpace::POS;
508 sign = Calculus::KSpace::POS;
511 sign = Calculus::KSpace::POS;
522 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
526 sign = Calculus::KSpace::POS;
529 sign = ( *
calculus.myKSpace.uDirs(cell) == 2 ? Calculus::KSpace::NEG : Calculus::KSpace::POS );
532 sign = Calculus::KSpace::NEG;
543 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
547 sign = Calculus::KSpace::POS;
550 sign = ( *
calculus.myKSpace.uDirs(cell) == 2 ? Calculus::KSpace::POS : Calculus::KSpace::NEG );
553 sign = Calculus::KSpace::POS;
564 for (
int kk=2; kk<=18; kk++)
565 for (
int ll=16; ll<=24; ll++)
570 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
574 sign = Calculus::KSpace::POS;
577 sign = ( *
calculus.myKSpace.uDirs(cell) == 0 ? Calculus::KSpace::NEG : Calculus::KSpace::POS );
580 sign = Calculus::KSpace::POS;
591 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
595 sign = Calculus::KSpace::POS;
598 sign = ( *
calculus.myKSpace.uDirs(cell) == 0 ? Calculus::KSpace::POS : Calculus::KSpace::NEG );
601 sign = Calculus::KSpace::NEG;
612 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
616 sign = Calculus::KSpace::POS;
619 sign = Calculus::KSpace::POS;
622 sign = Calculus::KSpace::POS;
633 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
637 sign = Calculus::KSpace::POS;
640 sign = Calculus::KSpace::NEG;
643 sign = Calculus::KSpace::NEG;
653 for (
int kk=4; kk<=36; kk++)
654 for (
int ll=0; ll<=12; ll++)
659 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
663 sign = Calculus::KSpace::POS;
666 sign = Calculus::KSpace::POS;
669 sign = Calculus::KSpace::NEG;
680 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
684 sign = Calculus::KSpace::POS;
687 sign = Calculus::KSpace::NEG;
690 sign = Calculus::KSpace::POS;
701 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
705 sign = Calculus::KSpace::POS;
708 sign = Calculus::KSpace::POS;
711 sign = Calculus::KSpace::NEG;
722 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
726 sign = Calculus::KSpace::POS;
729 sign = Calculus::KSpace::NEG;
732 sign = Calculus::KSpace::POS;
742 for (
int kk=0; kk<=12; kk++)
743 for (
int ll=16; ll<=24; ll++)
748 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
752 sign = Calculus::KSpace::POS;
755 sign = Calculus::KSpace::POS;
758 sign = Calculus::KSpace::NEG;
769 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
773 sign = Calculus::KSpace::POS;
776 sign = Calculus::KSpace::NEG;
779 sign = Calculus::KSpace::POS;
790 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
794 sign = Calculus::KSpace::POS;
797 sign = Calculus::KSpace::POS;
800 sign = Calculus::KSpace::NEG;
811 Calculus::KSpace::Sign sign = Calculus::KSpace::POS;
815 sign = Calculus::KSpace::POS;
818 sign = Calculus::KSpace::NEG;
821 sign = Calculus::KSpace::POS;
839 viewer->setWindowTitle(
"structure");
847 const Calculus::PrimalDerivative0 d0 =
calculus.derivative<0,
PRIMAL>();
848 const Calculus::PrimalDerivative1 d1 =
calculus.derivative<1,
PRIMAL>();
849 const Calculus::DualDerivative1 d1p =
calculus.derivative<1,
DUAL>();
850 const Calculus::DualDerivative2 d2p =
calculus.derivative<2,
DUAL>();
853 const Calculus::DualHodge2 h2p =
calculus.hodge<2,
DUAL>();
854 const Calculus::DualHodge3 h3p =
calculus.hodge<3,
DUAL>();
860 const Calculus::PrimalIdentity0 laplace =
calculus.laplace<
PRIMAL>();
861 const Eigen::VectorXd laplace_diag = laplace.myContainer.diagonal();
863 boost::array<int, 7> degrees;
864 std::fill(degrees.begin(), degrees.end(), 0);
865 for (
int kk=0; kk<laplace_diag.rows(); kk++)
867 const int degree = laplace_diag[kk];
868 ASSERT( degree >= 0 );
869 ASSERT(
static_cast<unsigned int>(degree) < degrees.size() );
874 for (
int kk=0; kk<7; kk++)
875 trace.
info() << kk <<
" " << degrees[kk] << endl;
879 Calculus::PrimalVectorField input_vector_field(
calculus);
883 input_vector_field.myCoordinates(ii, 0) = -cos(-.3*cell_center[0] + .6*cell_center[1] + .8*cell_center[2]);
884 input_vector_field.myCoordinates(ii, 1) = sin(.8*cell_center[0] + .3*cell_center[1] - .4*cell_center[2]);
885 input_vector_field.myCoordinates(ii, 2) = -cos(cell_center[2]*.5);
887 trace.
info() << input_vector_field << endl;
889 const Calculus::PrimalForm1 input_one_form =
calculus.
flat(input_vector_field);
891 const Calculus::PrimalForm0 input_one_form_anti_derivated = ad1 * input_one_form;
892 const Calculus::PrimalForm2 input_one_form_derivated = d1 * input_one_form;
898 viewer->setWindowTitle(
"input vector field");
906 Calculus::PrimalForm0 solution_curl_free(
calculus);
914 solution_curl_free = solver.
solve(input_one_form_anti_derivated);
917 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
918 trace.
info() <<
"min=" << solution_curl_free.myContainer.minCoeff() <<
" max=" << solution_curl_free.myContainer.maxCoeff() << endl;
926 viewer->setWindowTitle(
"curl free solution");
932 Calculus::PrimalForm2 solution_div_free(
calculus);
940 solution_div_free = solver.
solve(input_one_form_derivated);
943 trace.
info() << solver.isValid() <<
" " << solver.myLinearAlgebraSolver.info() << endl;
944 trace.
info() <<
"min=" << solution_div_free.myContainer.minCoeff() <<
" max=" << solution_div_free.myContainer.maxCoeff() << endl;
952 viewer->setWindowTitle(
"div free solution");
959 const Calculus::PrimalForm1 solution_harmonic = input_one_form - d0*solution_curl_free - ad2*solution_div_free;
961 trace.
info() <<
"min=" << solution_harmonic.myContainer.minCoeff() <<
" max=" << solution_harmonic.myContainer.maxCoeff() << endl;
967 viewer->setWindowTitle(
"harmonic");
976 int main(
int argc,
char* argv[])
978 QApplication app(argc,argv);
981 solve2d_dual_decomposition();
982 solve2d_primal_decomposition();
983 solve3d_decomposition();
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Structure representing an RGB triple with alpha component.
Aim: This class provides static members to create DEC structures from various other DGtal structures.
Aim: This wraps a linear algebra solver around a discrete exterior calculus.
SolutionKForm solve(const InputKForm &input_kform) const
DiscreteExteriorCalculusSolver & compute(const Operator &linear_operator)
Aim: DiscreteExteriorCalculus represents a calculus in the dec package. This is the main structure in...
Aim: LinearOperator represents discrete linear operator between discrete kforms in the DEC package.
DenseMatrix sharp(const Face f) const
DenseMatrix flat(const Face f) const
void beginBlock(const std::string &keyword="")
virtual void show()
Overload QWidget method in order to add a call to updateList() method (to ensure that the lists are w...
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Space::RealPoint RealPoint
Space::RealPoint RealPoint
DGtal is the top-level namespace which contains all DGtal functions and types.
DGtal::uint32_t Dimension
static void draw(Display3D< Space, KSpace > &display, const DGtal::DiscreteExteriorCalculus< dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger > &calculus)
Eigen::SimplicialLLT< SparseMatrix > SolverSimplicialLLT
Solvers on sparse matrices.
Eigen::SimplicialLDLT< SparseMatrix > SolverSimplicialLDLT
Eigen::BiCGSTAB< SparseMatrix > SolverBiCGSTAB
Eigen::SparseQR< SparseMatrix, Eigen::COLAMDOrdering< SparseMatrix::Index > > SolverSparseQR
Eigen::SparseLU< SparseMatrix > SolverSparseLU
Eigen::ConjugateGradient< SparseMatrix > SolverConjugateGradient
int main(int argc, char **argv)
unsigned int dim(const Vector &z)