PolyFEM
Loading...
Searching...
No Matches
Laplacian.cpp
Go to the documentation of this file.
1#include "Laplacian.hpp"
2
3namespace polyfem::assembler
4{
5 namespace
6 {
7 bool delta(int i, int j)
8 {
9 return (i == j) ? true : false;
10 }
11
12 Eigen::VectorXd local_scalar_values(const NonLinearAssemblerData &data)
13 {
14 assert(data.x.cols() == 1);
15
16 const int n_bases = int(data.vals.basis_values.size());
17 Eigen::VectorXd local_u = Eigen::VectorXd::Zero(n_bases);
18 for (int i = 0; i < n_bases; ++i)
19 {
20 const auto &bs = data.vals.basis_values[i];
21 for (const auto &global : bs.global)
22 local_u(i) += global.val * data.x(global.index);
23 }
24
25 return local_u;
26 }
27 } // namespace
28
29 Laplacian::Laplacian(const std::string &conductivity_param_name)
30 : conductivity_param_name_(conductivity_param_name),
31 conductivity_(conductivity_param_name.empty() ? "conductivity" : conductivity_param_name)
32 {
33 }
34
35 std::map<std::string, Assembler::ParamFunc> Laplacian::parameters() const
36 {
37 std::map<std::string, ParamFunc> res;
38 if (!conductivity_param_name_.empty())
39 {
40 res[conductivity_param_name_] = [this](const RowVectorNd &uv, const RowVectorNd &p, double t, int e) {
41 return conductivity(uv, p, t, e);
42 };
43 }
44
45 return res;
46 }
47
48 void Laplacian::add_multimaterial(const int index, const json &params, const Units &units, const std::string &root_path)
49 {
50 if (!conductivity_param_name_.empty())
51 conductivity_.add_multimaterial(index, params, units.thermal_conductivity(), root_path);
52 }
53
54 double Laplacian::conductivity(const RowVectorNd &, const RowVectorNd &p, double t, int element_id) const
55 {
56 if (conductivity_param_name_.empty())
57 return 1.0;
58
59 return conductivity_(p, t, element_id);
60 }
61
62 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1> Laplacian::assemble(const LinearAssemblerData &data) const
63 {
64 const Eigen::MatrixXd &gradi = data.vals.basis_values[data.i].grad_t_m;
65 const Eigen::MatrixXd &gradj = data.vals.basis_values[data.j].grad_t_m;
66 // return ((gradi.array() * gradj.array()).rowwise().sum().array() * da.array()).colwise().sum();
67 double res = 0;
68 assert(gradi.rows() == data.da.size());
69 for (int k = 0; k < gradi.rows(); ++k)
70 {
71 const double kappa = conductivity(data.vals.quadrature.points.row(k), data.vals.val.row(k), data.t, data.vals.element_id);
72 // compute grad(phi_i) dot grad(phi_j) weighted by quadrature weights
73 res += kappa * gradi.row(k).dot(gradj.row(k)) * data.da(k);
74 }
75 return Eigen::Matrix<double, 1, 1>::Constant(res);
76 }
77
79 {
80 assert(size() == 1);
81
82 const Eigen::VectorXd local_u = local_scalar_values(data);
83 return 0.5 * local_u.dot(assemble_hessian(data) * local_u);
84 }
85
86 Eigen::VectorXd Laplacian::assemble_gradient(const NonLinearAssemblerData &data) const
87 {
88 assert(size() == 1);
89
90 return assemble_hessian(data) * local_scalar_values(data);
91 }
92
93 Eigen::MatrixXd Laplacian::assemble_hessian(const NonLinearAssemblerData &data) const
94 {
95 assert(size() == 1);
96
97 const int n_bases = int(data.vals.basis_values.size());
98 Eigen::MatrixXd hessian = Eigen::MatrixXd::Zero(n_bases, n_bases);
99 for (int i = 0; i < n_bases; ++i)
100 {
101 for (int j = 0; j < n_bases; ++j)
102 hessian(i, j) = assemble(LinearAssemblerData(data.vals, data.t, i, j, data.da))(0);
103 }
104
105 return hessian;
106 }
107
108 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1> Laplacian::compute_rhs(const AutodiffHessianPt &pt) const
109 {
110 Eigen::Matrix<double, 1, 1> result;
111 assert(pt.size() == 1);
112 result(0) = pt(0).getHessian().trace();
113 return result;
114 }
115
116 Eigen::Matrix<AutodiffScalarGrad, Eigen::Dynamic, 1, 0, 3, 1> Laplacian::kernel(const int dim, const AutodiffGradPt &rvect, const AutodiffScalarGrad &r) const
117 {
118 Eigen::Matrix<AutodiffScalarGrad, Eigen::Dynamic, 1, 0, 3, 1> res(1);
119
120 if (dim == 2)
121 res(0) = -1. / (2 * M_PI) * log(r);
122 else if (dim == 3)
123 res(0) = 1. / (4 * M_PI * r);
124 else
125 assert(false);
126
127 return res;
128 }
129
131 const Eigen::MatrixXd &mat,
132 Eigen::MatrixXd &stress,
133 Eigen::MatrixXd &result) const
134 {
135 stress = data.grad_u_i;
136 result = mat;
137 }
138
141 const Eigen::MatrixXd &local_pts,
142 const Eigen::MatrixXd &displacement,
143 Eigen::MatrixXd &tensor) const
144 {
145 const int dim = local_pts.cols();
146 tensor.resize(local_pts.rows(), dim * dim);
147 assert(displacement.cols() == 1);
148
149 for (long p = 0; p < local_pts.rows(); ++p)
150 {
151 const double kappa = conductivity(vals.quadrature.points.row(p), vals.val.row(p), t, vals.element_id);
152 for (int i = 0, idx = 0; i < dim; i++)
153 for (int j = 0; j < dim; j++)
154 {
155 tensor(p, idx) = kappa * delta(i, j);
156 idx++;
157 }
158 }
159 }
160} // namespace polyfem::assembler
double val
Definition Assembler.cpp:89
ElementAssemblyValues vals
Definition Assembler.cpp:25
int x
std::string thermal_conductivity() const
Definition Units.hpp:36
stores per element basis values at given quadrature points and geometric mapping
void add_multimaterial(const int index, const json &params, const std::string &unit_type, const std::string &root_path)
Definition MatParams.cpp:30
Eigen::Matrix< AutodiffScalarGrad, Eigen::Dynamic, 1, 0, 3, 1 > kernel(const int dim, const AutodiffGradPt &rvect, const AutodiffScalarGrad &r) const override
kernel of the pde, used in kernel problem
double compute_energy(const NonLinearAssemblerData &data) const override
Definition Laplacian.cpp:78
void compute_stress_grad_multiply_mat(const OptAssemblerData &data, const Eigen::MatrixXd &mat, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
Definition Laplacian.cpp:93
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 9, 1 > assemble(const LinearAssemblerData &data) const override
computes local stiffness matrix (1x1) for bases i,j where i,j is passed in through data ie integral o...
Definition Laplacian.cpp:62
Laplacian(const std::string &conductivity_param_name="")
Definition Laplacian.cpp:29
double conductivity(const RowVectorNd &uv, const RowVectorNd &p, double t, int element_id) const
Definition Laplacian.cpp:54
void add_multimaterial(const int index, const json &params, const Units &units, const std::string &root_path) override
Definition Laplacian.cpp:48
Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override
Definition Laplacian.cpp:86
void compute_stiffness_value(const double t, const assembler::ElementAssemblyValues &vals, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &displacement, Eigen::MatrixXd &tensor) const override
GenericMatParam conductivity_
Definition Laplacian.hpp:60
std::map< std::string, ParamFunc > parameters() const override
Definition Laplacian.cpp:35
VectorNd compute_rhs(const AutodiffHessianPt &pt) const override
uses autodiff to compute the rhs for a fabricated solution in this case it just return pt....
const ElementAssemblyValues & vals
stores the evaluation for that element
const QuadratureVector & da
contains both the quadrature weight and the change of metric in the integral
Used for test only.
Eigen::Matrix< AutodiffScalarHessian, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffHessianPt
nlohmann::json json
Definition Common.hpp:9
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13
Eigen::Matrix< AutodiffScalarGrad, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffGradPt
Automatic differentiation scalar with first-order derivatives.
Definition autodiff.h:112