21 const double c10 = 1.7;
22 const double bulk = 8.5;
23 const double theta = .03;
32 std::exp(.04), 0., 0., std::exp(-.015), 0., std::exp(.005)};
34 std::exp(-.04), 0., 0., std::exp(.015), 0., std::exp(-.005)};
37 deformation(
i,
j) = t_rotation(
i,
k) * t_u(
k,
j);
38 t_inverse_transpose(
i,
j) = t_rotation(
i,
k) * t_inverse_u(
k,
j);
39 const double jacobian = std::exp(theta);
40 const double invariant = deformation(
i,
j) * deformation(
i,
j);
42 (2. * c10 * std::exp(-2. * theta / 3.)) *
43 (deformation(
i,
j) - (invariant / 3.) * t_inverse_transpose(
i,
j)) +
44 (bulk * jacobian * (jacobian - 1.)) * t_inverse_transpose(
i,
j);
45 deviator = Tensor2SymmetricDeviatorBasis::getCoordinates(t_h);
47 std::exp(.06), 0., 0., std::exp(-.05), 0., std::exp(-.01)};
48 stress = Tensor2SymmetricDeviatorBasis::getCoordinates(t_exp_2d);
50 stress(A) *= 2. * c10;
55 enum Error {
F,
P,
D, THETA, TD, OMEGA,
W, FLUX, FACE_FLUX, COUNT };
56 std::array<double, COUNT> error{};
57 std::array<double, 3> reaction{};
58 PetscInt volumePoints = 0;
60 double boundaryArea = 0.;
64struct OpCheckVolume : VolumeElement::UserDataOperator {
65 OpCheckVolume(boost::shared_ptr<DataAtIntegrationPts> data,
66 boost::shared_ptr<Audit> audit,
67 boost::shared_ptr<Reference> reference)
69 auditPtr(audit), referencePtr(reference) {}
76 const int points = getGaussPts().size2();
79 "Patch requires multiple volume quadrature points");
80 auto t_f = dataPtr->getFTensorSmallH(points);
81 auto t_p = dataPtr->getFTensorApproxP(points);
82 auto t_omega = dataPtr->getFTensorRotAxis(points);
83 auto t_w = dataPtr->getFTensorSmallWL2(points);
84 auto t_x = getFTensor1CoordsAtGaussPts();
86 *dataPtr->auxiliaryData->logDeviator, points)();
88 *dataPtr->auxiliaryData->logJacobian, points)();
90 *dataPtr->auxiliaryData->stress, points)();
91 const auto &reference = *referencePtr;
95 const auto update = [&](Audit::Error index,
double error) {
96 auditPtr->error[index] = std::max(
97 auditPtr->error[index], std::isfinite(error)
99 :
std::numeric_limits<
double>::infinity());
101 for (
int gg = 0; gg != points; ++gg) {
102 t_matrix_error(
i,
j) = t_f(
i,
j) - reference.deformation(
i,
j);
103 update(Audit::F, std::sqrt(t_matrix_error(
i,
j) * t_matrix_error(
i,
j)));
104 t_matrix_error(
i,
j) = t_p(
i,
j) - reference.piola(
i,
j);
105 update(Audit::P, std::sqrt(t_matrix_error(
i,
j) * t_matrix_error(
i,
j)));
106 t_material_error(A) = t_d(A) - reference.deviator(A);
107 update(Audit::D, std::sqrt(t_material_error(A) * t_material_error(A)));
108 update(Audit::THETA, std::abs(t_theta(0) - reference.theta));
109 t_material_error(A) = t_stress(A) - reference.stress(A);
110 update(Audit::TD, std::sqrt(t_material_error(A) * t_material_error(A)));
111 t_vector_error(
i) = t_omega(
i) - reference.omega(
i);
112 update(Audit::OMEGA, t_vector_error.
l2());
113 t_vector_error(
i) = t_w(
i) -
114 (reference.deformation(
i,
j) - t_identity(
i,
j)) * t_x(
j);
115 update(Audit::W, t_vector_error.
l2());
125 auditPtr->volumePoints += points;
129 boost::shared_ptr<DataAtIntegrationPts> dataPtr;
130 boost::shared_ptr<Audit> auditPtr;
131 boost::shared_ptr<Reference> referencePtr;
135 OpPatchTraction(boost::shared_ptr<DataAtIntegrationPts> data,
136 boost::shared_ptr<Audit> audit,
137 boost::shared_ptr<Reference> reference)
139 referencePtr(reference) {}
144 if (getLoopSize() != 1)
146 "Patch flux check requires an exterior face");
148 const int points = getGaussPts().size2();
149 auto t_normal = getFTensor1NormalsAtGaussPts();
151 auditPtr->exactTraction, points)();
152 for (
int gg = 0; gg != points; ++gg) {
153 t_exact(
i) = referencePtr->piola(
i,
j) *
154 (getSkeletonSense() * t_normal(
j) / t_normal.l2());
161 boost::shared_ptr<Audit> auditPtr;
162 boost::shared_ptr<Reference> referencePtr;
165struct OpCheckFace : FaceElement::UserDataOperator {
166 OpCheckFace(boost::shared_ptr<DataAtIntegrationPts> data,
167 boost::shared_ptr<Audit> audit)
174 const int points = getGaussPts().size2();
175 auto t_weight = getFTensor0IntegrationWeight();
176 auto t_traction = dataPtr->getFTensorTraction(points);
178 auditPtr->exactTraction, points)();
182 for (
int gg = 0; gg != points; ++gg) {
183 const double weight = t_weight * getMeasure();
184 t_error(
i) = t_traction(
i) - t_exact(
i);
185 if (!std::isfinite(t_error.l2()))
187 "Nonfinite patch traction error");
188 auditPtr->error[Audit::FLUX] =
189 std::max(auditPtr->error[Audit::FLUX], t_error.l2());
190 t_face_error(
i) += weight * t_error(
i);
191 t_reaction(
i) += weight * t_traction(
i);
199 "Nonpositive patch face area");
200 auditPtr->error[Audit::FACE_FLUX] = std::max(
201 auditPtr->error[Audit::FACE_FLUX], t_face_error.l2() / area);
202 auditPtr->reaction[0] += t_reaction(0);
203 auditPtr->reaction[1] += t_reaction(1);
204 auditPtr->reaction[2] += t_reaction(2);
205 auditPtr->boundaryArea += area;
210 boost::shared_ptr<DataAtIntegrationPts> dataPtr;
211 boost::shared_ptr<Audit> auditPtr;
217 CHKERR MPI_Comm_size(PETSC_COMM_WORLD, &ranks);
220 "Prepare the patch mesh on one rank before partitioning");
221 char source[PETSC_MAX_PATH_LEN] =
"";
222 char output[PETSC_MAX_PATH_LEN] =
"";
226 sizeof(output),
nullptr);
227 if (!
source[0] || !output[0] || std::string(
source) == output)
229 "Patch mesh preparation requires distinct source and output files");
231 new ParallelComm(&moab, PETSC_COMM_WORLD);
237 std::vector<std::pair<CubitBCType, int>> old_sets;
238 for (
auto it = meshsets->getBegin(); it != meshsets->getEnd(); ++it)
239 old_sets.emplace_back(
CubitBCType(it->getMaskedBcTypeULong()),
241 for (
const auto &entry : old_sets)
242 CHKERR meshsets->deleteMeshset(entry.first, entry.second);
244 CHKERR moab.get_entities_by_type(0, MBTET, tets);
247 "Patch fixture requires tetrahedra");
248 Skinner skinner(&moab);
249 CHKERR skinner.find_skin(0, tets,
false, skin);
250 const std::string name =
"ANALYTICAL_DISPLACEMENT_1001";
253 CHKERR meshsets->setAttributes(
BLOCKSET, 1001, {1., 1., 1.}, name);
254 CHKERR moab.write_file(output);
255 CHKERR PetscPrintf(PETSC_COMM_WORLD,
256 "Prepared affine patch: %d tetrahedra, %d skin faces\n",
257 static_cast<int>(tets.size()),
static_cast<int>(skin.size()));
263 auto reference = boost::make_shared<Reference>();
268 auto ts =
createTS(PETSC_COMM_WORLD);
269 CHKERR TSSetType(ts, TSBEULER);
272 CHKERR TSGetAdapt(ts, &adapt);
273 CHKERR TSAdaptSetType(adapt, TSADAPTNONE);
275 TSConvergedReason reason;
277 CHKERR TSGetConvergedReason(ts, &reason);
278 CHKERR TSGetTime(ts, &time);
279 if (reason <= 0 || std::abs(time - 1.) > 1.e-12)
281 "Patch solve did not reach t=1: reason %d, time %g", reason, time);
285 auto audit = boost::make_shared<Audit>();
286 auto volume = boost::make_shared<VolumeElement>(ep.
mField);
288 volume->getOpPtrVector().push_back(
289 new OpCheckVolume(ep.
dataAtPts, audit, reference));
292 auto face = boost::make_shared<FaceElement>(ep.
mField);
294 CHKERR EshelbianPlasticity::AddHOOps<2, 3, 3>::add(
298 face->getOpPtrVector().push_back(side);
299 auto side_fe = side->getSideFEPtr();
300 side_fe->getUserPolynomialBase() =
301 boost::make_shared<CGGUserPolynomialBase>();
302 CHKERR EshelbianPlasticity::AddHOOps<3, 3, 3>::add(
307 boost::make_shared<double>(1.)));
310 side_fe->getOpPtrVector().push_back(
311 new OpPatchTraction(ep.
dataAtPts, audit, reference));
312 face->getOpPtrVector().push_back(
new OpCheckFace(ep.
dataAtPts, audit));
315 std::array<double, Audit::COUNT> error;
316 std::array<double, 3> reaction;
317 PetscInt points, faces;
319 CHKERR MPI_Allreduce(audit->error.data(), error.data(), Audit::COUNT,
321 CHKERR MPI_Allreduce(audit->reaction.data(), reaction.data(), 3, MPI_DOUBLE,
323 CHKERR MPI_Allreduce(&audit->volumePoints, &points, 1, MPIU_INT, MPI_SUM,
325 CHKERR MPI_Allreduce(&audit->faces, &faces, 1, MPIU_INT, MPI_SUM,
327 CHKERR MPI_Allreduce(&audit->boundaryArea, &area, 1, MPI_DOUBLE, MPI_SUM,
329 double tolerance = 1.e-7;
332 if (!(tolerance > 0.) || points == 0 || faces == 0 || !(area > 0.))
334 "Invalid patch tolerance or incomplete quadrature coverage");
335 const std::array<const char *, Audit::COUNT> names{
336 "F",
"P",
"D",
"theta",
"Td",
"omega",
"w",
"normal flux",
337 "integrated face flux/area"};
338 for (
int index = 0; index != Audit::COUNT; ++index) {
340 names[index], error[index]);
341 if (!std::isfinite(error[index]) || error[index] > tolerance)
343 "Patch %s error %g exceeds %g", names[index], error[index],
347 reaction[0], reaction[1], reaction[2]};
348 if (!std::isfinite(t_reaction.l2()) || t_reaction.l2() / area > tolerance)
350 "Patch total flux/area %g exceeds %g", t_reaction.l2() / area,
353 "Auxiliary homogeneous patch passed: %d volume points, "
354 "%d faces, total flux/area %.3e\n",
355 static_cast<int>(points),
static_cast<int>(faces),
356 t_reaction.l2() / area);
362static char help[] =
"Prepare and solve an affine auxiliary logarithmic patch.\n";
364int main(
int argc,
char *argv[]) {
366#ifdef ENABLE_PYTHON_BINDING
370 auto core_log = logging::core::get();
382 moab::Core options_moab;
386 PetscBool prepare = PETSC_FALSE;
Shared mesh and problem setup for auxiliary formulation atoms.
Evaluation of independent logarithmic material fields.
Lie algebra implementation.
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
#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.
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.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)