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 io::ResourceIO &resources, const std::string &path)
19 {
20 auto file = resources.open(path, false);
21
22 std::string s;
23
24 while (getline(*file, s))
25 {
26 std::stringstream input(s);
27
28 int id;
29 input >> id;
30 raw_ids_.push_back(id);
31
32 bool flag;
33 input >> flag;
34 raw_dirichlet_.push_back(flag);
35
36 double temp;
37 raw_data_.emplace_back();
38 std::vector<double> &currentLine = raw_data_.back();
39
40 while (input >> temp)
41 currentLine.push_back(temp);
42 }
43 }
44
45 void NodeValues::init(const mesh::Mesh &mesh)
46 {
47 const int n_primitive = mesh.is_volume() ? mesh.n_faces() : mesh.n_edges();
48 if (!data_.empty())
49 {
50 assert(data_.size() == n_primitive);
51 assert(dirichlet_.size() == n_primitive);
52 return;
53 }
54
55 data_.resize(n_primitive);
56 dirichlet_.resize(n_primitive);
57
58 for (size_t i = 0; i < raw_ids_.size(); ++i)
59 {
60 const int index = raw_ids_[i];
61
62 dirichlet_[index] = raw_dirichlet_[i];
63
64 data_[index].resize(raw_data_[i].size());
65 for (size_t j = 0; j < raw_data_[i].size(); ++j)
66 data_[index](j) = raw_data_[i][j];
67 }
68 }
69
70 double NodeValues::interpolate(const int p_id, const Eigen::MatrixXd &uv, bool is_dirichlet) const
71 {
72 assert(dirichlet_[p_id] == is_dirichlet);
73
74 const auto &vals = data_[p_id];
75 assert(uv.size() == vals.size());
76
77 return (uv.array() * vals.transpose().array()).sum();
78 }
79
80 NodeProblem::NodeProblem(const std::string &name)
81 : Problem(name), rhs_(0), is_all_(false)
82 {
83 }
84
85 void NodeProblem::init(const mesh::Mesh &mesh)
86 {
87 values_.init(mesh);
88 }
89
90 void NodeProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int) const
91 {
92 val = Eigen::MatrixXd::Constant(pts.rows(), pts.cols(), rhs_);
93 }
94
95 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 int) const
96 {
97 val = Eigen::MatrixXd::Zero(pts.rows(), 1);
98
99 for (long i = 0; i < uv.rows(); ++i)
100 {
101 const int p_id = global_ids(i);
102 if (is_all_)
103 {
104 val(i) = values_.dirichlet_interpolate(p_id, uv.row(i));
105 }
106 else
107 {
108 const int id = mesh.get_boundary_id(p_id);
109 for (size_t b = 0; b < boundary_ids_.size(); ++b)
110 {
111 if (id == boundary_ids_[b])
112 {
113 val(i) = values_.dirichlet_interpolate(p_id, uv.row(i));
114 break;
115 }
116 }
117 }
118 }
119 }
120
121 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 int) const
122 {
123 val = Eigen::MatrixXd::Zero(pts.rows(), 1);
124
125 for (long i = 0; i < uv.rows(); ++i)
126 {
127 const int p_id = global_ids(i);
128 const int id = mesh.get_boundary_id(p_id);
129 for (size_t b = 0; b < boundary_ids_.size(); ++b)
130 {
131 if (id == boundary_ids_[b])
132 {
133 val(i) = values_.neumann_interpolate(p_id, uv.row(i));
134 break;
135 }
136 }
137 }
138 }
139
140 bool NodeProblem::is_dimension_dirichet(const int tag, const int dim, const int fe_space_id) const
141 {
142 if (all_dimensions_dirichlet(fe_space_id))
143 return true;
144
145 if (is_all_)
146 {
147 return dirichlet_dimensions_[0][dim];
148 }
149
150 for (size_t b = 0; b < boundary_ids_.size(); ++b)
151 {
152 if (tag == boundary_ids_[b])
153 {
154 auto &tmp = dirichlet_dimensions_[b];
155 return tmp[dim];
156 }
157 }
158
159 assert(false);
160 return true;
161 }
162
163 void NodeProblem::set_parameters(const json &params, const io::ResourceIO &resources)
164 {
165 if (params.contains("rhs"))
166 {
167 rhs_ = params["rhs"];
168 }
169
170 if (params.contains("values"))
171 {
172 const std::string path = params["values"];
173 values_.load(resources, path);
174 }
175
176 if (params.contains("dirichlet_boundary"))
177 {
178 boundary_ids_.clear();
179 std::vector<json> j_boundary = utils::json_as_array(params["dirichlet_boundary"]);
180
181 boundary_ids_.resize(j_boundary.size());
182 dirichlet_dimensions_.resize(j_boundary.size());
183
184 for (size_t i = 0; i < boundary_ids_.size(); ++i)
185 {
186 if (j_boundary[i]["id"] == "all")
187 {
188 assert(boundary_ids_.size() == 1);
189 is_all_ = true;
190 boundary_ids_.clear();
191 }
192 else
193 boundary_ids_[i] = j_boundary[i]["id"];
194
195 dirichlet_dimensions_[i].setConstant(false);
196
197 if (j_boundary[i].contains("dimension"))
198 {
200 auto &tmp = j_boundary[i]["dimension"];
201 assert(tmp.is_array());
202 for (size_t k = 0; k < tmp.size(); ++k)
203 dirichlet_dimensions_[i](k) = tmp[k];
204 }
205 }
206 }
207
208 if (params.contains("neumann_boundary"))
209 {
210 neumann_boundary_ids_.clear();
211 auto j_boundary = params["neumann_boundary"];
212
213 neumann_boundary_ids_.resize(j_boundary.size());
214
215 for (size_t i = 0; i < neumann_boundary_ids_.size(); ++i)
216 {
217 neumann_boundary_ids_[i] = j_boundary[i]["id"];
218 }
219 }
220 }
221 } // namespace problem
222} // namespace polyfem
double val
Definition Assembler.cpp:90
ElementAssemblyValues vals
Definition Assembler.cpp:26
std::vector< int > boundary_ids_
Definition Problem.hpp:126
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:127
Read-only interface to a hierarchical collection of simulation resources.
virtual std::unique_ptr< std::istream > open(const std::string &path, bool binary) const =0
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
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:466
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
NodeProblem(const std::string &name)
void set_parameters(const json &params, const io::ResourceIO &resources) override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const 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 int fe_space_id=-1) const override
bool all_dimensions_dirichlet(const int fe_space_id) const override
std::vector< Eigen::Matrix< bool, 1, 3, Eigen::RowMajor > > dirichlet_dimensions_
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 int fe_space_id=-1) const override
bool is_dimension_dirichet(const int tag, const int dim, const int fe_space_id=-1) const override
std::vector< bool > dirichlet_
double neumann_interpolate(const int p_id, const Eigen::MatrixXd &uv) const
std::vector< int > raw_ids_
std::vector< bool > raw_dirichlet_
void load(const io::ResourceIO &resources, const std::string &path)
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:49
nlohmann::json json
Definition Common.hpp:9