v0.16.3
Loading...
Searching...
No Matches
schrod_eig.cpp
Go to the documentation of this file.
1/**
2 * \file schrod_eig.cpp
3 * \example schrod _eig.cpp
4 *
5 * Calculate wave functions of Schrödinger equation in 2d problems.
6 *
7 */
8#ifndef EXECUTABLE_DIMENSION
9 #define EXECUTABLE_DIMENSION 2
10#endif
11
12#include <MoFEM.hpp>
13#include <schrod_eig.hpp>
14#undef EPS
15#include <slepceps.h>
16
17using namespace MoFEM;
18using namespace schrod_eig;
19
20template <int DIM> struct ElementsAndOps {};
21
22template <> struct ElementsAndOps<2> {
24};
25
26template <> struct ElementsAndOps<3> {
28};
29
30constexpr int SPACE_DIM =
31 EXECUTABLE_DIMENSION; // Space dimension of problem, mesh
32
34using DomainEleOp = DomainEle::UserDataOperator;
36
41
42//! [Physical constants and parameters]
43double hbar = 1.054571817e-34; // Reduced Planck Constant [J*s]
44double m0 = 9.1093837015e-31; // Free electron mass [kg]
45double scale = 1e-9; // Length scaling factor: nanometer → meter [m]
46double effMass = 1; // Effective mass in units of m0 [a.u.]
47double q = 1.602176634e-19; // Elementary charge [C]
48double potential = 0 * q; // Potential energy inside the potential well [J]
49//! [Physical constants and parameters]
50
51int order = 2;
52
53static char help[] = "...\n\n";
54
55struct Example {
56
57 Example(MoFEM::Interface &m_field) : mField(m_field) {}
58
60
61private:
64
72
73 SmartPetscObj<Mat> M; // Mass matrix
74 SmartPetscObj<Mat> H; // Hamiltonian matrix
76};
77
78//! [Run problem]
89}
90//! [Run problem]
91
92//! [Read mesh]
96
97 MOFEM_LOG("EXAMPLE", Sev::inform)
98 << "Read mesh for problem in " << EXECUTABLE_DIMENSION;
102}
103//! [Read mesh]
104
105//! [Set up problem]
108 // Add field
110 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
114}
115//! [Set up problem]
116
117//! [Applying essential BC]
120
121 auto bc_mng = mField.getInterface<BcManager>();
122
124 simple->getProblemName(), "BOUNDARY", std::string("PHI"),
125 true); // Dirichlet BC. (PHI=0 on the boundaries).
126
128}
129//! [Applying essential BC]
130
131//! [Push operators to pipeline]
134 auto *pipeline_mng = mField.getInterface<PipelineManager>();
135
136 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-effMass", &effMass,
137 PETSC_NULLPTR);
138
139 auto get_kinetic_coe = [&](const double, const double, const double) {
140 return hbar * hbar /
141 (2.0 * effMass * m0 *
142 (scale * scale)); // Coefficient for kinetic energy term
143 };
144 auto get_potential = [](const double, const double, const double) {
145 return potential;
146 };
147 auto get_mass_coe = [](const double, const double, const double) {
148 return 1.0;
149 };
150
151 auto dm = simple->getDM();
153 M = matDuplicate(H, MAT_SHARE_NONZERO_PATTERN);
154
155 auto calculate_Hamiltonian = [&]() {
157 pipeline_mng->getDomainLhsFE().reset();
158
160 pipeline_mng->getOpDomainLhsPipeline(), {H1});
161 pipeline_mng->getOpDomainLhsPipeline().push_back(
162 new OpDomainGradGrad("PHI", "PHI", get_kinetic_coe));
163 pipeline_mng->getOpDomainLhsPipeline().push_back(
164 new OpDomainMass("PHI", "PHI", get_potential));
165 auto integration_rule = [](int, int, int approx_order) {
166 return 2 * (approx_order - 1);
167 };
168
169 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
170 pipeline_mng->getDomainLhsFE()->B = H;
171 CHKERR MatZeroEntries(H);
172 CHKERR pipeline_mng->loopFiniteElements();
173 CHKERR MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY);
174 CHKERR MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY);
176 };
177
178 auto calculate_mass_matrix = [&]() {
180 pipeline_mng->getDomainLhsFE().reset();
181
183 pipeline_mng->getOpDomainLhsPipeline(), {H1});
184 pipeline_mng->getOpDomainLhsPipeline().push_back(
185 new OpDomainMass("PHI", "PHI", get_mass_coe));
186
187 auto integration_rule = [](int, int, int approx_order) {
188 return 2 * approx_order;
189 };
190 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
191 CHKERR MatZeroEntries(M);
192 pipeline_mng->getDomainLhsFE()->B = M;
193 CHKERR pipeline_mng->loopFiniteElements();
194 CHKERR MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
195 CHKERR MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
197 };
198
199 CHKERR calculate_Hamiltonian();
200 CHKERR calculate_mass_matrix();
201
203}
204//! [Push operators to pipeline]
205
206//! [Solve]
209
210 auto create_eps = [](MPI_Comm comm) {
211 EPS eps;
212 CHKERR EPSCreate(comm, &eps);
213 return SmartPetscObj<EPS>(eps);
214 };
215
216 auto setup_eps = [&]() {
218 CHKERR EPSSetProblemType(eps, EPS_GHEP);
219 CHKERR EPSSetWhichEigenpairs(eps, EPS_SMALLEST_MAGNITUDE);
220 CHKERR EPSSetFromOptions(eps);
221 PetscInt nev = 20;
222 EPSSetDimensions(eps, nev, PETSC_DEFAULT, PETSC_DEFAULT);
224 };
225
226 auto print_info = [&]() {
228 ST st;
229 EPSType type;
230 PetscReal tol;
231 PetscInt nev, maxit, its;
232 // Optional: Get some information from the solver and display it
233 CHKERR EPSGetIterationNumber(eps, &its);
234 MOFEM_LOG_C("EXAMPLE", Sev::inform,
235 " Number of iterations of the method: %d", its);
236 CHKERR EPSGetST(eps, &st);
237 CHKERR EPSGetType(eps, &type);
238 MOFEM_LOG_C("EXAMPLE", Sev::inform, " Solution method: %s", type);
239 CHKERR EPSGetDimensions(eps, &nev, NULL, NULL);
240 MOFEM_LOG_C("EXAMPLE", Sev::inform, " Number of requested eigenvalues: %d",
241 nev);
242 CHKERR EPSGetTolerances(eps, &tol, &maxit);
243 MOFEM_LOG_C("EXAMPLE", Sev::inform,
244 " Stopping condition: tol=%.4g, maxit=%d", (double)tol, maxit);
245
247 };
248
249 // Create eigensolver context
250 eps = create_eps(mField.get_comm());
251 CHKERR EPSSetOperators(eps, H, M);
252
253 // Setup EPS
254 CHKERR setup_eps();
255
256 // Solve problem
257 CHKERR EPSSolve(eps);
258
259 // Print info
260 CHKERR print_info();
261
263}
264//! [Solve]
265
266//! [Postprocess results]
269 auto *pipeline_mng = mField.getInterface<PipelineManager>();
270
271 pipeline_mng->getDomainLhsFE().reset();
272 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
273
274 auto phi_ptr = boost::make_shared<VectorDouble>();
275 auto square_ptr = boost::make_shared<VectorDouble>();
276
277 post_proc_fe->getOpPtrVector().push_back(
278 new OpCalculateScalarFieldValues("PHI", phi_ptr));
279 post_proc_fe->getOpPtrVector().push_back(new OpSquare(
280 square_ptr,
281 phi_ptr)); // Calculate square of wave function for checking probability density.
282
284
285 post_proc_fe->getOpPtrVector().push_back(
286
287 new OpPPMap(post_proc_fe->getPostProcMesh(),
288 post_proc_fe->getMapGaussPts(),
289
290 OpPPMap::DataMapVec{{"PHI", phi_ptr}, {"SQUARE", square_ptr}},
291
293
295
297
298 );
299
300 pipeline_mng->getDomainRhsFE() = post_proc_fe;
301
302 auto dm = simple->getDM();
303 auto D = createDMVector(dm);
304
305 PetscInt nev, nconv, n_output = 0;
306 CHKERR EPSGetDimensions(eps, &nev, PETSC_NULLPTR, PETSC_NULLPTR);
307 CHKERR EPSGetConverged(eps, &nconv);
308 n_output = std::min(nconv, nev);
309 if (nconv < nev) {
310 MOFEM_LOG_C("EXAMPLE", Sev::warning,
311 " Only %" PetscInt_FMT " of %" PetscInt_FMT
312 " requested eigenpairs converged",
313 nconv, nev);
314 }
315 PetscScalar eigr, eigi;
316 for (PetscInt nn = 0; nn < n_output; nn++) {
317 CHKERR EPSGetEigenpair(eps, nn, &eigr, &eigi, D, PETSC_NULLPTR);
318 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
319 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
320 MOFEM_LOG_C("EXAMPLE", Sev::inform,
321 " Eigenpair = %" PetscInt_FMT " Eigen Energy = %.8g eV", nn,
322 eigr / q); // Convert the unit Joule to eV for output.
323 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
324 CHKERR pipeline_mng->loopFiniteElements();
325 post_proc_fe->writeFile("out_schrod_" +
326 boost::lexical_cast<std::string>(nn) + ".h5m");
327 }
328
330}
331//! [Postprocess results]
332
333//! [Check]
336 PetscBool test_flg = PETSC_FALSE;
337 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test", &test_flg,
338 PETSC_NULLPTR);
339 if (test_flg) {
340 PetscInt nconv;
341 CHKERR EPSGetConverged(eps, &nconv);
342 if (nconv < 1) {
343 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
344 "No eigenpairs converged");
345 }
346 PetscScalar eigr, eigi;
347 CHKERR EPSGetEigenpair(eps, 0, &eigr, &eigi, PETSC_NULLPTR, PETSC_NULLPTR);
348 constexpr double regression_value =
349 0.188; // Check the result for ground energy level [eV]
350 if (fabs(eigr / q - regression_value) > 1e-3) {
351 PetscPrintf(PETSC_COMM_WORLD,
352 "Calculated ground energy: %.4g, expected %.4g\n",
353 (double)eigr / q, regression_value);
354 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
355 "Regression test faileed; wrong eigen value. Try higher order or "
356 "finer mesh.");
357 }
358 }
360}
361//! [Check]
362
363int main(int argc, char *argv[]) {
364
365 // Initialisation of MoFEM/PETSc and MOAB data structures
366 const char param_file[] = "param_file.petsc";
367 SlepcInitialize(&argc, &argv, param_file, help);
368 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
369
370 // Add logging channel for example
371 auto core_log = logging::core::get();
372 core_log->add_sink(
374 LogManager::setLog("EXAMPLE");
375 MOFEM_LOG_TAG("EXAMPLE", "example");
376
377 try {
378
379 //! [Register MoFEM discrete manager in PETSc]
380 DMType dm_name = "DMMOFEM";
381 CHKERR DMRegister_MoFEM(dm_name);
382 //! [Register MoFEM discrete manager in PETSc
383
384 //! [Create MoAB]
385 moab::Core mb_instance; ///< mesh database
386 moab::Interface &moab = mb_instance; ///< mesh database interface
387 //! [Create MoAB]
388
389 //! [Create MoFEM]
390 MoFEM::Core core(moab); ///< finite element database
391 MoFEM::Interface &m_field = core; ///< finite element database insterface
392 //! [Create MoFEM]
393
394 //! [Example]
395 Example ex(m_field);
396 CHKERR ex.runProblem();
397 //! [Example]
398 }
400
401 SlepcFinalize();
403}
std::string type
#define MOFEM_LOG_C(channel, severity, format,...)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
static const double eps
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
Definition definitions.h:64
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
auto integration_rule
PetscErrorCode DMCreateMatrix_MoFEM(DM dm, Mat *M)
Definition DMMoFEM.cpp:1188
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 DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
@ PETSC
Standard PETSc assembly.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
MoFEMErrorCode removeBlockDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true, bool is_distributed_mesh=true)
Remove DOFs from problem based on block entities.
Definition BcManager.cpp:72
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< 1, 1, SPACE_DIM > OpDomainGradGrad
Definition helmholtz.cpp:25
double D
double tol
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Mat > matDuplicate(Mat mat, MatDuplicateOption op)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
static constexpr int approx_order
double effMass
static char help[]
#define EXECUTABLE_DIMENSION
Definition schrod_eig.cpp:9
constexpr int SPACE_DIM
double q
double m0
double scale
double hbar
[Physical constants and parameters]
double potential
int order
[Physical constants and parameters]
Calculate the square of wave function.
[Operators_definition]
[Example]
Definition plastic.cpp:216
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
Simple * simple
MoFEMErrorCode checkResults()
SmartPetscObj< Mat > M
MoFEMErrorCode solveSystem()
SmartPetscObj< Mat > H
Example(MoFEM::Interface &m_field)
MoFEMErrorCode runProblem()
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:226
MoFEMErrorCode setupProblem()
MoFEMErrorCode outputResults()
SmartPetscObj< EPS > eps
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Template specialization for scalar field boundary conditions.
virtual MPI_Comm & get_comm() const =0
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Specialization for double precision scalar field values calculation.
Post post-proc data at points from hash maps.
std::map< std::string, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainLhsFE()
Get domain left-hand side finite element.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
Definition Simple.cpp:191
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
Definition Simple.cpp:735
const std::string getProblemName() const
Get the Problem Name.
Definition Simple.hpp:450
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
[Calculate square of wave function]
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
double scale
Definition plastic.cpp:123