16 return (E * nu) / ((1.0 + nu) * (1.0 - 2.0 * nu));
18 return (nu * E) / (1.0 - nu * nu);
23 std::vector<Eigen::Vector3d> read_cell_vectors_legacy_vtk(
25 const std::string &description,
26 const std::string &field_name)
28 std::vector<Eigen::Vector3d> out;
33 while (std::getline(in, line))
35 std::istringstream ss(line);
38 if (tok ==
"CELL_DATA")
42 else if (tok ==
"VECTORS")
46 if (name != field_name)
50 out.resize(n_cell_data);
51 for (
int i = 0; i < n_cell_data; ++i)
53 if (!(in >> out[i].
x() >> out[i].
y() >> out[i].
z()))
55 "Fiber VTK '{}' ended early: expected {} vectors", description, n_cell_data));
63 "VECTORS '{}' not found under CELL_DATA in {}", field_name, description));
69 return E / (2.0 * (1.0 + nu));
74 : param_name_(param_name)
80 for (
int i =
param_.size(); i <= index; ++i)
83 param_.back().set_unit_type(unit_type);
96 const double x = p(0);
97 const double y = p(1);
98 const double z = p.size() == 3 ? p(2) : 0;
100 return (*
this)(
x,
y,
z, t, index);
109 return tmp_param(
x,
y,
z, t, index);
113 : param_name_(param_name)
126 for (
int i = 0; i < params_array.size(); ++i)
129 for (
int i = 0; i <
params_.size(); ++i)
131 for (
int j =
params_.at(i).param_.size(); j <= index; ++j)
133 params_.at(i).param_.emplace_back();
134 params_.at(i).param_.back().set_unit_type(unit_type);
137 params_.at(i).param_[index].init(params_array[i], resources);
187 entries[3], stress_units, resources);
213 stress_units, resources);
228 entries[8], stress_units, resources);
267 (*this)(0, 0) = 2 * mu + lambda;
268 (*this)(0, 1) = lambda;
271 (*this)(1, 1) = 2 * mu + lambda;
278 (*this)(0, 0) = 2 * mu + lambda;
279 (*this)(0, 1) = lambda;
280 (*this)(0, 2) = lambda;
285 (*this)(1, 1) = 2 * mu + lambda;
286 (*this)(1, 2) = lambda;
291 (*this)(2, 2) = 2 * mu + lambda;
313 0.0, 0.0, (1.0 - nu) / 2.0;
321 v, 1. - v, v, 0, 0, 0,
322 v, v, 1. - v, 0, 0, 0,
323 0, 0, 0, (1. - 2. * v) / 2., 0, 0,
324 0, 0, 0, 0, (1. - 2. * v) / 2., 0,
325 0, 0, 0, 0, 0, (1. - 2. * v) / 2.;
331 double Ex,
double Ey,
double Ez,
332 double nuXY,
double nuXZ,
double nuYZ,
333 double muYZ,
double muZX,
double muXY,
const std::string &stress_units,
const io::ResourceIO &resources)
338 double nuYX = nuXY * Ey / Ex;
339 double nuZX = nuXZ * Ez / Ex;
340 double nuZY = nuYZ * Ez / Ey;
342 Eigen::MatrixXd compliance;
343 compliance.setZero(6, 6);
344 compliance << 1 / Ex, -nuYX / Ey, -nuZX / Ez, 0, 0, 0,
345 -nuXY / Ex, 1 / Ey, -nuZY / Ez, 0, 0, 0,
346 -nuXZ / Ex, -nuYZ / Ey, 1 / Ez, 0, 0, 0,
347 0, 0, 0, 1 / (2 * muYZ), 0, 0,
348 0, 0, 0, 0, 1 / (2 * muZX), 0,
349 0, 0, 0, 0, 0, 1 / (2 * muXY);
358 double nuYX = nuXY * Ey / Ex;
360 Eigen::MatrixXd compliance;
361 compliance.setZero(3, 3);
362 compliance << 1.0 / Ex, -nuYX / Ey, 0.0,
363 -nuXY / Ex, 1.0 / Ey, 0.0,
364 0.0, 0.0, 1.0 / (2 * muXY);
369 double Et,
double Ea,
370 double nu_t,
double nu_a,
371 double Ga,
const std::string &stress_units,
const io::ResourceIO &resources)
376 Eigen::MatrixXd compliance;
377 compliance.setZero(6, 6);
378 compliance << 1 / Et, -nu_t / Et, -nu_a / Ea, 0, 0, 0,
379 -nu_t / Et, 1 / Et, -nu_a / Ea, 0, 0, 0,
380 -nu_a / Ea, -nu_a / Ea, 1 / Ea, 0, 0, 0,
381 0, 0, 0, 1 / Ga, 0, 0,
382 0, 0, 0, 0, 1 / Ga, 0,
383 0, 0, 0, 0, 0, (2 * (1 + nu_t)) / Et;
392 for (
int k = 0; k < DIM; ++k)
393 res += (*
this)(j, k) * strain[k];
429 double llambda = tmp1(
x,
y,
z, t, el_id);
430 double mmu = tmp2(
x,
y,
z, t, el_id);
449 assert(!std::isnan(lambda));
450 assert(!std::isnan(mu));
451 assert(!std::isinf(lambda));
452 assert(!std::isinf(mu));
457 const int size = is_volume ? 3 : 2;
469 if (params.count(
"young"))
471 set_e_nu(index, params[
"young"], params[
"nu"], stress_unit, resources);
473 else if (params.count(
"E"))
475 set_e_nu(index, params[
"E"], params[
"nu"], stress_unit, resources);
477 else if (params.count(
"lambda"))
480 mu_or_nu_[index].init(params[
"mu"], resources);
483 mu_or_nu_[index].set_unit_type(stress_unit);
509 rho_.back().init(1.0);
514 assert(
rho_.size() == 1 || el_id <
rho_.size());
516 const auto &tmp =
rho_.size() == 1 ?
rho_[0] :
rho_[el_id];
517 const double res = tmp(
x,
y,
z, t, el_id);
518 assert(!std::isnan(res));
519 assert(!std::isinf(res));
525 for (
int i =
rho_.size(); i <= index; ++i)
530 if (params.count(
"rho"))
532 rho_[index].init(params[
"rho"], resources);
534 else if (params.count(
"density"))
536 rho_[index].init(params[
"density"], resources);
541 rho_[index].set_unit_type(density_unit);
545 : rho_(
"rho"), heat_capacity_(
"heat_capacity")
565 assert(!std::isnan(res));
566 assert(!std::isinf(res));
572 return rho_(p, t, el_id);
586 assert(size == 2 || size == 3);
590 for (
const auto &m :
dir_)
592 assert((m.rows() == size && m.cols() == size) || (m.rows() == size && m.cols() == 1));
597 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3>
FiberDirection::operator()(
double px,
double py,
double pz,
double x,
double y,
double z,
double t,
int el_id)
const
603 if (el_id < 0 || el_id >=
static_cast<int>(
per_el_fibers_.size()))
605 "Fiber el_id {} out of range [0,{})", el_id,
per_el_fibers_.size()));
606 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> res;
607 res.resize(
size_, 1);
608 for (
int i = 0; i <
size_; ++i)
613 assert(
dir_.size() == 1 || el_id <
dir_.size());
615 const auto &tmp =
dir_.size() == 1 ?
dir_[0] :
dir_[el_id];
616 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> res;
617 res.resize(tmp.rows(), tmp.cols());
618 for (
int i = 0; i < tmp.rows(); ++i)
620 for (
int j = 0; j < tmp.cols(); ++j)
622 res(i, j) = tmp(i, j)(
x,
y,
z, t, el_id);
624 assert(!std::isnan(res(i, j)));
625 assert(!std::isinf(res(i, j)));
631 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6>
FiberDirection::stiffness_rotation_voigt(
double px,
double py,
double pz,
double x,
double y,
double z,
double t,
int el_id)
const
636 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> rot = (*this)(px, py, pz,
x,
y,
z, t, el_id);
637 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6> res;
639 int dim = rot.rows();
641 static const double sqrt2 = std::sqrt(2.0);
656 res << rot(0, 0) * rot(0, 0), rot(0, 1) * rot(0, 1), rot(0, 2) * rot(0, 2), sqrt2 * rot(0, 1) * rot(0, 2), sqrt2 * rot(0, 0) * rot(0, 2), sqrt2 * rot(0, 0) * rot(0, 1),
657 rot(1, 0) * rot(1, 0), rot(1, 1) * rot(1, 1), rot(1, 2) * rot(1, 2), sqrt2 * rot(1, 1) * rot(1, 2), sqrt2 * rot(1, 0) * rot(1, 2), sqrt2 * rot(1, 0) * rot(1, 1),
658 rot(2, 0) * rot(2, 0), rot(2, 1) * rot(2, 1), rot(2, 2) * rot(2, 2), sqrt2 * rot(2, 1) * rot(2, 2), sqrt2 * rot(2, 0) * rot(2, 2), sqrt2 * rot(2, 0) * rot(2, 1),
659 sqrt2 * rot(1, 0) * rot(2, 0), sqrt2 * rot(1, 1) * rot(2, 1), sqrt2 * rot(1, 2) * rot(2, 2), rot(1, 1) * rot(2, 2) + rot(1, 2) * rot(2, 1), rot(1, 0) * rot(2, 2) + rot(1, 2) * rot(2, 0), rot(1, 0) * rot(2, 1) + rot(1, 1) * rot(2, 0),
660 sqrt2 * rot(0, 0) * rot(2, 0), sqrt2 * rot(0, 1) * rot(2, 1), sqrt2 * rot(0, 2) * rot(2, 2), rot(0, 1) * rot(2, 2) + rot(0, 2) * rot(2, 1), rot(0, 0) * rot(2, 2) + rot(0, 2) * rot(2, 0), rot(0, 0) * rot(2, 1) + rot(0, 1) * rot(2, 0),
661 sqrt2 * rot(0, 0) * rot(1, 0), sqrt2 * rot(0, 1) * rot(1, 1), sqrt2 * rot(0, 2) * rot(1, 2), rot(0, 1) * rot(1, 2) + rot(0, 2) * rot(1, 1), rot(0, 0) * rot(1, 2) + rot(0, 2) * rot(1, 0), rot(0, 0) * rot(1, 1) + rot(0, 1) * rot(1, 0);
675 if (dir.is_object() && dir.value(
"type", std::string()) ==
"per_element_file")
677 const std::string field = dir.value(
"field", std::string(
"FIB_DIR1"));
678 const std::string path = dir.at(
"path").get<std::string>();
679 const std::string description = resources.
describe(path);
680 auto input = resources.
open(path,
false);
682 per_el_fibers_ = read_cell_vectors_legacy_vtk(*input, description, field);
685 const double n = v.norm();
692 logger().info(
"FiberDirection: loaded {} per-element fibers ('{}') from {}",
697 for (
int i =
dir_.size(); i <= index; ++i)
702 if (dir.size() == 3 || dir.size() == 2)
704 const int size = dir.size();
705 const int other_size = dir[0].is_array() ? size : 1;
707 assert(size ==
size_);
708 dir_[index].resize(size, other_size);
709 for (
int i = 0; i < size; ++i)
713 if (dir[i].is_array())
715 log_and_throw_error(fmt::format(
"Fiber must be a {} vector, row {} is {}", size, i, dir[i].dump()));
717 dir_[index](i, 0).init(dir[i], resources);
718 dir_[index](i, 0).set_unit_type(unit);
721 if (dir[i].size() != size)
723 log_and_throw_error(fmt::format(
"Fiber must be {}x{}, row {} is {}", size, other_size, i, dir[i].dump()));
725 for (
int j = 0; j < size; ++j)
727 dir_[index](i, j).init(dir[i][j], resources);
728 dir_[index](i, j).set_unit_type(unit);
733 else if (dir.size() == 9 || dir.size() == 4)
735 const int size = dir.size() == 9 ? 3 : 2;
736 assert(size ==
size_);
737 dir_[index].resize(size, size);
738 for (
int i = 0; i < size; ++i)
740 for (
int j = 0; j < size; ++j)
742 dir_[index](i, j).init(dir[i * size + j], resources);
743 dir_[index](i, j).set_unit_type(unit);
748 else if (dir.empty())
751 for (
int i = 0; i <
size_; ++i)
753 for (
int j = 0; j <
size_; ++j)
755 dir_[index](i, j).init(i == j ? 1.0 : 0.0);
756 dir_[index](i, j).set_unit_type(unit);
768 template double ElasticityTensor::compute_stress<3>(
const std::array<double, 3> &strain,
const int j)
const;
769 template double ElasticityTensor::compute_stress<6>(
const std::array<double, 6> &strain,
const int j)
const;
std::vector< Eigen::Triplet< double > > entries
std::vector< utils::ExpressionValue > rho_
virtual void add_multimaterial(const int index, const json ¶ms, const std::string &density_unit, const io::ResourceIO &resources)
virtual double operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
double operator()(int i, int j) const
void set_from_young_poisson(const double young, const double poisson, const std::string &stress_unit, const io::ResourceIO &resources)
void set_from_entries(const std::vector< double > &entries, const std::string &stress_unit, const io::ResourceIO &resources)
void rotate_stiffness(const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > &rotation_mtx_voigt)
void resize(const int size)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > stiffness_tensor_
void set_transversely_isotropic(double Et, double Ea, double nu_t, double nu_a, double Ga, const std::string &stress_units, const io::ResourceIO &resources)
void set_orthotropic(double Ex, double Ey, double Ez, double nuXY, double nuXZ, double nuYZ, double muYZ, double muZX, double muXY, const std::string &stress_unit, const io::ResourceIO &resources)
void set_from_lambda_mu(const double lambda, const double mu, const std::string &stress_unit, const io::ResourceIO &resources)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > reference_stiffness_tensor_
double compute_stress(const std::array< double, DIM > &strain, const int j) const
void unrotate_stiffness()
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6 > stiffness_rotation_voigt(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
std::vector< Eigen::Matrix< utils::ExpressionValue, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3 > > dir_
bool use_per_element_file_
void resize(const int size)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3 > operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
std::vector< Eigen::Vector3d > per_el_fibers_
void add_multimaterial(const int index, const json ¶ms, const std::string &unit, const io::ResourceIO &resources)
double operator()(const RowVectorNd &p, double t, int index) const
GenericMatParam(const std::string ¶m_name)
void add_multimaterial(const int index, const json ¶ms, const std::string &unit_type, const io::ResourceIO &resources)
std::vector< utils::ExpressionValue > param_
const std::string param_name_
std::vector< GenericMatParam > params_
void add_multimaterial(const int index, const json ¶ms, const std::string &unit_type, const io::ResourceIO &resources)
GenericMatParams(const std::string ¶m_name)
const std::string param_name_
std::vector< utils::ExpressionValue > mu_or_nu_
void lambda_mu(double px, double py, double pz, double x, double y, double z, double t, int el_id, double &lambda, double &mu) const
void add_multimaterial(const int index, const json ¶ms, const bool is_volume, const std::string &stress_unit, const io::ResourceIO &resources)
std::vector< utils::ExpressionValue > lambda_or_E_
void set_e_nu(const int index, const json &E, const json &nu, const std::string &stress_unit, const io::ResourceIO &resources)
Eigen::MatrixXd lambda_mat_
double rho(const RowVectorNd &p, double t, int el_id) const
double heat_capacity(const RowVectorNd &p, double t, int el_id) const
GenericMatParam heat_capacity_
double operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const override
void add_multimaterial(const int index, const json ¶ms, const std::string &density_unit, const io::ResourceIO &resources) override
Read-only interface to a hierarchical collection of simulation resources.
virtual std::string describe(const std::string &path) const =0
virtual std::unique_ptr< std::istream > open(const std::string &path, bool binary) const =0
constexpr const char * MATERIAL_ELEMENT_INDEX
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
spdlog::logger & logger()
Retrieves the current logger.
double convert_to_mu(const double E, const double nu)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
double convert_to_lambda(const bool is_volume, const double E, const double nu)
void log_and_throw_error(const std::string &msg)