PolyFEM
Loading...
Searching...
No Matches
AssemblerUtils.cpp
Go to the documentation of this file.
1
2#include "AssemblerUtils.hpp"
3
23
26
27// #include <unsupported/Eigen/SparseExtra>
28
29namespace polyfem
30{
31 using namespace basis;
32 using namespace utils;
33
34 namespace assembler
35 {
36
37 std::string AssemblerUtils::other_assembler_name(const std::string &formulation)
38 {
39 if (formulation == "Bilaplacian")
40 return "BilaplacianAux";
41 else if (formulation == "Stokes" || formulation == "NavierStokes" || formulation == "OperatorSplitting")
42 return "StokesPressure";
43 else if (formulation == "IncompressibleLinearElasticity")
44 return "IncompressibleLinearElasticityPressure";
45
46 return "";
47 }
48
49 std::shared_ptr<Assembler> AssemblerUtils::make_assembler(const std::string &formulation)
50 {
51 if (formulation == "Helmholtz")
52 return std::make_shared<Helmholtz>();
53 else if (formulation == "Laplacian")
54 return std::make_shared<Laplacian>();
55 else if (formulation == "Bilaplacian")
56 return std::make_shared<BilaplacianMain>();
57 else if (formulation == "BilaplacianAux")
58 return std::make_shared<BilaplacianAux>();
59
60 else if (formulation == "LinearElasticity")
61 return std::make_shared<LinearElasticity>();
62 else if (formulation == "HookeLinearElasticity")
63 return std::make_shared<HookeLinearElasticity>();
64 else if (formulation == "IncompressibleLinearElasticity")
65 return std::make_shared<IncompressibleLinearElasticityDispacement>();
66 else if (formulation == "IncompressibleLinearElasticityPressure")
67 return std::make_shared<IncompressibleLinearElasticityPressure>();
68
69 else if (formulation == "SaintVenant")
70 return std::make_shared<SaintVenantElasticity>();
71 else if (formulation == "NeoHookean")
72 return std::make_shared<NeoHookeanElasticity>();
73 else if (formulation == "MooneyRivlin")
74 return std::make_shared<MooneyRivlinElasticity>();
75 else if (formulation == "MooneyRivlin3Param")
76 return std::make_shared<MooneyRivlin3ParamElasticity>();
77 else if (formulation == "MooneyRivlin3ParamSymbolic")
78 return std::make_shared<MooneyRivlin3ParamSymbolic>();
79 else if (formulation == "MultiModels")
80 return std::make_shared<MultiModel>();
81 else if (formulation == "UnconstrainedOgden")
82 return std::make_shared<UnconstrainedOgdenElasticity>();
83 else if (formulation == "IncompressibleOgden")
84 return std::make_shared<IncompressibleOgdenElasticity>();
85
86 else if (formulation == "Stokes")
87 return std::make_shared<StokesVelocity>();
88 else if (formulation == "StokesPressure")
89 return std::make_shared<StokesPressure>();
90 else if (formulation == "NavierStokes")
91 return std::make_shared<NavierStokesVelocity>();
92 else if (formulation == "OperatorSplitting")
93 return std::make_shared<OperatorSplitting>();
94
95 else if (formulation == "AMIPS")
96 return std::make_shared<AMIPSEnergy>();
97 else if (formulation == "AMIPSAutodiff")
98 return std::make_shared<AMIPSEnergyAutodiff>();
99 else if (formulation == "FixedCorotational")
100 return std::make_shared<FixedCorotational>();
101
102 log_and_throw_error("Inavalid assembler name {}", formulation);
103 }
104
105 std::shared_ptr<MixedAssembler> AssemblerUtils::make_mixed_assembler(const std::string &formulation)
106 {
107 if (formulation == "Bilaplacian")
108 return std::make_shared<BilaplacianMixed>();
109 else if (formulation == "IncompressibleLinearElasticity")
110 return std::make_shared<IncompressibleLinearElasticityMixed>();
111 else if (formulation == "Stokes" || formulation == "NavierStokes" || formulation == "OperatorSplitting")
112 return std::make_shared<StokesMixed>();
113
114 log_and_throw_error("Inavalid mixed assembler name {}", formulation);
115 }
116
118 const int n_bases, const int n_pressure_bases, const int problem_dim, const bool add_average,
119 const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness,
120 StiffnessMatrix &stiffness)
121 {
122 assert(velocity_stiffness.rows() == velocity_stiffness.cols());
123 assert(velocity_stiffness.rows() == n_bases * problem_dim);
124
125 assert(mixed_stiffness.size() == 0 || mixed_stiffness.rows() == n_bases * problem_dim);
126 assert(mixed_stiffness.size() == 0 || mixed_stiffness.cols() == n_pressure_bases);
127
128 assert(pressure_stiffness.size() == 0 || pressure_stiffness.rows() == n_pressure_bases);
129 assert(pressure_stiffness.size() == 0 || pressure_stiffness.cols() == n_pressure_bases);
130
131 const int avg_offset = add_average ? 1 : 0;
132
133 std::vector<Eigen::Triplet<double>> blocks;
134 blocks.reserve(velocity_stiffness.nonZeros() + 2 * mixed_stiffness.nonZeros() + pressure_stiffness.nonZeros() + 2 * avg_offset * velocity_stiffness.rows());
135
136 for (int k = 0; k < velocity_stiffness.outerSize(); ++k)
137 {
138 for (StiffnessMatrix::InnerIterator it(velocity_stiffness, k); it; ++it)
139 {
140 blocks.emplace_back(it.row(), it.col(), it.value());
141 }
142 }
143
144 for (int k = 0; k < mixed_stiffness.outerSize(); ++k)
145 {
146 for (StiffnessMatrix::InnerIterator it(mixed_stiffness, k); it; ++it)
147 {
148 blocks.emplace_back(it.row(), n_bases * problem_dim + it.col(), it.value());
149 blocks.emplace_back(it.col() + n_bases * problem_dim, it.row(), it.value());
150 }
151 }
152
153 for (int k = 0; k < pressure_stiffness.outerSize(); ++k)
154 {
155 for (StiffnessMatrix::InnerIterator it(pressure_stiffness, k); it; ++it)
156 {
157 blocks.emplace_back(n_bases * problem_dim + it.row(), n_bases * problem_dim + it.col(), it.value());
158 }
159 }
160
161 if (add_average)
162 {
163 const double val = 1.0 / n_pressure_bases;
164 for (int i = 0; i < n_pressure_bases; ++i)
165 {
166 blocks.emplace_back(n_bases * problem_dim + i, n_bases * problem_dim + n_pressure_bases, val);
167 blocks.emplace_back(n_bases * problem_dim + n_pressure_bases, n_bases * problem_dim + i, val);
168 }
169 }
170
171 stiffness.resize(n_bases * problem_dim + n_pressure_bases + avg_offset, n_bases * problem_dim + n_pressure_bases + avg_offset);
172 stiffness.setFromTriplets(blocks.begin(), blocks.end());
173 stiffness.makeCompressed();
174
175 // static int c = 0;
176 // Eigen::saveMarket(stiffness, "stiffness.txt");
177 // Eigen::saveMarket(velocity_stiffness, "velocity_stiffness.txt");
178 // Eigen::saveMarket(mixed_stiffness, "mixed_stiffness.txt");
179 // Eigen::saveMarket(pressure_stiffness, "pressure_stiffness.txt");
180 }
181
182 int AssemblerUtils::quadrature_order(const std::string &assembler, const int basis_degree, const BasisType &b_type, const int dim)
183 {
184 // note: minimum quadrature order is always 1
185 if (assembler == "Mass")
186 {
187 // multiply by two since we are multiplying phi_i by phi_j
188 if (b_type == BasisType::SIMPLEX_LAGRANGE || b_type == BasisType::CUBE_LAGRANGE)
189 return std::max(basis_degree * 2, 1);
190 else
191 return basis_degree * 2 + 1;
192 }
193 else if (assembler == "NavierStokes")
194 {
195 if (b_type == BasisType::SIMPLEX_LAGRANGE)
196 return std::max((basis_degree - 1) + basis_degree, 1);
197 else if (b_type == BasisType::CUBE_LAGRANGE)
198 return std::max(basis_degree * 2, 1);
199 else
200 return basis_degree * 2 + 1;
201 }
202 else
203 {
204 // subtract one since we take a derivative (lowers polynomial order by 1)
205 // multiply by two since we are multiplying grad phi_i by grad phi_j
206 if (b_type == BasisType::SIMPLEX_LAGRANGE) {
207 return std::max((basis_degree - 1) * 2, 1);
208 }
209 else if (b_type == BasisType::CUBE_LAGRANGE) {
210 // in this case we have a tensor product basis
211 // this computes the quadrature order along a single axis
212 // the Quadrature itself takes a tensor product of the given quadrature points
213 // to form the full quadrature for the basis
214 // taking a gradient leaves at least one variable whose power remains unchanged
215 // thus, we don't subtract 1
216 // note that this is overkill for the variable that was differentiated
217 return std::max(basis_degree * 2, 1);
218 }
219 else {
220 return (basis_degree - 1) * 2 + 1;
221 }
222 }
223 }
224
225 } // namespace assembler
226} // namespace polyfem
double val
Definition Assembler.cpp:86
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 std::shared_ptr< Assembler > make_assembler(const std::string &formulation)
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:71
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:22