PolyFEM
Loading...
Searching...
No Matches
NodeProblem.cpp
Go to the documentation of this file.
1#include "NodeProblem.hpp"
4
5#include <iostream>
6#include <fstream>
7
8namespace polyfem
9{
10 using namespace utils;
11
12 namespace problem
13 {
17
18 void NodeValues::load(const std::string &path)
19 {
20 std::fstream file;
21 file.open(path.c_str());
22
23 if (!file.good())
24 {
25 logger().error("Failed to open file: {}", path);
26 file.close();
27 }
28
29 std::string s;
30
31 while (getline(file, s))
32 {
33 std::stringstream input(s);
34
35 int id;
36 input >> id;
37 raw_ids_.push_back(id);
38
39 bool flag;
40 input >> flag;
41 raw_dirichlet_.push_back(flag);
42
43 double temp;
44 raw_data_.emplace_back();
45 std::vector<double> &currentLine = raw_data_.back();
46
47 while (input >> temp)
48 currentLine.push_back(temp);
49 }
50
51 file.close();
52 }
53
54 void NodeValues::init(const mesh::Mesh &mesh)
55 {
56 const int n_primitive = mesh.is_volume() ? mesh.n_faces() : mesh.n_edges();
57 if (!data_.empty())
58 {
59 assert(data_.size() == n_primitive);
60 assert(dirichlet_.size() == n_primitive);
61 return;
62 }
63
64 data_.resize(n_primitive);
65 dirichlet_.resize(n_primitive);
66
67 for (size_t i = 0; i < raw_ids_.size(); ++i)
68 {
69 const int index = raw_ids_[i];
70
71 dirichlet_[index] = raw_dirichlet_[i];
72
73 data_[index].resize(raw_data_[i].size());
74 for (size_t j = 0; j < raw_data_[i].size(); ++j)
75 data_[index](j) = raw_data_[i][j];
76 }
77 }
78
79 double NodeValues::interpolate(const int p_id, const Eigen::MatrixXd &uv, bool is_dirichlet) const
80 {
81 assert(dirichlet_[p_id] == is_dirichlet);
82
83 const auto &vals = data_[p_id];
84 assert(uv.size() == vals.size());
85
86 return (uv.array() * vals.transpose().array()).sum();
87 }
88
89 NodeProblem::NodeProblem(const std::string &name)
90 : Problem(name), rhs_(0), is_all_(false)
91 {
92 }
93
94 void NodeProblem::init(const mesh::Mesh &mesh)
95 {
96 values_.init(mesh);
97 }
98
99 void NodeProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
100 {
101 val = Eigen::MatrixXd::Constant(pts.rows(), pts.cols(), rhs_);
102 }
103
104 void NodeProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
105 {
106 val = Eigen::MatrixXd::Zero(pts.rows(), 1);
107
108 for (long i = 0; i < uv.rows(); ++i)
109 {
110 const int p_id = global_ids(i);
111 if (is_all_)
112 {
113 val(i) = values_.dirichlet_interpolate(p_id, uv.row(i));
114 }
115 else
116 {
117 const int id = mesh.get_boundary_id(p_id);
118 for (size_t b = 0; b < boundary_ids_.size(); ++b)
119 {
120 if (id == boundary_ids_[b])
121 {
122 val(i) = values_.dirichlet_interpolate(p_id, uv.row(i));
123 break;
124 }
125 }
126 }
127 }
128 }
129
130 void NodeProblem::neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val) const
131 {
132 val = Eigen::MatrixXd::Zero(pts.rows(), 1);
133
134 for (long i = 0; i < uv.rows(); ++i)
135 {
136 const int p_id = global_ids(i);
137 const int id = mesh.get_boundary_id(p_id);
138 for (size_t b = 0; b < boundary_ids_.size(); ++b)
139 {
140 if (id == boundary_ids_[b])
141 {
142 val(i) = values_.neumann_interpolate(p_id, uv.row(i));
143 break;
144 }
145 }
146 }
147 }
148
149 bool NodeProblem::is_dimension_dirichet(const int tag, const int dim) const
150 {
152 return true;
153
154 if (is_all_)
155 {
156 return dirichlet_dimensions_[0][dim];
157 }
158
159 for (size_t b = 0; b < boundary_ids_.size(); ++b)
160 {
161 if (tag == boundary_ids_[b])
162 {
163 auto &tmp = dirichlet_dimensions_[b];
164 return tmp[dim];
165 }
166 }
167
168 assert(false);
169 return true;
170 }
171
173 {
174 if (params.contains("rhs"))
175 {
176 rhs_ = params["rhs"];
177 }
178
179 if (params.contains("values"))
180 {
181 const std::string path = params["values"];
182 values_.load(path);
183 }
184
185 if (params.contains("dirichlet_boundary"))
186 {
187 boundary_ids_.clear();
188 std::vector<json> j_boundary = utils::json_as_array(params["dirichlet_boundary"]);
189
190 boundary_ids_.resize(j_boundary.size());
191 dirichlet_dimensions_.resize(j_boundary.size());
192
193 for (size_t i = 0; i < boundary_ids_.size(); ++i)
194 {
195 if (j_boundary[i]["id"] == "all")
196 {
197 assert(boundary_ids_.size() == 1);
198 is_all_ = true;
199 boundary_ids_.clear();
200 }
201 else
202 boundary_ids_[i] = j_boundary[i]["id"];
203
204 dirichlet_dimensions_[i].setConstant(false);
205
206 if (j_boundary[i].contains("dimension"))
207 {
209 auto &tmp = j_boundary[i]["dimension"];
210 assert(tmp.is_array());
211 for (size_t k = 0; k < tmp.size(); ++k)
212 dirichlet_dimensions_[i](k) = tmp[k];
213 }
214 }
215 }
216
217 if (params.contains("neumann_boundary"))
218 {
219 neumann_boundary_ids_.clear();
220 auto j_boundary = params["neumann_boundary"];
221
222 neumann_boundary_ids_.resize(j_boundary.size());
223
224 for (size_t i = 0; i < neumann_boundary_ids_.size(); ++i)
225 {
226 neumann_boundary_ids_[i] = j_boundary[i]["id"];
227 }
228 }
229 }
230 } // namespace problem
231} // namespace polyfem
double val
Definition Assembler.cpp:86
ElementAssemblyValues vals
Definition Assembler.cpp:22
std::vector< int > boundary_ids_
Definition Problem.hpp:78
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:79
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:39
virtual int get_boundary_id(const int primitive) const
Get the boundary selection of an element (face in 3d, edge in 2d)
Definition Mesh.hpp:478
virtual bool is_volume() const =0
checks if mesh is volume
virtual int n_faces() const =0
number of faces
virtual int n_edges() const =0
number of edges
void init(const mesh::Mesh &mesh) override
bool is_dimension_dirichet(const int tag, const int dim) const override
NodeProblem(const std::string &name)
void set_parameters(const json &params) override
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
std::vector< Eigen::Matrix< bool, 1, 3, Eigen::RowMajor > > dirichlet_dimensions_
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val) const override
bool all_dimensions_dirichlet() const override
std::vector< bool > dirichlet_
void load(const std::string &path)
double neumann_interpolate(const int p_id, const Eigen::MatrixXd &uv) const
std::vector< int > raw_ids_
std::vector< bool > raw_dirichlet_
double interpolate(const int p_id, const Eigen::MatrixXd &uv, bool is_dirichlet) const
void init(const mesh::Mesh &mesh)
std::vector< std::vector< double > > raw_data_
double dirichlet_interpolate(const int p_id, const Eigen::MatrixXd &uv) const
std::vector< Eigen::VectorXd > data_
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
Definition JSONUtils.hpp:38
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:42
nlohmann::json json
Definition Common.hpp:9