You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

90 lines
3.0 KiB

#include <medusa/Medusa.hpp>
#include <Eigen/SparseCore>
#include <Eigen/IterativeLinearSolvers>
/// Basic medusa example, we are solving 2D Poisson's equation on a parametric domain
/// discretized with variable density with Dirichlet boundary conditions.
/// http://e6.ijs.si/medusa/wiki/index.php/Parametric_domains
using namespace mm; // NOLINT
int main() {
// Define paramteric curve and its Jacobian matrix.
auto example_r = [](Vec<double, 1> t) {
double r = pow(abs(cos(1.5 * t(0))), sin(3 * t(0)));
return Vec2d(r * cos(t(0)), r * sin(t(0)));
};
auto der_example_r = [](Vec<double, 1> t) {
double r = pow(abs(cos(1.5 * t(0))), sin(3 * t(0)));
double der_r = (-1.5 * pow(abs(cos(1.5 * t(0))),
sin(3 * t(0))) * sin(3 * t(0)) * sin(1.5 * t(0)) +
3 * pow(abs(cos(1.5 * t(0))),
sin(3 * t(0))) * cos(3 * t(0)) * cos(1.5 * t(0))
* log(abs(cos(1.5 * t(0))))) / cos(1.5 * t(0));
Eigen::Matrix<double, 2, 1> jm;
jm.col(0) << der_r * cos(t(0)) - r * sin(t(0)), der_r * sin(t(0)) + r * cos(t(0));
return jm;
};
// Define parametric curve's domain.
BoxShape<Vec1d> param_bs(Vec<double, 1>{0.0}, Vec<double, 1>{2 * PI});
// Fill domain.
UnknownShape<Vec2d> shape;
DomainDiscretization<Vec2d> domain(shape);
auto gradient_h = [](Vec2d p){
double h_0 = 0.005;
double h_m = 0.03 - h_0;
return (0.5 * h_m * (p(0) + p(1) + 3.0) + h_0) / 5.0;
};
GeneralSurfaceFill<Vec2d, Vec1d> gsf;
domain.fill(gsf, param_bs, example_r, der_example_r, gradient_h);
GeneralFill<Vec2d> gf;
domain.fill(gf, gradient_h);
// Find support for the nodes.
int N = domain.size();
domain.findSupport(FindClosest(9)); // the support for each node is the closest 9 nodes
// Construct the approximation engine.
int m = 2; // basis order
Monomials<Vec2d> mon(m);
RBFFD<Polyharmonic<double, 3>, Vec2d> approx({}, mon);
// Compute the shapes (we only need the Laplacian).
auto storage = domain.computeShapes<sh::lap>(approx);
Eigen::SparseMatrix<double, Eigen::RowMajor> M(N, N);
Eigen::VectorXd rhs(N); rhs.setZero();
M.reserve(storage.supportSizes());
// Construct implicit operators over our storage.
auto op = storage.implicitOperators(M, rhs);
for (int i : domain.interior()) {
// set the case for nodes in the domain
op.lap(i) = 0.5;
}
for (int i : domain.boundary()) {
// enforce the boundary conditions
op.value(i) = 0.0;
}
Eigen::BiCGSTAB<decltype(M), Eigen::IncompleteLUT<double>> solver;
solver.compute(M);
ScalarFieldd u = solver.solve(rhs);
// Write the solution into file.
std::ofstream out_file("parametric_domain_2D_data.m");
out_file << "positions = " << domain.positions() << ";" << std::endl;
out_file << "solution = " << u << ";" << std::endl;
out_file.close();
return 0;
}