1#ifndef MOFEM_PLASTIC_FLOW_PRECONDITIONER_TESTS_HPP
2#define MOFEM_PLASTIC_FLOW_PRECONDITIONER_TESTS_HPP
17 SmartPetscObj<IS> latent_is(raw_is);
19 const PetscInt *indices =
nullptr;
21 CHKERR ISGetIndices(latent_is, &indices);
22 for (PetscInt
i = 0;
i !=
size; ++
i)
23 CHKERR MatSetValue(matrix, indices[
i], indices[
i], 1., ADD_VALUES);
24 CHKERR ISRestoreIndices(latent_is, &indices);
25 CHKERR MatAssemblyBegin(matrix, MAT_FINAL_ASSEMBLY);
26 CHKERR MatAssemblyEnd(matrix, MAT_FINAL_ASSEMBLY);
38 using namespace PlasticIncrementalOptimizationInternal;
40 Mat raw_matrix =
nullptr;
41 CHKERR DMCreateMatrix(flow_dm, &raw_matrix);
42 SmartPetscObj<Mat> matrix(raw_matrix);
52 KSP raw_ksp =
nullptr;
54 SmartPetscObj<KSP>
ksp(raw_ksp);
55 CHKERR KSPSetOptionsPrefix(
ksp,
"incremental_optimization_tensor_");
58 CHKERR PCSetType(pc, PCBJACOBI);
60 CHKERR VecZeroEntries(zero_latent);
61 parameters.regularisationEpsilon = 1e-4;
62 PetscReal direction_norm = 0;
64 const double step = 1e-7 / std::max(1., direction_norm);
65 for (
const double hardening : {0., .3}) {
66 parameters.hardeningModulus = hardening;
67 for (
const double flow_scale : {0., .01, .1}) {
72 ep, flow_dm,
flow, latent_dm,
latent, latent_dm, latent_centre,
75 CHKERR VecZeroEntries(reference);
77 ep, flow_dm,
flow, latent_dm,
latent, latent_dm, latent_centre,
78 direction, zero_latent, parameters, reference);
79 PetscReal norm = 0, action_error = 0;
80 CHKERR VecNorm(reference, NORM_2, &norm);
81 CHKERR VecAXPY(reference, -1., action);
82 CHKERR VecNorm(reference, NORM_2, &action_error);
83 if (!std::isfinite(action_error) || action_error > 1e-11 * (1. + norm))
85 "Local matrix/action mismatch %g, norm %g, "
86 "flow scale %g, hardening %g",
87 action_error, norm, flow_scale, hardening);
92 CHKERR VecZeroEntries(out);
94 ep, flow_dm, trial, latent_dm,
latent, latent_dm, latent_centre,
100 CHKERR VecAXPY(plus, -1., minus);
101 CHKERR VecScale(plus, .5 / step);
102 CHKERR VecAXPY(plus, -1., action);
103 PetscReal fd_error = 0;
104 CHKERR VecNorm(plus, NORM_2, &fd_error);
105 if (!std::isfinite(fd_error) || fd_error > 1e-8 + 1e-5 * norm)
107 "Local matrix gradient difference error %g, "
108 "norm %g, flow scale %g, hardening %g",
109 fd_error, norm, flow_scale, hardening);
111 <<
"Local flow preconditioner verified: flow scale " << flow_scale
112 <<
", hardening " << hardening <<
", action error " << action_error
113 <<
", FD error " << fd_error;
117 CHKERR addLatentIdentityRows(ep, flow_dm, matrix);
118 CHKERR KSPSetOperators(
ksp, matrix, matrix);
121 CHKERR MatMult(matrix, solution, solve_residual);
123 PetscReal solve_error = 0;
124 CHKERR VecNorm(solve_residual, NORM_2, &solve_error);
125 if (!std::isfinite(solve_error) ||
126 solve_error > 1e-8 * std::max(direction_norm, PETSC_SMALL))
128 "Updated flow preconditioner inverse failed: "
129 "relative residual %g, flow scale %g, hardening %g",
130 solve_error / std::max(direction_norm, PETSC_SMALL), flow_scale,
133 <<
"Flow preconditioner factors verified: flow scale " << flow_scale
134 <<
", hardening " << hardening <<
", relative inverse residual "
135 << solve_error / std::max(direction_norm, PETSC_SMALL);
141using TestMaterialActionByElement = std::map<EntityHandle, MatrixDouble>;
146 using DL = DataLayoutTraits<DataLayout::GaussByCoeffs>;
147 OpTestLocalMaterialFlowAction(
148 boost::shared_ptr<DataAtIntegrationPts> data,
149 boost::shared_ptr<MatrixDouble> direction,
150 boost::shared_ptr<TestMaterialActionByElement> actions)
158 const int count = getGaussPts().size2();
161 "Local material assembly test requires multiple Gauss points");
162 auto hp =
data->getFTensorPlasticH(count);
163 auto ue =
data->getFTensorStretch(count);
164 auto he =
data->getFTensorLogStretch(count);
166 *direction, count)();
168 (*actions)[getFEEntityHandle()], count)();
174 vectors(
m,
n) =
h(
m,
n);
176 "Diagonalise independent material action test tensor");
179 const auto &basis = Tensor2SymmetricDeviatorBasis::getBasis();
180 for (
int gg = 0; gg != count; ++gg) {
184 elastic_h(
i,
j) = he(
i,
j);
185 const auto fp =
function(
h, [](
double x) {
return std::exp(x); });
187 anchor(
i,
j) = u(
i,
k) * fp(
k,
j);
189 constexpr double step = 2e-6;
190 for (
int col = 0; col != 5; ++col) {
195 tensor_v(
i,
j) = basis(
i,
j,
a) * unit(
a);
196 const auto evaluate = [&](
double shift) {
198 trial(
i,
j) =
h(
i,
j) + shift * tensor_v(
i,
j);
200 function(trial, [](
double x) {
return std::exp(-x); });
203 cauchy(
i,
j) = fe(
k,
i) * fe(
k,
j);
205 return function(
metric, [](
double x) {
return .5 * std::log(x); });
207 const auto plus = evaluate(step), minus = evaluate(-step);
208 difference(
i,
j) = (plus(
i,
j) - minus(
i,
j)) / (2. * step);
209 coordinates(
a) = basis(
i,
j,
a) * difference(
i,
j);
210 for (
int row = 0; row != 5; ++row)
211 map(row, col) = coordinates(row);
214 CHKERR data->physicsPtr->evaluateElasticLogarithmicMaterialHessian(
215 getFEEntityHandle(), gg, *data, elastic_h, tangent);
217 direction_h(
a) = map(
a, b) *
v(b);
218 stress(
a) = tangent(
a, b) * direction_h(b);
223 LogarithmicMaterialCurvature oracle;
224 oracle.stretch(
i,
j) = elastic_h(
i,
j);
225 oracle.direction(
i,
j) = basis(
i,
j,
a) * direction_h(
a);
226 oracle.adjoint(
i,
j) = 0.;
227 oracle.stressAdjoint(
a) = 0.;
228 oracle.stressDirection(
a) = 0.;
229 CHKERR data->physicsPtr->evaluateHelmholtzCurvature(getFEEntityHandle(),
232 oracle.stretchResult(0), .5 * oracle.stretchResult(1),
233 .5 * oracle.stretchResult(2), oracle.stretchResult(3),
234 .5 * oracle.stretchResult(4), oracle.stretchResult(5));
236 error(
a) = stress(
a) - basis(
i,
j,
a) * covector(
i,
j);
237 if (std::sqrt(error(
a) * error(
a)) >
238 1e-9 * (1. + std::sqrt(stress(
a) * stress(
a))))
240 "Pure material Hessian differs from zero-adjoint response");
249 boost::shared_ptr<DataAtIntegrationPts>
data;
251 boost::shared_ptr<TestMaterialActionByElement>
actions;
255 using DL = DataLayoutTraits<DataLayout::GaussByCoeffs>;
256 OpTestLoadLocalMaterialAction(
257 boost::shared_ptr<TestMaterialActionByElement>
actions,
258 boost::shared_ptr<MatrixDouble>
values)
264 const int count = getGaussPts().size2();
266 actions->at(getFEEntityHandle()), count)();
269 for (
int gg = 0; gg != count; ++gg) {
270 output(
a) = input(
a);
276 boost::shared_ptr<TestMaterialActionByElement>
actions;
288 const auto plastic_only = [&
ep](
FEMethod *method) {
292 auto actions = boost::make_shared<TestMaterialActionByElement>();
293 auto values = boost::make_shared<MatrixDouble>();
295 boost::make_shared<VolumeElementForcesAndSourcesCore>(
ep.
mField);
296 mechanical->ts_ctx = TSMethod::CTX_TSSETIJACOBIAN;
299 mechanical->exeTestHook = plastic_only;
300 mechanical->getOpPtrVector().push_back(
new OpCalculateVectorFieldValues<5>(
303 mechanical->getOpPtrVector().push_back(
305 TetPolynomialBase::switchCacheBaseOn<HDIV>({mechanical.get()});
308 TetPolynomialBase::switchCacheBaseOff<HDIV>({mechanical.get()});
310 auto flow = boost::make_shared<VolumeElementForcesAndSourcesCore>(
ep.
mField);
311 flow->getUserPolynomialBase() =
312 boost::make_shared<CGGUserPolynomialBase>(
nullptr,
true);
314 flow->getRuleHook = mechanical->getRuleHook;
315 flow->exeTestHook = plastic_only;
318 flow->getOpPtrVector().push_back(
320 using Form = FormsIntegrators<VolUserDataOperator>::Assembly<
A>
::LinearForm<
321 GAUSS>::OpBaseTimesVector<1, 5, 5>;
323 CHKERR VecZeroEntries(action);
325 CHKERR VecAssemblyBegin(action);
326 CHKERR VecAssemblyEnd(action);
327 CHKERR VecGhostUpdateBegin(action, ADD_VALUES, SCATTER_REVERSE);
328 CHKERR VecGhostUpdateEnd(action, ADD_VALUES, SCATTER_REVERSE);
336 PlasticIncrementalOptimizationInternal::
337 ReducedBulkMaterialEnergyHessianWorkspace &workspace,
339 using namespace PlasticIncrementalOptimizationInternal;
341 Mat raw_matrix =
nullptr;
342 CHKERR DMCreateMatrix(flow_dm, &raw_matrix);
343 SmartPetscObj<Mat> matrix(raw_matrix);
344 KSP raw_ksp =
nullptr;
346 SmartPetscObj<KSP>
ksp(raw_ksp);
347 CHKERR KSPSetOptionsPrefix(
ksp,
"incremental_optimization_tensor_");
350 CHKERR PCSetType(pc, PCBJACOBI);
353 for (
const double flow_shift : {0., .03, .12}) {
356 ep, ts, flow_dm, current_flow, base_state, workspace);
357 CHKERR MatZeroEntries(matrix);
368 const auto set_flow = [&](
Vec flow) {
374 constexpr double step = 1e-4;
383 const auto plus_error =
gradient(step, plus);
384 const auto minus_error = plus_error ? 0 :
gradient(-step, minus);
385 const auto restore_error = set_flow(current_flow);
389 CHKERR VecAXPY(plus, -1., minus);
390 CHKERR VecScale(plus, .5 / step);
391 CHKERR VecAXPY(plus, 1., material_action);
392 PetscReal reference_norm = 0;
393 CHKERR VecNorm(plus, NORM_2, &reference_norm);
394 CHKERR VecAXPY(plus, -1., action);
396 CHKERR VecNorm(plus, NORM_2, &error);
397 if (!std::isfinite(error) || error > 1e-8 + 1e-5 * reference_norm)
400 "Frozen flow plus local material curvature failed: error %g, norm %g",
401 error, reference_norm);
405 CHKERR VecShift(second, .17);
407 CHKERR MatMult(matrix, second, second_action);
408 PetscScalar uv = 0, vu = 0;
410 CHKERR VecDot(second, action, &vu);
411 const double symmetry_error = std::abs(PetscRealPart(uv - vu));
412 if (symmetry_error > 1e-10 * (1. + std::max(std::abs(PetscRealPart(uv)),
413 std::abs(PetscRealPart(vu)))))
415 "Frozen flow curvature symmetry error %g", symmetry_error);
417 <<
"Frozen flow plus local material preconditioner verified: FD error "
418 << error <<
", norm " << reference_norm <<
", symmetry error "
422 CHKERR addLatentIdentityRows(ep, flow_dm, matrix);
423 CHKERR KSPSetOperators(
ksp, matrix, matrix);
428 PetscReal inverse_error = 0., rhs_norm = 0.;
431 if (!std::isfinite(inverse_error) || inverse_error > 1e-8 * rhs_norm)
433 "Local material Pmat factor refresh failed: relative residual %g",
434 inverse_error / rhs_norm);
436 <<
"Local material Pmat factors verified: flow shift " << flow_shift
437 <<
", relative inverse residual " << inverse_error / rhs_norm;
440 base_state, workspace);
SmartPetscObj< Mat > metric
Mixed directional derivatives of matrix exponentials for the reduced Hessian of the logarithmic plast...
boost::shared_ptr< DataAtIntegrationPts > data
boost::shared_ptr< MatrixDouble > direction
boost::shared_ptr< TestMaterialActionByElement > actions
boost::shared_ptr< MatrixDouble > flow
boost::shared_ptr< VectorDouble > latent
PetscErrorCode(* function)(TS, PetscReal, Vec, Vec, Vec, void *)
SmartPetscObj< Vec > residual
SmartPetscObj< Vec > gradient
SmartPetscObj< Vec > values
SmartPetscObj< Mat > inverse
#define FTENSOR_INDEXES(DIM,...)
#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.
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
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
boost::function< T(const T)> Fun
const FTensor::Tensor2< T, Dim, Dim > Vec
auto getMat(A &&t_val, B &&t_vec, Fun< double > f)
Get the Mat object.
MoFEMErrorCode assemblePlasticAdjointContribution(EshelbianCore &ep, DM flow_output_dm, Vec adjoint, Vec gradient)
MoFEMErrorCode assemblePlasticReconstructedLocalFlowGradient(EshelbianCore &ep, DM flow_dm, Vec flow, DM latent_dm, Vec latent, DM centre_dm, Vec latent_centre, const PlasticLocalLawParameters ¶meters, Vec flow_gradient)
PlasticLocalLawParametersT< double > PlasticLocalLawParameters
MoFEMErrorCode setStateOnMesh(EshelbianCore &ep, Vec state)
MoFEMErrorCode assemblePlasticReconstructedLocalFlowHessianAction(EshelbianCore &ep, DM flow_dm, Vec flow, DM latent_dm, Vec latent, DM centre_dm, Vec latent_centre, Vec flow_direction, Vec latent_direction, const PlasticLocalLawParameters ¶meters, Vec flow_action)
MoFEMErrorCode prepareReducedBulkMaterialEnergyHessian(EshelbianCore &ep, TS ts, Vec control, Vec equilibrated_state, ReducedBulkMaterialEnergyHessianWorkspace &workspace)
Vec getReducedBulkMaterialEnergyBaseAdjoint(const ReducedBulkMaterialEnergyHessianWorkspace &workspace)
MoFEMErrorCode assemblePlasticReconstructedLocalFlowPreconditioner(EshelbianCore &ep, DM flow_dm, Vec flow, DM latent_dm, Vec latent, DM centre_dm, Vec latent_centre, const PlasticLocalLawParameters ¶meters, Mat preconditioner)
MoFEMErrorCode setReducedHessianControl(EshelbianCore &ep, DM control_dm, Vec control)
MoFEMErrorCode assembleReducedBulkMaterialEnergyFlowPreconditioner(EshelbianCore &ep, ReducedBulkMaterialEnergyHessianWorkspace &workspace, Mat preconditioner, bool retain_base_adjoint=true)
VolumeElementForcesAndSourcesCore::UserDataOperator VolUserDataOperator
DataLayoutTraits< DataLayout::GaussByCoeffs > DL
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
FTensor::Index< 'm', 3 > m
MoFEM::Interface & mField
boost::shared_ptr< Range > plasticVolumes
const std::string materialH1Positions
const std::string elementVolumeName
const std::string plasticFlowField
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.
const std::string plasticLatentField
Add operators pushing bases from local to physical configuration.
virtual MPI_Comm & get_comm() const =0
Data on single entity (This is passed as argument to DataOperator::doWork)
@ OPCOL
operator doWork function is executed on FE columns