21MoFEMErrorCode checkNear(
const double actual,
const double expected,
22 const char *name,
const double tolerance = 2.e-6) {
24 if (!std::isfinite(actual) ||
25 std::abs(actual - expected) >
26 tolerance * std::max(1., std::abs(expected)))
28 "%s: expected %.16e, obtained %.16e", name, expected, actual);
33 const double theta,
const Coordinates &t_stress) {
36 const Problem *problem =
nullptr;
40 const std::array<double, 3> rotation{.14, -.11, .07};
41 for (
const auto &dof : *problem->getNumeredRowDofsPtr()) {
42 const auto index = dof->getPetscGlobalDofIdx();
43 if (index < first || index >= last || dof->getDofOrder() != 0)
45 const auto &name = dof->getName();
46 const auto component = dof->getDofCoeffIdx();
49 value = t_d(component);
53 value = t_stress(component);
55 value = rotation.at(component);
56 CHKERR VecSetValue(
state, index, value, INSERT_VALUES);
60 CHKERR VecGhostUpdateBegin(
state, INSERT_VALUES, SCATTER_FORWARD);
61 CHKERR VecGhostUpdateEnd(
state, INSERT_VALUES, SCATTER_FORWARD);
65MoFEMErrorCode readTag(moab::Interface &mesh,
const EntityHandle vertex,
66 const std::string &name,
const int size,
70 CHKERR mesh.tag_get_handle(name.c_str(), tag);
72 CHKERR mesh.tag_get_length(tag, length);
75 "Output tag %s has length %d instead of %d", name.c_str(), length,
77 CHKERR mesh.tag_get_data(tag, &vertex, 1, values);
81MoFEMErrorCode checkTensor(moab::Interface &mesh,
const EntityHandle vertex,
82 const std::string &name,
85 std::array<double, 9> values;
86 CHKERR readTag(mesh, vertex, name, values.size(), values.data());
87 auto t_actual = getFTensor2FromPtr<3, 3>(values.data());
90 t_error(
i,
j) = t_actual(
i,
j) - t_expected(
i,
j);
91 CHKERR checkNear(std::sqrt(t_error(
i,
j) * t_error(
i,
j)), 0., name.c_str());
96 const char *description) {
99 CHKERR VecWAXPY(difference, -1., before, after);
101 CHKERR VecNorm(difference, NORM_INFINITY, &norm);
102 CHKERR checkNear(norm, 0., description, 0.);
106MoFEMErrorCode checkOutput(
const std::string &file,
const Coordinates &t_d,
107 const double theta,
const Coordinates &t_stress,
108 const bool variation) {
113 double deviatoric_energy, gap;
120 Coordinates t_copy_error;
122 const double copy_error = std::sqrt(t_copy_error(
a) * t_copy_error(
a));
123 const double physical_energy = deviatoric_energy + volume.
energy;
124 const double mixed_energy =
126 if (gap <= .01 || copy_error <= .01)
128 "Output test requires distinct material and kinematic copies");
132 t_commutator(
i,
j) = t_d_tensor(
i,
k) * t_stress_tensor(
k,
j) -
133 t_stress_tensor(
i,
k) * t_d_tensor(
k,
j);
134 if (std::sqrt(t_commutator(
i,
j) * t_commutator(
i,
j)) <= .01)
136 "Output test requires noncoaxial D and Td");
140 t_eigenvectors(
i,
j) = t_log_stretch(
i,
j);
144 [](
double value) {
return std::exp(value); });
148 for (
const auto *name : {
"FenchelGap",
"PointwiseCopyMismatch"}) {
150 if (output.tag_get_handle(name, tag) != MB_TAG_NOT_FOUND)
152 "Unexpected material diagnostic output tag %s", name);
154 for (
const auto *prefix :
155 {
"D_",
"Td_",
"D_m_",
"VarD_",
"VarTd_",
"ResD_",
"ResTd_"})
156 for (
int c = 0;
c != 5; ++
c) {
157 const std::string name = prefix + std::to_string(
c);
159 if (output.tag_get_handle(name.c_str(), tag) != MB_TAG_NOT_FOUND)
161 "Unexpected scalar coordinate output tag %s", name.c_str());
164 CHKERR output.get_entities_by_type(0, MBVERTEX, vertices);
165 if (vertices.empty())
167 "Production output %s contains no vertices",
file.c_str());
168 for (
const auto vertex : vertices) {
169 CHKERR checkTensor(output, vertex,
"D", t_d_tensor);
170 CHKERR checkTensor(output, vertex,
"Td", t_stress_tensor);
171 CHKERR checkTensor(output, vertex,
"D_m",
173 CHKERR checkTensor(output, vertex,
"LogSpatialStretch", t_log_stretch);
174 CHKERR checkTensor(output, vertex,
"SpatialStretch", t_stretch);
175 const std::array<std::pair<const char *, double>, 6>
scalar_values{
178 {
"PhysicalEnergy", physical_energy},
179 {
"MixedStoredEnergy", mixed_energy},
180 {
"Vartheta", .25 * theta},
181 {
"Restheta", -.75 * theta}}};
182 double saved_physical = 0., saved_mixed = 0.;
184 if (std::string(name) ==
"Vartheta" && !variation)
187 CHKERR readTag(output, vertex, name, 1, &actual);
188 CHKERR checkNear(actual, expected, name);
189 if (std::string(name) ==
"PhysicalEnergy")
190 saved_physical = actual;
191 else if (std::string(name) ==
"MixedStoredEnergy")
192 saved_mixed = actual;
194 CHKERR checkNear(saved_physical - saved_mixed, gap,
195 "PhysicalEnergy - MixedStoredEnergy = FenchelGap", 6.e-6);
196 Coordinates t_residual;
197 t_residual(
a) = -.75 * t_d(
a);
199 t_residual(
a) = -.75 * t_stress(
a);
200 CHKERR checkTensor(output, vertex,
"ResTd",
203 Coordinates t_variation;
204 t_variation(
a) = .25 * t_d(
a);
205 CHKERR checkTensor(output, vertex,
"VarD",
207 CHKERR checkTensor(output, vertex,
"VarLogSpatialStretch",
209 t_variation(
a) = .25 * t_stress(
a);
210 CHKERR checkTensor(output, vertex,
"VarTd",
214 CHKERR PetscPrintf(PETSC_COMM_WORLD,
215 "Checked %d production output vertices in %s; "
216 "gap %.6e, pointwise copy mismatch %.6e\n",
217 static_cast<int>(vertices.size()),
file.c_str(), gap,
226 "The output inspection atom runs on one rank");
228 const Coordinates t_d(.12, -.08, .06, -.04, .09);
229 const Coordinates t_stress(-.8, .4, .5, .3, -.7);
230 const double theta = .13;
237 CHKERR VecScale(variation, .25);
238 CHKERR VecGhostUpdateBegin(variation, INSERT_VALUES, SCATTER_FORWARD);
239 CHKERR VecGhostUpdateEnd(variation, INSERT_VALUES, SCATTER_FORWARD);
242 CHKERR VecScale(residual, -.75);
243 CHKERR VecGhostUpdateBegin(residual, INSERT_VALUES, SCATTER_FORWARD);
244 CHKERR VecGhostUpdateEnd(residual, INSERT_VALUES, SCATTER_FORWARD);
247 CHKERR VecGhostUpdateBegin(ep.
solTSStep, INSERT_VALUES, SCATTER_FORWARD);
248 CHKERR VecGhostUpdateEnd(ep.
solTSStep, INSERT_VALUES, SCATTER_FORWARD);
258 boost::shared_ptr<VolumeElementForcesAndSourcesCore> rhs, lhs;
264 const std::string skin_file =
"auxiliary_output_skin.h5m";
268 CHKERR checkVectorUnchanged(mesh_before, mesh_after,
269 "Skin output changed mesh coefficients");
271 "Skin output changed previous coefficients");
272 CHKERR checkOutput(skin_file, t_d, theta, t_stress,
true);
274 const std::string skeleton_file =
"auxiliary_output_skeleton.h5m";
278 CHKERR checkVectorUnchanged(mesh_before, mesh_after,
279 "Skeleton output changed mesh coefficients");
281 "Skeleton output changed previous coefficients");
282 CHKERR checkOutput(skeleton_file, t_d, theta, t_stress,
false);
284 "Auxiliary logarithmic stress output atom passed\n");
290static char help[] =
"Check production auxiliary material diagnostic output.\n";
292int main(
int argc,
char *argv[]) {
294 auto core_log = logging::core::get();
Shared mesh and problem setup for auxiliary formulation atoms.
Neo-Hookean material law in orthonormal logarithmic coordinates.
#define FTENSOR_INDEXES(DIM,...)
#define CATCH_ERRORS
Catch errors.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMMoFEMGetProblemPtr(DM dm, const MoFEM::Problem **problem_ptr)
Get pointer to problem data structure.
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto getMat(A &&t_val, B &&t_vec, Fun< double > f)
Get the Mat object.
MoFEMErrorCode runAuxiliaryLogarithmicStressTest(const std::function< MoFEMErrorCode(EshelbianCore &)> &test)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
MoFEMErrorCode setElasticElementOps(const int tag)
MoFEM::Interface & mField
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
SmartPetscObj< DM > dM
Coupled problem all fields.
const std::string elementVolumeName
MoFEMErrorCode postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, Vec gradient=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
const std::string logDeviator
const std::string logJacobian
MoFEMErrorCode setVolumeElementOps(const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
const std::string auxiliaryLogStress
const std::string rotAxis
SmartPetscObj< Vec > solTSStep
SmartPetscObj< DM > dmElastic
Elastic problem.
Coordinates tMaterialDeviator
static MoFEMErrorCode evaluateInverse(const Parameters ¶meters, const Coordinates &t_stress, InverseState &state)
Recover Dm(Td), its compliance and conjugate energy; no state is cached.
static SymmetricTensor getTensor(const Coordinates &t_coordinates, double theta=0.)
Reconstruct H = D + theta*I/3 from the fixed five-coordinate basis.
static MoFEMErrorCode evaluateDeviator(const Parameters ¶meters, const Coordinates &t_deviator, double &energy, Coordinates *stress_ptr=nullptr, Tangent *hessian_ptr=nullptr)
Evaluate f(D), optionally its five-component gradient and Hessian.
FTensor::Tensor1< double, 5 > Coordinates
static MoFEMErrorCode evaluateFenchelGap(const Parameters ¶meters, const Coordinates &t_deviator, const Coordinates &t_stress, const InverseState &inverse, double &gap, double *energy_ptr=nullptr)
static MoFEMErrorCode evaluateVolume(const Parameters ¶meters, double theta, VolumeState &state)
Evaluate g(J) = K*(J-1)^2/2 and its logarithmic-volume derivatives.
virtual int get_comm_size() const =0
virtual MPI_Comm & get_comm() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
static boost::shared_ptr< std::ostream > getStrmSelf()
Get the strm self object.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
keeps basic data about problem
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.