11#define ArcFunctionBegin \
13 MOFEM_LOG_CHANNEL("ARC_LENGTH"); \
14 MOFEM_LOG_FUNCTION(); \
15 MOFEM_LOG_TAG("ARC_LENGTH", "ArcLength");
23 MOFEM_LOG_C(
"ARC_LENGTH", Sev::inform,
"\tSet s = %6.4e", this->s);
32 "\tSet alpha = %6.4e beta = %6.4e",
33 this->alpha, this->beta);
38 const std::string &problem_name,
40 : mField(m_field), dx2(0), F_lambda2(0), res_lambda(0) {
42 auto create_f_lambda = [&]() {
46 CHKERR VecSetOption(
F_lambda, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
50 auto vec_duplicate = [&]() {
59 auto zero_vectors = [&]() {
69 auto find_lambda_dof = [&]() {
74 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_ptr_no_const =
77 auto dIt = dofs_ptr_no_const->get<
Unique_mi_tag>().lower_bound(
79 auto hi_dit = dofs_ptr_no_const->get<
Unique_mi_tag>().upper_bound(
81 if (std::distance(dIt, hi_dit) != 1)
83 (
"can not find unique LAMBDA (load factor) but found " +
84 boost::lexical_cast<std::string>(std::distance(dIt, hi_dit)))
90 auto create_ghost_vecs = [&]() {
92 Vec ghost_d_lambda, ghost_diag;
113 CHKERRABORT(PETSC_COMM_SELF, create_f_lambda());
114 CHKERRABORT(PETSC_COMM_SELF, vec_duplicate());
115 CHKERRABORT(PETSC_COMM_SELF, zero_vectors());
116 CHKERRABORT(PETSC_COMM_SELF, find_lambda_dof());
117 CHKERRABORT(PETSC_COMM_SELF, create_ghost_vecs());
125 : Aij(aij, true), problemName(problem_name), arcPtrRaw(arc_ptr_raw) {}
128 boost::shared_ptr<ArcLengthCtx> arc_ptr,
130 : Aij(aij, true), problemName(problem_name), arcPtrRaw(arc_ptr.get()),
134 ScatterMode scattermode) {
140 switch (scattermode) {
141 case SCATTER_FORWARD: {
145 PETSC_NULLPTR,
lambda, &lambda_ghost);
155 CHKERR VecGhostUpdateBegin(lambda_ghost, INSERT_VALUES, SCATTER_FORWARD);
156 CHKERR VecGhostUpdateEnd(lambda_ghost, INSERT_VALUES, SCATTER_FORWARD);
157 CHKERR VecDestroy(&lambda_ghost);
159 case SCATTER_REVERSE: {
162 CHKERR VecGetArray(ksp_x, &array);
164 CHKERR VecRestoreArray(ksp_x, &array);
177 CHKERR MatShellGetContext(
A, &void_ctx);
194 : shellAij(shell_Aij, true), Aij(aij, true), arcPtrRaw(arc_ptr) {
195 auto comm = PetscObjectComm((PetscObject)aij);
198 CHKERRABORT(PETSC_COMM_WORLD, KSPAppendOptionsPrefix(
kSP,
"arc_length_"));
203 : pC(pc, true), shellAij(shell_Aij, true), Aij(aij, true),
205 auto comm = PetscObjectComm((PetscObject)aij);
207 CHKERRABORT(PETSC_COMM_WORLD, KSPAppendOptionsPrefix(
kSP,
"arc_length_"));
211 boost::shared_ptr<ArcLengthCtx> arc_ptr)
212 : shellAij(shell_Aij, true), Aij(aij, true), arcPtrRaw(arc_ptr.get()),
214 auto comm = PetscObjectComm((PetscObject)aij);
217 CHKERRABORT(PETSC_COMM_WORLD, KSPAppendOptionsPrefix(
kSP,
"arc_length_"));
221 boost::shared_ptr<ArcLengthCtx> arc_ptr)
222 : pC(pc, true), shellAij(shell_Aij, true), Aij(aij, true),
223 arcPtrRaw(arc_ptr.get()), arcPtr(arc_ptr) {
224 auto comm = PetscObjectComm((PetscObject)aij);
226 CHKERRABORT(PETSC_COMM_WORLD, KSPAppendOptionsPrefix(
kSP,
"arc_length_"));
232 CHKERR PCShellGetContext(pc, &void_ctx);
238 CHKERR PetscObjectTypeCompare((PetscObject)ctx->
kSP, KSPPREONLY, &same);
244 CHKERR KSPSetInitialGuessNonzero(ctx->
kSP, PETSC_FALSE);
245 CHKERR KSPSetInitialGuessKnoll(ctx->
kSP, PETSC_FALSE);
251 if (same != PETSC_TRUE) {
252 CHKERR KSPSetInitialGuessNonzero(ctx->
kSP, PETSC_TRUE);
254 CHKERR KSPSetInitialGuessNonzero(ctx->
kSP, PETSC_FALSE);
257 double db_dot_x_lambda;
262 double ddlambda = -(res_lambda - db_dot_pc_x) / denominator;
268 if (ddlambda != ddlambda || denominator == 0) {
270 double nrm2_pc_f, nrm2_db, nrm2_pc_x, nrm2_xLambda;
271 CHKERR VecNorm(pc_f, NORM_2, &nrm2_pc_f);
273 CHKERR VecNorm(pc_x, NORM_2, &nrm2_pc_x);
277 <<
"problem with ddlambda=" << ddlambda;
278 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"res_lambda=" << res_lambda;
279 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"denominator=" << denominator;
280 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"db_dot_pc_x=" << db_dot_pc_x;
282 <<
"db_dot_x_lambda=" << db_dot_x_lambda;
285 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"nrm2_db=" << nrm2_db;
286 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"nrm2_pc_f=" << nrm2_pc_f;
287 MOFEM_LOG(
"ARC_LENGTH", Sev::error) <<
"nrm2_pc_x=" << nrm2_pc_x;
289 <<
"nrm2_xLambda=" << nrm2_xLambda;
292 "Increment of lambda is not number");
298 CHKERR VecDuplicate(pc_x, &y);
300 CHKERR VecAXPY(y, -1, pc_f);
306 CHKERR VecNorm(y, NORM_2, &norm_y);
308 "Debug res y = %3.4e res_lambda_y = %3.4e", norm_y,
319 CHKERR PCShellGetContext(pc, &void_ctx);
321 auto get_pc_ops = [&](
auto pc) {
323 Mat shell_aij_raw, aij_raw;
324 CHKERR PCGetOperators(pc, &shell_aij_raw, &aij_raw);
330 CHKERR PCSetUseAmat(pc, PETSC_TRUE);
334#if PETSC_VERSION_LT(3, 12, 0)
337 CHKERR PetscObjectSetTabLevel((PetscObject)ctx->
kSP, 3);
355 case CTX_SNESSETFUNCTION: {
357 auto zero_vals = [&](
auto v) {
359 int size = problemPtr->getNbLocalDofsRow();
360 int ghosts = problemPtr->getNbGhostDofsRow();
363 for (
int i = 0;
i != size + ghosts; ++
i)
365 CHKERR VecRestoreArray(
v, &array);
369 Vec l_x_lambda, l_f_lambda;
370 CHKERR VecGhostGetLocalForm(
arcPtr->xLambda, &l_x_lambda);
371 CHKERR VecGhostGetLocalForm(
arcPtr->F_lambda, &l_f_lambda);
372 CHKERR zero_vals(l_x_lambda);
373 CHKERR zero_vals(l_f_lambda);
374 CHKERR VecGhostRestoreLocalForm(
arcPtr->xLambda, &l_x_lambda);
375 CHKERR VecGhostRestoreLocalForm(
arcPtr->F_lambda, &l_f_lambda);
380 "Lambda can be zeroed ONLY when the right hand side is evaluated.");
385#ifdef __DIRICHLET_HPP__
387AssembleFlambda::AssembleFlambda(boost::shared_ptr<ArcLengthCtx> arc_ptr,
388 boost::shared_ptr<DirichletDisplacementBc> bc)
405 case CTX_SNESSETFUNCTION: {
407 CHKERR VecAssemblyBegin(arcPtr->F_lambda);
408 CHKERR VecAssemblyEnd(arcPtr->F_lambda);
409 CHKERR VecAssemblyBegin(snes_f);
410 CHKERR VecAssemblyEnd(snes_f);
411 CHKERR VecGhostUpdateBegin(arcPtr->F_lambda, ADD_VALUES, SCATTER_REVERSE);
412 CHKERR VecGhostUpdateEnd(arcPtr->F_lambda, ADD_VALUES, SCATTER_REVERSE);
413 CHKERR VecGhostUpdateBegin(snes_f, ADD_VALUES, SCATTER_REVERSE);
414 CHKERR VecGhostUpdateEnd(snes_f, ADD_VALUES, SCATTER_REVERSE);
416 auto set_bc = [&](
auto l_snes_f,
auto l_f_lambda) {
419 double *f_array, *f_lambda_array;
420 CHKERR VecGetArray(l_snes_f, &f_array);
421 CHKERR VecGetArray(l_f_lambda, &f_lambda_array);
422 for (
auto &bc : bCs) {
423 for (
auto idx : bc->dofsIndices) {
424 auto weak_dof = problemPtr->getRowDofsByPetscGlobalDofIdx(idx);
425 if (
auto shared_dof = weak_dof.lock()) {
426 f_array[shared_dof->getPetscLocalDofIdx()] = 0;
427 f_lambda_array[shared_dof->getPetscLocalDofIdx()] = 0;
431 CHKERR VecRestoreArray(l_snes_f, &f_array);
432 CHKERR VecRestoreArray(l_f_lambda, &f_lambda_array);
437 auto add_f_lambda = [&](
auto l_snes_f,
auto l_f_lambda) {
439 int size = problemPtr->getNbLocalDofsRow();
440 int ghosts = problemPtr->getNbGhostDofsRow();
441 double lambda = arcPtr->getFieldData();
442 int local_lambda_idx = arcPtr->getPetscLocalDofIdx();
443 double *f_array, *f_lambda_array;
444 CHKERR VecGetArray(l_snes_f, &f_array);
445 CHKERR VecGetArray(l_f_lambda, &f_lambda_array);
446 for (
int i = 0;
i != size; ++
i) {
447 f_array[
i] +=
lambda * f_lambda_array[
i];
449 CHKERR VecRestoreArray(l_snes_f, &f_array);
450 CHKERR VecRestoreArray(l_f_lambda, &f_lambda_array);
454 auto zero_ghost = [&](
auto l_snes_f,
auto l_f_lambda) {
456 int size = problemPtr->getNbLocalDofsRow();
457 int ghosts = problemPtr->getNbGhostDofsRow();
458 double lambda = arcPtr->getFieldData();
459 int local_lambda_idx = arcPtr->getPetscLocalDofIdx();
460 double *f_array, *f_lambda_array;
461 CHKERR VecGetArray(l_snes_f, &f_array);
462 CHKERR VecGetArray(l_f_lambda, &f_lambda_array);
463 f_lambda_array[local_lambda_idx] = 0;
464 for (
int i = size;
i != size + ghosts; ++
i) {
466 f_lambda_array[
i] = 0;
468 CHKERR VecRestoreArray(l_snes_f, &f_array);
469 CHKERR VecRestoreArray(l_f_lambda, &f_lambda_array);
473 Vec l_snes_f, l_f_lambda;
474 CHKERR VecGhostGetLocalForm(snes_f, &l_snes_f);
475 CHKERR VecGhostGetLocalForm(arcPtr->F_lambda, &l_f_lambda);
476 CHKERR add_f_lambda(l_snes_f, l_f_lambda);
477 CHKERR set_bc(l_snes_f, l_f_lambda);
478 CHKERR zero_ghost(l_snes_f, l_f_lambda);
480 CHKERR VecGhostRestoreLocalForm(snes_f, &l_snes_f);
481 CHKERR VecGhostRestoreLocalForm(arcPtr->F_lambda, &l_f_lambda);
483 double snes_fnorm, snes_xnorm;
484 CHKERR VecNorm(snes_f, NORM_2, &snes_fnorm);
485 CHKERR VecNorm(snes_x, NORM_2, &snes_xnorm);
486 CHKERR VecDot(arcPtr->F_lambda, arcPtr->F_lambda, &arcPtr->F_lambda2);
489 "\tF_lambda2 = %6.4g lambda = %6.4g", arcPtr->F_lambda2,
490 arcPtr->getFieldData());
492 "\tsnes_f norm = %6.4e snes_x norm = %6.4g", snes_fnorm,
495 if (!boost::math::isfinite(snes_fnorm)) {
496 CHKERR arcPtr->mField.getInterface<
Tools>()->checkVectorForNotANumber(
497 problemPtr,
ROW, snes_f);
504 "Lambda can be assembled only when the right hand side is evaluated.");
517 boost::shared_ptr<ArcLengthCtx> &arc_ptr,
const bool assemble)
518 :
FEMethod(), arcPtr(arc_ptr), aSsemble(assemble) {}
525 case CTX_SNESSETFUNCTION: {
527 CHKERR VecAssemblyBegin(snes_f);
528 CHKERR VecAssemblyEnd(snes_f);
533 case CTX_SNESSETJACOBIAN: {
535 CHKERR MatAssemblyBegin(snes_B, MAT_FLUSH_ASSEMBLY);
536 CHKERR MatAssemblyEnd(snes_B, MAT_FLUSH_ASSEMBLY);
548 case CTX_SNESSETFUNCTION: {
550 CHKERR VecSetValue(snes_f,
arcPtr->getPetscGlobalDofIdx(),
551 arcPtr->res_lambda, ADD_VALUES);
553 case CTX_SNESSETJACOBIAN: {
555 CHKERR MatSetValue(snes_B,
arcPtr->getPetscGlobalDofIdx(),
556 arcPtr->getPetscGlobalDofIdx(), 1, ADD_VALUES);
567 case CTX_SNESSETFUNCTION: {
569 CHKERR VecAssemblyBegin(snes_f);
570 CHKERR VecAssemblyEnd(snes_f);
573 case CTX_SNESSETJACOBIAN: {
575 CHKERR MatAssemblyBegin(snes_B, MAT_FLUSH_ASSEMBLY);
576 CHKERR MatAssemblyEnd(snes_B, MAT_FLUSH_ASSEMBLY);
578 CHKERR VecGhostUpdateBegin(
arcPtr->ghostDiag, INSERT_VALUES,
580 CHKERR VecGhostUpdateEnd(
arcPtr->ghostDiag, INSERT_VALUES, SCATTER_FORWARD);
595 CHKERR VecGhostUpdateBegin(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
596 CHKERR VecGhostUpdateEnd(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
603 CHKERR VecGhostUpdateBegin(
arcPtr->x0, INSERT_VALUES, SCATTER_FORWARD);
604 CHKERR VecGhostUpdateEnd(
arcPtr->x0, INSERT_VALUES, SCATTER_FORWARD);
607 CHKERR VecGhostGetLocalForm(x, &l_x);
611 double *x_array, *x0_array, *dx_array;
612 CHKERR VecGetArray(l_x, &x_array);
613 CHKERR VecGetArray(l_x0, &x0_array);
614 CHKERR VecGetArray(l_dx, &dx_array);
616 problemPtr->getNbLocalDofsRow() + problemPtr->getNbGhostDofsRow();
617 for (
int i = 0;
i != size; ++
i) {
618 dx_array[
i] = x_array[
i] - x0_array[
i];
620 CHKERR VecRestoreArray(l_x, &x_array);
621 CHKERR VecRestoreArray(l_x0, &x0_array);
622 CHKERR VecRestoreArray(l_dx, &dx_array);
624 CHKERR VecGhostRestoreLocalForm(x, &l_x);
629 if (
arcPtr->getPetscLocalDofIdx() != -1) {
633 array[
arcPtr->getPetscLocalDofIdx()] = 0;
636 CHKERR VecGhostUpdateBegin(
arcPtr->ghosTdLambda, INSERT_VALUES,
638 CHKERR VecGhostUpdateEnd(
arcPtr->ghosTdLambda, INSERT_VALUES,
642 double x_nrm, x0_nrm;
643 CHKERR VecNorm(x, NORM_2, &x_nrm);
648 "\tx norm = %6.4e x0 norm = %6.4e dx2 = %6.4e", x_nrm, x0_nrm,
657 :
FEMethod(), arcPtrRaw(arc_ptr_raw) {}
660 boost::shared_ptr<ArcLengthCtx> &arc_ptr)
661 :
FEMethod(), arcPtrRaw(arc_ptr.get()), arcPtr(arc_ptr) {}
668 case CTX_SNESSETFUNCTION: {
672 case CTX_SNESSETJACOBIAN: {
696 case CTX_SNESSETFUNCTION: {
700 MOFEM_LOG_C(
"ARC_LENGTH", Sev::verbose,
"\tres_lambda = %6.4e",
703 case CTX_SNESSETJACOBIAN: {
718 case CTX_SNESSETFUNCTION: {
719 MOFEM_LOG_C(
"ARC_LENGTH", Sev::verbose,
"\tlambda = %6.4e",
722 case CTX_SNESSETJACOBIAN: {
727 CHKERR MatAssemblyBegin(snes_B, MAT_FLUSH_ASSEMBLY);
728 CHKERR MatAssemblyEnd(snes_B, MAT_FLUSH_ASSEMBLY);
729 MOFEM_LOG_C(
"ARC_LENGTH", Sev::verbose,
"\tdiag = %6.4e",
770 if (!(*dlambda == *dlambda)) {
775 "Increment of lambda is not a number");
786 CHKERR VecGetArray(x, &array);
788 if (!(dlambda == dlambda)) {
793 "Increment of lambda is not a number");
797 "\tlambda = %6.4e, %6.4e (%6.4e)", lambda_old,
799 CHKERR VecRestoreArray(x, &array);
#define MOFEM_LOG_C(channel, severity, format,...)
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
auto createKSP(MPI_Comm comm)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createPC(MPI_Comm comm)
constexpr auto field_name
Store variables for ArcLength analysis.
double s
arc length radius
SmartPetscObj< Vec > xLambda
solution of eq. K*xLambda = F_lambda
double res_lambda
f_lambda - s
DofIdx getPetscLocalDofIdx()
Get local index of load factor.
NumeredDofEntity * arcDofRawPtr
MoFEMErrorCode setAlphaBeta(double alpha, double beta)
set parameters controlling arc-length equations alpha controls off diagonal therms beta controls diag...
ArcLengthCtx(MoFEM::Interface &m_field, const std::string &problem_name, const std::string &field_name="LAMBDA")
double alpha
displacement scaling factor
MoFEMErrorCode setS(double s)
set arc radius
double F_lambda2
inner_prod(F_lambda,F_lambda);
SmartPetscObj< Vec > dx
dx = x-x0
double dIag
diagonal value
double dx2
inner_prod(dX,dX)
FieldData & getFieldData()
Get value of load factor.
MoFEM::Interface & mField
SmartPetscObj< Vec > F_lambda
F_lambda reference load vector.
SmartPetscObj< Vec > ghostDiag
SmartPetscObj< Vec > ghosTdLambda
double dLambda
increment of load factor
double beta
force scaling factor
int getPart()
Get proc owning lambda dof.
SmartPetscObj< Vec > db
db derivative of f(dx*dx), i.e. db = d[ f(dx*dx) ]/dx
DofIdx getPetscGlobalDofIdx()
Get global index of load factor.
SmartPetscObj< Vec > x0
displacement vector at beginning of step
shell matrix for arc-length method
ArcLengthMatShell(Mat aij, boost::shared_ptr< ArcLengthCtx > arc_ptr, string problem_name)
MoFEMErrorCode setLambda(Vec ksp_x, double *lambda, ScatterMode scattermode)
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Structure for user loop methods on finite elements.
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
unsigned int getPart() const
keeps basic data about problem
auto & getNumeredRowDofsPtr() const
get access to numeredRowDofsPtr storing DOFs on rows
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
structure for Arc Length pre-conditioner
SmartPetscObj< Mat > shellAij
PCArcLengthCtx(Mat shell_Aij, Mat aij, boost::shared_ptr< ArcLengthCtx > arc_ptr)
MoFEMErrorCode preProcess()
MoFEMErrorCode calculateDb()
Calculate db.
MoFEMErrorCode operator()()
SimpleArcLengthControl(boost::shared_ptr< ArcLengthCtx > &arc_ptr, const bool assemble=false)
double calculateLambdaInt()
Calculate internal lambda.
MoFEMErrorCode calculateDxAndDlambda(Vec x)
MoFEMErrorCode postProcess()
boost::shared_ptr< ArcLengthCtx > arcPtr
~SimpleArcLengthControl()
MoFEMErrorCode postProcess()
virtual MoFEMErrorCode calculateDxAndDlambda(Vec x)
MoFEMErrorCode preProcess()
MoFEMErrorCode operator()()
virtual ~SphericalArcLengthControl()
virtual MoFEMErrorCode calculateDb()
Calculate db.
DEPRECATED SphericalArcLengthControl(ArcLengthCtx *arc_ptr_raw)
virtual double calculateLambdaInt()
Calculate f_lambda(dx,lambda)
virtual MoFEMErrorCode calculateInitDlambda(double *dlambda)
virtual MoFEMErrorCode setDlambdaToX(Vec x, double dlambda)
ZeroFLmabda(boost::shared_ptr< ArcLengthCtx > arc_ptr)
MoFEMErrorCode preProcess()
boost::shared_ptr< ArcLengthCtx > arcPtr