v0.15.5
Loading...
Searching...
No Matches
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
11namespace MoFEM {
12
14 : cOre(const_cast<Core &>(core)) {}
15
17OperatorsTester::query_interface(boost::typeindex::type_index type_index,
18 UnknownInterface **iface) const {
19 *iface = const_cast<OperatorsTester *>(this);
20 return 0;
21}
22
24 SmartPetscObj<DM> dm, std::vector<RandomFieldData> random_fields,
25 boost::shared_ptr<Range> ents_ptr, RowColData r) {
26
27 MoFEM::Interface &m_field = cOre;
28
29 auto prb_ptr = getProblemPtr(dm);
30
31 auto get_random_number = [](auto &range) {
32 const auto r = static_cast<double>(std::rand()) / RAND_MAX;
33 return range[0] + r * (range[1] - range[0]);
34 };
35
36 auto v = createDMVector(dm, r);
37 double *array;
38 CHKERR VecGetArray(v, &array);
39
40 int size;
41 VecGetLocalSize(v, &size);
42
43 MOFEM_LOG_CHANNEL("WORLD");
44
45 for (auto &rf : random_fields) {
46 const auto field_id = m_field.get_field_bit_number(rf.first);
47 MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "OperatorsTester")
48 << "Set random field " << rf.first << " " << static_cast<int>(field_id);
49
50 auto get_numbered_dofs = [&]() {
51 switch (r) {
52 case RowColData::ROW:
53 return prb_ptr->getNumeredRowDofsPtr();
54 case RowColData::COL:
55 return prb_ptr->getNumeredColDofsPtr();
56 default:
57 throw std::runtime_error("Invalid RowColData");
58 }
59 };
60
61 if (!ents_ptr) {
62 auto lo = get_numbered_dofs()->lower_bound(
64 const auto hi = get_numbered_dofs()->upper_bound(
66 for (; lo != hi; ++lo) {
67 const auto idx = (*lo)->getPetscLocalDofIdx();
68 if (idx >= 0 && idx < size) {
69 array[idx] = get_random_number(rf.second);
70 }
71 }
72 } else {
73 for (auto pit = ents_ptr->const_pair_begin();
74 pit != ents_ptr->const_pair_end(); ++pit) {
75 auto lo = get_numbered_dofs()->get<Unique_mi_tag>().lower_bound(
76 DofEntity::getLoFieldEntityUId(field_id, pit->first));
77 auto hi = get_numbered_dofs()->get<Unique_mi_tag>().upper_bound(
78 DofEntity::getHiFieldEntityUId(field_id, pit->second));
79 for (; lo != hi; ++lo) {
80 const auto idx = (*lo)->getPetscLocalDofIdx();
81 if (idx >= 0 && idx < size) {
82 array[idx] = get_random_number(rf.second);
83 }
84 }
85 }
86 }
87 }
88
89 CHKERR VecRestoreArray(v, &array);
90
91 CHKERR VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD);
92 CHKERR VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD);
93
94 return v;
95};
96
99 boost::shared_ptr<FEMethod> pipeline,
101 SmartPetscObj<Vec> delta2_x, double time,
102 double delta_t, CacheTupleWeakPtr cache_ptr) {
103
104 pipeline->data_ctx = PetscData::CtxSetF | PetscData::CtxSetTime;
105 auto f = createDMVector(dm);
106 pipeline->f = f;
107 pipeline->ts_t = time;
108 pipeline->ts_dt = delta_t;
109
110 pipeline->ksp_ctx = KspMethod::KSPContext::CTX_SETFUNCTION;
113
114 auto [v, a] = setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
115 std::ignore = a;
116 std::ignore = v;
117
119 DMoFEMMeshToLocalVector(dm, x, INSERT_VALUES, SCATTER_REVERSE),
120 "loc to vec");
121 CHK_THROW_MESSAGE(DMoFEMLoopFiniteElements(dm, fe_name, pipeline, cache_ptr),
122 "Run assemble pipeline");
123 CHK_THROW_MESSAGE(VecAssemblyBegin(f), "Asmb vector");
124 CHK_THROW_MESSAGE(VecAssemblyEnd(f), "Asmb vector");
125
126 CHK_THROW_MESSAGE(VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE),
127 "Update vec");
128 CHK_THROW_MESSAGE(VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE),
129 "Update vec");
130 CHK_THROW_MESSAGE(VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD),
131 "Update vec");
132 CHK_THROW_MESSAGE(VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD),
133 "Update vec");
134
135 auto get_norm = [](auto f) {
136 double fnorm;
137 VecNorm(f, NORM_2, &fnorm);
138 return fnorm;
139 };
140 MOFEM_LOG_CHANNEL("WORLD");
141 MOFEM_TAG_AND_LOG_C("WORLD", Sev::noisy, "OpTester", "Vec norm %3.4e",
142 get_norm(f));
143
144 return f;
145}
146
149 boost::shared_ptr<FEMethod> pipeline,
151 SmartPetscObj<Vec> delta2_x, double time,
152 double delta_t, CacheTupleWeakPtr cache_ptr) {
153 auto m = createDMMatrix(dm);
154
155 pipeline->data_ctx =
157 pipeline->A = m;
158 pipeline->B = m;
159
160 pipeline->ts_t = time;
161
162 pipeline->ts_dt = delta_t;
163 pipeline->ts_a = 1. / delta_t;
164 pipeline->ts_aa = 1. / pow(delta_t, 2);
165
166 pipeline->ksp_ctx = KspMethod::KSPContext::CTX_OPERATORS;
169
170 auto [v, a] = setPipelineX(pipeline, x, delta_x, delta2_x, delta_t);
171 std::ignore = a;
172 std::ignore = v;
173
175 DMoFEMMeshToLocalVector(dm, x, INSERT_VALUES, SCATTER_REVERSE),
176 "loc to vec");
177 CHK_THROW_MESSAGE(DMoFEMLoopFiniteElements(dm, fe_name, pipeline, cache_ptr),
178 "Run assemble pipeline");
179 CHK_THROW_MESSAGE(MatAssemblyBegin(m, MAT_FINAL_ASSEMBLY), "Asmb mat");
180 CHK_THROW_MESSAGE(MatAssemblyEnd(m, MAT_FINAL_ASSEMBLY), "Asmb mat");
181
182 auto get_norm = [](auto m) {
183 double fnorm;
184 MatNorm(m, NORM_1, &fnorm);
185 return fnorm;
186 };
187 MOFEM_LOG_CHANNEL("WORLD");
188 MOFEM_TAG_AND_LOG_C("WORLD", Sev::noisy, "OpTester", "Matrix norm %3.4e",
189 get_norm(m));
190
191 return m;
192}
193
195 SmartPetscObj<DM> dm, std::string fe_name,
196 boost::shared_ptr<FEMethod> pipeline, SmartPetscObj<Vec> x,
197 SmartPetscObj<Vec> delta_x, SmartPetscObj<Vec> delta2_x,
198 SmartPetscObj<Vec> diff_x, double time, double delta_t, double eps,
199 CacheTupleWeakPtr cache_ptr) {
200
201 auto axpy = [&](auto v0, auto diff_v, auto eps) {
203 if (v0.use_count()) {
204 v = vectorDuplicate(v0);
205 CHK_THROW_MESSAGE(VecCopy(v0, v), "Cpy");
206 CHK_THROW_MESSAGE(VecAXPY(v, eps, diff_v), "Add");
207 CHK_THROW_MESSAGE(VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD),
208 "ghost");
209 CHK_THROW_MESSAGE(VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD),
210 "ghost");
211 }
212 return v;
213 };
214
215 auto fm1 = assembleVec(dm, fe_name, pipeline,
216 //
217 axpy(x, diff_x, -eps),
218 //
219 axpy(delta_x, diff_x, -eps),
220 //
221 axpy(delta2_x, diff_x, -eps),
222 //
223 time, delta_t, cache_ptr);
224
225 auto fp1 = assembleVec(dm, fe_name, pipeline,
226 //
227 axpy(x, diff_x, eps),
228 //
229 axpy(delta_x, diff_x, eps),
230 //
231 axpy(delta2_x, diff_x, eps),
232 //
233 time, delta_t, cache_ptr);
234
235 auto calculate_derivative = [eps](auto fm1, auto fp1) {
236 int size;
237 VecGetLocalSize(fp1, &size);
238 VecAXPY(fp1, -1, fm1);
239 double *array;
240 VecGetArray(fp1, &array);
241 for (int j = 0; j != size; ++j) {
242 array[j] /= 2 * eps;
243 }
244 VecRestoreArray(fp1, &array);
245 return fp1;
246 };
247
248 return calculate_derivative(fm1, fp1);
249}
250
252 SmartPetscObj<DM> dm, std::string fe_name,
253 boost::shared_ptr<FEMethod> pipeline_rhs,
254 boost::shared_ptr<FEMethod> pipeline_lhs, SmartPetscObj<Vec> x,
255 SmartPetscObj<Vec> delta_x, SmartPetscObj<Vec> delta2_x,
256 SmartPetscObj<Vec> diff_x, double time, double delta_t, double eps,
257 CacheTupleWeakPtr cache_ptr) {
258
260 dm, fe_name, pipeline_rhs, x, delta_x, delta2_x, diff_x, time, delta_t,
261 eps, cache_ptr);
262
263 auto m = assembleMat(dm, fe_name, pipeline_lhs, x, delta_x, delta2_x, time,
264 delta_t, cache_ptr);
265
266 auto fm = vectorDuplicate(fd_diff);
267 CHK_THROW_MESSAGE(MatMult(m, diff_x, fm), "Mat mult");
268 CHK_THROW_MESSAGE(VecAXPY(fd_diff, -1., fm), "Add");
269
270 return fd_diff;
271}
272
273std::pair<SmartPetscObj<Vec>, SmartPetscObj<Vec>>
274OperatorsTester::setPipelineX(boost::shared_ptr<FEMethod> pipeline,
276 SmartPetscObj<Vec> delta2_x, double delta_t) {
277
278 // Set dofs vector to finite element instance
279 pipeline->x = x;
280 pipeline->data_ctx |= PetscData::CTX_SET_X;
281
282 SmartPetscObj<Vec> x_t, x_tt;
283
284 // Set velocity dofs vector to finite element instance
285
286 if (delta_x.use_count()) {
287 x_t = vectorDuplicate(x);
288 VecCopy(delta_x, x_t);
289 VecScale(x_t, 1. / delta_t);
290 CHK_THROW_MESSAGE(VecGhostUpdateBegin(x_t, INSERT_VALUES, SCATTER_FORWARD),
291 "ghost");
292 CHK_THROW_MESSAGE(VecGhostUpdateEnd(x_t, INSERT_VALUES, SCATTER_FORWARD),
293 "ghost");
294 pipeline->x_t = x_t;
295 pipeline->data_ctx |= PetscData::CTX_SET_X_T;
296 } else {
297 pipeline->x_t = PETSC_NULLPTR;
298 }
299
300 // Set acceleration dofs vector to finite element instance
301
302 if (delta2_x.use_count()) {
303 x_tt = vectorDuplicate(x);
304 VecCopy(delta2_x, x_tt);
305 VecScale(x_tt, 1. / pow(delta_t, 2));
306 CHK_THROW_MESSAGE(VecGhostUpdateBegin(x_tt, INSERT_VALUES, SCATTER_FORWARD),
307 "ghost");
308 CHK_THROW_MESSAGE(VecGhostUpdateEnd(x_tt, INSERT_VALUES, SCATTER_FORWARD),
309 "ghost");
310 pipeline->x_tt = x_tt;
311 pipeline->data_ctx |= PetscData::CTX_SET_X_TT;
312 } else {
313 pipeline->x_tt = PETSC_NULLPTR;
314 }
315
316 return std::make_pair(x_t, x_tt);
317}
318} // namespace MoFEM
#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.
constexpr double a
static const double eps
RowColData
RowColData.
@ COL
@ ROW
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#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
Definition DMMoFEM.cpp:514
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:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1194
#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
Definition Common.hpp:10
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto getProblemPtr(DM dm)
get problem pointer from DM
Definition DMMoFEM.hpp:1182
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
Core (interface) class.
Definition Core.hpp:82
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)
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.
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