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