21 const double c10 = 1.7;
22 const double bulk = 8.5;
23 const double theta = .03;
30 double total_angle =
omega.l2();
32 "-test_patch_total_rotation",
33 &total_angle,
nullptr),
34 "get patch rotation");
38 std::exp(.04), 0., 0., std::exp(-.015), 0., std::exp(.005)};
40 std::exp(-.04), 0., 0., std::exp(.015), 0., std::exp(-.005)};
43 deformation(
i,
j) = t_rotation(
i,
k) * t_u(
k,
j);
44 t_inverse_transpose(
i,
j) = t_rotation(
i,
k) * t_inverse_u(
k,
j);
45 const double jacobian = std::exp(theta);
46 const double invariant = deformation(
i,
j) * deformation(
i,
j);
48 (2. * c10 * std::exp(-2. * theta / 3.)) *
49 (deformation(
i,
j) - (invariant / 3.) * t_inverse_transpose(
i,
j)) +
53 std::exp(.06), 0., 0., std::exp(-.05), 0., std::exp(-.01)};
56 stress(A) *= 2. * c10;
61 enum Error {
F,
P,
D, THETA, TD, OMEGA,
W, FLUX, FACE_FLUX, COUNT };
62 std::array<double, COUNT> error{};
63 std::array<double, 3> reaction{};
64 PetscInt volumePoints = 0;
66 double boundaryArea = 0.;
70struct OpCheckVolume : VolumeElement::UserDataOperator {
71 OpCheckVolume(boost::shared_ptr<DataAtIntegrationPts>
data,
72 boost::shared_ptr<Audit> audit,
73 boost::shared_ptr<Reference> reference)
75 auditPtr(audit), referencePtr(reference) {}
82 const int points = getGaussPts().size2();
85 "Patch requires multiple volume quadrature points");
86 auto t_f =
dataPtr->getFTensorSmallH(points);
87 auto t_p =
dataPtr->getFTensorApproxP(points);
88 auto rotation =
dataPtr->getFTensorRotMat(points);
89 auto t_w =
dataPtr->getFTensorSmallWL2(points);
90 auto t_x = getFTensor1CoordsAtGaussPts();
92 *
dataPtr->auxiliaryData->logDeviator, points)();
94 *
dataPtr->auxiliaryData->logJacobian, points)();
97 *
dataPtr->auxiliaryData->stress, points)();
98 const auto &reference = *referencePtr;
102 const auto update = [&](Audit::Error index,
double error) {
103 auditPtr->error[index] = std::max(
104 auditPtr->error[index],
105 std::isfinite(error) ? error
106 :
std::numeric_limits<
double>::infinity());
108 for (
int gg = 0; gg != points; ++gg) {
109 t_matrix_error(
i,
j) = t_f(
i,
j) - reference.deformation(
i,
j);
110 update(Audit::F, std::sqrt(t_matrix_error(
i,
j) * t_matrix_error(
i,
j)));
111 t_matrix_error(
i,
j) = t_p(
i,
j) - reference.piola(
i,
j);
112 update(Audit::P, std::sqrt(t_matrix_error(
i,
j) * t_matrix_error(
i,
j)));
113 t_material_error(A) = t_d(A) - reference.deviator(A);
114 update(Audit::D, std::sqrt(t_material_error(A) * t_material_error(A)));
115 update(Audit::THETA, std::abs(t_theta(0) - reference.theta));
116 t_material_error(A) = t_stress(A) - reference.stress(A);
117 update(Audit::TD, std::sqrt(t_material_error(A) * t_material_error(A)));
119 const auto expected_rotation =
121 t_matrix_error(
i,
j) = rotation(
i,
j) - expected_rotation(
i,
j);
123 std::sqrt(t_matrix_error(
i,
j) * t_matrix_error(
i,
j)));
125 t_w(
i) - (reference.deformation(
i,
j) - t_identity(
i,
j)) * t_x(
j);
126 update(Audit::W, t_vector_error.
l2());
136 auditPtr->volumePoints += points;
140 boost::shared_ptr<DataAtIntegrationPts>
dataPtr;
141 boost::shared_ptr<Audit> auditPtr;
142 boost::shared_ptr<Reference> referencePtr;
146 OpPatchTraction(boost::shared_ptr<DataAtIntegrationPts>
data,
147 boost::shared_ptr<Audit> audit,
148 boost::shared_ptr<Reference> reference)
150 referencePtr(reference) {}
155 if (getLoopSize() != 1)
157 "Patch flux check requires an exterior face");
159 const int points = getGaussPts().size2();
160 auto t_normal = getFTensor1NormalsAtGaussPts();
163 auditPtr->exactTraction, points)();
164 for (
int gg = 0; gg != points; ++gg) {
165 t_exact(
i) = referencePtr->piola(
i,
j) *
166 (getSkeletonSense() * t_normal(
j) / t_normal.l2());
173 boost::shared_ptr<Audit> auditPtr;
174 boost::shared_ptr<Reference> referencePtr;
177struct OpCheckFace : FaceElement::UserDataOperator {
178 OpCheckFace(boost::shared_ptr<DataAtIntegrationPts>
data,
179 boost::shared_ptr<Audit> audit)
186 const int points = getGaussPts().size2();
187 auto t_weight = getFTensor0IntegrationWeight();
188 auto t_traction =
dataPtr->getFTensorTraction(points);
190 auditPtr->exactTraction, points)();
194 for (
int gg = 0; gg != points; ++gg) {
195 const double weight = t_weight * getMeasure();
196 t_error(
i) = t_traction(
i) - t_exact(
i);
197 if (!std::isfinite(t_error.l2()))
199 "Nonfinite patch traction error");
200 auditPtr->error[Audit::FLUX] =
201 std::max(auditPtr->error[Audit::FLUX], t_error.l2());
202 t_face_error(
i) += weight * t_error(
i);
203 t_reaction(
i) += weight * t_traction(
i);
211 "Nonpositive patch face area");
212 auditPtr->error[Audit::FACE_FLUX] =
213 std::max(auditPtr->error[Audit::FACE_FLUX], t_face_error.l2() / area);
214 auditPtr->reaction[0] += t_reaction(0);
215 auditPtr->reaction[1] += t_reaction(1);
216 auditPtr->reaction[2] += t_reaction(2);
217 auditPtr->boundaryArea += area;
222 boost::shared_ptr<DataAtIntegrationPts>
dataPtr;
223 boost::shared_ptr<Audit> auditPtr;
229 CHKERR MPI_Comm_size(PETSC_COMM_WORLD, &ranks);
232 "Prepare the patch mesh on one rank before partitioning");
233 char source[PETSC_MAX_PATH_LEN] =
"";
234 char output[PETSC_MAX_PATH_LEN] =
"";
238 sizeof(output),
nullptr);
239 if (!
source[0] || !output[0] || std::string(
source) == output)
241 "Patch mesh preparation requires distinct source and output files");
243 new ParallelComm(&moab, PETSC_COMM_WORLD);
249 std::vector<std::pair<CubitBCType, int>> old_sets;
250 for (
auto it = meshsets->getBegin(); it != meshsets->getEnd(); ++it)
251 old_sets.emplace_back(
CubitBCType(it->getMaskedBcTypeULong()),
253 for (
const auto &entry : old_sets)
254 CHKERR meshsets->deleteMeshset(entry.first, entry.second);
256 CHKERR moab.get_entities_by_type(0, MBTET, tets);
259 "Patch fixture requires tetrahedra");
260 Skinner skinner(&moab);
261 CHKERR skinner.find_skin(0, tets,
false, skin);
262 const std::string
name =
"ANALYTICAL_DISPLACEMENT_1001";
266 CHKERR moab.write_file(output);
268 PETSC_COMM_WORLD,
"Prepared affine patch: %d tetrahedra, %d skin faces\n",
269 static_cast<int>(tets.size()),
static_cast<int>(skin.size()));
275 auto reference = boost::make_shared<Reference>();
280 auto ts =
createTS(PETSC_COMM_WORLD);
281 CHKERR TSSetType(ts, TSBEULER);
284 CHKERR TSGetAdapt(ts, &adapt);
285 CHKERR TSAdaptSetType(adapt, TSADAPTNONE);
287 TSConvergedReason reason;
289 CHKERR TSGetConvergedReason(ts, &reason);
290 CHKERR TSGetTime(ts, &time);
291 if (reason <= 0 || std::abs(time - 1.) > 1.e-12)
293 "Patch solve did not reach t=1: reason %d, time %g", reason, time);
297 auto audit = boost::make_shared<Audit>();
298 auto volume = boost::make_shared<VolumeElement>(
ep.
mField);
300 volume->getOpPtrVector().push_back(
301 new OpCheckVolume(
ep.
dataAtPts, audit, reference));
304 auto face = boost::make_shared<FaceElement>(
ep.
mField);
306 CHKERR EshelbianPlasticity::AddHOOps<2, 3, 3>::add(
310 face->getOpPtrVector().push_back(side);
311 auto side_fe = side->getSideFEPtr();
312 side_fe->getUserPolynomialBase() =
313 boost::make_shared<CGGUserPolynomialBase>();
314 CHKERR EshelbianPlasticity::AddHOOps<3, 3, 3>::add(
319 boost::make_shared<double>(1.)));
322 side_fe->getOpPtrVector().push_back(
323 new OpPatchTraction(
ep.
dataAtPts, audit, reference));
324 face->getOpPtrVector().push_back(
new OpCheckFace(
ep.
dataAtPts, audit));
327 std::array<double, Audit::COUNT> error;
328 std::array<double, 3> reaction;
329 PetscInt points, faces;
331 CHKERR MPI_Allreduce(audit->error.data(), error.data(), Audit::COUNT,
333 CHKERR MPI_Allreduce(audit->reaction.data(), reaction.data(), 3, MPI_DOUBLE,
335 CHKERR MPI_Allreduce(&audit->volumePoints, &points, 1, MPIU_INT, MPI_SUM,
337 CHKERR MPI_Allreduce(&audit->faces, &faces, 1, MPIU_INT, MPI_SUM,
339 CHKERR MPI_Allreduce(&audit->boundaryArea, &area, 1, MPI_DOUBLE, MPI_SUM,
341 double tolerance = 1.e-7;
344 if (!(tolerance > 0.) || points == 0 || faces == 0 || !(area > 0.))
346 "Invalid patch tolerance or incomplete quadrature coverage");
347 const std::array<const char *, Audit::COUNT> names{
350 "w",
"normal flux",
"integrated face flux/area"};
351 for (
int index = 0; index != Audit::COUNT; ++index) {
353 names[index], error[index]);
354 if (!std::isfinite(error[index]) || error[index] > tolerance)
356 "Patch %s error %g exceeds %g", names[index], error[index],
361 if (!std::isfinite(t_reaction.l2()) || t_reaction.l2() / area > tolerance)
363 "Patch total flux/area %g exceeds %g", t_reaction.l2() / area,
366 "Auxiliary homogeneous patch passed: %d volume points, "
367 "%d faces, total flux/area %.3e\n",
368 static_cast<int>(points),
static_cast<int>(faces),
369 t_reaction.l2() / area);
376 "Prepare and solve an affine auxiliary logarithmic patch.\n";
378int main(
int argc,
char *argv[]) {
380#ifdef ENABLE_PYTHON_BINDING
384 auto core_log = logging::core::get();
398 moab::Core options_moab;
402 PetscBool prepare = PETSC_FALSE;
Shared mesh and problem setup for auxiliary formulation atoms.
Evaluation of independent logarithmic material fields.
Lie algebra implementation.
boost::shared_ptr< DataAtIntegrationPts > data
boost::shared_ptr< PlasticLocalLawGaussData > dataPtr
SmartPetscObj< Mat > jacobian
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
#define CATCH_ERRORS
Catch errors.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#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.
constexpr double omega
Save field DOFS on vertices/tags.
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
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
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
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
MoFEMErrorCode runAuxiliaryLogarithmicStressTest(const std::function< MoFEMErrorCode(EshelbianCore &)> &test)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< 32 > CubitBCType
implementation of Data Operators for Forces and Sources
PetscErrorCode PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
auto createTS(MPI_Comm comm)
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
PetscErrorCode TSAdaptCreateMoFEM(TSAdapt adapt)
Craete MOFEM adapt.
auto deviator(FTensor::Tensor2_symmetric< T, DIM > &t_stress, double trace, FTensor::Tensor2_symmetric< double, DIM > &t_alpha, FTensor::Number< DIM >)
const double D
diffusivity
MoFEMErrorCode setElasticElementOps(const int tag)
boost::shared_ptr< Range > frontAdjEdges
MoFEM::Interface & mField
const std::string materialH1Positions
const std::string elementVolumeName
MoFEMErrorCode solveElastic(TS ts, Vec x)
const std::string piolaStress
MoFEMErrorCode setElasticElementToTs(DM dm)
const std::string bubbleField
const std::string skinElement
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, const bool add_bubble=true)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
SmartPetscObj< DM > dmElastic
Elastic problem.
static auto exp(A &&t_w_vee, B &&theta)
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.
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
static MoFEMErrorCode setMeshFileFromJson()
Set -file_name from JSON before Core is available.
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.
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode setMeshsetFromFile(const string file_name, const bool clean_file_options=true)
add blocksets reading config file
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Element used to execute operators on side of the element.
static FTensor::Tensor1< double, 5 > getCoordinates(const Tensor &t_tensor)
Project a full or symmetric tensor onto the five orthonormal columns.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)