15 using namespace MoFEM;
17 static char help[] =
"...\n\n";
36 86, -142, -193, -126, 0, 126, 193, 142, -86};
73 PETSC>::LinearForm<GAUSS>::OpSource<1, 1>;
88 boost::shared_ptr<std::vector<unsigned char>> boundaryMarker;
108 static std::vector<double>
rZ;
109 static std::vector<MatrixInt>
iI;
116 static std::pair<int, int> getCoordsInImage(
double x,
double y);
118 static double rhsSource(
const double x,
const double y,
const double);
119 static double lhsFlux(
const double x,
const double y,
const double);
133 auto &
m = iI[focalIndex];
134 x -= aveMaxMin[MIN_X];
135 y -= aveMaxMin[MIN_Y];
136 x *= (
m.size1() - 1) / (aveMaxMin[MAX_X] - aveMaxMin[MIN_X]);
137 y *= (
m.size2() - 1) / (aveMaxMin[MAX_Y] - aveMaxMin[MIN_Y]);
138 const auto p = std::make_pair<int, int>(std::round(x), std::round(y));
141 if (p.first < 0 && p.first >=
m.size1())
143 if (p.second < 0 && p.second >=
m.size2())
151 const auto idx = getCoordsInImage(x, y);
156 const auto &intensity = iI[
i];
157 v += intensity(idx.first, idx.second) * savitzkyGolayWeights[
w];
159 v =
static_cast<double>(
v) / savitzkyGolayNormalisation;
161 const auto dz = rZ[focalIndex + 1] - rZ[focalIndex - 1];
166 const auto idx = getCoordsInImage(x, y);
167 const auto &
m = iI[focalIndex];
168 return 1. /
m(idx.first, idx.second);
172 BoundaryOp(boost::shared_ptr<MatrixDouble> flux_ptr,
double &glob_flux)
177 const auto nb_gauss_pts = getGaussPts().size2();
178 auto t_flux = getFTensor1FromMat<3>(*fluxPtr);
179 auto t_normal = getFTensor1Normal();
180 auto t_w = getFTensor0IntegrationWeight();
182 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
183 globFlux += t_w * t_normal(
i) * t_flux(
i);
201 char images_array_files[255] =
"out_arrays.txt";
203 images_array_files, 255, PETSC_NULL);
207 auto read_images = [&]() {
209 in.open(images_array_files);
210 std::vector<int> values;
211 values.insert(values.end(), std::istream_iterator<int>(in),
212 std::istream_iterator<int>());
213 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Read data size " << values.size();
218 auto structure_data = [&](
auto &&data) {
219 constexpr
double scale = 1e4;
220 auto it = data.begin();
221 if (it == data.end()) {
226 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Number of images " << *it;
228 for (; it != data.end();) {
229 rZ.emplace_back(*(it++) /
scale);
230 const auto r = *(it++);
231 const auto c = *(it++);
232 iI.emplace_back(
r,
c);
234 <<
"Read data set " << rZ.back() <<
" size " <<
r <<
" by " <<
c;
236 for (
auto rit =
m.begin1(); rit !=
m.end1(); ++rit) {
237 for (
auto cit = rit.begin(); cit != rit.end(); ++cit) {
244 structure_data(read_images());
252 int window_shift = 0;
256 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Wave number " <<
k;
261 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Window shift " << window_shift;
263 if ((rZ.size() - 1) % 2)
265 "Expected even number of images");
267 focalIndex = (rZ.size() - 1) / 2 + window_shift;
268 MOFEM_LOG(
"WORLD", Sev::inform) <<
"zR for mid plane " << rZ[focalIndex];
273 "Wrong Savitzky Golay order");
276 if (!d1_sg_data_window)
278 "Wrong Savitzky Golay window");
280 savitzkyGolayNormalisation =
282 savitzkyGolayWeights = d1_sg_data_window;
284 CHKERR assembleSystemIntensity();
296 auto get_bounding_box = [&]() {
297 auto &moab = mField.get_moab();
299 MOAB_THROW(moab.get_entities_by_type(0, MBVERTEX, verts));
301 ParallelComm *pcomm =
305 CHKERR pcomm->filter_pstatus(verts, PSTATUS_SHARED | PSTATUS_MULTISHARED,
306 PSTATUS_NOT, -1, &verts_part);
309 CHKERR moab.get_coords(verts_part, &*coords.data().begin());
311 std::array<double, 2> ave_coords{0, 0};
312 for (
auto v = 0;
v != verts_part.size(); ++
v) {
313 ave_coords[0] += coords(
v, 0);
314 ave_coords[1] += coords(
v, 1);
317 auto comm = mField.get_comm();
319 int local_count = verts_part.size();
321 MPI_Allreduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, comm);
322 std::array<double, 2> ave_coords_glob{0, 0};
323 MPI_Allreduce(ave_coords.data(), ave_coords.data(), 2, MPI_DOUBLE, MPI_SUM,
325 ave_coords_glob[0] /= global_count;
326 ave_coords_glob[1] /= global_count;
328 std::array<double, 2> max_coords{ave_coords_glob[0], ave_coords_glob[1]};
329 for (
auto v = 0;
v != verts_part.size(); ++
v) {
330 max_coords[0] = std::max(max_coords[0], coords(
v, 0));
331 max_coords[1] = std::max(max_coords[1], coords(
v, 1));
333 std::array<double, 2> max_coords_glob{0, 0};
334 MPI_Allreduce(max_coords.data(), max_coords_glob.data(), 2, MPI_DOUBLE,
337 std::array<double, 2> min_coords{max_coords_glob[0], max_coords_glob[1]};
338 for (
auto v = 0;
v != verts_part.size(); ++
v) {
339 min_coords[0] = std::min(min_coords[0], coords(
v, 0));
340 min_coords[1] = std::min(min_coords[1], coords(
v, 1));
342 std::array<double, 2> min_coords_glob{0, 0};
343 MPI_Allreduce(min_coords.data(), min_coords_glob.data(), 2, MPI_DOUBLE,
346 return std::array<double, LAST_BB>{ave_coords_glob[0], ave_coords_glob[1],
347 max_coords_glob[0], max_coords_glob[1],
348 min_coords_glob[0], min_coords_glob[1]};
351 CHKERR mField.getInterface(simpleInterface);
352 CHKERR simpleInterface->getOptions();
353 CHKERR simpleInterface->loadFile();
355 aveMaxMin = get_bounding_box();
358 <<
"Centre " << aveMaxMin[CENTER_X] <<
" " << aveMaxMin[CENTER_Y];
360 <<
"Max " << aveMaxMin[MAX_X] <<
" " << aveMaxMin[MAX_Y];
362 <<
"Min " << aveMaxMin[MIN_X] <<
" " << aveMaxMin[MIN_Y];
388 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Base order " << base_order;
390 CHKERR simpleInterface->setFieldOrder(
"S", base_order);
391 CHKERR simpleInterface->setFieldOrder(
"PHI", base_order - 1);
392 CHKERR simpleInterface->setUp();
395 CHKERR simpleInterface->addFieldToEmptyFieldBlocks(
"PHI",
"PHI");
407 pipeline_mng->getDomainRhsFE().reset();
408 pipeline_mng->getBoundaryRhsFE().reset();
411 pipeline_mng->setBoundaryRhsIntegrationRule(rule_vol);
413 auto flux_ptr = boost::make_shared<MatrixDouble>();
414 pipeline_mng->getOpBoundaryRhsPipeline().push_back(
416 pipeline_mng->getOpBoundaryRhsPipeline().push_back(
418 pipeline_mng->getOpBoundaryRhsPipeline().push_back(
422 CHKERR pipeline_mng->loopFiniteElements();
423 double global_flux_assembeld = 0;
424 MPI_Allreduce(&calc_flux, &global_flux_assembeld, 1, MPI_DOUBLE, MPI_SUM,
426 calc_flux = global_flux_assembeld;
439 pipeline_mng->getDomainRhsFE().reset();
440 pipeline_mng->getBoundaryRhsFE().reset();
443 pipeline_mng->setDomainLhsIntegrationRule(rule_vol);
444 pipeline_mng->setDomainRhsIntegrationRule(rule_vol);
446 auto det_ptr = boost::make_shared<VectorDouble>();
447 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
448 auto jac_ptr = boost::make_shared<MatrixDouble>();
450 pipeline_mng->getOpDomainLhsPipeline().push_back(
452 pipeline_mng->getOpDomainLhsPipeline().push_back(
455 pipeline_mng->getOpDomainLhsPipeline().push_back(
457 pipeline_mng->getOpDomainLhsPipeline().push_back(
461 pipeline_mng->getOpDomainLhsPipeline().push_back(
463 auto unity = []() {
return 1; };
464 pipeline_mng->getOpDomainLhsPipeline().push_back(
465 new OpHdivU(
"S",
"PHI", unity,
true));
468 pipeline_mng->getOpDomainRhsPipeline().push_back(
479 auto dm = simpleInterface->getDM();
483 CHKERR KSPSetFromOptions(solver);
488 CHKERR KSPSolve(solver,
F, iD);
489 CHKERR VecGhostUpdateBegin(iD, INSERT_VALUES, SCATTER_FORWARD);
490 CHKERR VecGhostUpdateEnd(iD, INSERT_VALUES, SCATTER_FORWARD);
493 double i_lambda_flux;
494 CHKERR calculateFlux(i_lambda_flux);
497 <<
"iD flux " << std::scientific << i_lambda_flux;
513 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
514 auto jac_ptr = boost::make_shared<MatrixDouble>();
515 post_proc_fe->getOpPtrVector().push_back(
518 post_proc_fe->getOpPtrVector().push_back(
521 auto s_ptr = boost::make_shared<VectorDouble>();
522 auto phi_ptr = boost::make_shared<MatrixDouble>();
523 post_proc_fe->getOpPtrVector().push_back(
525 post_proc_fe->getOpPtrVector().push_back(
530 post_proc_fe->getOpPtrVector().push_back(
532 new OpPPMap(post_proc_fe->getPostProcMesh(),
533 post_proc_fe->getMapGaussPts(),
553 CHKERR post_proc_fe->writeFile(
"out_" + boost::lexical_cast<std::string>(
i) +
559 int main(
int argc,
char *argv[]) {
562 const char param_file[] =
"param_file.petsc";
568 DMType dm_name =
"DMMOFEM";