25 boost::shared_ptr<Range> ents_ptr,
RowColData r) {
30 std::mt19937 rng(0x4d584431u);
32 auto get_random_number = [&rng](
auto &range) {
33 std::uniform_real_distribution<double> dist(range[0], range[1]);
46 for (
auto &rf : random_fields) {
49 <<
"Set random field " << rf.first <<
" " <<
static_cast<int>(field_id);
51 auto get_numbered_dofs = [&]() {
54 return prb_ptr->getNumeredRowDofsPtr();
56 return prb_ptr->getNumeredColDofsPtr();
58 throw std::runtime_error(
"Invalid RowColData");
63 auto lo = get_numbered_dofs()->lower_bound(
65 const auto hi = get_numbered_dofs()->upper_bound(
67 for (; lo != hi; ++lo) {
68 const auto idx = (*lo)->getPetscLocalDofIdx();
69 if (idx >= 0 && idx <
size) {
70 array[idx] = get_random_number(rf.second);
74 for (
auto pit = ents_ptr->const_pair_begin();
75 pit != ents_ptr->const_pair_end(); ++pit) {
76 auto lo = get_numbered_dofs()->get<
Unique_mi_tag>().lower_bound(
78 auto hi = get_numbered_dofs()->get<
Unique_mi_tag>().upper_bound(
80 for (; lo != hi; ++lo) {
81 const auto idx = (*lo)->getPetscLocalDofIdx();
82 if (idx >= 0 && idx <
size) {
83 array[idx] = get_random_number(rf.second);
90 CHKERR VecRestoreArray(
v, &array);
92 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
93 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
100 boost::shared_ptr<FEMethod> pipeline,
108 pipeline->ts_t = time;
109 pipeline->ts_dt = delta_t;
115 auto [
v,
a] =
setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
123 "Run assemble pipeline");
136 auto get_norm = [](
auto f) {
138 VecNorm(f, NORM_2, &fnorm);
150 boost::shared_ptr<FEMethod> pipeline,
161 pipeline->ts_t = time;
163 pipeline->ts_dt = delta_t;
164 pipeline->ts_a = 1. / delta_t;
165 pipeline->ts_aa = 1. / pow(delta_t, 2);
171 auto [
v,
a] =
setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
179 "Run assemble pipeline");
183 auto get_norm = [](
auto m) {
185 MatNorm(
m, NORM_1, &fnorm);
202 auto axpy = [&](
auto v0,
auto diff_v,
auto eps) {
204 if (v0.use_count()) {
218 axpy(x, diff_x, -
eps),
220 axpy(delta_x, diff_x, -
eps),
222 axpy(delta2_x, diff_x, -
eps),
224 time, delta_t, cache_ptr);
228 axpy(x, diff_x,
eps),
230 axpy(delta_x, diff_x,
eps),
232 axpy(delta2_x, diff_x,
eps),
234 time, delta_t, cache_ptr);
236 auto calculate_derivative = [
eps](
auto fm1,
auto fp1) {
238 VecGetLocalSize(fp1, &
size);
239 VecAXPY(fp1, -1, fm1);
241 VecGetArray(fp1, &array);
242 for (
int j = 0;
j !=
size; ++
j) {
245 VecRestoreArray(fp1, &array);
249 return calculate_derivative(fm1, fp1);
254 boost::shared_ptr<FEMethod> pipeline_rhs,
261 dm, fe_name, pipeline_rhs, x, delta_x, delta2_x, diff_x, time, delta_t,
264 auto m =
assembleMat(dm, fe_name, pipeline_lhs, x, delta_x, delta2_x, time,
275 Vec x, Vec direction, Vec
gradient,
const double eps,
277 PetscReal &assembled_derivative) {
279 if (!(
eps > 0) || !evaluate)
281 "Scalar directional-derivative test requires a positive step "
285 CHKERR VecWAXPY(x_plus,
eps, direction, x);
286 CHKERR VecWAXPY(x_minus, -
eps, direction, x);
287 CHKERR VecGhostUpdateBegin(x_plus, INSERT_VALUES, SCATTER_FORWARD);
288 CHKERR VecGhostUpdateEnd(x_plus, INSERT_VALUES, SCATTER_FORWARD);
289 CHKERR VecGhostUpdateBegin(x_minus, INSERT_VALUES, SCATTER_FORWARD);
290 CHKERR VecGhostUpdateEnd(x_minus, INSERT_VALUES, SCATTER_FORWARD);
291 PetscReal value_plus = 0;
292 PetscReal value_minus = 0;
293 CHKERR evaluate(x_plus, value_plus);
294 CHKERR evaluate(x_minus, value_minus);
295 finite_difference = (value_plus - value_minus) / (2 *
eps);
296 PetscScalar derivative = 0;
298 assembled_derivative = PetscRealPart(derivative);
303 Vec x, Vec direction, Vec function_layout, Mat
jacobian,
const double eps,
306 if (!(
eps > 0) || !evaluate)
308 "Vector directional-derivative test requires a positive step "
315 CHKERR VecWAXPY(x_plus,
eps, direction, x);
316 CHKERR VecWAXPY(x_minus, -
eps, direction, x);
317 CHKERR VecGhostUpdateBegin(x_plus, INSERT_VALUES, SCATTER_FORWARD);
318 CHKERR VecGhostUpdateEnd(x_plus, INSERT_VALUES, SCATTER_FORWARD);
319 CHKERR VecGhostUpdateBegin(x_minus, INSERT_VALUES, SCATTER_FORWARD);
320 CHKERR VecGhostUpdateEnd(x_minus, INSERT_VALUES, SCATTER_FORWARD);
321 CHKERR evaluate(x_plus, value_plus);
322 CHKERR evaluate(x_minus, value_minus);
323 CHKERR VecCopy(value_plus, error);
324 CHKERR VecAXPY(error, -1., value_minus);
327 CHKERR VecAXPY(error, -1., assembled);
346 VecCopy(delta_x, x_t);
347 VecScale(x_t, 1. / delta_t);
355 pipeline->x_t = PETSC_NULLPTR;
362 VecCopy(delta2_x, x_tt);
363 VecScale(x_tt, 1. / pow(delta_t, 2));
368 pipeline->x_tt = x_tt;
371 pipeline->x_tt = PETSC_NULLPTR;
374 return std::make_pair(x_t, x_tt);
#define MOFEM_TAG_AND_LOG_C(channel, severity, tag, format,...)
Tag and log in channel.
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
SmartPetscObj< Vec > gradient
SmartPetscObj< Mat > jacobian
#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 ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
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.
auto createDMMatrix(DM dm)
Get smart matrix from DM.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'j', 3 > j
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.
auto getProblemPtr(DM dm)
get problem pointer from DM
boost::weak_ptr< CacheTuple > CacheTupleWeakPtr
FTensor::Index< 'm', 3 > m
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
Deprecated interface functions.
static UId getLoFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getHiFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
@ CTX_SETFUNCTION
Setting up the linear system function.
@ CTX_OPERATORS
Setting up linear operators.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
SmartPetscObj< Mat > assembleMat(SmartPetscObj< DM > dm, std::string fe_name, boost::shared_ptr< FEMethod > pipeline, SmartPetscObj< Vec > x, SmartPetscObj< Vec > delta_x, SmartPetscObj< Vec > delta2_x, double time, double delta_t, CacheTupleWeakPtr cache_ptr)
Assemble the left hand side vector.
SmartPetscObj< Vec > checkCentralFiniteDifference(SmartPetscObj< DM > dm, std::string fe_name, boost::shared_ptr< FEMethod > pipeline_rhs, boost::shared_ptr< FEMethod > pipeline_lhs, SmartPetscObj< Vec > x, SmartPetscObj< Vec > delta_x, SmartPetscObj< Vec > delta2_x, SmartPetscObj< Vec > diff_x, double time, double delta_t, double eps, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Check consistency between directional derivative with matrix.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
OperatorsTester(const MoFEM::Core &core)
MoFEMErrorCode checkScalarCentralFiniteDifference(Vec x, Vec direction, Vec gradient, double eps, const ScalarFunction &evaluate, PetscReal &finite_difference, PetscReal &assembled_derivative)
std::function< MoFEMErrorCode(Vec, PetscReal &)> ScalarFunction
SmartPetscObj< Vec > assembleVec(SmartPetscObj< DM > dm, std::string fe_name, boost::shared_ptr< FEMethod > pipeline, SmartPetscObj< Vec > x, SmartPetscObj< Vec > delta_x, SmartPetscObj< Vec > delta2_x, double time, double delta_t, CacheTupleWeakPtr cache_ptr)
Assemble the right hand side vector.
SmartPetscObj< Vec > setRandomFields(SmartPetscObj< DM > dm, std::vector< RandomFieldData > random_fields, boost::shared_ptr< Range > ents=nullptr, RowColData r=RowColData::COL)
Generate random fields.
std::pair< SmartPetscObj< Vec >, SmartPetscObj< Vec > > setPipelineX(boost::shared_ptr< FEMethod > pipeline, SmartPetscObj< Vec > x, SmartPetscObj< Vec > delta_x, SmartPetscObj< Vec > delta2_x, double delta_t)
Set vectors, x, x_t, and x_tt to finite element instance.
std::function< MoFEMErrorCode(Vec, Vec)> VectorFunction
MoFEMErrorCode checkVectorCentralFiniteDifference(Vec x, Vec direction, Vec function_layout, Mat jacobian, double eps, const VectorFunction &evaluate, Vec error)
SmartPetscObj< Vec > directionalCentralFiniteDifference(SmartPetscObj< DM > dm, std::string fe_name, boost::shared_ptr< FEMethod > pipeline, SmartPetscObj< Vec > x, SmartPetscObj< Vec > delta_x, SmartPetscObj< Vec > delta2_x, SmartPetscObj< Vec > diff_x, double time, double delta_t, double eps, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Calculate directional directive using finite difference.
static constexpr Switches CtxSetA
Jacobian matrix switch.
static constexpr Switches CtxSetF
Residual vector switch.
@ CTX_SET_X_T
Time derivative X_t is set.
@ CTX_SET_X
Solution vector X is set.
@ CTX_SET_X_TT
Second time derivative X_tt is set.
static constexpr Switches CtxSetB
Preconditioner matrix switch.
static constexpr Switches CtxSetTime
Time value switch.
intrusive_ptr for managing petsc objects
@ CTX_SNESSETJACOBIAN
Setting up Jacobian matrix computation.
@ CTX_SNESSETFUNCTION
Setting up nonlinear function evaluation.
@ CTX_TSSETIFUNCTION
Setting up implicit function.
@ CTX_TSSETIJACOBIAN
Setting up implicit Jacobian.
base class for all interface classes