PolyFEM
Loading...
Searching...
No Matches
VarFormFactory.cpp
Go to the documentation of this file.
2
16
17namespace polyfem::varform
18{
19 namespace
20 {
21 bool is_scalar_formulation(const std::string &formulation)
22 {
23 return formulation == "Helmholtz"
24 || formulation == "Laplacian"
25 || formulation == "Electrostatics";
26 }
27
28 bool is_linear_elastic_formulation(const std::string &formulation)
29 {
30 return formulation == "LinearElasticity"
31 || formulation == "HookeLinearElasticity";
32 }
33
34 bool is_nonlinear_elastic_formulation(const std::string &formulation)
35 {
36 return formulation == "SaintVenant"
37 || formulation == "NeoHookean"
38 || formulation == "IsochoricNeoHookean"
39 || formulation == "MooneyRivlin"
40 || formulation == "MooneyRivlin3Param"
41 || formulation == "MooneyRivlin3ParamSymbolic"
42 || formulation == "MultiModels"
43 || formulation == "MaterialSum"
44 || formulation == "UnconstrainedOgden"
45 || formulation == "IncompressibleOgden"
46 || formulation == "VolumePenalty"
47 || formulation == "InversionBarrier"
48 || formulation == "HGOFiber"
49 || formulation == "HGODispersion"
50 || formulation == "ActiveFiber"
51 || formulation == "AMIPS"
52 || formulation == "FixedCorotational";
53 }
54
55 bool is_elastic_formulation(const std::string &formulation)
56 {
57 return is_linear_elastic_formulation(formulation)
58 || is_nonlinear_elastic_formulation(formulation);
59 }
60
61 bool has_non_empty_entries(const json &args, const json::json_pointer &path)
62 {
63 return args.contains(path) && !args.at(path).empty();
64 }
65
66 bool has_two_mesh_fsi_material(const json &args)
67 {
68 if (!args.contains("materials") || args["materials"].is_null())
69 return false;
70
71 const auto has_solid_fields = [](const json &material) {
72 return material.contains("fluid_geometry_id")
73 && material.contains("solid_geometry_id")
74 && material.contains("displacement_space_id")
75 && material.contains("solid_material");
76 };
77
78 const json &materials = args["materials"];
79 if (!materials.is_array())
80 return has_solid_fields(materials);
81 if (materials.empty())
82 return false;
83
84 for (const json &material : materials)
85 if (!has_solid_fields(material))
86 return false;
87 return true;
88 }
89 } // namespace
90
91 std::string formulation_from_args(const json &args)
92 {
93 if (!args.contains("materials") || args["materials"].is_null())
94 return "";
95
96 if (args["materials"].is_array())
97 {
98 std::string current;
99 for (const auto &m : args["materials"])
100 {
101 const std::string tmp = m["type"];
102 if (current.empty())
103 current = tmp;
104 else if (current != tmp)
105 {
108 {
109 current = "MultiModels";
110 }
111 else
112 {
113 return "";
114 }
115 }
116 }
117
118 return current;
119 }
120
121 return args["materials"].value("type", "");
122 }
123
124 bool uses_varform_state(json args, const io::ResourceIO &resources)
125 {
126 utils::apply_common_params(args, resources);
127 const std::string formulation = formulation_from_args(args);
128 return !formulation.empty() && VarFormFactory::supports(formulation, args);
129 }
130
132 const std::string &formulation,
133 const json &args,
134 const bool is_optimization)
135 {
136 if (args.value("/space/remesh/enabled"_json_pointer, false))
137 return false;
138
139 const bool homogenization = args.contains("/constraints/macro_displacement_gradient"_json_pointer);
140 const bool has_contact = args.value("/contact/enabled"_json_pointer, false);
141 const bool has_periodic_constraints =
142 has_non_empty_entries(args, "/boundary_conditions/periodic"_json_pointer);
143 const bool periodic_contact = args.value("/contact/periodic"_json_pointer, false);
144 if (periodic_contact)
145 {
146 if (!homogenization)
147 return false;
148 if (!has_contact)
149 return false;
150 if (!has_periodic_constraints)
151 return false;
152 }
153
154 if (homogenization && !is_optimization)
155 return false;
156 if (homogenization && args.contains("time") && !args["time"].is_null())
157 return false;
158
159 const bool has_pressure = has_non_empty_entries(args, "/boundary_conditions/pressure_boundary"_json_pointer)
160 || has_non_empty_entries(args, "/boundary_conditions/pressure_cavity"_json_pointer);
161 const bool has_file_constraints =
162 has_non_empty_entries(args, "/constraints/hard"_json_pointer)
163 || has_non_empty_entries(args, "/constraints/soft"_json_pointer);
164 const json zero_mean = args.contains("/constraints/zero_mean"_json_pointer)
165 ? args.at("/constraints/zero_mean"_json_pointer)
166 : json(false);
167 const bool has_zero_mean_constraints =
168 (zero_mean.is_boolean() && zero_mean.get<bool>())
169 || (zero_mean.is_array() && !zero_mean.empty());
170 const bool has_constraints =
171 has_file_constraints || has_periodic_constraints || has_zero_mean_constraints;
172
173 if (formulation == "ThermoElasticity")
174 return !is_optimization && !has_pressure && !has_constraints;
175
176 if (formulation == "Stokes")
177 return !is_optimization && !has_contact && !has_constraints;
178 if (formulation == "NavierStokes")
179 return !is_optimization && !has_contact && !has_constraints;
180 if (formulation == "NavierStokesFSI")
181 return !is_optimization
182 && args.contains("time") && !args["time"].is_null()
183 && (!has_contact || has_two_mesh_fsi_material(args)) && !has_constraints;
184 if (formulation == "OperatorSplitting")
185 return !is_optimization
186 && args.contains("time") && !args["time"].is_null()
187 && !has_contact && !has_constraints;
188 if (formulation == "IncompressibleLinearElasticity")
189 return !is_optimization && !has_contact && !has_pressure && !has_constraints;
190 if (formulation == "Bilaplacian")
191 return !is_optimization && !has_contact && !has_constraints;
192
193 if (is_scalar_formulation(formulation))
194 {
195 return !homogenization && !has_contact && !has_pressure && !has_file_constraints;
196 }
197
198 return is_elastic_formulation(formulation);
199 }
200
201 std::shared_ptr<VarForm> VarFormFactory::create(
202 const std::string &formulation,
203 const json &args,
204 const io::ResourceIO &resources,
205 const bool is_optimization)
206 {
207 if (!supports(formulation, args, is_optimization))
208 return nullptr;
209
210 if (formulation == "ThermoElasticity")
211 return std::make_shared<ThermoElasticVarForm>(resources);
212 if (formulation == "Stokes")
213 return std::make_shared<StokesVarForm>(resources);
214 if (formulation == "NavierStokes")
215 return std::make_shared<NavierStokesVarForm>(resources);
216 if (formulation == "NavierStokesFSI")
217 return std::make_shared<NavierStokesFSIVarForm>(resources);
218 if (formulation == "OperatorSplitting")
219 return std::make_shared<OperatorSplittingVarForm>(resources);
220 if (formulation == "IncompressibleLinearElasticity")
221 return std::make_shared<IncompressibleElasticVarForm>(resources);
222 if (formulation == "Bilaplacian")
223 return std::make_shared<BilaplacianVarForm>(resources);
224
225 if (is_scalar_formulation(formulation))
226 return is_optimization
227 ? std::static_pointer_cast<VarForm>(std::make_shared<DifferentiableScalarVarForm>(resources))
228 : std::make_shared<ScalarVarForm>(resources);
229
230 const bool homogenization = args.contains("/constraints/macro_displacement_gradient"_json_pointer);
231
232 if (homogenization)
233 return std::make_shared<DifferentiableNonlinearElasticStaticVarForm>(resources);
234
235 const bool has_contact = args.value("/contact/enabled"_json_pointer, false);
236 const bool has_pressure = has_non_empty_entries(args, "/boundary_conditions/pressure_boundary"_json_pointer)
237 || has_non_empty_entries(args, "/boundary_conditions/pressure_cavity"_json_pointer);
238 const bool has_file_constraints =
239 has_non_empty_entries(args, "/constraints/hard"_json_pointer)
240 || has_non_empty_entries(args, "/constraints/soft"_json_pointer);
241 const bool has_periodic_constraints =
242 has_non_empty_entries(args, "/boundary_conditions/periodic"_json_pointer);
243 const json zero_mean = args.contains("/constraints/zero_mean"_json_pointer)
244 ? args.at("/constraints/zero_mean"_json_pointer)
245 : json(false);
246 const bool has_zero_mean_constraints =
247 (zero_mean.is_boolean() && zero_mean.get<bool>())
248 || (zero_mean.is_array() && !zero_mean.empty());
249 const bool has_constraints =
250 has_file_constraints || has_periodic_constraints || has_zero_mean_constraints;
251
252 if (is_linear_elastic_formulation(formulation)
253 && !has_contact && !has_pressure && !has_constraints)
254 {
255 return is_optimization
256 ? std::static_pointer_cast<VarForm>(std::make_shared<DifferentiableLinearElasticVarForm>(resources))
257 : std::make_shared<LinearElasticVarForm>(resources);
258 }
259
260 if (args.contains("time") && !args["time"].is_null())
261 {
262 return is_optimization
263 ? std::static_pointer_cast<VarForm>(std::make_shared<DifferentiableNonlinearElasticTransientVarForm>(resources))
264 : std::make_shared<NonlinearElasticTransientVarForm>(resources);
265 }
266
267 return is_optimization
268 ? std::static_pointer_cast<VarForm>(std::make_shared<DifferentiableNonlinearElasticStaticVarForm>(resources))
269 : std::make_shared<NonlinearElasticStaticVarForm>(resources);
270 }
271} // namespace polyfem::varform
static bool is_elastic_material(const std::string &material)
utility to check if material is one of the elastic materials
Read-only interface to a hierarchical collection of simulation resources.
static std::shared_ptr< VarForm > create(const std::string &formulation, const json &args, const io::ResourceIO &resources, bool is_optimization=false)
static bool supports(const std::string &formulation, const json &args, bool is_optimization=false)
std::unique_ptr< const io::ResourceIO > apply_common_params(json &args, const io::ResourceIO &resources)
Definition JSONUtils.cpp:24
std::string formulation_from_args(const json &args)
Extracts the formulation type from the given JSON arguments.
bool uses_varform_state(json args, const io::ResourceIO &resources)
Checks if the given JSON arguments use a VarForm state.
nlohmann::json json
Definition Common.hpp:9