Compare commits
7
Commits
Eikonal
...
maglev-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e176bb8d06 | ||
|
|
c1509fde91 | ||
|
|
44f25808b9 | ||
|
|
8296bca522 | ||
|
|
d4825be0ca | ||
|
|
ff143322bd | ||
|
|
b08c652314 |
@@ -197,6 +197,46 @@ void VectorDomainLFIntegrator::AssembleRHSElementVect(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DomainGradLFIntegrator::AssembleRHSElementVect(
|
||||
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
||||
{
|
||||
DenseMatrix Q_ir, dshape, adjJ;
|
||||
Vector vec1, vec2, q_dot_ds;
|
||||
|
||||
int nd = el.GetDof();
|
||||
int dim = Q.GetVDim();
|
||||
vec1.SetSize(dim);
|
||||
vec2.SetSize(dim);
|
||||
adjJ.SetSize(dim,dim);
|
||||
dshape.SetSize(nd,dim);
|
||||
elvect.SetSize(nd);
|
||||
q_dot_ds.SetSize(nd);
|
||||
|
||||
const IntegrationRule *ir = IntRule;
|
||||
if (ir == NULL)
|
||||
{
|
||||
int intorder = el.GetOrder() + 1;
|
||||
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
||||
}
|
||||
|
||||
Q.Eval(Q_ir, Tr, *ir);
|
||||
|
||||
elvect = 0.0;
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(i);
|
||||
Tr.SetIntPoint(&ip);
|
||||
el.CalcDShape(ip, dshape);
|
||||
CalcAdjugate(Tr.Jacobian(), adjJ);
|
||||
Q_ir.GetColumnReference(i, vec1);
|
||||
vec1 *= ip.weight;
|
||||
adjJ.Mult(vec1, vec2);
|
||||
dshape.Mult(vec2, q_dot_ds);
|
||||
elvect += q_dot_ds;
|
||||
}
|
||||
}
|
||||
|
||||
void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
|
||||
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
||||
{
|
||||
|
||||
@@ -146,6 +146,28 @@ public:
|
||||
using LinearFormIntegrator::AssembleRHSElementVect;
|
||||
};
|
||||
|
||||
|
||||
/** Class for domain integration of L(v) := (f, grad v), where
|
||||
f=(f1,...,fn) and v scalar. */
|
||||
class DomainGradLFIntegrator : public LinearFormIntegrator
|
||||
{
|
||||
private:
|
||||
VectorCoefficient &Q;
|
||||
|
||||
public:
|
||||
/// Constructs a domain integrator with a given VectorCoefficient
|
||||
DomainGradLFIntegrator(VectorCoefficient &QF) : Q(QF) { }
|
||||
|
||||
/** Given a particular Finite Element and a transformation (Tr)
|
||||
computes the element right hand side element vector, elvect. */
|
||||
virtual void AssembleRHSElementVect(const FiniteElement &el,
|
||||
ElementTransformation &Tr,
|
||||
Vector &elvect);
|
||||
|
||||
using LinearFormIntegrator::AssembleRHSElementVect;
|
||||
};
|
||||
|
||||
|
||||
/** Class for boundary integration of L(v) := (g, v), where
|
||||
f=(f1,...,fn) and v=(v1,...,vn). */
|
||||
class VectorBoundaryLFIntegrator : public LinearFormIntegrator
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
// A 2D static magnetic levitation miniapp
|
||||
//
|
||||
// Compile with: make maglev
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
|
||||
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to define a
|
||||
|
||||
#include "maglev.hpp"
|
||||
#include "../../common/pfem_extras.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
void solveForAz(MaglevProblemGeometry &problem,
|
||||
ParFiniteElementSpace &fes_h1,
|
||||
ParGridFunction &x,
|
||||
ParGridFunction &conv,
|
||||
ParGridFunction &mag);
|
||||
|
||||
void solveForJz(MaglevProblemGeometry &problem,
|
||||
ParFiniteElementSpace &fes_h1,
|
||||
ParGridFunction &az,
|
||||
ParGridFunction &jz);
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
int order = 1;
|
||||
int num_refine = 4;
|
||||
double domain_length = 3.0;
|
||||
double domain_height = 2.0;
|
||||
double ha_len = 2.0;
|
||||
double ha_thick = 0.1;
|
||||
int ha_num_magnets = 20;
|
||||
double ha_yoff = 0.05;
|
||||
double ha_vx = 0.0;
|
||||
double ha_mu = 1.32e-6;
|
||||
double ha_sigma = 6.67e5;
|
||||
double ha_remanence = 1.0;
|
||||
double conductor_thick = 0.025;
|
||||
double conductor_yoff = 1.0;
|
||||
double conductor_vx = -100.0;
|
||||
double conductor_mu = 1.257e-6;
|
||||
double conductor_sigma = 3.5e7;
|
||||
double air_mu = 1.257e-6;
|
||||
double air_sigma = 3e-15;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&num_refine, "-nr", "--num_refine",
|
||||
"Number of times to refine the mesh after initial setup.");
|
||||
args.AddOption(&domain_length, "-dl", "--domain_length",
|
||||
"Length (x) of the simulation domain (m).");
|
||||
args.AddOption(&domain_height, "-dh", "--domain_height",
|
||||
"Height (y) of the simulation domain (m).");
|
||||
args.AddOption(&ha_len, "-hl", "--ha_len",
|
||||
"Physical length of the Halbach array (m).");
|
||||
args.AddOption(&ha_thick, "-ht", "--ha_thick",
|
||||
"Physical thickness of the Halbach array (m).");
|
||||
args.AddOption(&ha_num_magnets, "-hn", "--ha_num_magnets",
|
||||
"Number of magnets in the Halbach array.");
|
||||
args.AddOption(&ha_yoff, "-hy", "--ha_yoff",
|
||||
"Distance between the Halbach array and the conductor (m).");
|
||||
args.AddOption(&ha_vx, "-hv", "--ha_vx",
|
||||
"Velocity of the Halbach array in the x direction.");
|
||||
args.AddOption(&ha_mu, "-hm", "--ha_mu",
|
||||
"Permeability of the Halbach array (H/m).");
|
||||
args.AddOption(&ha_sigma, "-hs", "--ha_sigma",
|
||||
"Conductivity of the halbach array (S/m).");
|
||||
args.AddOption(&ha_remanence, "-hr", "--ha_remanence",
|
||||
"Remanence of the halbach array (T).");
|
||||
args.AddOption(&conductor_thick, "-ct", "--conductor_thick",
|
||||
"Physical thickness of the conductor (m).");
|
||||
args.AddOption(&conductor_yoff, "-cy", "--conductor_yoff",
|
||||
"Distance from the bottom of the domain to the top of the conductor (m).");
|
||||
args.AddOption(&conductor_vx, "-cv", "--conductor_vx",
|
||||
"Velocity of the conductor in the x direction (m/s).");
|
||||
args.AddOption(&conductor_mu, "-cm", "--conductor_mu",
|
||||
"Permeability of the conductor (H/m).");
|
||||
args.AddOption(&conductor_sigma, "-cs", "--conductor_sigma",
|
||||
"Conductivity of the conductor (S/m).");
|
||||
args.AddOption(&air_mu, "-am", "--air_mu",
|
||||
"Permeability of the air (H/m).");
|
||||
args.AddOption(&air_sigma, "-as", "--air_sigma",
|
||||
"Conductivity of the air (S/m).");
|
||||
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// Generate the mesh from the given inputs and set up the
|
||||
// the object that holds on to all the problem definitions.
|
||||
double dx = ha_len / double(ha_num_magnets);
|
||||
double dy = min(min(ha_thick, conductor_thick), ha_yoff);
|
||||
int nx = round(domain_length / dx);
|
||||
int ny = round(domain_height / dy);
|
||||
Mesh *mesh = new Mesh(nx, ny, Element::QUADRILATERAL, 1,
|
||||
domain_length, domain_height);
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
for (int l = 0; l < num_refine; l++)
|
||||
{
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
MaglevProblemGeometry problem(conductor_yoff - conductor_thick, conductor_yoff, conductor_vx,
|
||||
conductor_mu, conductor_sigma,
|
||||
domain_length/2.0 - ha_len/2.0, domain_length/2.0 + ha_len/2.0,
|
||||
conductor_yoff+ha_yoff, conductor_yoff+ha_yoff+ha_thick,
|
||||
ha_num_magnets, ha_vx, ha_mu, ha_sigma, ha_remanence/ha_mu,
|
||||
air_mu, air_sigma);
|
||||
|
||||
// Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use continuous Lagrange finite elements of the specified order.
|
||||
FiniteElementCollection *fec_h1 = new H1_FECollection(order, 2);
|
||||
FiniteElementCollection *fec_rt = new RT_FECollection(order, 2);
|
||||
FiniteElementCollection *fec_l2 = new L2_FECollection(0, 2);
|
||||
ParFiniteElementSpace *fes_h1 = new ParFiniteElementSpace(pmesh, fec_h1);
|
||||
ParFiniteElementSpace *fes_rt = new ParFiniteElementSpace(pmesh, fec_rt);
|
||||
ParFiniteElementSpace *fes_l2 = new ParFiniteElementSpace(pmesh, fec_l2);
|
||||
ParFiniteElementSpace *fes_vl2 = new ParFiniteElementSpace(pmesh, fec_l2, 2);
|
||||
HYPRE_Int ndof = fes_h1->GlobalTrueVSize();
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Number of finite element unknowns: " << ndof << endl;
|
||||
}
|
||||
|
||||
ParGridFunction az(fes_h1);
|
||||
ParGridFunction conv(fes_vl2);
|
||||
ParGridFunction mag(fes_vl2);
|
||||
solveForAz(problem, *fes_h1, az, conv, mag);
|
||||
|
||||
//Compute Bfield = curl A so we can visualize it
|
||||
ParGridFunction bfield(fes_rt);
|
||||
miniapps::ParDiscreteCurlOperator curl(fes_h1,fes_rt);
|
||||
curl.Assemble();
|
||||
curl.Finalize();
|
||||
curl.Mult(az, bfield);
|
||||
|
||||
ParGridFunction jz(fes_h1);
|
||||
solveForJz(problem, *fes_h1, az, jz);
|
||||
|
||||
//Make grid functions out of these coefficients for visualization
|
||||
ParGridFunction vx(fes_l2);
|
||||
ParGridFunction sigma(fes_l2);
|
||||
ParGridFunction mu(fes_l2);
|
||||
VxCoeff vx_coeff(problem);
|
||||
SigmaCoeff sigma_coeff(problem);
|
||||
MuCoeff mu_coeff(problem);
|
||||
vx.ProjectCoefficient(vx_coeff);
|
||||
sigma.ProjectCoefficient(sigma_coeff);
|
||||
mu.ProjectCoefficient(mu_coeff);
|
||||
|
||||
VisItDataCollection visit_dc("maglev", pmesh);
|
||||
visit_dc.RegisterField("Az", &az);
|
||||
visit_dc.RegisterField("Jz", &jz);
|
||||
visit_dc.RegisterField("B", &bfield);
|
||||
visit_dc.RegisterField("convection_coeff", &conv);
|
||||
visit_dc.RegisterField("mag_coeff", &mag);
|
||||
visit_dc.RegisterField("vx", &vx);
|
||||
visit_dc.RegisterField("sigma", &sigma);
|
||||
visit_dc.RegisterField("mu", &mu);
|
||||
visit_dc.Save();
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Solve Delta Az - mu sigma v dot grad Az = curl M
|
||||
//x: The solution Az
|
||||
//conv: The convection coefficient (for vizualization)
|
||||
//mag: The magnitization coefficient (for vizualization)
|
||||
void solveForAz(MaglevProblemGeometry &problem,
|
||||
ParFiniteElementSpace &fes_h1,
|
||||
ParGridFunction &az,
|
||||
ParGridFunction &conv,
|
||||
ParGridFunction &mag)
|
||||
{
|
||||
// Set up the parallel bilinear form dc(.,.) on the finite element space
|
||||
// corresponding to the Laplacian operator Delta Az - mu sigma v dot grad Az.
|
||||
ConstantCoefficient one(-1.0);
|
||||
ConvectionCoeff conv_coeff(problem);
|
||||
ParBilinearForm dc(&fes_h1);
|
||||
dc.AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
dc.AddDomainIntegrator(new ConvectionIntegrator(conv_coeff));
|
||||
dc.Assemble();
|
||||
|
||||
// Determine the list of true (i.e. parallel conforming) essential
|
||||
// boundary dofs. In this example, the boundary conditions are defined
|
||||
// by marking all the boundary attributes from the mesh as essential
|
||||
// (Dirichlet) and converting them to a list of true dofs.
|
||||
ParMesh *pmesh = fes_h1.GetParMesh();
|
||||
Array<int> ess_tdof_list(fes_h1.GlobalTrueVSize());
|
||||
ess_tdof_list = 0;
|
||||
if (pmesh->bdr_attributes.Size())
|
||||
{
|
||||
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
fes_h1.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
}
|
||||
|
||||
// Set up the parallel linear form b(.) which corresponds to the
|
||||
// right-hand side of the FEM linear system, which in this case is
|
||||
// (1,phi_i) where phi_i are the basis functions in fes_h1.
|
||||
ParLinearForm b(&fes_h1);
|
||||
MagnetizationCoeff mag_coeff(problem);
|
||||
b.AddDomainIntegrator(new DomainGradLFIntegrator(mag_coeff));
|
||||
b.Assemble();
|
||||
|
||||
// Assemble the parallel bilinear form and the corresponding linear
|
||||
// system, applying any necessary transformations such as
|
||||
HypreParMatrix DC;
|
||||
Vector B, AZ;
|
||||
dc.FormLinearSystem(ess_tdof_list, az, b, DC, AZ, B);
|
||||
|
||||
// Define and apply a parallel GMRES solver for AX=B with the BoomerAMG
|
||||
// preconditioner from hypre.
|
||||
HypreParaSails sails(DC);
|
||||
HypreGMRES gmres(DC);
|
||||
gmres.SetTol(1e-7);
|
||||
gmres.SetKDim(250);
|
||||
gmres.SetMaxIter(10000);
|
||||
gmres.SetPrintLevel(2);
|
||||
gmres.SetPreconditioner(sails);
|
||||
gmres.Mult(B, AZ);
|
||||
|
||||
// Recover the parallel grid function corresponding to X. This is the
|
||||
// local finite element solution on each processor.
|
||||
dc.RecoverFEMSolution(AZ, b, az);
|
||||
|
||||
//Project these coefficients onto corresponding grid functions for vizualization
|
||||
conv.ProjectCoefficient(conv_coeff);
|
||||
mag.ProjectCoefficient(mag_coeff);
|
||||
}
|
||||
|
||||
|
||||
//Solve Jz = -Delta 1/mu Az
|
||||
void solveForJz(MaglevProblemGeometry &problem,
|
||||
ParFiniteElementSpace &fes_h1,
|
||||
ParGridFunction &az,
|
||||
ParGridFunction &jz)
|
||||
{
|
||||
Array<int> ess_tdof_list(fes_h1.GlobalTrueVSize());
|
||||
ess_tdof_list = 0;
|
||||
|
||||
//Set up M matrix for the left hand side
|
||||
ConstantCoefficient one(-1.0);
|
||||
ParBilinearForm m(&fes_h1);
|
||||
m.AddDomainIntegrator(new MassIntegrator(one));
|
||||
m.Assemble();
|
||||
|
||||
//Set up the biliinear for the K matrix for -Delta 1/mu on the right hand side
|
||||
MuInvCoeff muinv_coeff(problem);
|
||||
ParBilinearForm k(&fes_h1);
|
||||
k.AddDomainIntegrator(new DiffusionIntegrator(muinv_coeff));
|
||||
k.Assemble();
|
||||
|
||||
//Compute B = K AZ
|
||||
ParGridFunction b(&fes_h1);
|
||||
HypreParMatrix K;
|
||||
HypreParVector *AZ = az.GetTrueDofs();
|
||||
HypreParVector B(*AZ);
|
||||
k.FormSystemMatrix(ess_tdof_list, K);
|
||||
K.Mult(*AZ, B);
|
||||
|
||||
//Now Set up the linear system for M JZ = B and get jz
|
||||
jz = 0.0;
|
||||
HypreParVector *JZ = jz.GetTrueDofs();
|
||||
HypreParMatrix M;
|
||||
m.FormSystemMatrix(ess_tdof_list, M);
|
||||
HypreBoomerAMG amg(M);
|
||||
HypreGMRES gmres(M);
|
||||
gmres.SetTol(1e-12);
|
||||
gmres.SetKDim(250);
|
||||
gmres.SetMaxIter(10000);
|
||||
gmres.SetPrintLevel(2);
|
||||
gmres.SetPreconditioner(amg);
|
||||
gmres.Mult(B, *JZ);
|
||||
jz = *JZ;
|
||||
|
||||
delete AZ;
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
#include "mfem.hpp"
|
||||
|
||||
class MaglevProblemGeometry
|
||||
{
|
||||
public:
|
||||
MaglevProblemGeometry(double conductor_bottom, double conductor_top,
|
||||
double conductor_vx, double conductor_mu, double conductor_sigma,
|
||||
double ha_left, double ha_right, double ha_bottom, double ha_top,
|
||||
int ha_num_magnets, double ha_vx, double ha_mu, double ha_sigma, double ha_mag,
|
||||
double air_mu, double air_sigma) :
|
||||
m_conductor_bottom(conductor_bottom),
|
||||
m_conductor_top(conductor_top),
|
||||
m_conductor_vx(conductor_vx),
|
||||
m_conductor_mu(conductor_mu),
|
||||
m_conductor_sigma(conductor_sigma),
|
||||
m_ha_left(ha_left),
|
||||
m_ha_right(ha_right),
|
||||
m_ha_bottom(ha_bottom),
|
||||
m_ha_top(ha_top),
|
||||
m_ha_num_magnets(ha_num_magnets),
|
||||
m_ha_vx(ha_vx),
|
||||
m_ha_mu(ha_mu),
|
||||
m_ha_sigma(ha_sigma),
|
||||
m_ha_mag(ha_mag),
|
||||
m_air_vx(0.0),
|
||||
m_air_mu(air_mu),
|
||||
m_air_sigma(air_sigma) {m_magnet_size = (m_ha_right - m_ha_left) / double(m_ha_num_magnets);}
|
||||
|
||||
inline int getMagnetNumber(const mfem::Vector &x);
|
||||
inline double getMu(const mfem::Vector &x);
|
||||
inline double getSigma(const mfem::Vector &x);
|
||||
inline double getVx(const mfem::Vector &x);
|
||||
inline void getMuSigmaV(const mfem::Vector &x, mfem::Vector &out);
|
||||
inline void getMPerp(const mfem::Vector &x, mfem::Vector &out);
|
||||
|
||||
private:
|
||||
double m_conductor_bottom;
|
||||
double m_conductor_top;
|
||||
double m_conductor_vx;
|
||||
double m_conductor_mu;
|
||||
double m_conductor_sigma;
|
||||
double m_ha_left;
|
||||
double m_ha_right;
|
||||
double m_ha_bottom;
|
||||
double m_ha_top;
|
||||
int m_ha_num_magnets;
|
||||
double m_ha_vx;
|
||||
double m_ha_mu;
|
||||
double m_ha_sigma;
|
||||
double m_ha_mag;
|
||||
double m_air_vx;
|
||||
double m_air_mu;
|
||||
double m_air_sigma;
|
||||
double m_magnet_size;
|
||||
};
|
||||
|
||||
|
||||
class ConvectionCoeff : public mfem::VectorCoefficient
|
||||
{
|
||||
public:
|
||||
ConvectionCoeff(MaglevProblemGeometry &problem) :
|
||||
VectorCoefficient(2),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual void Eval(mfem::Vector &V, mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
class MagnetizationCoeff : public mfem::VectorCoefficient
|
||||
{
|
||||
public:
|
||||
MagnetizationCoeff(MaglevProblemGeometry problem) :
|
||||
VectorCoefficient(2),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual void Eval(mfem::Vector &V, mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
class MuInvCoeff : public mfem::Coefficient
|
||||
{
|
||||
public:
|
||||
MuInvCoeff(MaglevProblemGeometry &problem) :
|
||||
Coefficient(),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual double Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
class VxCoeff : public mfem::Coefficient
|
||||
{
|
||||
public:
|
||||
VxCoeff(MaglevProblemGeometry &problem) :
|
||||
Coefficient(),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual double Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
class MuCoeff : public mfem::Coefficient
|
||||
{
|
||||
public:
|
||||
MuCoeff(MaglevProblemGeometry &problem) :
|
||||
Coefficient(),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual double Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
class SigmaCoeff : public mfem::Coefficient
|
||||
{
|
||||
public:
|
||||
SigmaCoeff(MaglevProblemGeometry &problem) :
|
||||
Coefficient(),
|
||||
m_problem(problem) {}
|
||||
|
||||
virtual double Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip);
|
||||
|
||||
private:
|
||||
MaglevProblemGeometry &m_problem;
|
||||
};
|
||||
|
||||
|
||||
inline int MaglevProblemGeometry::getMagnetNumber(const mfem::Vector &x)
|
||||
{
|
||||
return int((x[0] - m_ha_left) / m_magnet_size);
|
||||
}
|
||||
|
||||
|
||||
inline double MaglevProblemGeometry::getVx(const mfem::Vector &x)
|
||||
{
|
||||
double vx;
|
||||
if (x[1] >= m_conductor_bottom && x[1] <= m_conductor_top)
|
||||
{
|
||||
vx = m_conductor_vx;
|
||||
}
|
||||
else if (x[0] >= m_ha_left && x[0] <= m_ha_right && x[1] >= m_ha_bottom && x[1] <= m_ha_top)
|
||||
{
|
||||
vx = m_ha_vx;
|
||||
}
|
||||
else
|
||||
{
|
||||
vx = m_air_vx;
|
||||
}
|
||||
return vx;
|
||||
}
|
||||
|
||||
|
||||
inline double MaglevProblemGeometry::getMu(const mfem::Vector &x)
|
||||
{
|
||||
double mu;
|
||||
if (x[1] >= m_conductor_bottom && x[1] <= m_conductor_top)
|
||||
{
|
||||
mu = m_conductor_mu;
|
||||
}
|
||||
else if (x[0] >= m_ha_left && x[0] <= m_ha_right && x[1] >= m_ha_bottom && x[1] <= m_ha_top)
|
||||
{
|
||||
mu = m_ha_mu;
|
||||
}
|
||||
else
|
||||
{
|
||||
mu = m_air_mu;
|
||||
}
|
||||
return mu;
|
||||
}
|
||||
|
||||
|
||||
inline double MaglevProblemGeometry::getSigma(const mfem::Vector &x)
|
||||
{
|
||||
double sigma;
|
||||
if (x[1] >= m_conductor_bottom && x[1] <= m_conductor_top)
|
||||
{
|
||||
sigma = m_conductor_sigma;
|
||||
}
|
||||
else if (x[0] >= m_ha_left && x[0] <= m_ha_right && x[1] >= m_ha_bottom && x[1] <= m_ha_top)
|
||||
{
|
||||
sigma = m_ha_sigma;
|
||||
}
|
||||
else
|
||||
{
|
||||
sigma = m_air_sigma;
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
|
||||
inline void MaglevProblemGeometry::getMuSigmaV(const mfem::Vector &x, mfem::Vector &out)
|
||||
{
|
||||
out = 0.0;
|
||||
out[0] = getMu(x)*getSigma(x)*getVx(x);
|
||||
}
|
||||
|
||||
|
||||
inline void MaglevProblemGeometry::getMPerp(const mfem::Vector &x, mfem::Vector &out)
|
||||
{
|
||||
out = 0.0;
|
||||
if (x[0] >= m_ha_left && x[0] <= m_ha_right && x[1] >= m_ha_bottom && x[1] <= m_ha_top)
|
||||
{
|
||||
int mag = getMagnetNumber(x) % 4;
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
if (mag == 0)
|
||||
{
|
||||
a = -m_ha_mag;
|
||||
}
|
||||
else if (mag == 1)
|
||||
{
|
||||
b = m_ha_mag;
|
||||
}
|
||||
else if (mag == 2)
|
||||
{
|
||||
a = m_ha_mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = -m_ha_mag;
|
||||
}
|
||||
|
||||
//perpendicular to (a,b)
|
||||
out[0] = -b;
|
||||
out[1] = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConvectionCoeff::Eval(mfem::Vector &V, mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
|
||||
V.SetSize(2);
|
||||
m_problem.getMuSigmaV(transip, V);
|
||||
}
|
||||
|
||||
|
||||
void MagnetizationCoeff::Eval(mfem::Vector &V, mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
|
||||
V.SetSize(2);
|
||||
m_problem.getMPerp(transip, V);
|
||||
}
|
||||
|
||||
|
||||
//1/mu for the Jz = -laplace(1/mu Az) calculation
|
||||
double MuInvCoeff::Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
return 1.0 / m_problem.getMu(transip);
|
||||
}
|
||||
|
||||
|
||||
double VxCoeff::Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
return m_problem.getVx(transip);
|
||||
}
|
||||
|
||||
|
||||
double MuCoeff::Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
return m_problem.getMu(transip);
|
||||
}
|
||||
|
||||
|
||||
double SigmaCoeff::Eval(mfem::ElementTransformation &T,
|
||||
const mfem::IntegrationPoint &ip)
|
||||
{
|
||||
double x[3];
|
||||
mfem::Vector transip(x, 3);
|
||||
|
||||
T.Transform(ip, transip);
|
||||
return 1.0 / m_problem.getSigma(transip);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Use the MFEM build directory
|
||||
MFEM_DIR ?= ../../..
|
||||
MFEM_BUILD_DIR ?= ../../..
|
||||
SRC = $(MFEM_DIR)/miniapps/electromagnetics/maglev/
|
||||
CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
TEST_MK = $(MFEM_DIR)/config/test.mk
|
||||
COMMON_O=../../common/pfem_extras.o
|
||||
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
SEQ_MINIAPPS = maglev
|
||||
PAR_MINIAPPS =
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
MINIAPPS = $(SEQ_MINIAPPS)
|
||||
else
|
||||
MINIAPPS = $(PAR_MINIAPPS) $(SEQ_MINIAPPS)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .cpp .mk
|
||||
.PHONY: all clean clean-build clean-exec
|
||||
.PRECIOUS: %.o
|
||||
|
||||
# Remove built-in rules
|
||||
%: %.cpp
|
||||
%.o: %.cpp
|
||||
|
||||
all: $(MINIAPPS)
|
||||
|
||||
# Rules for building the miniapps
|
||||
$(MINIAPPS): \
|
||||
%: $(SRC)%.cpp $(COMMON_O) $(MFEM_LIB_FILE) $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) $< -o $@ ../../common/pfem_extras.o $(MFEM_LIBS)
|
||||
|
||||
$(COMMON_O): \
|
||||
%.o: $(SRC)%.cpp $(SRC)%.hpp $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) -c $(<) -o $(@)
|
||||
|
||||
MFEM_TESTS = MINIAPPS
|
||||
include $(TEST_MK)
|
||||
|
||||
# Generate an error message if the MFEM library is not built and exit
|
||||
$(MFEM_LIB_FILE):
|
||||
$(error The MFEM library is not built)
|
||||
|
||||
clean: clean-build clean-exec
|
||||
|
||||
clean-build:
|
||||
rm -f *.o *~ $(SEQ_MINIAPPS) $(PAR_MINIAPPS)
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
|
||||
clean-exec:
|
||||
rm -rf maglev
|
||||
rm -rf *.000000 *.00000 maglev_000000 maglev_000000.mfem_root
|
||||
Reference in New Issue
Block a user