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