PolyFEM
Loading...
Searching...
No Matches
AssemblerUtils.cpp
Go to the documentation of this file.
1
2#include "AssemblerUtils.hpp"
3
31
34
35// #include <unsupported/Eigen/SparseExtra>
36
37namespace polyfem
38{
39 using namespace basis;
40 using namespace utils;
41
42 namespace assembler
43 {
44
45 std::string AssemblerUtils::other_assembler_name(const std::string &formulation)
46 {
47 if (formulation == "Bilaplacian")
48 return "BilaplacianAux";
49 else if (formulation == "Stokes" || formulation == "NavierStokes" || formulation == "OperatorSplitting")
50 return "StokesPressure";
51 else if (formulation == "IncompressibleLinearElasticity")
52 return "IncompressibleLinearElasticityPressure";
53
54 return "";
55 }
56
57 std::shared_ptr<Assembler> AssemblerUtils::make_assembler(const std::string &formulation)
58 {
59 if (formulation == "Helmholtz")
60 return std::make_shared<Helmholtz>();
61 else if (formulation == "Laplacian")
62 return std::make_shared<Laplacian>();
63 else if (formulation == "Electrostatics")
64 return std::make_shared<Electrostatics>();
65
66 else if (formulation == "Bilaplacian")
67 return std::make_shared<BilaplacianMain>();
68 else if (formulation == "BilaplacianAux")
69 return std::make_shared<BilaplacianAux>();
70
71 else if (formulation == "LinearElasticity")
72 return std::make_shared<LinearElasticity>();
73 else if (formulation == "HookeLinearElasticity")
74 return std::make_shared<HookeLinearElasticity>();
75 else if (formulation == "IncompressibleLinearElasticity")
76 return std::make_shared<IncompressibleLinearElasticityDispacement>();
77 else if (formulation == "IncompressibleLinearElasticityPressure")
78 return std::make_shared<IncompressibleLinearElasticityPressure>();
79
80 else if (formulation == "SaintVenant")
81 return std::make_shared<SaintVenantElasticity>();
82 else if (formulation == "NeoHookean")
83 return std::make_shared<NeoHookeanElasticity>();
84 else if (formulation == "IsochoricNeoHookean")
85 return std::make_shared<IsochoricNeoHookean>();
86 else if (formulation == "MooneyRivlin")
87 return std::make_shared<MooneyRivlinElasticity>();
88 else if (formulation == "MooneyRivlin3Param")
89 return std::make_shared<MooneyRivlin3ParamElasticity>();
90 else if (formulation == "MooneyRivlin3ParamSymbolic")
91 return std::make_shared<MooneyRivlin3ParamSymbolic>();
92 else if (formulation == "MultiModels")
93 return std::make_shared<MultiModel>();
94 else if (formulation == "MaterialSum")
95 return std::make_shared<SumModel>();
96 else if (formulation == "UnconstrainedOgden")
97 return std::make_shared<UnconstrainedOgdenElasticity>();
98 else if (formulation == "IncompressibleOgden")
99 return std::make_shared<IncompressibleOgdenElasticity>();
100 else if (formulation == "VolumePenalty")
101 return std::make_shared<VolumePenalty>();
102 else if (formulation == "InversionBarrier")
103 return std::make_shared<InversionBarrier>();
104
105 else if (formulation == "HGOFiber")
106 return std::make_shared<HGOFiber>();
107
108 else if (formulation == "ActiveFiber")
109 return std::make_shared<ActiveFiber>();
110
111 else if (formulation == "Stokes")
112 return std::make_shared<StokesVelocity>();
113 else if (formulation == "StokesPressure")
114 return std::make_shared<StokesPressure>();
115 else if (formulation == "NavierStokes")
116 return std::make_shared<NavierStokesVelocity>();
117 else if (formulation == "OperatorSplitting")
118 return std::make_shared<OperatorSplitting>();
119
120 else if (formulation == "AMIPS")
121 return std::make_shared<AMIPSEnergy>();
122 else if (formulation == "FixedCorotational")
123 return std::make_shared<FixedCorotational>();
124
125 log_and_throw_error("Inavalid assembler name {}", formulation);
126 }
127
128 std::shared_ptr<MixedAssembler> AssemblerUtils::make_mixed_assembler(const std::string &formulation)
129 {
130 if (formulation == "Bilaplacian")
131 return std::make_shared<BilaplacianMixed>();
132 else if (formulation == "IncompressibleLinearElasticity")
133 return std::make_shared<IncompressibleLinearElasticityMixed>();
134 else if (formulation == "Stokes" || formulation == "NavierStokes" || formulation == "OperatorSplitting")
135 return std::make_shared<StokesMixed>();
136
137 log_and_throw_error("Inavalid mixed assembler name {}", formulation);
138 }
139
140 std::shared_ptr<MixedNLAssembler> AssemblerUtils::make_mixed_nl_assembler(const std::string &formulation)
141 {
142 if (formulation == "ThermoElasticity")
143 return std::make_shared<ThermoElasticity>();
144
145 log_and_throw_error("Inavalid mixed nonlinear assembler name {}", formulation);
146 }
147
149 const int n_bases, const int n_pressure_bases, const int problem_dim, const bool add_average,
150 const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness,
151 StiffnessMatrix &stiffness)
152 {
153 assert(velocity_stiffness.rows() == velocity_stiffness.cols());
154 assert(velocity_stiffness.rows() == n_bases * problem_dim);
155
156 assert(mixed_stiffness.size() == 0 || mixed_stiffness.rows() == n_bases * problem_dim);
157 assert(mixed_stiffness.size() == 0 || mixed_stiffness.cols() == n_pressure_bases);
158
159 assert(pressure_stiffness.size() == 0 || pressure_stiffness.rows() == n_pressure_bases);
160 assert(pressure_stiffness.size() == 0 || pressure_stiffness.cols() == n_pressure_bases);
161
162 const int avg_offset = add_average ? 1 : 0;
163
164 std::vector<Eigen::Triplet<double>> blocks;
165 blocks.reserve(velocity_stiffness.nonZeros() + 2 * mixed_stiffness.nonZeros() + pressure_stiffness.nonZeros() + 2 * avg_offset * velocity_stiffness.rows());
166
167 for (int k = 0; k < velocity_stiffness.outerSize(); ++k)
168 {
169 for (StiffnessMatrix::InnerIterator it(velocity_stiffness, k); it; ++it)
170 {
171 blocks.emplace_back(it.row(), it.col(), it.value());
172 }
173 }
174
175 for (int k = 0; k < mixed_stiffness.outerSize(); ++k)
176 {
177 for (StiffnessMatrix::InnerIterator it(mixed_stiffness, k); it; ++it)
178 {
179 blocks.emplace_back(it.row(), n_bases * problem_dim + it.col(), it.value());
180 blocks.emplace_back(it.col() + n_bases * problem_dim, it.row(), it.value());
181 }
182 }
183
184 for (int k = 0; k < pressure_stiffness.outerSize(); ++k)
185 {
186 for (StiffnessMatrix::InnerIterator it(pressure_stiffness, k); it; ++it)
187 {
188 blocks.emplace_back(n_bases * problem_dim + it.row(), n_bases * problem_dim + it.col(), it.value());
189 }
190 }
191
192 if (add_average)
193 {
194 const double val = 1.0 / n_pressure_bases;
195 for (int i = 0; i < n_pressure_bases; ++i)
196 {
197 blocks.emplace_back(n_bases * problem_dim + i, n_bases * problem_dim + n_pressure_bases, val);
198 blocks.emplace_back(n_bases * problem_dim + n_pressure_bases, n_bases * problem_dim + i, val);
199 }
200 }
201
202 stiffness.resize(n_bases * problem_dim + n_pressure_bases + avg_offset, n_bases * problem_dim + n_pressure_bases + avg_offset);
203 stiffness.setFromTriplets(blocks.begin(), blocks.end());
204 stiffness.makeCompressed();
205
206 // static int c = 0;
207 // Eigen::saveMarket(stiffness, "stiffness.txt");
208 // Eigen::saveMarket(velocity_stiffness, "velocity_stiffness.txt");
209 // Eigen::saveMarket(mixed_stiffness, "mixed_stiffness.txt");
210 // Eigen::saveMarket(pressure_stiffness, "pressure_stiffness.txt");
211 }
212
213 int AssemblerUtils::quadrature_order(const std::string &assembler, const int basis_degree, const BasisType &b_type, const int dim)
214 {
215 // note: minimum quadrature order is always 1
216 if (assembler == "Mass")
217 {
218 // multiply by two since we are multiplying phi_i by phi_j
219 if (b_type == BasisType::SIMPLEX_LAGRANGE || b_type == BasisType::CUBE_LAGRANGE)
220 return std::max(basis_degree * 2, 1);
221 else
222 return basis_degree * 2 + 1;
223 }
224 else if (assembler == "NavierStokes")
225 {
226 if (b_type == BasisType::SIMPLEX_LAGRANGE)
227 return std::max((basis_degree - 1) + basis_degree, 1);
228 else if (b_type == BasisType::CUBE_LAGRANGE)
229 return std::max(basis_degree * 2, 1);
230 else
231 return basis_degree * 2 + 1;
232 }
233 else
234 {
235 // subtract one since we take a derivative (lowers polynomial order by 1)
236 // multiply by two since we are multiplying grad phi_i by grad phi_j
237 if (b_type == BasisType::SIMPLEX_LAGRANGE)
238 {
239 return std::max((basis_degree - 1) * 2, 1);
240 }
241 else if (b_type == BasisType::CUBE_LAGRANGE || b_type == BasisType::PRISM_LAGRANGE || b_type == BasisType::PYRAMID_LAGRANGE)
242 {
243 // in this case we have a tensor product basis
244 // this computes the quadrature order along a single axis
245 // the Quadrature itself takes a tensor product of the given quadrature points
246 // to form the full quadrature for the basis
247 // taking a gradient leaves at least one variable whose power remains unchanged
248 // thus, we don't subtract 1
249 // note that this is overkill for the variable that was differentiated
250 return std::max(basis_degree * 2, 1);
251 }
252 else
253 {
254 return (basis_degree - 1) * 2 + 1;
255 }
256 }
257 }
258
259 std::vector<std::string> AssemblerUtils::elastic_materials()
260 {
261 const static std::vector<std::string> elastic_materials = {
262 "LinearElasticity",
263 "HookeLinearElasticity",
264 "SaintVenant",
265 "NeoHookean",
266 "MooneyRivlin",
267 "MooneyRivlin3Param",
268 "MooneyRivlin3ParamSymbolic",
269 "UnconstrainedOgden",
270 "IncompressibleOgden",
271 "IsochoricNeoHookean",
272 "HGOFiber",
273 "ActiveFiber",
274 "FixedCorotational",
275 "VolumePenalty",
276 "AMIPS",
277 "MaterialSum",
278 "MultiModels"};
279
280 return elastic_materials;
281 }
282
283 bool AssemblerUtils::is_elastic_material(const std::string &material)
284 {
285 for (const auto &m : elastic_materials())
286 {
287 if (material == m)
288 return true;
289 }
290 return false;
291 }
292
294 {
295 for (const auto &m : AssemblerUtils::elastic_materials())
296 {
297 // skip multimodels
298 // this is a special case where we have multiple models
299 // and we need to create a new assembler for each model
300 // this is handled in the MultiModel class
301 // and not here
302 if (m == "MultiModels")
303 continue;
304 const auto assembler = AssemblerUtils::make_assembler(m);
305 // cast assembler to elasticity assembler
306 elastic_material_map_[m] = std::dynamic_pointer_cast<ElasticityNLAssembler>(assembler);
307 assert(elastic_material_map_[m] != nullptr);
308 }
309 }
310
311 void AllElasticMaterials::set_size(const int size)
312 {
313 for (auto &it : elastic_material_map_)
314 {
315 it.second->set_size(size);
316 }
317 }
318
319 void AllElasticMaterials::add_multimaterial(const int index, const json &params, const Units &units, const std::string &root_path)
320 {
321 for (auto &it : elastic_material_map_)
322 {
323 it.second->add_multimaterial(index, params, units, root_path);
324 }
325 }
326
327 std::shared_ptr<assembler::ElasticityNLAssembler> AllElasticMaterials::get_assembler(const std::string &name) const
328 {
329 return elastic_material_map_.at(name);
330 }
331
332 std::map<std::string, Assembler::ParamFunc> AllElasticMaterials::parameters() const
333 {
334 std::map<std::string, Assembler::ParamFunc> params;
335 for (const auto &m : elastic_material_map_)
336 {
337 const auto assembler = m.second;
338 auto p = assembler->parameters();
339 for (auto &it : p)
340 {
341 params[m.first + "/" + it.first] = it.second;
342 }
343 }
344 return params;
345 }
346 } // namespace assembler
347} // namespace polyfem
double val
Definition Assembler.cpp:89
std::shared_ptr< assembler::ElasticityNLAssembler > get_assembler(const std::string &name) const
std::map< std::string, Assembler::ParamFunc > parameters() const
void add_multimaterial(const int index, const json &params, const Units &units, const std::string &root_path)
std::unordered_map< std::string, std::shared_ptr< assembler::ElasticityNLAssembler > > elastic_material_map_
static std::shared_ptr< MixedAssembler > make_mixed_assembler(const std::string &formulation)
static std::string other_assembler_name(const std::string &formulation)
static int quadrature_order(const std::string &assembler, const int basis_degree, const BasisType &b_type, const int dim)
utility for retrieving the needed quadrature order to precisely integrate the given form on the given...
static std::shared_ptr< MixedNLAssembler > make_mixed_nl_assembler(const std::string &formulation)
static void merge_mixed_matrices(const int n_bases, const int n_pressure_bases, const int problem_dim, const bool add_average, const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness, StiffnessMatrix &stiffness)
utility to merge 3 blocks of mixed matrices, A=velocity_stiffness, B=mixed_stiffness,...
static bool is_elastic_material(const std::string &material)
utility to check if material is one of the elastic materials
static std::vector< std::string > elastic_materials()
list of all elastic materials
static std::shared_ptr< Assembler > make_assembler(const std::string &formulation)
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24