Compare commits

...
Author SHA1 Message Date
Brody Bassett 571f84b6e7 Formatting. 2023-08-01 03:00:30 -07:00
Brody Bassett c35a4d36b0 Formatting. 2023-08-01 02:56:15 -07:00
Brody Bassett 0484571327 Formatting. 2023-08-01 02:53:31 -07:00
Brody Bassett 4c38e5a8fa Added rk examples to sample runs. 2023-08-01 02:45:08 -07:00
Brody Bassett 1a1ac1f2c2 Formatting. 2023-07-26 13:45:59 -07:00
Brody Bassett 228e84afa7 Split lines for doxygen. 2023-07-26 13:45:37 -07:00
Brody Bassett 61afeac61a Removed unused function. 2023-07-26 13:36:12 -07:00
Brody Bassett e59d31c5b1 Renamed class. 2023-07-26 13:31:40 -07:00
Brody Bassett c2b9e59f56 Updated comment. 2023-07-18 17:21:51 -07:00
Brody Bassett da82f2734e Added comments to distance. 2023-07-18 17:20:34 -07:00
Brody Bassett 445bb8e040 More comments. 2023-07-18 17:12:56 -07:00
Brody Bassett 93d3fb1a81 Added comment on point selection. 2023-07-18 17:04:29 -07:00
Brody Bassett 7cf414c969 Added comment. 2023-07-18 16:52:30 -07:00
Brody Bassett 5c595b3163 Removed superfluous comments. 2023-07-18 16:49:07 -07:00
Brody Bassett 156953730e Removed stray character. 2023-07-18 16:47:51 -07:00
Brody Bassett 9fc6ba9a02 Converted comments to doxygen. Renamed class. 2023-07-18 16:44:11 -07:00
Brody Bassett 4950a75cfa Merge branch 'master' into meshless-kernels 2023-07-18 16:10:55 -07:00
Brody Bassett 56b622a9a3 Update CHANGELOG. 2023-07-10 13:10:38 -07:00
Brody Bassett 4bcbddbf93 Added comments. 2023-07-10 12:52:51 -07:00
Brody Bassett ef670c8ba5 Reverted formatting. 2023-07-10 12:36:11 -07:00
Tzanio Kolev 9cf7443241 Merge branch 'master' into meshless-kernels 2023-06-24 14:43:52 -07:00
Brody Bassett 4c883e2674 Added comments. 2023-06-06 12:49:35 -07:00
Brody Bassett 83fed93231 Added parameter to choose distance from edge for rbf points. 2023-06-06 11:57:04 -07:00
Brody Bassett 7da7baecc2 Merge branch 'master' into meshless-kernels 2023-06-06 10:35:23 -07:00
Brody Bassett 30d6701bb1 Merge branch 'master' into meshless-kernels 2023-05-15 11:31:40 -07:00
Brody Bassett c208b8f769 Unused variable. 2023-05-15 10:55:07 -07:00
Brody Bassett cbab91143e Fixed shadow error. 2023-05-15 10:45:38 -07:00
Brody Bassett 57977fb1c9 Formatting. 2023-05-11 03:05:59 -07:00
Brody Bassett f35a9df42e Added ex18p for RK. 2023-05-11 03:05:23 -07:00
Brody Bassett 4eed46a463 Added comments. 2023-05-11 03:04:08 -07:00
Brody Bassett 2b1ed66c08 Fixed RBF parameters. 2023-05-11 01:01:23 -07:00
Brody Bassett 151ab20545 Formatting. 2023-05-10 18:37:35 -07:00
Brody Bassett a0669dfdac Added projection for RBF. 2023-05-10 18:34:16 -07:00
Brody Bassett 961b049f34 Formatting. 2023-05-09 16:08:33 -07:00
Brody Bassett e40de76a7e Improved options. 2023-05-09 16:05:48 -07:00
Brody Bassett 63e6eca5fe Added RK to example. 2023-05-09 15:47:21 -07:00
Brody Richard Bassett 783854ef0b Added RBF to example. 2023-05-08 16:15:32 -07:00
Brody Bassett 6548ab92c2 Remove unneeded change. 2023-05-08 12:23:49 -07:00
Brody Richard Bassett 283b1f9169 Merge branch 'master' into meshless-kernels 2023-05-08 12:12:59 -07:00
Brody Richard Bassett 974222a4c9 Removed unused function. 2020-09-15 15:36:37 -07:00
Brody Richard Bassett 1aefb30c85 Merge branch 'master' into meshless-kernels 2020-09-15 15:30:34 -07:00
Brody Richard Bassett 1d9e2b406c Updated a few functions. 2020-08-27 13:16:36 -07:00
Brody Richard Bassett 239e8c03fe Removed changes to display-basis. 2020-08-26 15:37:10 -07:00
Brody Richard Bassett 4d122fb917 Restored examples overwritten by merge. 2020-08-26 15:35:40 -07:00
Brody Richard Bassett 37f02b1792 Added DomainGradLFIntegrator. 2020-08-26 15:29:37 -07:00
Brody Richard Bassett faee127fc3 Switched RK functions back to mono polynomials instead of Legendre. 2020-08-26 15:28:17 -07:00
Brody Richard Bassett 49534b1e01 Resolved some compilation errors. 2020-08-26 15:27:06 -07:00
Brody Richard Bassett 9ff8923e06 Finished adding compact RBFs, along with a few more kernels. 2020-08-26 15:25:53 -07:00
Brody Richard Bassett b534a29da9 Added first draft of compact support RBFs. 2020-08-26 15:24:52 -07:00
Brody Richard Bassett 227c5db7d5 Made smoothing parameter more invariant between kernels. 2020-08-26 15:23:50 -07:00
Brody Richard Bassett 7a7512ee2f Generalized the distance to be an arbitrary Lp norm. 2020-08-26 15:23:04 -07:00
Brody Richard Bassett 6e76fff419 Added a localized RBF. 2020-08-26 15:23:03 -07:00
Brody Richard Bassett 402f3bd06e Improved name for kernel fe collection. Fixed issues with thread safe version of kernels. 2020-08-26 15:23:03 -07:00
Brody Richard Bassett 2db465d846 Mirrored some of the interface from the L2_FECollection. 2020-08-26 15:23:03 -07:00
Brody Richard Bassett 3437c4b641 Updated finite elements to use nodes instead of separate matrix for positions. Added a first attempt at some face/vertix/edge information. 2020-08-26 15:23:02 -07:00
Brody Richard Bassett 4795a9ed44 Made the interface for meshless functions more user-friendly and removed memory allocation pitfalls. 2020-08-26 15:23:02 -07:00
Brody Richard Bassett a8438ce5c4 Upgraded example for kernel functions. 2020-08-26 15:23:02 -07:00
Brody Richard Bassett c846576049 Got RK derivatives working. 2020-08-26 15:22:45 -07:00
Brody Richard Bassett 5590670e11 Started switching over to native MFEM polynomials for corrections. 2020-08-26 15:21:26 -07:00
Brody Richard Bassett a87ed76081 Denoted scratch variables differently to prevent confusion with local function calls. 2020-08-26 15:21:25 -07:00
Brody Richard Bassett a42ea6f8ae Fixed issue with distance derivatives. 2020-08-26 15:21:25 -07:00
Brody Richard Bassett 5322781eec Switch from Array to C array for storage of dense matrices and vectors. 2020-08-26 15:21:07 -07:00
Brody Richard Bassett eddeb02121 Fixed 3d evaluations of polynomials and a few other bugs. 2020-08-26 15:20:05 -07:00
Brody Richard Bassett 6f81db97a9 Added more virtual destructors to kernel functions. 2020-08-26 15:16:28 -07:00
Brody Richard Bassett bafa730fd1 Changed destructors in kernel classes to be virtual. 2020-08-26 15:16:28 -07:00
Brody Richard Bassett 71df36d975 Added collection for kernel finite elements. 2020-08-26 15:16:28 -07:00
Brody Richard Bassett b034fdd364 Added a base class for kernel finite elements. Started adding a kernel FE collection. 2020-08-26 15:16:27 -07:00
Brody Richard Bassett 50f2625c94 Made the RBF automatically choose the correct dimension for the distance metric. 2020-08-26 15:16:27 -07:00
Brody Richard Bassett 20a8165db1 Added an additional distance measure. 2020-08-26 15:16:26 -07:00
Brody Richard Bassett b5216ac96e Added a few more RBFs. 2020-08-26 15:16:26 -07:00
Brody Richard Bassett 11ccbf19d2 Fixed compilation errors. 2020-08-26 15:16:26 -07:00
Brody Richard Bassett ac966979dd Finished adding the basics of radial basis functions and reproducing kernels. 2020-08-26 15:16:25 -07:00
Brody Richard Bassett 4c1e20325b Started adding radial basis functions and reproducing kernels as a finite element type. 2020-08-26 15:16:07 -07:00
12 changed files with 2418 additions and 16 deletions
+3
View File
@@ -56,6 +56,9 @@ Discretization improvements
- Added support for p-refined meshes in FindPointsGSLIB.
- Added radial basis functions and reproducing kernels as alternatives to
polynomial functions. These are accessed through the LocalKernelFECollection.
Linear and nonlinear solvers
----------------------------
- Updated interface to MUMPS direct solver to support multiple right-hand
+20 -3
View File
@@ -18,6 +18,8 @@
// ex14 -m ../data/amr-quad.mesh -r 3
// ex14 -m ../data/amr-hex.mesh
// ex14 -m ../data/fichera-amr.mesh
// ex14 -m ../data/inline-quad.mesh -r 2 -rk
// ex14 -m ../data/star.mesh -r 0 -o 3 -rk
//
// Description: This example code demonstrates the use of MFEM to define a
// discontinuous Galerkin (DG) finite element discretization of
@@ -43,10 +45,11 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/star.mesh";
int ref_levels = -1;
int order = 1;
bool rk = false;
double sigma = -1.0;
double kappa = -1.0;
double eta = 0.0;
bool visualization = 1;
bool visualization = true;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -54,7 +57,9 @@ int main(int argc, char *argv[])
args.AddOption(&ref_levels, "-r", "--refine",
"Number of times to refine the mesh uniformly, -1 for auto.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) >= 0.");
"Finite element order (polynomial degree) >= 0 OR reproducing kernel order.");
args.AddOption(&rk, "-rk", "--rk", "-no-rk", "--no-rk",
"Use reproducing kernel functions");
args.AddOption(&sigma, "-s", "--sigma",
"One of the three DG penalty parameters, typically +1/-1."
" See the documentation of class DGDiffusionIntegrator.");
@@ -75,6 +80,10 @@ int main(int argc, char *argv[])
{
kappa = (order+1)*(order+1);
}
if (rk && sigma < 0.0)
{
sigma = 1.0;
}
args.PrintOptions(cout);
// 2. Read the mesh from the given mesh file. We can handle triangular,
@@ -104,7 +113,15 @@ int main(int argc, char *argv[])
// 4. Define a finite element space on the mesh. Here we use discontinuous
// finite elements of the specified order >= 0.
FiniteElementCollection *fec = new DG_FECollection(order, dim);
FiniteElementCollection *fec;
if (rk)
{
fec = new LocalKernelFECollection(dim, 4, 6, order, 1.01 + order, 0.0);
}
else
{
fec = new DG_FECollection(order, dim);
}
FiniteElementSpace *fespace = new FiniteElementSpace(mesh, fec);
cout << "Number of unknowns: " << fespace->GetVSize() << endl;
+18 -1
View File
@@ -17,6 +17,8 @@
// mpirun -np 4 ex14p -m ../data/inline-segment.mesh -rs 5
// mpirun -np 4 ex14p -m ../data/amr-quad.mesh -rs 3
// mpirun -np 4 ex14p -m ../data/amr-hex.mesh
// mpirun -np 4 ex14p -m ../data/star.mesh -rs 1 -o 2 -rk
// mpirun -np 4 ex14p -m ../data/amr-quad.mesh -rs 2 -rk
//
// Description: This example code demonstrates the use of MFEM to define a
// discontinuous Galerkin (DG) finite element discretization of
@@ -81,6 +83,7 @@ int main(int argc, char *argv[])
int ser_ref_levels = -1;
int par_ref_levels = 2;
int order = 1;
bool rk = false;
double sigma = -1.0;
double kappa = -1.0;
double eta = 0.0;
@@ -96,6 +99,8 @@ int main(int argc, char *argv[])
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) >= 0.");
args.AddOption(&rk, "-rk", "--rk", "-no-rk", "--no-rk",
"Use reproducing kernel functions");
args.AddOption(&sigma, "-s", "--sigma",
"One of the three DG penalty parameters, typically +1/-1."
" See the documentation of class DGDiffusionIntegrator.");
@@ -119,6 +124,10 @@ int main(int argc, char *argv[])
{
kappa = (order+1)*(order+1);
}
if (rk && sigma < 0.0)
{
sigma = 1.0;
}
if (myid == 0)
{
args.PrintOptions(cout);
@@ -163,7 +172,15 @@ int main(int argc, char *argv[])
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use discontinuous finite elements of the specified order >= 0.
FiniteElementCollection *fec = new DG_FECollection(order, dim);
FiniteElementCollection *fec;
if (rk)
{
fec = new LocalKernelFECollection(dim, 4, 6, order, 1.01 + order, 0.0);
}
else
{
fec = new DG_FECollection(order, dim);
}
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_BigInt size = fespace->GlobalTrueVSize();
if (myid == 0)
+18 -4
View File
@@ -9,6 +9,8 @@
// ex18 -p 1 -r 0 -o 5 -s 6
// ex18 -p 2 -r 1 -o 1 -s 3
// ex18 -p 2 -r 0 -o 3 -s 3
// ex18 -p 1 -r 1 -o 3 -s 4 -rk
// ex18 -p 2 -r 0 -o 3 -s 3 -rk
//
// Description: This example code solves the compressible Euler system of
// equations, a model nonlinear hyperbolic PDE, with a
@@ -65,6 +67,7 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/periodic-square.mesh";
int ref_levels = 1;
int order = 3;
bool rk = false;
int ode_solver_type = 4;
double t_final = 2.0;
double dt = -0.01;
@@ -84,6 +87,8 @@ int main(int argc, char *argv[])
"Number of times to refine the mesh uniformly.");
args.AddOption(&order, "-o", "--order",
"Order (degree) of the finite elements.");
args.AddOption(&rk, "-rk", "--rk", "-no-rk", "--no-rk",
"Use reproducing kernel functions");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
"ODE solver: 1 - Forward Euler,\n\t"
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
@@ -139,13 +144,21 @@ int main(int argc, char *argv[])
// 5. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
DG_FECollection fec(order, dim);
FiniteElementCollection *fec;
if (rk)
{
fec = new LocalKernelFECollection(dim, 5, 7, order, 2.01 + order, 1.0);
}
else
{
fec = new DG_FECollection(order, dim);
}
// Finite element space for a scalar (thermodynamic quantity)
FiniteElementSpace fes(&mesh, &fec);
FiniteElementSpace fes(&mesh, fec);
// Finite element space for a mesh-dim vector quantity (momentum)
FiniteElementSpace dfes(&mesh, &fec, dim, Ordering::byNODES);
FiniteElementSpace dfes(&mesh, fec, dim, Ordering::byNODES);
// Finite element space for all variables together (total thermodynamic state)
FiniteElementSpace vfes(&mesh, &fec, num_equation, Ordering::byNODES);
FiniteElementSpace vfes(&mesh, fec, num_equation, Ordering::byNODES);
// This example depends on this ordering of the space.
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
@@ -304,6 +317,7 @@ int main(int argc, char *argv[])
// Free the used memory.
delete ode_solver;
delete fec;
return 0;
}
+18 -4
View File
@@ -9,6 +9,8 @@
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 1 -o 5 -s 6
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 1 -s 3
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 3 -s 3
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 0 -o 3 -s 4 -rk
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 0 -o 3 -s 3 -rk
//
// Description: This example code solves the compressible Euler system of
// equations, a model nonlinear hyperbolic PDE, with a
@@ -70,6 +72,7 @@ int main(int argc, char *argv[])
int ser_ref_levels = 0;
int par_ref_levels = 1;
int order = 3;
bool rk = false;
int ode_solver_type = 4;
double t_final = 2.0;
double dt = -0.01;
@@ -93,6 +96,8 @@ int main(int argc, char *argv[])
" partitioning.");
args.AddOption(&order, "-o", "--order",
"Order (degree) of the finite elements.");
args.AddOption(&rk, "-rk", "--rk", "-no-rk", "--no-rk",
"Use reproducing kernel functions");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
"ODE solver: 1 - Forward Euler,\n\t"
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
@@ -161,13 +166,21 @@ int main(int argc, char *argv[])
// 7. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
DG_FECollection fec(order, dim);
FiniteElementCollection *fec;
if (rk)
{
fec = new LocalKernelFECollection(dim, 5, 7, order, 2.01 + order, 1.0);
}
else
{
fec = new DG_FECollection(order, dim);
}
// Finite element space for a scalar (thermodynamic quantity)
ParFiniteElementSpace fes(&pmesh, &fec);
ParFiniteElementSpace fes(&pmesh, fec);
// Finite element space for a mesh-dim vector quantity (momentum)
ParFiniteElementSpace dfes(&pmesh, &fec, dim, Ordering::byNODES);
ParFiniteElementSpace dfes(&pmesh, fec, dim, Ordering::byNODES);
// Finite element space for all variables together (total thermodynamic state)
ParFiniteElementSpace vfes(&pmesh, &fec, num_equation, Ordering::byNODES);
ParFiniteElementSpace vfes(&pmesh, fec, num_equation, Ordering::byNODES);
// This example depends on this ordering of the space.
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
@@ -375,6 +388,7 @@ int main(int argc, char *argv[])
// Free the used memory.
delete ode_solver;
delete fec;
return 0;
}
+2
View File
@@ -68,6 +68,7 @@ set(SRCS
fe/fe_nd.cpp
fe/fe_nurbs.cpp
fe/fe_pos.cpp
fe/fe_rbf.cpp
fe/fe_rt.cpp
fe/fe_ser.cpp
fe_coll.cpp
@@ -175,6 +176,7 @@ set(HDRS
fe/fe_nd.hpp
fe/fe_nurbs.hpp
fe/fe_pos.hpp
fe/fe_rbf.hpp
fe/fe_rt.hpp
fe/fe_ser.hpp
fe_coll.hpp
+1
View File
@@ -26,5 +26,6 @@
#include "fe/fe_nurbs.hpp"
#include "fe/fe_pos.hpp"
#include "fe/fe_ser.hpp"
#include "fe/fe_rbf.hpp"
#endif
+3 -3
View File
@@ -1026,9 +1026,6 @@ private:
static Array2D<int> binom;
static void CalcMono(const int p, const double x, double *u);
static void CalcMono(const int p, const double x, double *u, double *d);
static void CalcChebyshev(const int p, const double x, double *u);
static void CalcChebyshev(const int p, const double x, double *u, double *d);
static void CalcChebyshev(const int p, const double x, double *u, double *d,
@@ -1165,6 +1162,9 @@ public:
static void CalcLegendre(const int p, const double x, double *u);
static void CalcLegendre(const int p, const double x, double *u, double *d);
static void CalcMono(const int p, const double x, double *u);
static void CalcMono(const int p, const double x, double *u, double *d);
~Poly_1D();
};
+1470
View File
File diff suppressed because it is too large Load Diff
+596
View File
@@ -0,0 +1,596 @@
// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_FE_RBF
#define MFEM_FE_RBF
#include "fe_base.hpp"
namespace mfem
{
/** @brief Pure virtual class for dimensionless radial basis functions (RBFs).
Many RBFs are shaped like a Gaussian and are used here as an alternative
to polynomials in RBF and RK elements. The input for these
is a dimensionless radius r = ||x|| / h, where ||x|| is a distance and
h is the smoothing parameter, which controls the gradient of the RBF.
For reference: https://doi.org/10.1017/S0962492900000015 */
class RBFKernel
{
public:
static const double GlobalRadius; // functions with r>=GR are considered global
RBFKernel() { };
virtual ~RBFKernel() { }
/// Evaluate the dimensionless RBF
virtual double BaseFunction(double r) const = 0;
/// Evaluate the derivative of the dimensionless RBF with respect to r
virtual double BaseDerivative(double r) const = 0;
/// Evaluate the second derivative of the dimensionless RBF with respect to r
virtual double BaseDerivative2(double r) const = 0;
/// The support radius, outside of which the function is zero if the function has compact support
virtual double Radius() const { return GlobalRadius; }
/// Does function have compact support?
virtual bool CompactSupport() const { return false; }
/** #brief This normalizes the smoothing parameter h such that h doesn't
need to be changed based on the choice of basis function */
virtual double HNorm() const = 0;
};
/// Gaussian RBF, exp(-r^2)
class GaussianRBF : public RBFKernel
{
// hNorm minimizes integral of Gaussian minus Wendland kernel over r=0,1
static const double hNorm;
public:
GaussianRBF() { };
virtual ~GaussianRBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double HNorm() const { return hNorm; }
};
/// Multiquadric RBF, sqrt(1+r^2)
class MultiquadricRBF : public RBFKernel
{
// Same as inverse multiquadric
static const double hNorm;
public:
MultiquadricRBF() { };
virtual ~MultiquadricRBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double HNorm() const { return hNorm; }
};
/// Inverse multiquadric RBF, 1/sqrt(1+r^2)
class InvMultiquadricRBF : public RBFKernel
{
// hNorm minimizes integral of Gaussian minus InvMQ kernel over r=0,0.5
static const double hNorm;
public:
InvMultiquadricRBF() { };
virtual ~InvMultiquadricRBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double HNorm() const { return hNorm; }
};
/** @brief Identitcal to the Gaussian RBF, but subtracted by a factor
such that the function is exactly zero at the chosen radius */
class CompactGaussianRBF : public RBFKernel
{
static const double hNorm;
const double radius;
double multK, shiftK;
public:
CompactGaussianRBF(const double rad = 5.0);
virtual ~CompactGaussianRBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double Radius() const { return radius; }
virtual double HNorm() const { return hNorm; }
virtual bool CompactSupport() const { return true; }
};
/// Identical to the Gaussian, but truncated (set to zero) at the chosen radius
class TruncatedGaussianRBF : public RBFKernel
{
static const double hNorm;
const double radius;
public:
TruncatedGaussianRBF(const double rad = 5.0)
: radius(rad) { }
virtual ~TruncatedGaussianRBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double Radius() const { return radius; }
virtual double HNorm() const { return hNorm; }
virtual bool CompactSupport() const { return true; }
};
/// Wendland 11 RBF, (1-r)^3 * (1+3r) if r < 1
class Wendland11RBF : public RBFKernel
{
static const double radius;
public:
Wendland11RBF() { }
virtual ~Wendland11RBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double Radius() const { return radius; }
virtual double HNorm() const { return 1.0 / radius; }
virtual bool CompactSupport() const { return true; }
};
/// Wendland 31 RBF, (1-r)^4 * (1+4r) if r < 1
class Wendland31RBF : public RBFKernel
{
static const double radius;
public:
Wendland31RBF() { };
virtual ~Wendland31RBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double Radius() const { return radius; }
virtual double HNorm() const { return 1.0 / radius; }
virtual bool CompactSupport() const { return true; }
};
/// Wendland 33 RBF, (1-r)^8 * (1+8r+25r^2+32r^3) if r < 1
class Wendland33RBF : public RBFKernel
{
static const double radius;
public:
Wendland33RBF() { };
virtual ~Wendland33RBF() { }
virtual double BaseFunction(double r) const;
virtual double BaseDerivative(double r) const;
virtual double BaseDerivative2(double r) const;
virtual double Radius() const { return radius; }
virtual double HNorm() const { return 1.0 / radius; }
virtual bool CompactSupport() const { return true; }
};
/// Class for storing and creating the various RBFs
class RBFType
{
public:
/// Represent each type of function for input/output
enum
{
Gaussian = 0,
Multiquadric = 1,
InvMultiquadric = 2,
TruncatedGaussian = 3,
CompactGaussian = 4,
Wendland11 = 5,
Wendland31 = 6,
Wendland33 = 7,
NumRBFTypes = 8
};
/// Return the requested RBF
static RBFKernel *GetRBF(const int rbfType)
{
switch (rbfType)
{
case RBFType::Gaussian:
return new GaussianRBF();
case RBFType::Multiquadric:
return new MultiquadricRBF();
case RBFType::InvMultiquadric:
return new InvMultiquadricRBF();
case RBFType::TruncatedGaussian:
return new TruncatedGaussianRBF();
case RBFType::CompactGaussian:
return new CompactGaussianRBF();
case RBFType::Wendland11:
return new Wendland11RBF();
case RBFType::Wendland31:
return new Wendland31RBF();
case RBFType::Wendland33:
return new Wendland33RBF();
}
MFEM_ABORT("unknown RBF type");
return NULL;
}
/// Abort if rbfType is invalid
static int Check(const int rbfType)
{
MFEM_VERIFY(0 <= rbfType && rbfType < NumRBFTypes,
"unknown RBF type: " << rbfType);
return rbfType;
}
/// Convert rbf int to identifier for storage
static char GetChar(const int rbfType)
{
static const char ident[] = { 'G', 'M', 'I',
'T', 'C',
'1', '3', '6'
};
return ident[Check(rbfType)];
}
/// Convert identifier to rbf int
static int GetType(const char rbfIdent)
{
switch (rbfIdent)
{
case 'G': return Gaussian;
case 'M': return Multiquadric;
case 'I': return InvMultiquadric;
case 'T': return TruncatedGaussian;
case 'C': return CompactGaussian;
case '1': return Wendland11;
case '3': return Wendland31;
case '6': return Wendland33;
}
MFEM_ABORT("unknown RBF identifier: " << rbfIdent);
return -1;
}
};
/// Dimensionless distance metrics, whose output is the input for RBFs
class DistanceMetric
{
protected:
int dim;
public:
/** @brief Create a distance metric
@param D Reference space dimension */
DistanceMetric(int D) { dim = D; }
virtual ~DistanceMetric() { }
/// Set the reference dimension
virtual void SetDim(int D) { dim = D; }
/// Given a vector of length D, return a physical distance
virtual void Distance(const Vector &x,
double &r) const = 0;
/** @brief Given a vector of length D, return the gradient of the
distance with respect to the original coordinates */
virtual void DDistance(const Vector &x,
Vector &dr) const = 0;
/** @brief Given a vector of length D, return the Hessian of the
distance with respect to the original coordinates */
virtual void DDDistance(const Vector &x,
DenseMatrix &ddr) const = 0;
/// Create an Lp distance metric for the requested dimension and norm
static DistanceMetric *GetDistance(int dim, int pnorm);
};
/// Dimensionless distance with r = |x| + |y| + ...
class L1Distance : public DistanceMetric
{
public:
L1Distance(int D) : DistanceMetric(D) { };
virtual ~L1Distance() { }
virtual void Distance(const Vector &x,
double &r) const;
virtual void DDistance(const Vector &x,
Vector &dr) const;
virtual void DDDistance(const Vector &x,
DenseMatrix &ddr) const;
};
/// Dimensionless distance with r = (x^2 + y^2 + ...)^(1/2)
class L2Distance : public DistanceMetric
{
public:
L2Distance(int D) : DistanceMetric(D) { };
virtual ~L2Distance() { }
virtual void Distance(const Vector &x,
double &r) const;
virtual void DDistance(const Vector &x,
Vector &dr) const;
virtual void DDDistance(const Vector &x,
DenseMatrix &ddr) const;
};
/// Dimensionless distance with r = (x^p + y^p + ...)^(1/p)
class LpDistance : public DistanceMetric
{
const int p;
const double pinv;
public:
LpDistance(int D, int pnorm)
: DistanceMetric(D),
p(pnorm),
pinv(1. / static_cast<double>(p))
{ };
virtual ~LpDistance() { }
virtual void Distance(const Vector &x,
double &r) const;
virtual void DDistance(const Vector &x,
Vector &dr) const;
virtual void DDDistance(const Vector &x,
DenseMatrix &ddr) const;
};
/** @brief Pure virtual class for a finite element with radial basis functions
instead of polynomials inside each element */
class KernelFiniteElement : public ScalarFiniteElement
{
private:
// Choose whether to interpolate or project when Project is called
bool interpolate = false;
public:
KernelFiniteElement(int D, Geometry::Type G, int Do, int O, int F)
: ScalarFiniteElement(D, G, Do, O, F) { }
virtual ~KernelFiniteElement() { }
/// Converts integration rule to vector
virtual void IntRuleToVec(const IntegrationPoint &ip,
Vector &vec) const;
/// Is base RBF compact?
virtual bool IsCompact() const = 0;
/// Return base kernel
virtual const RBFKernel *Kernel() const = 0;
/** @brief Return whether shape function is a tensor product, used in providing indices for compact support */
virtual bool TensorIndexed() const { return false; }
/** @brief Get range of indices (start and end for each dimension) that
that are nonzero for compact support for the given integration point */
virtual void GetTensorIndices(const Vector &ip,
int (&indices)[3][2]) const
{ MFEM_ABORT("GetTensorIndices(...)"); }
/** @brief Return total number of points in each dimension for tensor-
indexed points */
virtual void GetTensorNumPoints(int (&tNumPoints)[3]) const
{ MFEM_ABORT("GetTensorNumPoints(...)"); }
using FiniteElement::Project;
virtual void Project(Coefficient &coeff, ElementTransformation &Trans,
Vector &dofs) const;
virtual void Project(VectorCoefficient &vc, ElementTransformation &Trans,
Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ ScalarLocalInterpolation(Trans, I, *this); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
{ CheckScalarFE(fe).ScalarLocalInterpolation(Trans, I, *this); }
};
/** @brief Finite element using base radial basis functions without
polynomial corrections. */
class RBFFiniteElement : public KernelFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable double r_scr, df_scr, ddf_scr;
mutable Vector x_scr, y_scr, dy_scr, dr_scr;
mutable DenseMatrix ddr_scr;
mutable int cInd[3][2];
#endif
bool isCompact;
int dimPoints[3];
int numPointsD;
double delta; // Distance between points
double h;
double hPhys; // Shape parameter times distance between points times HNorm
double hPhysInv; // Inverse hPhys
double radPhys; // Radius adjusted by h
double faceFactor;
const RBFKernel *rbf;
const DistanceMetric *distance;
void InitializeGeometry();
// Get the dimensionless distance from x to the center of the RBF indexed i
virtual void DistanceVec(const int i,
const Vector &x,
Vector &y) const;
public:
/** @brief Construct RBFFiniteElement
@param D Reference space dimension
@param numPointsD Number of points across the element in each dimension
@param rbfType Type of radial basis function, from RBFType
@param distNorm Norm used for distance, usually 2 = Euclidean distance
@param intOrder Number of integration points per RBF point in each dimension
@param h Shape parameter, approximately equal to the number of points in the support radius in one dimension
@param faceFactor 1.0 = points end on face, 0.0 = points end at dx/2 from face
*/
RBFFiniteElement(const int D,
const int numPointsD,
const int rbfType,
const int distNorm,
const int intOrder,
const double h,
const double faceFactor);
virtual ~RBFFiniteElement() { delete rbf; delete distance; }
virtual bool TensorIndexed() const { return true; }
virtual void GetCompactIndices(const Vector &ip,
int (&indices)[3][2]) const;
virtual void GetGlobalIndices(const Vector &ip,
int (&indices)[3][2]) const;
virtual void GetTensorIndices(const Vector &ip,
int (&indices)[3][2]) const;
virtual void GetTensorNumPoints(int (&tNumPoints)[3]) const
{
tNumPoints[0] = dimPoints[0];
tNumPoints[1] = dimPoints[1];
tNumPoints[2] = dimPoints[2];
}
virtual bool IsCompact() const { return isCompact; }
virtual const RBFKernel *Kernel() const { return rbf; }
virtual void CalcShape(const IntegrationPoint &ip,
Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &hess) const;
};
/** @brief Reproducing kernel finite element, which includes polynomial
corrections to the standard radial basis function finite element
to guarantee a chosen order of accuracy */
class RKFiniteElement : public KernelFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable double f_scr;
mutable Vector x_scr, y_scr, g_scr, c_scr, s_scr, p_scr, df_scr;
mutable DenseMatrix q_scr, dq_scr, M_scr;
mutable Vector dc_scr[3], dp_scr[3];
mutable DenseMatrix dM_scr[3];
mutable DenseMatrixInverse Minv_scr;
mutable int cInd[3][2];
mutable int dimPoints[3];
#endif
int polyOrd, numPoly, numPoly1d;
KernelFiniteElement *baseFE;
// Get the vector of polynomials for the corrections, evaluated at x
virtual void GetPoly(const Vector &x,
Vector &p) const;
virtual void GetDPoly(const Vector &x,
Vector &p,
Vector (&dp)[3]) const;
/* Helper functions that return pieces of the RK evaluation
W_{RK,i} = P_i^T C_i W_{RBF,i}, where
P_i = [1, x, y, z, ...] is the polynomial vector evaluated at the point i,
M_i = P_i P_i^T W_{RBF,i} is a matrix used in calculating the corrections,
C_i = M_i^{-1} G are the RK corrections,
G = [1, 0, 0, ...] is a convencience vector */
virtual void GetG(Vector &g) const;
virtual void GetM(const Vector &baseShape,
const IntegrationPoint &ip,
DenseMatrix &M) const;
virtual void GetDM(const Vector &baseShape,
const DenseMatrix &baseDeriv,
const IntegrationPoint &ip,
DenseMatrix &M,
DenseMatrix (&dM)[3]) const;
virtual void AddToM(const Vector &p,
const double &f,
DenseMatrix &M) const;
virtual void AddToDM(const Vector &p,
const Vector (&dp)[3],
const double &f,
const Vector &df,
DenseMatrix (&dM)[3]) const;
// Given the corrections and base values, calculate the RK value at the ip
virtual void CalculateValues(const Vector &c,
const Vector &baseShape,
const IntegrationPoint &ip,
Vector &shape) const;
virtual void CalculateDValues(const Vector &c,
const Vector (&dc)[3],
const Vector &baseShape,
const DenseMatrix &baseDShape,
const IntegrationPoint &ip,
DenseMatrix &dshape) const;
// The corrections make the distance dimensionless, so no smoothing parameter
virtual void DistanceVec(const int i,
const Vector &x,
Vector &y) const;
public:
/** @brief Construct RBFFiniteElement
@param D Reference space dimension
@param numPointsD Number of points across the element in each dimension
@param rbfType Type of radial basis function, from RBFType
@param distNorm Norm used for distance, usually 2 = Euclidean distance
@param order Order of polynomial correction, >= 0
@param intOrder Number of integration points per RBF point in each dimension
@param h Shape parameter, approximately equal to the number of points in the support radius in one dimension
@param faceFactor 1.0 = points end on face, 0.0 = points end at dx/2 from face
*/
RKFiniteElement(const int D,
const int numPointsD,
const int rbfType,
const int distNorm,
const int order,
const int intOrder,
const double h,
const double faceFactor);
virtual ~RKFiniteElement() { delete baseFE; }
virtual bool IsCompact() const { return baseFE->IsCompact(); }
virtual const RBFKernel *Kernel() const { return baseFE->Kernel(); }
static int GetNumPoly(int polyOrd, int dim);
virtual void CalcShape(const IntegrationPoint &ip,
Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
} // end namespace mfem
#endif
+210
View File
@@ -347,6 +347,36 @@ FiniteElementCollection *FiniteElementCollection::New(const char *name)
fec = new NURBSFECollection();
}
}
else if (!strncmp(name, "RBF", 3) || !strncmp(name, "RK", 2))
{
// Example: RK4_G_2_V_2D_0020_1.00_4.01
// (RK order 4, Gaussian, L2 dist, Value map, 2 dimensions,
// 20 points across element, face factor 1.0, smoothing length of 4.01)
const int dim = atoi(name + 10);
const int numPoints = atoi(name + 13);
const double h = atof(name + 23);
const double faceFactor = atof(name + 18);
const int rbfType = RBFType::GetType(name[4]);
const int distNorm = atoi(name + 6);
const int mapType = (name[8] == 'V'
? FiniteElement::VALUE
: FiniteElement::INTEGRAL);
const int intOrder = 2; // keep this fixed for now
if (!strncmp(name, "RK", 2))
{
int order = atoi(name + 2);
fec = new LocalKernelFECollection(dim, numPoints, rbfType,
order, h, faceFactor,
intOrder, distNorm, mapType);
}
else
{
fec = new LocalKernelFECollection(dim, numPoints, rbfType,
-1, h, faceFactor,
intOrder, distNorm, mapType);
}
}
else
{
MFEM_ABORT("unknown FiniteElementCollection: " << name);
@@ -3510,4 +3540,184 @@ FiniteElementCollection *NURBSFECollection::GetTraceCollection() const
return NULL;
}
LocalKernelFECollection::LocalKernelFECollection(const int dim,
const int numPointsD,
const int rbfType,
const int order,
const double h,
const double faceFactor,
const int intOrder,
const int distNorm,
const int mapType)
{
const char *mapStr = NULL;
switch (mapType)
{
case FiniteElement::VALUE: mapStr = "V"; break;
case FiniteElement::INTEGRAL: mapStr = "I"; break;
default:
MFEM_ABORT("invalid mapType: " << mapType);
}
if (order == -1)
{
snprintf(d_name, 32, "RBF_%c_%d_%s_%dD_%04d_%1.2f_%.2f",
(int)RBFType::GetChar(rbfType), distNorm,
mapStr, dim, numPointsD, faceFactor, h);
}
else if (order >= 0)
{
snprintf(d_name, 32, "RK%d_%c_%d_%s_%dD_%04d_%1.2f_%.2f", order,
(int)RBFType::GetChar(rbfType), distNorm,
mapStr, dim, numPointsD, faceFactor, h);
}
else
{
MFEM_ABORT("invalid order: " << order);
}
for (int g = 0; g < Geometry::NumGeom; ++g)
{
L2_Elements[g] = NULL;
Tr_Elements[g] = NULL;
}
for (int i = 0; i < 2; i++)
{
SegDofOrd[i] = NULL;
}
OtherDofOrd = NULL;
if (dim == 0)
{
L2_Elements[Geometry::POINT] = new PointFiniteElement;
}
else if (dim == 1)
{
if (order == -1)
{
L2_Elements[Geometry::SEGMENT]
= new RBFFiniteElement(1, numPointsD, rbfType, distNorm,
intOrder, h, faceFactor);
}
else
{
L2_Elements[Geometry::SEGMENT]
= new RKFiniteElement(1, numPointsD, rbfType, distNorm,
order, intOrder, h, faceFactor);
}
L2_Elements[Geometry::SEGMENT]->SetMapType(mapType);
Tr_Elements[Geometry::POINT] = new PointFiniteElement;
}
else if (dim == 2)
{
if (order == -1)
{
L2_Elements[Geometry::SQUARE]
= new RBFFiniteElement(2, numPointsD, rbfType, distNorm,
intOrder, h, faceFactor);
Tr_Elements[Geometry::SEGMENT]
= new RBFFiniteElement(1, numPointsD, rbfType, distNorm,
intOrder, h, faceFactor);
}
else
{
L2_Elements[Geometry::SQUARE]
= new RKFiniteElement(2, numPointsD, rbfType, distNorm,
order, intOrder, h, faceFactor);
Tr_Elements[Geometry::SEGMENT]
= new RKFiniteElement(1, numPointsD, rbfType, distNorm,
order, intOrder, h, faceFactor);
}
L2_Elements[Geometry::SQUARE]->SetMapType(mapType);
}
else if (dim == 3)
{
if (order == -1)
{
L2_Elements[Geometry::CUBE]
= new RBFFiniteElement(3, numPointsD, rbfType, distNorm,
intOrder, h, faceFactor);
Tr_Elements[Geometry::SQUARE]
= new RBFFiniteElement(2, numPointsD, rbfType, distNorm,
intOrder, h, faceFactor);
}
else
{
L2_Elements[Geometry::CUBE]
= new RKFiniteElement(3, numPointsD, rbfType, distNorm,
order, intOrder, h, faceFactor);
Tr_Elements[Geometry::SQUARE]
= new RKFiniteElement(2, numPointsD, rbfType, distNorm,
order, intOrder, h, faceFactor);
}
L2_Elements[Geometry::CUBE]->SetMapType(mapType);
}
if (dim == 1)
{
SegDofOrd[0] = new int[2*numPointsD];
SegDofOrd[1] = SegDofOrd[0] + numPointsD;
for (int i = 0; i < numPointsD; ++i)
{
SegDofOrd[0][i] = i;
SegDofOrd[1][i] = numPointsD - i - 1;
}
}
else
{
const int geomType = TensorBasisElement::GetTensorProductGeometry(dim);
const int dof = L2_Elements[geomType]->GetDof();
OtherDofOrd = new int[dof];
for (int i = 0; i < dof; ++i)
{
OtherDofOrd[i] = i;
}
}
}
LocalKernelFECollection::~LocalKernelFECollection()
{
delete [] OtherDofOrd;
delete [] SegDofOrd[0];
for (int i = 0; i < Geometry::NumGeom; ++i)
{
delete L2_Elements[i];
}
}
const FiniteElement *
LocalKernelFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
return L2_Elements[GeomType];
}
const FiniteElement *
LocalKernelFECollection::TraceFiniteElementForGeometry(Geometry::Type GeomType)
const
{
return Tr_Elements[GeomType];
}
int LocalKernelFECollection::DofForGeometry(Geometry::Type GeomType) const
{
if (L2_Elements[GeomType])
{
return L2_Elements[GeomType]->GetDof();
}
return 0;
}
const int *LocalKernelFECollection::DofOrderForOrientation(
Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SEGMENT)
{
return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
}
else
{
return (Or == 0) ? OtherDofOrd : NULL;
}
}
} // namespace mfem
+59 -1
View File
@@ -1305,6 +1305,64 @@ public:
virtual int GetContType() const { return DISCONTINUOUS; }
};
}
/** @brief Radial basis function collection.
Instead of using polynomials as a basis, these methods use
Gaussian-like functions centered at chosen points. Reproducing
kernels augment the radial basis functions so that the resultant
basis can exactly represent functions of a chosen polynomial degree. */
class LocalKernelFECollection : public FiniteElementCollection
{
private:
int maxDim;
char d_name[32];
ScalarFiniteElement *Tr_Elements[Geometry::NumGeom];
ScalarFiniteElement *L2_Elements[Geometry::NumGeom];
int *SegDofOrd[2]; // for rotating segment dofs in 1D
int *OtherDofOrd;
public:
/** @brief Create a radial basis function (RBF) or reproducing kernel (RK)
finite element collection.
@param D Reference space dimension
@param numPointsD Number of points across the element in each dimension
@param rbfType Type of radial basis function, from RBFType
@param order Order of polynomial correction, >= 0 for RK or -1 for
RBF
@param h Shape parameter, approximately equal to the number of
points in the support radius in one dimension, should
generally be > order
@param distNorm Norm used for distance, usually 2 = Euclidean distance
@param intOrder Number of integration points per RBF point in each
dimension
@param faceFactor 1.0 = points end on face, 0.0 = points end at dx/2
from face
*/
LocalKernelFECollection(const int D,
const int numPointsD,
const int rbfType,
const int order,
const double h,
const double faceFactor = 0.0,
const int intOrder = 2,
const int distNorm = 2,
const int mapType = FiniteElement::VALUE);
virtual ~LocalKernelFECollection();
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual const FiniteElement *
TraceFiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int * DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return d_name; }
virtual int GetContType() const { return DISCONTINUOUS; }
};
} // namespace mfem
#endif