74 "Device configuration string, see Device::Configure().");
79 AddOption(&
dim,
"-dim",
"--dim",
"Dimension of the problem (2 or 3)");
80 AddOption(&
nx,
"-nx",
"--nx",
"Number of elements in x direction");
81 AddOption(&
ny,
"-ny",
"--ny",
"Number of elements in y direction");
82 AddOption(&
nz,
"-nz",
"--nz",
"Number of elements in z direction");
83 AddOption(&
sx,
"-sx",
"--sx",
"Size of the domain in x direction");
84 AddOption(&
sy,
"-sy",
"--sy",
"Size of the domain in y direction");
85 AddOption(&
sz,
"-sz",
"--sz",
"Size of the domain in z direction");
87 "--no-periodic",
"Use a periodic mesh.");
89 "Impose or not essential boundary conditions.");
91 "Enable or disable leapfrog.");
97 "Enable or disable jet.");
100 AddOption(&
rtol,
"-rtol",
"--rtol",
"Solvers relative tolerance");
101 AddOption(&
atol,
"-atol",
"--atol",
"Solvers absolute tolerance");
102 AddOption(&
ftz,
"-ftz",
"--ftz",
"Flush to zero threshold");
106 "--no-visualization",
"Enable or not GLVis visualization");
108 "--no-paraview",
"Enable or not Paraview visualization");
113 "Velocity: 0: Vorticity: 1 (leapfrog only)");
116 MFEM_VERIFY(
jet ^
leapfrog,
"'jet' or 'leapfrog' option must be set");
118 "Invalid visualization data option.");
130#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
138#include <cuComplex.h>
139#ifdef MFEM_USE_SINGLE
147#include <hip/hip_complex.h>
148#ifdef MFEM_USE_SINGLE
165 template <
typename U>
168 return (*
this = *
this * z, *
this);
171 template <
typename U>
174 return (*
this = *
this / z, *
this);
185 return Complex(
a.real() +
b.real(),
a.imag() +
b.imag());
195 return Complex(
a.real() *
b.real() -
a.imag() *
b.imag(),
196 a.real() *
b.imag() +
a.imag() *
b.real());
206 return std::hypot(z.
real(), z.
imag());
212#ifdef MFEM_USE_SINGLE
213 sincosf(q.
imag(), &s, &c);
215 sincos(q.
imag(), &s, &c);
234template <
typename TMesh,
235 typename TFiniteElementSpace,
236 typename TComplexGridFunction,
237 typename TGridFunction,
239 typename TMixedBilinearForm,
240 typename TLinearForm>
273 std::function<
CGSolver()> CreateCGSolver):
281 std::vector<Vector> Tr2 = {
Vector({
sx, 0.0_r }),
292 std::vector<Vector> Tr3 = {
Vector({
sx, 0.0_r, 0.0_r }),
311 v.SetSize(
dim), v[0] = 1.0, v[1] = 0.0;
312 if (
dim == 3) { v[2] = 0.0; }
317 if (
dim == 3) { v[2] = 0.0; }
322 if (
dim == 3) { v[2] = 1.0; }
334 if (
periodic ||
mesh.bdr_attributes.Size() == 0) { return; }
436 rhs.UseFastAssembly(
true);
445 const auto phase = phase_r.
Read();
452 const complex_t eps = 0.01, i_phase(0, phase[n]);
455 psi1_r(n) = z1.real(), psi1_i(n) = z1.imag();
456 psi2_r(n) = z2.real(), psi2_i(n) = z2.imag();
473 if (fabs(psi_norm) < 1e-16) {
return; }
474 psi1_r(n) /= psi_norm, psi1_i(n) /= psi_norm;
475 psi2_r(n) /= psi_norm, psi2_i(n) /= psi_norm;
483 MFEM_VERIFY(
jet,
"Jet must be enabled use restrict.");
484 const auto isJet = isJet_in.Read();
485 const auto phase = phase_in.Read();
492 if (isJet[n] == 0) {
return; }
496 psi1 = amp1 *
exp(i_pn_omega_t);
497 psi2 = amp2 *
exp(i_pn_omega_t);
498 psi1_r(n) =
psi1.real(), psi1_i(n) =
psi1.imag();
499 psi2_r(n) =
psi2.real(), psi2_i(n) =
psi2.imag();
503 template<
typename Gfn,
typename Xfn,
typename Yfn,
typename Zfn>
504 void GradPsi(Gfn &Grad_nd, Xfn &x_dot_Mm1, Yfn &y_dot_Mm1, Zfn &z_dot_Mm1)
532 TGridFunction &uy, TGridFunction &uz)
561 vx(n) = psi1r(n) * Gpsi1ix(n) - psi1i(n) * Gpsi1rx(n);
562 vx(n) += psi2r(n) * Gpsi2ix(n) - psi2i(n) * Gpsi2rx(n);
563 vx(n) *= (fabs(vx(n)) < FTZ) ? 0.0 :
hbar;
564 vy(n) = psi1r(n) * Gpsi1iy(n) - psi1i(n) * Gpsi1ry(n);
565 vy(n) += psi2r(n) * Gpsi2iy(n) - psi2i(n) * Gpsi2ry(n);
566 vy(n) *= (fabs(vy(n)) < FTZ) ? 0.0 :
hbar;
567 if (
DIM == 2) {
return; }
568 vz(n) = psi1r(n) * Gpsi1iz(n) - psi1i(n) * Gpsi1rz(n);
569 vz(n) += psi2r(n) * Gpsi2iz(n) - psi2i(n) * Gpsi2rz(n);
570 vz(n) *= (fabs(vz(n)) < FTZ) ? 0.0 :
hbar;
588 div_u_w(n) = psi1i(n) * Dpsi1r(n) - psi1r(n) * Dpsi1i(n);
589 div_u_w(n) += psi2i(n) * Dpsi2r(n) - psi2r(n) * Dpsi2i(n);
608 psi1_r(n) =
psi1.real(), psi1_i(n) =
psi1.imag();
609 psi2_r(n) =
psi2.real(), psi2_i(n) =
psi2.imag();
617 MFEM_VERIFY(swirling > 0.0,
"Swirling strength must be positive");
619 const real3_t o = { center[0], center[1], center[2] };
620 const real_t norm2 = std::sqrt(normal[0] * normal[0] +
621 normal[1] * normal[1] +
622 normal[2] * normal[2]);
623 const real_t n0 = normal[0] / norm2, n1 = normal[1] / norm2,
624 n2 = normal[2] / norm2;
630 const real_t px =
X(0, n), py =
X(1, n),
631 pz =
DIM == 3 ?
X(2, n) : 0.0;
632 const real_t rx = px - o[0], ry = py - o[1], rz = pz - o[2];
633 const real_t z = rx * n0 + ry * n1 + rz * n2;
634 const bool inRange = (rx * rx + ry * ry + rz * rz - z * z) <
radius *
radius;
635 const bool inLayerP = inRange && (z > 0.0 && z <= (+swirling / 2.0));
636 const bool inLayerM = inRange && (z <= 0.0 && z >= (-swirling / 2.0));
638 if (inLayerP) {
alpha = -M_PI * (2.0 * z / swirling - 1.0); }
639 if (inLayerM) {
alpha = -M_PI * (2.0 * z / swirling + 1.0); }
643 psi1_r(n) =
psi1.real(), psi1_i(n) =
psi1.imag();
649template<
typename TFiniteElementSpace,
650 typename TSesquilinearForm,
651 typename TComplexGridFunction>
658 TComplexGridFunction
z;
671 one(1.0),
dthq(dt * hbar / 4.0),
mdthq(-dt * hbar / 4.0),
699 virtual void Mult(TComplexGridFunction &psi) = 0;
703template<
typename TSchrodingerSolver,
typename TGr
idFunction>
722 vx = 0.0,
vy = 0.0,
vz = 0.0;
737 velocity[1] = velocity[2] = 0.0;
744 for (
int i = 0; i < 3; i++) {
omega += velocity[i] * velocity[i]; }
747 auto phase_w =
phase.Write();
748 auto isJet_w =
isJet.Write();
754 const real_t r = SX / 16.0;
755 const real_t px =
X(0, n), py =
X(1, n),
756 pz =
DIM == 3 ?
X(2, n) : 0.0;
757 const real_t dx = px - (SX/8.0), dy = py - (SY/2.0),
758 dz =
DIM == 3 ? pz - (SZ/2.0) : 0.0;
760 if (geom == JetGeom::Band) { isJet_w[n] = (fabs(dy*dy) < (r*r)) ? 1 : 0; }
761 if (geom == JetGeom::Disc) { isJet_w[n] = (fabs(dx*dx + dy*dy + dz*dz) < (r*r)) ? 1 : 0; }
762 if (geom == JetGeom::Rect) { isJet_w[n] = (px > 0.2 && dx < 1.0 && fabs(dy*dy + dz*dz) < (r*r)) ? 1 : 0; }
763 phase_w[n] = kvec0 * px + kvec1 * py + kvec2 * pz;
773 const real_t z2 = zh * zh, y2 = yh * yh, r = sqrt(z2 + y2);
774 const real3_t n = { -1.0, 0.0, 0.0 },
775 o = {
sx / 2.0_r,
sy / 2.0_r,
DIM == 3 ?
sz / 2.0_r : 0.0_r };
814 MFEM_VERIFY(
jet,
"ConstrainJetVelocity() only for jet geometry");
815 for (
int i = 0; i < 10; i++)
824template <
typename TMesh,
825 typename TGridFunction,
826 typename TFiniteElementSpace,
827 typename TSchrodingerSolver,
828 typename TIncompressibleFlow>
838 const TIncompressibleFlow &
isf;
848 TSchrodingerSolver &
solver,
849 const TIncompressibleFlow &
isf,
850 std::function<std::string()> prefix):
871 auto viz_h1_w =
vis_gf.Write();
888 auto isJet_r =
isf.isJet.Read();
889 auto viz_h1_w =
vis_gf.Write();
900 const auto vx_r =
isf.vx.Read(), vy_r =
isf.vy.Read(), vz_r =
isf.vz.Read();
901 auto viz_h1_w =
vis_gf.Write();
904 const real_t vx = vx_r[i], vy = vy_r[i], vz = vz_r[i];
905 viz_h1_w[i] = std::sqrt(vx*vx + vy*vy + vz*vz);
916 const auto psi1_r =
solver.psi1.real().Read();
917 const auto psi1_i =
solver.psi1.imag().Read();
918 const auto psi2_r =
solver.psi2.real().Read();
919 const auto psi2_i =
solver.psi2.imag().Read();
920 auto viz_h1_w =
vis_gf.Write();
923 const auto psi1 = psi1_r[i] * psi1_r[i] + psi1_i[i] * psi1_i[i];
924 const auto psi2 = psi2_r[i] * psi2_r[i] + psi2_i[i] * psi2_i[i];
925 viz_h1_w[i] = psi1 * psi1 + psi2 * psi2;
940 <<
"keys " <<
vis_keys <<
"\n" << std::flush;
Conjugate gradient method.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
A coefficient that is constant across space and time.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
Class for domain integration .
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
Arbitrary order H1-conforming (continuous) finite elements.
Class for simulating incompressible Schrodinger flow.
IncompressibleBaseFlow(Options &config, TSchrodingerSolver &solver)
void Setup()
Setup the solver.
TSchrodingerSolver & solver
void Step(const real_t &t)
This function performs a single time step of the solver.
void ConstrainJetVelocity()
Restricts the velocity of the wavefunctions.
void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
void SetAbsTol(real_t atol)
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
static Mesh MakePeriodic(const Mesh &orig_mesh, const std::vector< int > &v2v)
Create a periodic mesh by identifying vertices of orig_mesh.
std::vector< int > CreatePeriodicVertexMapping(const std::vector< Vector > &translations, real_t tol=1e-8) const
Creates a mapping v2v from the vertex indices of the mesh such that coincident vertices under the giv...
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Arbitrary order H(curl)-conforming Nedelec finite elements.
Pointer to an Operator of a specified type.
Jacobi smoothing for a given bilinear form (no matrix necessary).
void ParseCheck(std::ostream &out=mfem::out)
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
The ordering method used when the number of unknowns per mesh node (vector dimension) is bigger than ...
Solver wrapper which orthogonalizes the input and output vector.
void SetSolver(Solver &s)
Set the solver used by the OrthoSolver.
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
void SetDataFormat(VTKFormat fmt)
Set the data format for the ParaView output files.
Writer for ParaView visualization (PVD and VTU format)
Writer for ParaView visualization (VTKHDF format)
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
A general vector function coefficient.
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
int close()
Close the socketstream.
bool is_open()
True if the socketstream is open, false otherwise.
MemoryClass operator*(MemoryClass mc1, MemoryClass mc2)
Return a suitable MemoryClass from a pair of MemoryClasses.
MFEM_ALWAYS_INLINE AutoSIMD< scalar_t, S, A > operator+(const scalar_t &e, const AutoSIMD< scalar_t, S, A > &v)
std::array< real_t, 3 > real3_t
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall(int N, lambda &&body)
MFEM_ALWAYS_INLINE AutoSIMD< scalar_t, S, A > operator/(const scalar_t &e, const AutoSIMD< scalar_t, S, A > &v)
MFEM_HOST_DEVICE real_t norm(const Complex &z)
MFEM_HOST_DEVICE Complex exp(const Complex &q)
MFEM_HOST_DEVICE real_t abs(const Complex &z)
std::complex< real_t > complex_t
Complex number type for device.
cuFloatComplex RealComplex_t
MFEM_HOST_DEVICE void imag(real_t i)
MFEM_HOST_DEVICE Complex(real_t r, real_t i)
MFEM_HOST_DEVICE Complex()=default
MFEM_HOST_DEVICE Complex(real_t r)
MFEM_HOST_DEVICE real_t real() const
MFEM_HOST_DEVICE Complex & operator/=(const U &z)
MFEM_HOST_DEVICE real_t imag() const
MFEM_HOST_DEVICE Complex & operator*=(const U &z)
MFEM_HOST_DEVICE void real(real_t r)
Crank-Nicolson time solver for the Schrodinger equation.
ConstantCoefficient mdthq
CrankNicolsonTimeBaseSolver(TFiniteElementSpace &fes, real_t hbar, real_t dt, std::function< GMRESSolver()> CreateGMRESSolver, real_t rtol, real_t atol, int maxiter, int print_level)
virtual void Mult(TComplexGridFunction &psi)=0
Options for the Incompressible Schrödinger Flow solver.
Options(int argc, char *argv[])
Base class for Schrodinger solver kernels.
void Restrict(const real_t t, const TGridFunction &isJet_in, const real_t omega, const TGridFunction &phase_in)
Restrict the wavefunctions psi1 and psi2.
TComplexGridFunction gpsi2_x
std::function< void()> SetEssentialTrueDofs
TComplexGridFunction gpsi1_x
TComplexGridFunction psi1
OperatorHandle nd_dot_y_h1_op
void GradPsiVelocity(const real_t hbar, TGridFunction &ux, TGridFunction &uy, TGridFunction &uz)
TFiniteElementSpace nodal_fes
OrthoSolver diff_h1_ortho
TMixedBilinearForm nd_dot_z_h1
TComplexGridFunction gpsi2_y
VectorFunctionCoefficient Vy
TComplexGridFunction delta_psi2
OperatorJacobiSmoother diff_h1_smoother
TMixedBilinearForm nd_dot_x_h1
VectorFunctionCoefficient Vx
TComplexGridFunction gpsi1_y
TComplexGridFunction psi2
TComplexGridFunction gpsi1_nd
void Normalize()
Normalize the wavefunctions psi1 and psi2.
OperatorHandle diff_h1_op
OperatorHandle nd_dot_x_h1_op
TComplexGridFunction gpsi1_z
VectorFunctionCoefficient Vz
void GradPsi(Gfn &Grad_nd, Xfn &x_dot_Mm1, Yfn &y_dot_Mm1, Zfn &z_dot_Mm1)
TFiniteElementSpace nd_fes
std::function< Mesh()> CreateMesh2D
TComplexGridFunction gpsi2_nd
OperatorHandle mass_h1_op
void Initialize(Vector &phase_r)
Initialize the wavefunctions psi1 and psi2.
Array< int > ess_tdof_list
TFiniteElementSpace h1_fes
OperatorHandle nd_dot_z_h1_op
GridFunctionCoefficient div_u_coeff
OperatorHandle grad_nd_op
TMixedBilinearForm grad_nd
TMixedBilinearForm nd_dot_y_h1
void AddCircularVortex(const real3_t center, const real3_t normal, const real_t radius, const real_t swirling)
Add a circular vortex to the wavefunctions psi1 and psi2.
std::function< Mesh()> CreateMesh3D
TComplexGridFunction gpsi2_z
SchrodingerBaseKernels(Options &config, std::function< TMesh(Mesh &)> CreateMesh, std::function< OrthoSolver()> CreateOrthoSolver, std::function< CGSolver()> CreateCGSolver)
OperatorHandle mass_nd_op
TComplexGridFunction delta_psi1
Base class for visualization.
ParaViewHDFDataCollection dc
const Options::VisData vis_data
const TIncompressibleFlow & isf
TGridFunction * operator()()
Get the visualization data.
void GLVis()
Send the visualization data to GLVis.
VisualizerBase(Options &config, TSchrodingerSolver &solver, const TIncompressibleFlow &isf, std::function< std::string()> prefix)
std::function< void()> vis_fn
std::function< std::string()> vis_prefix
void Save(int cycle, real_t time)
Save the visualization data to a file.
ParaViewDataCollection dc
const TSchrodingerSolver & solver