Comments (12)
@ryanblack129 There is a new branchmoonolith_h1_bugfix
where the bug is resolved. The example now runs H1 by default and the results look correct also in parallel. Let me know if you encounter any other problems.
from mfem.
I will prepare two pull requests next month for both bug fixes and new features, as my schedule is already quite dense this month. Cheers.
from mfem.
Thank you so much, everything works great for me
from mfem.
Hello,
Thank you for your interest. The support for vector FE is experimental in general (see VectorL2MortarIntegrator class description). Vector H1 was never considered. I will look into it and see if support can be properly added, which should be quite likely since it works in serial.
from mfem.
Please let me know if you are on a schedule for using this feature.
Best regards
from mfem.
Thank you for getting back to me.
I am working on an application code, and I am at the point where I would like to incorporate this feature. Ideally, as soon as you can.
from mfem.
Thank you so much, the example works for me in parallel.
Did you also have a chance to see if Vector H1 spaces could be supported? For my application code, I am working with this type of space and have an immediate need to incorporate this feature into my code. If it is at all possible to do this, I would really appreciate it.
Thanks,
Ryan
from mfem.
Sure thing. It would be great if you could create an example file with the intended usage (or equivalent modifications like you did for the bug). This way I can be sure about what you want to do.
from mfem.
Thank you, I will put together a small example and share it with you
from mfem.
// MFEM + Moonolith Example 1 (parallel version)
//
// Compile with: make ex1p
//
// Moonolith sample runs:
// mpirun -np 4 ex1p
// mpirun -np 4 ex1p --source_refinements 1 --dest_refinements 2
// mpirun -np 4 ex1p -s ../../data/inline-hex.mesh -d
// ../../data/inline-tet.mesh
//
// Description: This example code demonstrates the use of MFEM for transferring
// discrete fields from one finite element mesh to another. The
// meshes can be of arbitrary shape and completely unrelated with
// each other. This feature can be used for implementing immersed
// domain methods for fluid-structure interaction or general
// multi-physics applications.
//
// This particular example is for parallel runtimes. Vector FE is
// an experimental feature in parallel.
#include "example_utils.hpp"
#include "mfem.hpp"
using namespace mfem;
using namespace std;
void destination_transform(const Vector &x, Vector &x_new)
{
x_new = x;
// x_new *= 0.5;
}
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int num_procs, rank;
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Init transfer library context, with MPI handled outside the library
InitTransfer(argc, argv, MPI_COMM_WORLD);
const char *source_mesh_file = "../../data/inline-tri.mesh";
const char *destination_mesh_file = "../../data/inline-quad.mesh";
int src_n_refinements = 0;
int dest_n_refinements = 0;
int source_fe_order = 1;
int dest_fe_order = 1;
bool visualization = true;
bool use_vector_fe = false;
bool use_h1 = true;
bool use_vector_space = true;
bool verbose = false;
bool assemble_mass_and_coupling_together = true;
OptionsParser args(argc, argv);
args.AddOption(&source_mesh_file, "-s", "--source_mesh",
"Mesh file to use for src.");
args.AddOption(&destination_mesh_file, "-d", "--destination_mesh",
"Mesh file to use for dest.");
args.AddOption(&src_n_refinements, "-sr", "--source_refinements",
"Number of src refinements");
args.AddOption(&dest_n_refinements, "-dr", "--dest_refinements",
"Number of dest refinements");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&source_fe_order, "-so", "--source_fe_order",
"Order of the src finite elements");
args.AddOption(&dest_fe_order, "-do", "--dest_fe_order",
"Order of the dest finite elements");
args.AddOption(&verbose, "-verb", "--verbose", "--no-verb", "--no-verbose",
"Enable/Disable verbose output");
args.AddOption(&use_vector_fe, "-vfe", "--use_vector_fe", "-no-vfe",
"--no-vector_fe", "Use vector finite elements (Experimental)");
args.AddOption(&use_h1, "-h1", "--use-h1", "-nh1", "--no-h1",
"Use H1 collection");
args.AddOption(&assemble_mass_and_coupling_together, "-act",
"--assemble_mass_and_coupling_together", "-no-act",
"--no-assemble_mass_and_coupling_together",
"Assemble mass and coupling operators together (better for "
"non-affine elements)");
args.Parse();
check_options(args);
shared_ptr<Mesh> src_mesh, dest_mesh;
ifstream imesh;
imesh.open(destination_mesh_file);
if (imesh)
{
dest_mesh = make_shared<Mesh>(imesh, 1, 1);
imesh.close();
}
else
{
if (rank == 0)
mfem::err << "WARNING: Destination mesh file not found: "
<< destination_mesh_file << "\n"
<< "Using default 2D quad mesh.";
dest_mesh = make_shared<Mesh>(4, 4, Element::QUADRILATERAL);
}
const int dim = dest_mesh->Dimension();
dest_mesh->Transform(&destination_transform);
Vector box_min(dim), box_max(dim), range(dim);
dest_mesh->GetBoundingBox(box_min, box_max);
range = box_max;
range -= box_min;
imesh.open(source_mesh_file);
if (imesh)
{
src_mesh = make_shared<Mesh>(imesh, 1, 1);
imesh.close();
}
else
{
if (rank == 0)
mfem::err << "WARNING: Source mesh file not found: " << source_mesh_file
<< "\n"
<< "Using default box mesh.\n";
if (dim == 2)
{
src_mesh =
make_shared<Mesh>(4, 4, Element::TRIANGLE, 1, range[0], range[1]);
}
else if (dim == 3)
{
src_mesh = make_shared<Mesh>(4, 4, 4, Element::TETRAHEDRON, 1, range[0],
range[1], range[2]);
}
for (int i = 0; i < src_mesh->GetNV(); ++i)
{
double *v = src_mesh->GetVertex(i);
for (int d = 0; d < dim; ++d)
{
v[d] += box_min[d];
}
}
}
for (int i = 0; i < src_n_refinements; ++i)
{
src_mesh->UniformRefinement();
}
for (int i = 0; i < dest_n_refinements; ++i)
{
dest_mesh->UniformRefinement();
}
auto p_src_mesh = make_shared<ParMesh>(MPI_COMM_WORLD, *src_mesh);
auto p_dest_mesh = make_shared<ParMesh>(MPI_COMM_WORLD, *dest_mesh);
shared_ptr<FiniteElementCollection> src_fe_coll, dest_fe_coll;
if (use_vector_fe)
{
src_fe_coll =
make_shared<RT_FECollection>(source_fe_order, src_mesh->Dimension());
dest_fe_coll =
make_shared<RT_FECollection>(dest_fe_order, dest_mesh->Dimension());
}
else
{
if (use_h1)
{
src_fe_coll =
make_shared<H1_FECollection>(source_fe_order, src_mesh->Dimension());
dest_fe_coll =
make_shared<H1_FECollection>(dest_fe_order, dest_mesh->Dimension());
}
else
{
src_fe_coll =
make_shared<L2_FECollection>(source_fe_order, src_mesh->Dimension());
dest_fe_coll =
make_shared<L2_FECollection>(dest_fe_order, dest_mesh->Dimension());
}
}
auto src_fe =
make_shared<ParFiniteElementSpace>(p_src_mesh.get(), src_fe_coll.get(), use_vector_space ? src_mesh->Dimension() : 1);
auto dest_fe =
make_shared<ParFiniteElementSpace>(p_dest_mesh.get(), dest_fe_coll.get(), use_vector_space ? dest_mesh->Dimension() : 1);
ParGridFunction src_fun(src_fe.get());
// To be used with standard fe
FunctionCoefficient coeff(example_fun);
// To be used with vector fe
VectorFunctionCoefficient vector_coeff(dim, &vector_fun);
if (use_vector_fe || use_vector_space)
{
src_fun.ProjectCoefficient(vector_coeff);
src_fun.Update();
}
else
{
src_fun.ProjectCoefficient(coeff);
src_fun.Update();
}
ParGridFunction dest_fun(dest_fe.get());
dest_fun = 0.0;
dest_fun.Update();
ParMortarAssembler assembler(src_fe, dest_fe);
assembler.SetAssembleMassAndCouplingTogether(
assemble_mass_and_coupling_together);
assembler.SetVerbose(verbose);
if (use_vector_fe || use_vector_space)
{
assembler.AddMortarIntegrator(make_shared<VectorL2MortarIntegrator>());
}
else
{
assembler.AddMortarIntegrator(make_shared<L2MortarIntegrator>());
}
if (assembler.Transfer(src_fun, dest_fun))
{
if (visualization)
{
double src_err = 0;
double dest_err = 0;
if (use_vector_fe)
{
src_err = src_fun.ComputeL2Error(vector_coeff);
dest_err = dest_fun.ComputeL2Error(vector_coeff);
}
else
{
src_err = src_fun.ComputeL2Error(coeff);
dest_err = dest_fun.ComputeL2Error(coeff);
}
if (rank == 0)
{
mfem::out << "l2 error: src: " << src_err << ", dest: " << dest_err
<< std::endl;
}
plot(*p_src_mesh, src_fun, "source");
plot(*p_dest_mesh, dest_fun, "destination");
}
}
else
{
mfem::out << "No intersection no transfer!" << std::endl;
}
// Finalize transfer library context
FinalizeTransfer();
return MPI_Finalize();
}
from mfem.
The above extends example 1p for the case I was thinking of. The main change is to replace the lines where the ParFiniteElementSpace
are created with
auto src_fe =
make_shared<ParFiniteElementSpace>(p_src_mesh.get(), src_fe_coll.get(), use_vector_space ? src_mesh->Dimension() : 1);
auto dest_fe =
make_shared<ParFiniteElementSpace>(p_dest_mesh.get(), dest_fe_coll.get(), use_vector_space ? dest_mesh->Dimension() : 1);
from mfem.
@ryanblack129 Thanks. A new implementation to support this feature is now up on the branch moonolith_h1_vector_space
. Both serial and parallel results look ok. Let me know if it works as expected for your case.
from mfem.
Related Issues (20)
- Linking against Spack MFEM package HOT 4
- 【Usage】 How to caculate the right hand side (q\nabla T, v) HOT 5
- Spiro: perhaps an alternative for bezier spline by nurbs for more quality and faster optimization
- Matthek triangle method for fast optimization of edges in mechanics and fluid simulation
- How to extract solution at certain positions in mfem HOT 34
- Overlapping boundary attributes not inherited in submesh HOT 10
- Bug using mesh refinement and BC's HOT 5
- MFEM program crashes when solving linear static analysis problem when using AddBdrTriangle HOT 2
- Adding heat source to ex16 HOT 3
- Can MFEM handle multiple sources at the right hand side of equation HOT 3
- PrintVTK issues HOT 2
- Change some MFEM_ASSERT to MFEM_VERIFY, or report more info's to the users? HOT 2
- Face dofs for Periodic meshes HOT 5
- Inconsistency Between MFEM + ParaView for Symmetric Tensor Outputs HOT 1
- Request for an EasyBuild Configueation file HOT 2
- ND_R2D visualization with glvis fails HOT 3
- Bug: Poor performance for `HypreBoomerAMG` with `Ordering::byNODES` HOT 12
- Multiscale: An FE domain solve for every integration point HOT 1
- Why complex DOFs are split HOT 2
- use multi GPUs to accelerate discontinuous galerkin time domain method
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mfem.