Skip to content

Commit b33ee89

Browse files
committed
add back missing parametrizations
1 parent f0369b1 commit b33ee89

File tree

4 files changed

+171
-1
lines changed

4 files changed

+171
-1
lines changed

json-specs/opt-input-spec.json

+45-1
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,31 @@
335335
"sdf-to-mesh",
336336
"periodic-mesh-tile",
337337
"mesh-affine",
338-
"matrix-product"
338+
"matrix-product",
339+
"box-constraint-reparametrization"
339340
]
340341
},
342+
{
343+
"pointer": "/variable_to_simulation/*/composition/*",
344+
"type_name": "box-constraint-reparametrization",
345+
"type": "object",
346+
"required": [
347+
"bounds"
348+
],
349+
"doc": "Reparametrize variable to fit into box constraints."
350+
},
351+
{
352+
"pointer": "/variable_to_simulation/*/composition/*/bounds",
353+
"type": "list"
354+
},
355+
{
356+
"pointer": "/variable_to_simulation/*/composition/*/bounds/*",
357+
"type": "list"
358+
},
359+
{
360+
"pointer": "/variable_to_simulation/*/composition/*/bounds/*/*",
361+
"type": "float"
362+
},
341363
{
342364
"pointer": "/variable_to_simulation/*/composition/*",
343365
"type_name": "matrix-product",
@@ -641,6 +663,28 @@
641663
"default": 0,
642664
"type": "float"
643665
},
666+
{
667+
"pointer": "/variable_to_simulation/*/composition/*",
668+
"type_name": "periodic-mesh-tile",
669+
"type": "object",
670+
"required": [
671+
"dimensions"
672+
],
673+
"doc": "Append a list of constants at the end of the input vector"
674+
},
675+
{
676+
"pointer": "/variable_to_simulation/*/composition/*",
677+
"type_name": "mesh-affine",
678+
"type": "object",
679+
"required": [
680+
"type",
681+
"dimension"
682+
],
683+
"optional": [
684+
"transformation"
685+
],
686+
"doc": "Append a list of constants at the end of the input vector"
687+
},
644688
{
645689
"pointer": "/variable_to_simulation/*/composition/*/dimensions",
646690
"type": "list"

src/polyfem/solver/Optimizations.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,14 @@ namespace polyfem::solver
484484
{
485485
map = std::make_shared<InsertConstantMap>(args["size"], args["value"], args["start"]);
486486
}
487+
else if (type == "matrix-product")
488+
{
489+
map = std::make_shared<MatrixProduct>(args);
490+
}
491+
else if (type == "box-constraint-reparametrization")
492+
{
493+
map = std::make_shared<BoxConstraintReparametrization>(args);
494+
}
487495
else if (type == "linear-filter")
488496
{
489497
map = std::make_shared<LinearFilter>(*(states[args["state"]]->mesh), args["radius"]);

src/polyfem/solver/forms/parametrization/Parametrizations.cpp

+89
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <polyfem/basis/ElementBases.hpp>
44
#include <polyfem/utils/Logger.hpp>
55
#include <polyfem/Common.hpp>
6+
#include <polyfem/utils/JSONUtils.hpp>
67
#include <polyfem/utils/ElasticityUtils.hpp>
78

89
namespace polyfem::solver
@@ -493,4 +494,92 @@ namespace polyfem::solver
493494
return hess.transpose() * grad;
494495
}
495496

497+
MatrixProduct::MatrixProduct(const json &args)
498+
{
499+
int rows = args["matrix"].size();
500+
assert (args["matrix"][0].is_array());
501+
int cols = args["matrix"][0].size();
502+
503+
mat.setZero(rows, cols);
504+
Eigen::VectorXd tmp;
505+
for (int i = 0; i < rows; i++)
506+
{
507+
tmp = args["matrix"][i];
508+
assert(tmp.size() == cols);
509+
mat.row(i) = tmp;
510+
}
511+
512+
left_mult = args["left_multiply"];
513+
}
514+
int MatrixProduct::size(const int x_size) const
515+
{
516+
if (left_mult)
517+
return (x_size * mat.rows()) / mat.cols();
518+
else
519+
return (x_size * mat.cols()) / mat.rows();
520+
}
521+
Eigen::VectorXd MatrixProduct::eval(const Eigen::VectorXd &x) const
522+
{
523+
if (left_mult)
524+
{
525+
assert(x.size() % mat.cols() == 0);
526+
Eigen::MatrixXd input = utils::unflatten(x, x.size() / mat.cols());
527+
return utils::flatten(mat * input);
528+
}
529+
else
530+
{
531+
assert(x.size() % mat.rows() == 0);
532+
Eigen::MatrixXd input = utils::unflatten(x, mat.rows());
533+
return utils::flatten(input * mat);
534+
}
535+
}
536+
Eigen::VectorXd MatrixProduct::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
537+
{
538+
if (left_mult)
539+
{
540+
Eigen::MatrixXd grad_mat = utils::unflatten(grad, x.size() / mat.cols());
541+
return utils::flatten(mat.transpose() * grad_mat);
542+
}
543+
else
544+
{
545+
Eigen::MatrixXd grad_mat = utils::unflatten(grad, mat.cols());
546+
return utils::flatten(grad_mat * mat.transpose());
547+
}
548+
}
549+
550+
BoxConstraintReparametrization::BoxConstraintReparametrization(const json &args)
551+
{
552+
bounds = args["bounds"];
553+
if (bounds.rows() != 2)
554+
log_and_throw_adjoint_error("Invalid bounds size!");
555+
}
556+
int BoxConstraintReparametrization::size(const int x_size) const
557+
{
558+
return x_size;
559+
}
560+
Eigen::VectorXd BoxConstraintReparametrization::eval(const Eigen::VectorXd &x) const
561+
{
562+
Eigen::VectorXd y = x;
563+
if (bounds.cols() != x.size())
564+
log_and_throw_adjoint_error("Inconsistent input size, {} vs {}!", x.size(), bounds.cols());
565+
for (int i = 0; i < x.size(); i++)
566+
y(i) = logistic(x(i), bounds(0, i), bounds(1, i));
567+
return y;
568+
}
569+
Eigen::VectorXd BoxConstraintReparametrization::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
570+
{
571+
Eigen::VectorXd gradv = grad;
572+
for (int i = 0; i < x.size(); i++)
573+
gradv(i) *= logistic_grad(x(i), bounds(0, i), bounds(1, i));
574+
return gradv;
575+
}
576+
double BoxConstraintReparametrization::logistic(double x, double lower, double higher)
577+
{
578+
return lower + (higher - lower) / (1. + exp(-x));
579+
}
580+
double BoxConstraintReparametrization::logistic_grad(double x, double lower, double higher)
581+
{
582+
const double e = exp(-x);
583+
return (higher - lower) * e / (1 + e) / (1 + e);
584+
}
496585
} // namespace polyfem::solver

src/polyfem/solver/forms/parametrization/Parametrizations.hpp

+29
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,33 @@ namespace polyfem::solver
182182
const double start_val_;
183183
const double dt_;
184184
};
185+
186+
class MatrixProduct : public Parametrization
187+
{
188+
public:
189+
MatrixProduct(const json &args);
190+
191+
int size(const int x_size) const override;
192+
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override;
193+
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override;
194+
195+
private:
196+
Eigen::MatrixXd mat;
197+
bool left_mult;
198+
};
199+
200+
class BoxConstraintReparametrization : public Parametrization
201+
{
202+
public:
203+
BoxConstraintReparametrization(const json &args);
204+
205+
int size(const int x_size) const override;
206+
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override;
207+
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override;
208+
private:
209+
static double logistic(double x, double lower, double higher);
210+
static double logistic_grad(double x, double lower, double higher);
211+
212+
Eigen::MatrixXd bounds;
213+
};
185214
} // namespace polyfem::solver

0 commit comments

Comments
 (0)