On Mon, 29 Oct 2012, Kirk, Benjamin (JSC-EG311) wrote:
I don't think there are any examples that currently show this - I'll
try to add one after the next release.
See the attached ~300 lines of code. It reads a mesh and solution, L2
projects and then plots all gradient components of all solution
variables. It needs to be changed to have more than just
Tecplot-or-GMV output, and as you may have guessed this implies I
haven't tested it in a couple years, but other than that it ought to
be ready to drop in as fem_system_ex2.
---
Roy
// Open the mesh and solution file named in command line arguments,
// L2 project their gradient components,
// and plot them out to the given filename.
#include "libmesh.h"
#include "dof_map.h"
#include "equation_systems.h"
#include "fe_base.h"
#include "fem_context.h"
#include "fem_system.h"
#include "mesh.h"
#include "quadrature.h"
#include "system.h"
#include "gmv_io.h"
#include "tecplot_io.h"
class GradientSystem : public FEMSystem
{
public:
// Constructor
GradientSystem(EquationSystems& es,
const std::string& name,
const unsigned int number)
: FEMSystem(es, name, number) {}
System *original_system;
protected:
// System initialization
virtual void init_data ();
// Context initialization
virtual void init_context (DiffContext &context);
// Element residual and jacobian calculations
virtual bool element_constraint (bool request_jacobian,
DiffContext &context);
};
void GradientSystem::init_data ()
{
unsigned int n_original_vars = original_system->n_vars();
for (unsigned int v=0; v != n_original_vars; ++v)
{
std::string varname = original_system->variable_name(v);
this->add_variable(varname+"_x",
original_system->variable_type(v).order,
original_system->variable_type(v).family);
#if LIBMESH_DIM > 1
this->add_variable(varname+"_y",
original_system->variable_type(v).order,
original_system->variable_type(v).family);
#endif
#if LIBMESH_DIM > 2
this->add_variable(varname+"_z",
original_system->variable_type(v).order,
original_system->variable_type(v).family);
#endif
}
// Do the parent's initialization after variables are defined
FEMSystem::init_data();
}
void GradientSystem::init_context(DiffContext &context)
{
FEMContext &c = libmesh_cast_ref<FEMContext&>(context);
unsigned int n_original_vars = original_system->n_vars();
// Make sure we have requested all the data we need to build each
// linear system. Since we're reusing FEs of the same FEType, we
// don't need to do separate _x,_y,_z requests.
for (unsigned int v=0; v != n_original_vars; ++v)
{
c.element_fe_var[v]->get_JxW();
c.element_fe_var[v]->get_phi();
c.element_fe_var[v]->get_dphi();
}
FEMSystem::init_context(context);
}
bool GradientSystem::element_constraint (bool request_jacobian,
DiffContext &context)
{
FEMContext &c = libmesh_cast_ref<FEMContext&>(context);
unsigned int n_original_vars = original_system->n_vars();
// We assemble a separate linear system for each gradient direction
// of each variable. Solving this fully-coupled is unnecessary but
// doesn't hurt much.
for (unsigned int v = 0; v != n_original_vars; ++v)
{
// We have LIBMESH_DIM gradient variables for each original
// variable
unsigned int vx = v * LIBMESH_DIM;
#if LIBMESH_DIM > 1
unsigned int vy = v * LIBMESH_DIM+1;
#endif
#if LIBMESH_DIM > 2
unsigned int vz = v * LIBMESH_DIM+2;
#endif
// Element Jacobian * quadrature weights for interior integration
const std::vector<Real> &JxW = c.element_fe_var[v]->get_JxW();
// For test function values
const std::vector<std::vector<Real> > &phi =
c.element_fe_var[v]->get_phi();
// For target gradient values
const std::vector<std::vector<RealGradient> > &dphi =
c.element_fe_var[v]->get_dphi();
// The target dof indices
std::vector<unsigned int> original_dof_indices;
original_system->get_dof_map().dof_indices(c.elem, original_dof_indices,
v);
// The number of local degrees of freedom
const unsigned int n_u_dofs = c.dof_indices_var[vx].size();
// We're using the same basis for the original system and for
// each gradient component
libmesh_assert(n_u_dofs == original_dof_indices.size());
#if LIBMESH_DIM > 1
libmesh_assert(n_u_dofs == c.dof_indices_var[vy].size());
#endif
#if LIBMESH_DIM > 2
libmesh_assert(n_u_dofs == c.dof_indices_var[vz].size());
#endif
// The subvectors and submatrices we need to fill:
DenseSubMatrix<Number> &Kxx = *c.elem_subjacobians[vx][vx];
DenseSubVector<Number> &Fx = *c.elem_subresiduals[vx];
#if LIBMESH_DIM > 1
DenseSubMatrix<Number> &Kyy = *c.elem_subjacobians[vy][vy];
DenseSubVector<Number> &Fy = *c.elem_subresiduals[vy];
#endif
#if LIBMESH_DIM > 2
DenseSubMatrix<Number> &Kzz = *c.elem_subjacobians[vz][vz];
DenseSubVector<Number> &Fz = *c.elem_subresiduals[vz];
#endif
// Now we will build the element Jacobian and residual.
// Constructing the residual requires the solution and its
// gradient from the previous timestep. This must be
// calculated at each quadrature point by summing the
// solution degree-of-freedom values by the appropriate
// weight functions.
const unsigned int n_qpoints = c.element_qrule->n_points();
for (unsigned int qp=0; qp != n_qpoints; qp++)
{
// Compute the gradient we want to project
Gradient g = 0.;
for (unsigned int l=0; l != n_u_dofs; l++)
{
g.add_scaled(dphi[l][qp],
original_system->current_solution(original_dof_indices[l]));
}
// Compute the solution at the Newton iterate; we don't want
// the solution to drift if the user uses too weak a linear
// tolerance
const Number ux_iter = c.interior_value(vx, qp);
#if LIBMESH_DIM > 1
const Number uy_iter = c.interior_value(vy, qp);
#endif
#if LIBMESH_DIM > 2
const Number uz_iter = c.interior_value(vz, qp);
#endif
for (unsigned int i=0; i != n_u_dofs; i++)
{
Fx(i) += JxW[qp] * (ux_iter - g(0)) * phi[i][qp];
#if LIBMESH_DIM > 1
Fy(i) += JxW[qp] * (uy_iter - g(1)) * phi[i][qp];
#endif
#if LIBMESH_DIM > 2
Fz(i) += JxW[qp] * (uz_iter - g(2)) * phi[i][qp];
#endif
}
if (request_jacobian)
for (unsigned int i=0; i != n_u_dofs; i++)
for (unsigned int j=0; j != n_u_dofs; ++j)
{
Kxx(i,j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
#if LIBMESH_DIM > 1
Kyy(i,j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
#endif
#if LIBMESH_DIM > 2
Kzz(i,j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
#endif
}
} // end of the quadrature point qp-loop
} // end of the variable v-loop
return request_jacobian;
}
int main(int argc, char** argv)
{
LibMeshInit init(argc, argv);
Mesh mesh;
EquationSystems es(mesh);
std::cout << "Usage: " << argv[0]
<< " inputmesh inputsolution outputsolution" << std::endl;
START_LOG("mesh.read()", "main");
mesh.read(argv[1]);
std::cout << "Loaded mesh " << argv[1] << std::endl;
STOP_LOG("mesh.read()", "main");
START_LOG("es.read()", "main");
std::string solnname = argv[2];
libmesh_assert(solnname.find(".xdr") != std::string::npos ||
solnname.find(".xda") != std::string::npos);
const bool binary = (solnname.find(".xdr") != std::string::npos);
es.read(argv[2], binary ? libMeshEnums::DECODE : libMeshEnums::READ,
EquationSystems::READ_HEADER |
EquationSystems::READ_DATA |
EquationSystems::READ_ADDITIONAL_DATA);
std::cout << "Loaded " << (binary ? "binary" : "ascii") << " solution " <<
argv[2] << std::endl;
STOP_LOG("es.read()", "main");
const unsigned int n_systems = es.n_systems();
// We'll use a copy of the mesh and a new EquationSystems so as to
// leave the original Systems out of our writes
AutoPtr<MeshBase> newmesh = mesh.clone();
EquationSystems newes(*newmesh);
for (unsigned int s = 0; s != n_systems; ++s)
{
System &orig = es.get_system(s);
std::string sysname = orig.name();
GradientSystem &gradsys = newes.add_system<GradientSystem>(sysname);
gradsys.original_system = &orig;
}
newes.solve();
START_LOG("write_equation_systems()", "main");
std::string outputname(argv[3]);
if (outputname.find(".gmv") != std::string::npos)
GMVIO(*newmesh).write_equation_systems (outputname, newes);
else if (outputname.find(".plt") != std::string::npos)
TecplotIO(*newmesh).write_equation_systems (outputname, es);
STOP_LOG("write_equation_systems()", "main");
std::cout << "Wrote output " << argv[3] << std::endl;
}
------------------------------------------------------------------------------
The Windows 8 Center - In partnership with Sourceforge
Your idea - your app - 30 days.
Get started!
http://windows8center.sourceforge.net/
what-html-developers-need-to-know-about-coding-windows-8-metro-style-apps/
_______________________________________________
Libmesh-devel mailing list
Libmesh-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libmesh-devel