17 for (
int i = 0; i < constrained_dofs.Size(); i++) {
18 int j = constrained_dofs[i];
19 (*primal_field)[j] = (*bc_field_ptr)(j);
23 bc.setDofs(*primal_field, time);
49 const std::vector<FieldState>& states,
const std::vector<FieldState>& params,
50 const std::vector<double>& state_update_weights,
size_t primal_solve_state_index,
55 SLIC_ERROR_IF(states.size() != state_update_weights.size(),
"State and state weight fields are inconsistent");
56 SLIC_ERROR_IF(state_update_weights[primal_solve_state_index] != 1.0,
"Primal state must have a weight of 1.0");
58 std::vector<gretl::StateBase> allFields;
59 for (
auto& s : states) allFields.push_back(s);
60 for (
auto& p : params) allFields.push_back(p);
61 allFields.push_back(shape_disp);
63 bool have_bc_field = bc_field;
65 allFields.push_back(*bc_field);
68 FieldState sol = states[primal_solve_state_index].clone(allFields);
70 sol.set_eval([=](
const gretl::UpstreamStates& inputs, gretl::DownstreamState& output) {
73 const size_t num_states = state_update_weights.size();
75 std::vector<size_t> non_primal_to_state_index;
76 for (
size_t i = 0; i < num_states; ++i) {
77 if (i != primal_solve_state_index) {
78 non_primal_to_state_index.push_back(i);
82 const size_t num_extra_args = have_bc_field ? 2 : 1;
83 const size_t num_fields = inputs.size() - num_extra_args;
85 std::vector<FEFieldPtr> corrected_fields(num_fields);
86 for (
size_t field_index = 0; field_index < num_fields; ++field_index) {
87 if (field_index < state_update_weights.size() && state_update_weights[field_index] != 0.0) {
88 corrected_fields[field_index] = std::make_shared<FiniteElementState>(*inputs[field_index].get<FEFieldPtr>());
90 corrected_fields[field_index] = inputs[field_index].get<
FEFieldPtr>();
98 bc_field_ptr = inputs[num_fields + num_extra_args - 1].get<
FEFieldPtr>();
101 FEFieldPtr s0 = corrected_fields[primal_solve_state_index];
102 FEFieldPtr s = std::make_shared<FiniteElementState>(s0->space(),
"s");
104 if (bc_manager && (dirichlet_state_index == primal_solve_state_index)) {
111 FEFieldPtr primal_field = corrected_fields[primal_solve_state_index];
114 if (bc_manager && (dirichlet_state_index == primal_solve_state_index)) {
118 for (
size_t corrected_field_index : non_primal_to_state_index) {
119 if (state_update_weights[corrected_field_index] != 0.0) {
120 *corrected_fields[corrected_field_index] = *inputs[corrected_field_index].get<
FEFieldPtr>();
121 corrected_fields[corrected_field_index]->Add(state_update_weights[corrected_field_index], *primal_field);
122 corrected_fields[corrected_field_index]->Add(-state_update_weights[corrected_field_index], *s0);
129 if (dirichlet_state_index == primal_solve_state_index) {
131 r.SetSubVector(constrained_dofs, 0.0);
138 FEFieldPtr primal_field = corrected_fields[primal_solve_state_index];
141 if (bc_manager && (dirichlet_state_index == primal_solve_state_index)) {
145 for (
size_t corrected_field_index : non_primal_to_state_index) {
146 if (state_update_weights[corrected_field_index] != 0.0) {
147 *corrected_fields[corrected_field_index] = *inputs[corrected_field_index].get<
FEFieldPtr>();
148 corrected_fields[corrected_field_index]->Add(state_update_weights[corrected_field_index], *primal_field);
149 corrected_fields[corrected_field_index]->Add(-state_update_weights[corrected_field_index], *s0);
154 state_update_weights);
157 if (dirichlet_state_index == primal_solve_state_index) {
169 sol.set_vjp([=](gretl::UpstreamStates& inputs,
const gretl::DownstreamState& output) {
174 const size_t num_states = state_update_weights.size();
176 std::vector<size_t> non_primal_to_state_index;
177 for (
size_t i = 0; i < num_states; ++i) {
178 if (i != primal_solve_state_index) {
179 non_primal_to_state_index.push_back(i);
183 const size_t num_extra_args = have_bc_field ? 2 : 1;
184 const size_t num_fields = inputs.size() - num_extra_args;
186 std::vector<FEFieldPtr> corrected_fields(num_fields);
187 for (
size_t field_index = 0; field_index < num_fields; ++field_index) {
188 if (field_index < state_update_weights.size() && state_update_weights[field_index] != 0.0) {
189 corrected_fields[field_index] = std::make_shared<FiniteElementState>(*inputs[field_index].get<FEFieldPtr>());
191 corrected_fields[field_index] = inputs[field_index].get<
FEFieldPtr>();
199 *corrected_fields[primal_solve_state_index] = *s;
200 for (
size_t corrected_field_index : non_primal_to_state_index) {
201 if (state_update_weights[corrected_field_index] != 0.0) {
202 corrected_fields[corrected_field_index]->Add(state_update_weights[corrected_field_index], *s);
203 corrected_fields[corrected_field_index]->Add(-state_update_weights[corrected_field_index], *s0);
209 state_update_weights, {});
212 if (dirichlet_state_index == primal_solve_state_index) {
217 auto J_T = std::unique_ptr<mfem::HypreParMatrix>(J->Transpose());
220 auto s_adjoint_ptr = solver->
solveAdjoint(*s_dual, std::move(J_T));
223 if (dirichlet_state_index == primal_solve_state_index) {
228 *s_adjoint_ptr *= -1.0;
230 std::vector<DualFieldPtr> field_sensitivities(num_fields,
nullptr);
232 for (
size_t state_index = 0; state_index < num_states; ++state_index) {
235 for (
size_t param_index = num_states; param_index < num_fields; ++param_index) {
239 auto primal_sensitivity = std::make_shared<FiniteElementDual>(*field_sensitivities[primal_solve_state_index]);
240 field_sensitivities[primal_solve_state_index] = primal_sensitivity.get();
241 *field_sensitivities[primal_solve_state_index] = *s_dual;
244 s_adjoint_ptr.get(), shape_disp_sensitivity.get(), field_sensitivities, {});
246 if (bc_manager && have_bc_field && dirichlet_state_index == primal_solve_state_index) {
247 auto bc_dual_ptr = inputs[num_fields + num_extra_args - 1].get_dual<
FEDualPtr,
FEFieldPtr>();
248 field_sensitivities[primal_solve_state_index]->SetSubVectorComplement(bc_manager->
allEssentialTrueDofs(), 0.0);
249 *bc_dual_ptr += *field_sensitivities[primal_solve_state_index];
264 std::vector<double> state_update_weights(states.size(), 0.0);
265 state_update_weights[unknown_state_index] = 1.0;
266 return nonlinearSolve(&weak_form, shape_disp, states, params, state_update_weights, unknown_state_index,
270 std::vector<FieldState>
block_solve(
const std::vector<WeakForm*>& residual_evals,
271 const std::vector<std::vector<size_t>> block_indices,
const FieldState& shape_disp,
272 const std::vector<std::vector<FieldState>>& states,
273 const std::vector<std::vector<FieldState>>& params,
const TimeInfo& time_info,
275 const std::vector<const BoundaryConditionManager*>& bc_managers)
278 size_t num_rows_ = residual_evals.size();
280 SLIC_ERROR_IF(num_rows_ != block_indices.size(),
"Block indices size not consistent with number of residual rows");
281 SLIC_ERROR_IF(num_rows_ != states.size(),
282 "Number of state input vectors not consistent with number of residual rows");
283 SLIC_ERROR_IF(num_rows_ != params.size(),
284 "Number of parameter input vectors not consistent with number of residual rows");
285 SLIC_ERROR_IF(num_rows_ != bc_managers.size(),
286 "Number of boundary condition manager not consistent with number of residual rows");
288 for (
size_t r = 0; r < num_rows_; ++r) {
289 SLIC_ERROR_IF(num_rows_ != block_indices[r].
size(),
"All block index rows must have the same number of columns");
292 std::vector<size_t> num_state_inputs;
293 std::vector<gretl::StateBase> allFields;
294 for (
auto& ss : states) {
295 num_state_inputs.push_back(ss.size());
297 allFields.push_back(s);
300 std::vector<size_t> num_param_inputs;
301 for (
auto& ps : params) {
302 num_param_inputs.push_back(ps.size());
304 allFields.push_back(p);
307 allFields.push_back(shape_disp);
308 struct ZeroDualVectors {
309 std::vector<FEDualPtr> operator()(
const std::vector<FEFieldPtr>& fs)
311 std::vector<FEDualPtr> ds(fs.size());
312 for (
size_t i = 0; i < fs.size(); ++i) {
313 ds[i] = std::make_shared<FiniteElementDual>(fs[i]->
space(), fs[i]->name() +
"_dual");
320 shape_disp.create_state<std::vector<FEFieldPtr>, std::vector<FEDualPtr>>(allFields, ZeroDualVectors());
321 sol.set_eval([=](
const gretl::UpstreamStates& upstreams, gretl::DownstreamState& downstream) {
323 const size_t num_rows = num_state_inputs.size();
324 std::vector<std::vector<FEFieldPtr>> input_fields(num_rows);
325 SLIC_ERROR_IF(num_rows != num_param_inputs.size(),
"row count for params and states are inconsistent");
329 size_t field_count = 0;
330 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
331 for (
size_t state_i = 0; state_i < num_state_inputs[row_i]; ++state_i) {
332 input_fields[row_i].push_back(upstreams[field_count++].get<FEFieldPtr>());
335 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
336 for (
size_t param_i = 0; param_i < num_param_inputs[row_i]; ++param_i) {
337 input_fields[row_i].push_back(upstreams[field_count++].get<FEFieldPtr>());
341 std::vector<FEFieldPtr> diagonal_fields(num_rows);
342 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
343 size_t prime_unknown_row_i = block_indices[row_i][row_i];
344 SLIC_ERROR_IF(prime_unknown_row_i == invalid_block_index,
345 "The primary unknown field (field index for block_index[n][n], must not be invalid)");
346 diagonal_fields[row_i] = std::make_shared<FiniteElementState>(*input_fields[row_i][prime_unknown_row_i]);
349 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
350 FEFieldPtr primal_field_row_i = diagonal_fields[row_i];
354 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
355 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
356 size_t prime_unknown_ij = block_indices[row_i][col_j];
357 if (prime_unknown_ij != invalid_block_index) {
358 input_fields[row_i][block_indices[row_i][col_j]] = diagonal_fields[col_j];
365 auto eval_residuals = [=](
const std::vector<FEFieldPtr>& unknowns) {
366 SLIC_ERROR_IF(unknowns.size() != num_rows,
367 "block solver unknowns size must match the number or residuals in block_solve");
368 std::vector<mfem::Vector> residuals(num_rows);
370 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
371 FEFieldPtr primal_field_row_i = diagonal_fields[row_i];
372 *primal_field_row_i = *unknowns[row_i];
375 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
376 residuals[row_i] = residual_evals[row_i]->residual(time_info, shape_disp_ptr.get(),
378 residuals[row_i].SetSubVector(bc_managers[row_i]->allEssentialTrueDofs(), 0.0);
383 auto eval_jacobians = [=](
const std::vector<FEFieldPtr>& unknowns) {
384 SLIC_ERROR_IF(unknowns.size() != num_rows,
385 "block solver unknown size must match the number or residuals in block_solve");
386 std::vector<std::vector<std::unique_ptr<mfem::HypreParMatrix>>> jacobians(num_rows);
388 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
389 FEFieldPtr primal_field_row_i = diagonal_fields[row_i];
390 *primal_field_row_i = *unknowns[row_i];
394 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
395 std::vector<FEFieldPtr> row_field_inputs = input_fields[row_i];
396 std::vector<double> tangent_weights(row_field_inputs.size(), 0.0);
397 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
398 size_t field_index_to_diff = block_indices[row_i][col_j];
399 if (field_index_to_diff != invalid_block_index) {
400 tangent_weights[field_index_to_diff] = 1.0;
401 auto jac_ij = residual_evals[row_i]->jacobian(time_info, shape_disp_ptr.get(),
403 jacobians[row_i].emplace_back(std::move(jac_ij));
404 tangent_weights[field_index_to_diff] = 0.0;
406 jacobians[row_i].emplace_back(
nullptr);
412 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
413 if (jacobians[row_i][row_i]) {
414 jacobians[row_i][row_i]->EliminateBC(bc_managers[row_i]->allEssentialTrueDofs(),
415 mfem::Operator::DiagonalPolicy::DIAG_ONE);
417 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
418 if (col_j != row_i) {
419 if (jacobians[row_i][col_j]) {
420 jacobians[row_i][col_j]->EliminateRows(bc_managers[row_i]->allEssentialTrueDofs());
422 if (jacobians[col_j][row_i]) {
423 mfem::HypreParMatrix* Jji =
424 jacobians[col_j][row_i]->EliminateCols(bc_managers[row_i]->allEssentialTrueDofs());
433 diagonal_fields = solver->
solve(diagonal_fields, eval_residuals, eval_jacobians);
435 downstream.set<std::vector<FEFieldPtr>, std::vector<FEDualPtr>>(diagonal_fields);
440 sol.set_vjp([=](gretl::UpstreamStates& upstreams,
const gretl::DownstreamState& downstream) {
442 const std::vector<FEFieldPtr> s = downstream.get<std::vector<FEFieldPtr>>();
443 const std::vector<FEDualPtr> s_dual =
444 downstream.get_dual<std::vector<FEDualPtr>, std::vector<FEFieldPtr>>();
446 const size_t num_rows = num_state_inputs.size();
447 SLIC_ERROR_IF(s_dual.size() != num_rows,
448 "block solver vjp downstream size must match the number or residuals in block_solve");
450 std::vector<std::vector<FEFieldPtr>> input_fields(num_rows);
451 size_t field_count = 0;
452 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
453 for (
size_t state_i = 0; state_i < num_state_inputs[row_i]; ++state_i) {
454 input_fields[row_i].push_back(upstreams[field_count++].get<FEFieldPtr>());
457 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
458 for (
size_t param_i = 0; param_i < num_param_inputs[row_i]; ++param_i) {
459 input_fields[row_i].push_back(upstreams[field_count++].get<FEFieldPtr>());
465 std::vector<FEFieldPtr> diagonal_fields(num_rows);
466 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
467 diagonal_fields[row_i] = std::make_shared<FiniteElementState>(*input_fields[row_i][block_indices[row_i][row_i]]);
468 *diagonal_fields[row_i] = *s[row_i];
471 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
472 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
473 input_fields[row_i][block_indices[row_i][col_j]] = diagonal_fields[col_j];
481 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
482 FEFieldPtr primal_field_row_i = diagonal_fields[row_i];
488 std::vector<std::vector<std::unique_ptr<mfem::HypreParMatrix>>> jacobians(num_rows);
489 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
490 std::vector<FEFieldPtr> row_field_inputs = input_fields[row_i];
491 std::vector<double> tangent_weights(row_field_inputs.size(), 0.0);
492 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
493 size_t field_index_to_diff = block_indices[row_i][col_j];
494 tangent_weights[field_index_to_diff] = 1.0;
495 auto jac_ij = residual_evals[row_i]->jacobian(time_info, shape_disp_ptr.get(),
497 jacobians[row_i].emplace_back(std::move(jac_ij));
498 tangent_weights[field_index_to_diff] = 0.0;
503 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
504 s_dual[row_i]->SetSubVector(bc_managers[row_i]->allEssentialTrueDofs(), 0.0);
506 mfem::HypreParMatrix* Jii =
507 jacobians[row_i][row_i]->EliminateRowsCols(bc_managers[row_i]->allEssentialTrueDofs());
509 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
510 if (col_j != row_i) {
511 jacobians[row_i][col_j]->EliminateRows(bc_managers[row_i]->allEssentialTrueDofs());
512 mfem::HypreParMatrix* Jji =
513 jacobians[col_j][row_i]->EliminateCols(bc_managers[row_i]->allEssentialTrueDofs());
520 std::vector<std::vector<std::unique_ptr<mfem::HypreParMatrix>>> jacobians_T(num_rows);
521 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
522 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
523 jacobians_T[col_j].emplace_back(std::unique_ptr<mfem::HypreParMatrix>(jacobians[row_i][col_j]->Transpose()));
526 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
527 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
528 jacobians[row_i][col_j].reset();
532 std::vector<FEFieldPtr> adjoint_fields(num_rows);
533 adjoint_fields = solver->
solveAdjoint(s_dual, jacobians_T);
534 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
535 *adjoint_fields[row_i] *= -1.0;
539 std::vector<std::vector<FEDualPtr>> field_sensitivities(num_rows);
541 size_t dual_index = 0;
542 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
543 for (
size_t state_i = 0; state_i < num_state_inputs[row_i]; ++state_i) {
544 field_sensitivities[row_i].push_back(upstreams[dual_index++].get_dual<FEDualPtr, FEFieldPtr>());
547 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
548 for (
size_t param_i = 0; param_i < num_param_inputs[row_i]; ++param_i) {
549 field_sensitivities[row_i].push_back(upstreams[dual_index++].get_dual<FEDualPtr, FEFieldPtr>());
552 SLIC_ERROR_IF(field_count != dual_index,
"Number of sensitivities must equal to number of upstreams");
555 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
556 for (
size_t col_j = 0; col_j < num_rows; ++col_j) {
557 field_sensitivities[row_i][block_indices[row_i][col_j]] =
nullptr;
561 for (
size_t row_i = 0; row_i < num_rows; ++row_i) {
562 residual_evals[row_i]->vjp(time_info, shape_disp_ptr.get(),
getConstFieldPointers(input_fields[row_i]), {},
563 adjoint_fields[row_i].get(), shape_disp_sensitivity.get(),
572 std::vector<FieldState> results;
573 for (
size_t i = 0; i < num_rows_; ++i) {
574 FieldState s = gretl::create_state<FEFieldPtr, FEDualPtr>(
576 [i](
const std::vector<FEFieldPtr>& sols) {
577 auto state_copy = std::make_shared<FiniteElementState>(sols[i]->
space(), sols[i]->name());
578 *state_copy = *sols[i];
581 [i](
const std::vector<FEFieldPtr>&,
const FEFieldPtr&, std::vector<FEDualPtr>& sols_,
582 const FEDualPtr& output_) { *sols_[i] += *output_; },
585 results.emplace_back(s);
This file contains the declaration of the boundary condition manager class.
A container for the boundary condition information relating to a specific physics module.
const mfem::Array< int > & allEssentialTrueDofs() const
Returns all the true degrees of freedom associated with all the essential BCs.
std::vector< BoundaryCondition > & essentials()
Accessor for the essential BC objects.
Abstract interface to DifferentiableBlockSolver interface. Each differentiable block solve should pro...
virtual std::vector< FieldPtr > solveAdjoint(const std::vector< DualPtr > &u_bars, std::vector< std::vector< MatrixPtr >> &jacobian_transposed) const =0
Solve the (linear) adjoint set of equations with a vector of FiniteElementState as unknown.
virtual std::vector< FieldPtr > solve(const std::vector< FieldPtr > &u_guesses, std::function< std::vector< mfem::Vector >(const std::vector< FieldPtr > &)> residuals, std::function< std::vector< std::vector< MatrixPtr >>(const std::vector< FieldPtr > &)> jacobians) const =0
Solve a set of equations with a vector of FiniteElementState as unknown.
virtual void clearMemory() const
Interface option to clear memory between solves to avoid high-water mark memory usage.
Abstract interface to DifferentiableSolver interface. Each differentiable solve should provide both i...
virtual std::shared_ptr< smith::FiniteElementState > solve(const smith::FiniteElementState &u_guess, std::function< mfem::Vector(const smith::FiniteElementState &)> equation, std::function< std::unique_ptr< mfem::HypreParMatrix >(const smith::FiniteElementState &)> jacobian) const =0
Solve a set of equations with a FiniteElementState as unknown.
virtual std::shared_ptr< smith::FiniteElementState > solveAdjoint(const smith::FiniteElementDual &u_bar, std::unique_ptr< mfem::HypreParMatrix > jacobian_transposed) const =0
Solve the (linear) adjoint set of equations with a FiniteElementState as unknown.
virtual void clearMemory() const
Interface option to clear memory between solves to avoid high-water mark memory usage.
A generic class for setting Dirichlet boundary conditions on arbitrary physics.
const smith::BoundaryConditionManager & getBoundaryConditionManager() const
Return the smith BoundaryConditionManager.
Class for encapsulating the critical MFEM components of a primal finite element field.
This file contains the declaration of the DifferentiableSolver interface.
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Defines common types and helper functions for using the residual and scalar_objective classes.
Accelerator functionality.
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
std::shared_ptr< FiniteElementState > FEFieldPtr
typedef
gretl::State< std::vector< FEFieldPtr >, std::vector< FEDualPtr > > FieldVecState
typedef
void applyBoundaryConditions(double time, const smith::BoundaryConditionManager *bc_manager, smith::FEFieldPtr &primal_field, const smith::FEFieldPtr &bc_field_ptr)
apply boundary conditions
std::vector< FiniteElementState * > getFieldPointers(std::vector< FieldState > &states, std::vector< FieldState > params={})
Get a vector of FieldPtr or DualFieldPtr from a vector of FieldState.
gretl::State< FEFieldPtr, FEDualPtr > FieldState
typedef
constexpr SMITH_HOST_DEVICE int size(const tensor< T, n... > &)
returns the total number of stored values in a tensor
std::shared_ptr< FiniteElementDual > FEDualPtr
typedef
std::vector< const FiniteElementState * > getConstFieldPointers(const std::vector< FieldState > &states, const std::vector< FieldState > ¶ms={})
Get a vector of ConstFieldPtr or ConstDualFieldPtr from a vector of FieldState.
std::vector< FieldState > block_solve(const std::vector< WeakForm * > &residual_evals, const std::vector< std::vector< size_t >> block_indices, const FieldState &shape_disp, const std::vector< std::vector< FieldState >> &states, const std::vector< std::vector< FieldState >> ¶ms, const TimeInfo &time_info, const DifferentiableBlockSolver *solver, const std::vector< const BoundaryConditionManager * > &bc_managers)
Solve a block nonlinear system of equations as defined by the vector of weak form.
mfem::ParFiniteElementSpace & space(FieldState field)
Get the space from the primal field of a field states.
FieldState nonlinearSolve(const WeakForm *residual_eval, const FieldState &shape_disp, const std::vector< FieldState > &states, const std::vector< FieldState > ¶ms, const std::vector< double > &state_update_weights, size_t primal_solve_state_index, size_t dirichlet_state_index, const TimeInfo &time_info, const DifferentiableSolver *solver, const BoundaryConditionManager *bc_manager, const FieldState *bc_field=nullptr)
Solve a nonlinear system of equations as defined by the weak form.
FieldState solve(const WeakForm &weak_form, const FieldState &shape_disp, const std::vector< FieldState > &states, const std::vector< FieldState > ¶ms, const TimeInfo &time_info, const DifferentiableSolver &solver, const DirichletBoundaryConditions &bcs, size_t unknown_state_index)
Solve a nonlinear system of equations as defined by the weak form, assuming that the field indexed by...
Methods for solving systems of equations as given by WeakForms. Tracks these operations on the gretl ...
#define SMITH_MARK_FUNCTION
#define SMITH_MARK_BEGIN(name)
#define SMITH_MARK_END(name)
struct storing time and timestep information
double time() const
accessor for the current time
functor which takes a std::shared_ptr<FiniteElementState>, and returns a zero-valued std::shared_ptr<...