16using MatrixPtr = boost::shared_ptr<MatrixDouble>;
19 const char *description) {
21 if (!std::isfinite(value) ||
22 std::abs(value - expected) > 1.e-11 * std::max(1., std::abs(expected)))
24 "%s: expected %.16e, obtained %.16e", description, expected, value);
28MoFEMErrorCode getCellScale(moab::Interface &moab,
const EntityHandle entity,
31 const EntityHandle *connectivity;
33 CHKERR moab.get_connectivity(entity, connectivity, count,
true);
34 std::vector<double> coordinates(3 * count);
35 CHKERR moab.get_coords(connectivity, count, coordinates.data());
37 for (
const double coordinate : coordinates)
38 scale += 0.001 * coordinate / count;
49 "Auxiliary mode must register D/theta/Td without the old u field");
54 "Unexpected auxiliary material-field group");
55 const auto *finite_element =
59 const PetscInt basis_count = (
order + 1) * (
order + 2) * (
order + 3) / 6;
65 PetscInt local_tets = 0, global_tets;
66 for (
const auto &element : *problem->getNumeredFiniteElementsPtr())
67 if (element->getName() == ep.elementVolumeName &&
68 element->getPart() == rank && element->getEntType() == MBTET)
70 CHKERR MPI_Allreduce(&local_tets, &global_tets, 1, MPIU_INT, MPI_SUM,
74 "Layout atom requires tetrahedra");
75 for (
const auto &name : names) {
76 const int components = name == ep.
logJacobian ? 1 : 5;
78 if (field->getNbOfCoeffs() != components || field->getSpace() !=
L2 ||
81 "Field %s must have %d USER_BASE L2 components", name.c_str(),
83 for (
const auto mask : {finite_element->getBitFieldIdRow(),
84 finite_element->getBitFieldIdCol(),
85 finite_element->getBitFieldIdData()})
86 if ((mask & field->getId()) != field->getId())
88 "Field %s missing from volume FE row, column or data",
90 for (
const auto entry :
99 CHKERR ISGetSize(field_is, &size);
100 if (size != global_tets * components * basis_count)
102 "Field %s in %s/%s has %d DOFs, expected %d", name.c_str(),
103 entry.first == ep.
dmElastic.get() ?
"dmElastic" :
"dmMaterial",
105 static_cast<
int>(size),
106 static_cast<
int>(global_tets * components * basis_count));
109 for (
const auto &dof : *problem->getNumeredRowDofsPtr()) {
110 if (std::find(names.begin(), names.end(), dof->getName()) == names.end())
112 if (dof->getEntType() != MBTET ||
113 dof->getFieldEntityPtr()->getMaxOrder() !=
order)
115 "Material DOF has unexpected entity or approximation order");
118 "Auxiliary layout: %d tetrahedra, order %d, "
119 "%d scalar basis functions per field\n",
120 static_cast<int>(global_tets),
order,
121 static_cast<int>(basis_count));
125double getCoefficient(
const EshelbianCore &ep,
const std::string &name,
126 const int component) {
128 return 0.02 * (component + 1);
131 return -0.07 * (component + 1);
135 const double state_scale) {
137 CHKERR VecZeroEntries(vector);
138 PetscInt first, last;
139 CHKERR VecGetOwnershipRange(vector, &first, &last);
143 for (
const auto &dof : *problem->getNumeredRowDofsPtr()) {
144 const auto index = dof->getPetscGlobalDofIdx();
145 if (index < first || index >= last || dof->getDofOrder() != 0 ||
146 std::find(names.begin(), names.end(), dof->getName()) == names.end())
152 state_scale * cell_scale *
153 getCoefficient(ep, dof->getName(), dof->getDofCoeffIdx()),
156 CHKERR VecAssemblyBegin(vector);
157 CHKERR VecAssemblyEnd(vector);
158 CHKERR VecGhostUpdateBegin(vector, INSERT_VALUES, SCATTER_FORWARD);
159 CHKERR VecGhostUpdateEnd(vector, INSERT_VALUES, SCATTER_FORWARD);
163struct OpCheckMaterialFields :
public VolumeElement::UserDataOperator {
165 boost::shared_ptr<AuxiliaryLogarithmicStressData> data,
166 MatrixPtr reconstructed,
const double state_scale,
167 boost::shared_ptr<PetscInt> visited,
168 const bool compatible_state)
170 dataPtr(
std::move(data)), reconstructedPtr(
std::move(reconstructed)),
171 stateScale(state_scale), visitedPtr(
std::move(visited)),
172 compatibleState(compatible_state) {}
179 const int points = getGaussPts().size2();
182 "Layout test requires multiple integration points");
184 *dataPtr->logDeviator, points)();
186 *dataPtr->logJacobian, points)();
189 *dataPtr->stress, points)();
192 *reconstructedPtr, points)();
193 double cell_scale = 1.;
194 if (!compatibleState)
195 CHKERR getCellScale(eP.mField.get_moab(), getFEEntityHandle(),
197 const double scale = stateScale * cell_scale;
198 Coordinates t_expected_d, t_expected_stress;
199 for (
int aa = 0; aa != 5; ++aa) {
200 t_expected_d(aa) =
scale * getCoefficient(eP, eP.logDeviator, aa);
201 t_expected_stress(aa) =
202 scale * getCoefficient(eP, eP.auxiliaryLogStress, aa);
204 if (compatibleState) {
207 {1.7, 8.5}, t_expected_d, energy, &t_expected_stress);
209 for (
int gg = 0; gg != points; ++gg) {
211 t_error(A) = t_d(A) - t_expected_d(A);
212 CHKERR checkNear(std::sqrt(t_error(A) * t_error(A)), 0.,
"evaluated D");
213 t_error(A) = t_stress(A) - t_expected_stress(A);
214 CHKERR checkNear(std::sqrt(t_error(A) * t_error(A)), 0.,
"evaluated Td");
215 CHKERR checkNear(t_theta(0), 0.18 *
scale,
"evaluated theta");
216 CHKERR checkNear(t_h(
i,
i), t_theta(0),
"reconstructed trace");
218 t_d(A) * t_d(A) + t_theta(0) * t_theta(0) / 3.,
219 "reconstructed Frobenius norm");
220 const auto t_recovered = Tensor2SymmetricDeviatorBasis::getCoordinates(t_h);
221 t_error(A) = t_recovered(A) - t_d(A);
222 CHKERR checkNear(std::sqrt(t_error(A) * t_error(A)), 0.,
223 "reconstructed deviator");
224 if (compatibleState) {
225 Coordinates t_material_stress;
226 t_material_stress(A) = t_stress(A);
229 {1.7, 8.5}, t_material_stress, inverse);
231 CHKERR checkNear(std::sqrt(t_error(A) * t_error(A)), 0.,
232 "constant initialized material copy");
244 boost::shared_ptr<AuxiliaryLogarithmicStressData> dataPtr;
247 boost::shared_ptr<PetscInt> visitedPtr;
248 bool compatibleState;
254 const double current_scale,
255 const double previous_scale,
256 const bool compatible_state =
false) {
258 if (compatible_state) {
261 CHKERR VecCopy(current, previous);
262 CHKERR VecGhostUpdateBegin(previous, INSERT_VALUES, SCATTER_FORWARD);
263 CHKERR VecGhostUpdateEnd(previous, INSERT_VALUES, SCATTER_FORWARD);
265 CHKERR setMaterialVector(ep, current, current_scale);
266 CHKERR setMaterialVector(ep, previous, previous_scale);
271 CHKERR VecZeroEntries(round_trip);
274 CHKERR VecAXPY(round_trip, -1., current);
276 CHKERR VecNorm(round_trip, NORM_INFINITY, &error);
277 CHKERR checkNear(error, 0.,
"current vector-mesh-vector transfer");
279 auto fe = boost::make_shared<VolumeElement>(ep.
mField);
280 fe->getUserPolynomialBase() =
281 boost::make_shared<CGGUserPolynomialBase>(
nullptr,
true);
282 fe->getRuleHook = [](
int,
int,
int) {
return 4; };
285 auto visited = boost::make_shared<PetscInt>(0);
286 for (
const bool previous_state : {
false,
true}) {
287 auto data = boost::make_shared<AuxiliaryLogarithmicStressData>();
288 auto reconstructed = boost::make_shared<MatrixDouble>();
290 ep, fe->getOpPtrVector(), data, reconstructed,
292 fe->getOpPtrVector().push_back(
new OpCheckMaterialFields(
293 ep, data, reconstructed,
294 previous_state ? previous_scale : current_scale, visited,
298 PetscInt global_visited;
299 CHKERR MPI_Allreduce(visited.get(), &global_visited, 1, MPIU_INT, MPI_SUM,
303 "No auxiliary field evaluations were executed");
309 const Coordinates &t_deviator,
310 const double theta) {
312 Coordinates t_stress;
315 {1.7, 8.5}, t_deviator, energy, &t_stress);
317 auto set_field = [&]<
int Dim>(
const std::string &field,
321 auto set_constant = [&](boost::shared_ptr<FieldEntity> entity_ptr) {
323 auto data = entity_ptr->getEntFieldData();
324 if (data.size() < Dim)
326 "Field %s has no constant mode", field.c_str());
328 auto t_dof = getFTensor1FromPtr<Dim>(&data[0]);
329 t_dof(
i) = t_values(
i);
332 CHKERR field_blas->fieldLambdaOnEntities(set_constant, field);
344 CHKERR checkFieldLayout(ep);
348 Coordinates t_initial;
350 CHKERR setConstantMaterialState(ep, t_initial, 0.);
351 CHKERR checkStateEvaluation(ep, current, previous, 0., 0.,
true);
352 for (
const auto &name : ep.physicalEquations->getMaterialFields(ep))
354 for (
int aa = 0; aa != 5; ++aa)
355 t_initial(aa) = getCoefficient(ep, ep.
logDeviator, aa);
356 CHKERR setConstantMaterialState(ep, t_initial, 0.18);
357 CHKERR checkStateEvaluation(ep, current, previous, 1., 1.,
true);
358 CHKERR checkStateEvaluation(ep, current, previous, 1., -0.5);
359 CHKERR checkStateEvaluation(ep, current, previous, -0.25, 1.5);
360 CHKERR PetscPrintf(PETSC_COMM_WORLD,
361 "Auxiliary logarithmic stress layout atom passed\n");
367static char help[] =
"Verify the auxiliary logarithmic stress field layout.\n";
369int main(
int argc,
char *argv[]) {
371 auto core_log = logging::core::get();
Shared mesh and problem setup for auxiliary formulation atoms.
Evaluation of independent logarithmic material fields.
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
@ USER_BASE
user implemented approximation base
@ L2
field with C-1 continuity
#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
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
PetscErrorCode DMMoFEMGetFieldIS(DM dm, RowColData rc, const char field_name[], IS *is)
get field is in the problem
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual bool check_field(const std::string &name) const =0
check if field is in database
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
const FTensor::Tensor2< T, Dim, Dim > Vec
MoFEMErrorCode runAuxiliaryLogarithmicStressTest(const std::function< MoFEMErrorCode(EshelbianCore &)> &test)
boost::shared_ptr< MatrixDouble > MatrixPtr
MoFEMErrorCode pushAuxiliaryLogarithmicFields(const EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, boost::shared_ptr< AuxiliaryLogarithmicStressData > values, boost::shared_ptr< MatrixDouble > reconstructed_log_stretch, SmartPetscObj< Vec > state=nullptr)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
MoFEM::Interface & mField
const std::string materialH1Positions
const std::string elementVolumeName
static FieldApproximationBase brokenHdivBase
const std::string logDeviator
const std::string logJacobian
SmartPetscObj< DM > dmMaterial
Material problem.
const std::string auxiliaryLogStress
boost::shared_ptr< PhysicalEquations > physicalEquations
SmartPetscObj< DM > dmElastic
Elastic problem.
const std::string stretchTensor
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 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.
std::bitset< LAST_FEATURE > Features
@ AUXILIARY_LOGARITHMIC_STRESS
Auxiliary logarithmic stress formulation.
Add operators pushing bases from local to physical configuration.
virtual const FiniteElement * get_finite_element_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get finite element structure
virtual moab::Interface & get_moab()=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.
Data on single entity (This is passed as argument to DataOperator::doWork)
MoFEMErrorCode setField(const double val, const EntityType type, const std::string field_name)
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.
keeps basic data about problem
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.