v0.14.0
OperatorsTester.cpp
Go to the documentation of this file.
1 /**
2  * @file OperatorsTester.cpp
3  * @brief
4  * @version 0.13.2
5  * @date 2022-12-04
6  *
7  * @copyright Copyright (c) 2022
8  *
9  */
10 
11 namespace MoFEM {
12 
14  : cOre(const_cast<Core &>(core)) {}
15 
17 OperatorsTester::query_interface(boost::typeindex::type_index type_index,
18  UnknownInterface **iface) const {
19  *iface = const_cast<OperatorsTester *>(this);
20  return 0;
21 }
22 
25  std::vector<RandomFieldData> random_fields,
26  boost::shared_ptr<Range> ents_ptr) {
27 
28  MoFEM::Interface &m_field = cOre;
29 
30  auto prb_ptr = getProblemPtr(dm);
31 
32  auto get_random_number = [](auto &range) {
33  const auto r = static_cast<double>(std::rand()) / RAND_MAX;
34  return range[0] + r * (range[1] - range[0]);
35  };
36 
37  auto v = createDMVector(dm);
38  double *array;
39  CHKERR VecGetArray(v, &array);
40 
41  MOFEM_LOG_CHANNEL("WORLD");
42 
43  for (auto &rf : random_fields) {
44  const auto field_id = m_field.get_field_bit_number(rf.first);
45  MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "OperatorsTester")
46  << "Set random field " << rf.first << " " << static_cast<int>(field_id);
47 
48  if (!ents_ptr) {
49  auto lo = prb_ptr->getNumeredRowDofsPtr()->lower_bound(
51  const auto hi = prb_ptr->getNumeredRowDofsPtr()->upper_bound(
53  for (; lo != hi; ++lo) {
54  const auto idx = (*lo)->getPetscLocalDofIdx();
55  array[idx] = get_random_number(rf.second);
56  }
57  } else {
58  for (auto pit = ents_ptr->const_pair_begin();
59  pit != ents_ptr->const_pair_end(); ++pit) {
60  auto lo =
61  prb_ptr->getNumeredRowDofsPtr()->get<Unique_mi_tag>().lower_bound(
62  DofEntity::getLoFieldEntityUId(field_id, pit->first));
63  auto hi =
64  prb_ptr->getNumeredRowDofsPtr()->get<Unique_mi_tag>().upper_bound(
65  DofEntity::getHiFieldEntityUId(field_id, pit->second));
66  for (; lo != hi; ++lo) {
67  const auto idx = (*lo)->getPetscLocalDofIdx();
68  array[idx] = get_random_number(rf.second);
69  }
70  }
71  }
72  }
73 
74  CHKERR VecRestoreArray(v, &array);
75 
76  CHKERR VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD);
77  CHKERR VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD);
78 
79  return v;
80 };
81 
84  boost::shared_ptr<FEMethod> pipeline,
86  SmartPetscObj<Vec> delta2_x, double time,
87  double delta_t, CacheTupleWeakPtr cache_ptr) {
88 
89  pipeline->data_ctx = PetscData::CtxSetF | PetscData::CtxSetTime;
90  auto f = createDMVector(dm);
91  pipeline->f = f;
92  pipeline->ts_t = time;
93  pipeline->ts_dt = delta_t;
94 
95  auto [v, a] = setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
96  std::ignore = a;
97  std::ignore = v;
98 
100  DMoFEMMeshToLocalVector(dm, x, INSERT_VALUES, SCATTER_REVERSE),
101  "loc to vec");
102  CHK_THROW_MESSAGE(DMoFEMLoopFiniteElements(dm, fe_name, pipeline, cache_ptr),
103  "Run assemble pipeline");
104  CHK_THROW_MESSAGE(VecAssemblyBegin(f), "Asmb vector");
105  CHK_THROW_MESSAGE(VecAssemblyEnd(f), "Asmb vector");
106 
107  CHK_THROW_MESSAGE(VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE),
108  "Update vec");
109  CHK_THROW_MESSAGE(VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE),
110  "Update vec");
111  CHK_THROW_MESSAGE(VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD),
112  "Update vec");
113  CHK_THROW_MESSAGE(VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD),
114  "Update vec");
115 
116  return f;
117 }
118 
121  boost::shared_ptr<FEMethod> pipeline,
123  SmartPetscObj<Vec> delta2_x, double time,
124  double delta_t, CacheTupleWeakPtr cache_ptr) {
125  auto m = createDMMatrix(dm);
126 
127  pipeline->data_ctx =
129  pipeline->A = m;
130  pipeline->B = m;
131 
132  pipeline->ts_t = time;
133 
134  pipeline->ts_dt = delta_t;
135  pipeline->ts_a = 1. / delta_t;
136  pipeline->ts_aa = 1. / pow(delta_t, 2);
137 
138  auto [v, a] = setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
139  std::ignore = a;
140  std::ignore = v;
141 
143  DMoFEMMeshToLocalVector(dm, x, INSERT_VALUES, SCATTER_REVERSE),
144  "loc to vec");
145  CHK_THROW_MESSAGE(DMoFEMLoopFiniteElements(dm, fe_name, pipeline, cache_ptr),
146  "Run assemble pipeline");
147  CHK_THROW_MESSAGE(MatAssemblyBegin(m, MAT_FINAL_ASSEMBLY), "Asmb mat");
148  CHK_THROW_MESSAGE(MatAssemblyEnd(m, MAT_FINAL_ASSEMBLY), "Asmb mat");
149 
150  return m;
151 }
152 
154  SmartPetscObj<DM> dm, std::string fe_name,
155  boost::shared_ptr<FEMethod> pipeline, SmartPetscObj<Vec> x,
156  SmartPetscObj<Vec> delta_x, SmartPetscObj<Vec> delta2_x,
157  SmartPetscObj<Vec> diff_x, double time, double delta_t, double eps,
158  CacheTupleWeakPtr cache_ptr) {
159 
160  auto axpy = [&](auto v0, auto diff_v, auto eps) {
162  if (v0.use_count()) {
163  v = vectorDuplicate(v0);
164  CHK_THROW_MESSAGE(VecCopy(v0, v), "Cpy");
165  CHK_THROW_MESSAGE(VecAXPY(v, eps, diff_v), "Add");
166  CHK_THROW_MESSAGE(VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD),
167  "ghost");
168  CHK_THROW_MESSAGE(VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD),
169  "ghost");
170  }
171  return v;
172  };
173 
174  auto fm1 = assembleVec(dm, fe_name, pipeline,
175  //
176  axpy(x, diff_x, -eps),
177  //
178  axpy(delta_x, diff_x, -eps),
179  //
180  axpy(delta2_x, diff_x, -eps),
181  //
182  time, delta_t, cache_ptr);
183 
184  auto fp1 = assembleVec(dm, fe_name, pipeline,
185  //
186  axpy(x, diff_x, eps),
187  //
188  axpy(delta_x, diff_x, eps),
189  //
190  axpy(delta2_x, diff_x, eps),
191  //
192  time, delta_t, cache_ptr);
193 
194  auto calculate_derivative = [eps](auto fm1, auto fp1) {
195  int size;
196  VecGetLocalSize(fp1, &size);
197  VecAXPY(fp1, -1, fm1);
198  double *array;
199  VecGetArray(fp1, &array);
200  for (int j = 0; j != size; ++j) {
201  array[j] /= 2 * eps;
202  }
203  VecRestoreArray(fp1, &array);
204  return fp1;
205  };
206 
207  return calculate_derivative(fm1, fp1);
208 }
209 
211  SmartPetscObj<DM> dm, std::string fe_name,
212  boost::shared_ptr<FEMethod> pipeline_rhs,
213  boost::shared_ptr<FEMethod> pipeline_lhs, SmartPetscObj<Vec> x,
214  SmartPetscObj<Vec> delta_x, SmartPetscObj<Vec> delta2_x,
215  SmartPetscObj<Vec> diff_x, double time, double delta_t, double eps,
216  CacheTupleWeakPtr cache_ptr) {
217 
218  auto fd_diff = directionalCentralFiniteDifference(
219  dm, fe_name, pipeline_rhs, x, delta_x, delta2_x, diff_x, time, delta_t,
220  eps, cache_ptr);
221 
222  auto m = assembleMat(dm, fe_name, pipeline_lhs, x, delta_x, delta2_x, time,
223  delta_t, cache_ptr);
224 
225  auto fm = vectorDuplicate(fd_diff);
226  CHK_THROW_MESSAGE(MatMult(m, diff_x, fm), "Mat mult");
227  CHK_THROW_MESSAGE(VecAXPY(fd_diff, -1., fm), "Add");
228 
229  return fd_diff;
230 }
231 
232 std::pair<SmartPetscObj<Vec>, SmartPetscObj<Vec>>
233 OperatorsTester::setPipelineX(boost::shared_ptr<FEMethod> pipeline,
235  SmartPetscObj<Vec> delta2_x, double delta_t) {
236 
237  // Set dofs vector to finite element instance
238 
239  pipeline->x = x;
240  pipeline->data_ctx |= PetscData::CTX_SET_X;
241 
242  SmartPetscObj<Vec> x_t, x_tt;
243 
244  // Set velocity dofs vector to finite element instance
245 
246  if (delta_x.use_count()) {
247  x_t = vectorDuplicate(x);
248  VecCopy(delta_x, x_t);
249  VecScale(x_t, 1. / delta_t);
250  CHK_THROW_MESSAGE(VecGhostUpdateBegin(x_t, INSERT_VALUES, SCATTER_FORWARD),
251  "ghost");
252  CHK_THROW_MESSAGE(VecGhostUpdateEnd(x_t, INSERT_VALUES, SCATTER_FORWARD),
253  "ghost");
254  pipeline->x_t = x_t;
255  pipeline->data_ctx |= PetscData::CTX_SET_X_T;
256  } else {
257  pipeline->x_t = PETSC_NULL;
258  }
259 
260  // Set acceleration dofs vector to finite element instance
261 
262  if (delta2_x.use_count()) {
263  x_tt = vectorDuplicate(x);
264  VecCopy(delta2_x, x_tt);
265  VecScale(x_tt, 1. / pow(delta_t, 2));
266  CHK_THROW_MESSAGE(VecGhostUpdateBegin(x_tt, INSERT_VALUES, SCATTER_FORWARD),
267  "ghost");
268  CHK_THROW_MESSAGE(VecGhostUpdateEnd(x_tt, INSERT_VALUES, SCATTER_FORWARD),
269  "ghost");
270  pipeline->x_tt = x_tt;
271  pipeline->data_ctx |= PetscData::CTX_SET_X_TT;
272  } else {
273  pipeline->x_tt = PETSC_NULL;
274  }
275 
276  return std::make_pair(x_t, x_tt);
277 }
278 } // namespace MoFEM
MoFEM::OperatorsTester::OperatorsTester
OperatorsTester(const MoFEM::Core &core)
Definition: OperatorsTester.cpp:13
MoFEM::CoreTmp< 0 >
Core (interface) class.
Definition: Core.hpp:82
MOFEM_LOG_CHANNEL
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
Definition: LogManager.hpp:284
MoFEM::PetscData::CtxSetB
static constexpr Switches CtxSetB
Definition: LoopMethods.hpp:38
MoFEM::PetscData::CtxSetA
static constexpr Switches CtxSetA
Definition: LoopMethods.hpp:37
CHK_THROW_MESSAGE
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
Definition: definitions.h:609
MoFEM::Exceptions::MoFEMErrorCode
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
MoFEM::OperatorsTester::query_interface
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Definition: OperatorsTester.cpp:17
MoFEM::CoreInterface::get_field_bit_number
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
MoFEM::OperatorsTester::setPipelineX
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.
Definition: OperatorsTester.cpp:233
MoFEM::DMoFEMMeshToLocalVector
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition: DMMoFEM.cpp:523
sdf.r
int r
Definition: sdf.py:8
MoFEM::createDMMatrix
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition: DMMoFEM.hpp:1056
MoFEM::DeprecatedCoreInterface
Deprecated interface functions.
Definition: DeprecatedCoreInterface.hpp:16
MoFEM::PetscData::CTX_SET_X_TT
@ CTX_SET_X_TT
Definition: LoopMethods.hpp:29
MoFEM::OperatorsTester::assembleMat
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.
Definition: OperatorsTester.cpp:120
CHKERR
#define CHKERR
Inline error check.
Definition: definitions.h:548
MoFEM::createDMVector
auto createDMVector(DM dm)
Get smart vector from DM.
Definition: DMMoFEM.hpp:1099
MoFEM::SmartPetscObj::use_count
int use_count() const
Definition: PetscSmartObj.hpp:109
MoFEM
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:10
MoFEM::OperatorsTester::cOre
MoFEM::Core & cOre
Definition: OperatorsTester.hpp:145
a
constexpr double a
Definition: approx_sphere.cpp:30
MoFEM::FieldEntity::getLoBitNumberUId
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
Definition: FieldEntsMultiIndices.hpp:222
MoFEM::PetscData::CtxSetTime
static constexpr Switches CtxSetTime
Definition: LoopMethods.hpp:42
MoFEM::OperatorsTester::directionalCentralFiniteDifference
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.
Definition: OperatorsTester.cpp:153
MoFEM::DofEntity::getLoFieldEntityUId
static UId getLoFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
Definition: DofsMultiIndices.hpp:69
MoFEM::OperatorsTester::setRandomFields
SmartPetscObj< Vec > setRandomFields(SmartPetscObj< DM > dm, std::vector< RandomFieldData > random_fields, boost::shared_ptr< Range > ents=nullptr)
Generate random fileds.
Definition: OperatorsTester.cpp:24
MoFEM::OperatorsTester
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
Definition: OperatorsTester.hpp:21
MoFEM::UnknownInterface
base class for all interface classes
Definition: UnknownInterface.hpp:34
v
const double v
phase velocity of light in medium (cm/ns)
Definition: initial_diffusion.cpp:40
MOFEM_TAG_AND_LOG
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
Definition: LogManager.hpp:362
MoFEM::vectorDuplicate
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
Definition: PetscSmartObj.hpp:221
MoFEM::OperatorsTester::assembleVec
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.
Definition: OperatorsTester.cpp:83
MoFEM::DofEntity::getHiFieldEntityUId
static UId getHiFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
Definition: DofsMultiIndices.hpp:75
HenckyOps::f
auto f
Definition: HenckyOps.hpp:15
j
FTensor::Index< 'j', 3 > j
Definition: matrix_function.cpp:19
eps
static const double eps
Definition: check_base_functions_derivatives_on_tet.cpp:11
MoFEM::getProblemPtr
auto getProblemPtr(DM dm)
get problem pointer from DM
Definition: DMMoFEM.hpp:1044
MoFEM::CacheTupleWeakPtr
boost::weak_ptr< CacheTuple > CacheTupleWeakPtr
Definition: FEMultiIndices.hpp:494
MoFEM::PetscData::CTX_SET_X_T
@ CTX_SET_X_T
Definition: LoopMethods.hpp:28
MoFEM::FieldEntity::getHiBitNumberUId
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
Definition: FieldEntsMultiIndices.hpp:228
m
FTensor::Index< 'm', 3 > m
Definition: shallow_wave.cpp:80
MoFEM::PetscData::CtxSetF
static constexpr Switches CtxSetF
Definition: LoopMethods.hpp:36
MoFEM::Unique_mi_tag
Definition: TagMultiIndices.hpp:18
MoFEM::SmartPetscObj< Vec >
MoFEM::PetscData::CTX_SET_X
@ CTX_SET_X
Definition: LoopMethods.hpp:27
MoFEM::OperatorsTester::checkCentralFiniteDifference
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.
Definition: OperatorsTester.cpp:210
MoFEM::DMoFEMLoopFiniteElements
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition: DMMoFEM.cpp:586