I've attached a patch that I've tried for fixing output with complex
values (it doesn't work yet). The approach I've used is based on Paul's
suggestion in issue #47 on github.
I tested it with introduction_ex4 (using Exodus format) and it gives
incorrect solution fields.
It seems like the problem is in the indexing into soln in
EquationSystems::build_solution_vector, but it's not obvious to me how
to fix it. If someone more familiar with this section of the code could
have a look, that'd be helpful.
Thanks,
David
diff --git a/include/base/libmesh_common.h b/include/base/libmesh_common.h
index afabdb1..c81e3ac 100644
--- a/include/base/libmesh_common.h
+++ b/include/base/libmesh_common.h
@@ -140,12 +140,16 @@ typedef std::complex<Real> COMPLEX;
// Helper functions for complex/real numbers
// to clean up #ifdef LIBMESH_USE_COMPLEX_NUMBERS elsewhere
template<typename T> inline T libmesh_real(T a) { return a; }
+template<typename T> inline T libmesh_imag(T a) { return a; }
template<typename T> inline T libmesh_conj(T a) { return a; }
template<typename T>
inline T libmesh_real(std::complex<T> a) { return std::real(a); }
template<typename T>
+inline T libmesh_imag(std::complex<T> a) { return std::imag(a); }
+
+template<typename T>
inline std::complex<T> libmesh_conj(std::complex<T> a) { return std::conj(a); }
// isnan isn't actually C++ standard yet; in contexts where it's not defined in
diff --git a/src/mesh/gmv_io.C b/src/mesh/gmv_io.C
index 0bb225b..257936e 100644
--- a/src/mesh/gmv_io.C
+++ b/src/mesh/gmv_io.C
@@ -467,45 +467,12 @@ void GMVIO::write_ascii_new_impl (const std::string&
fname,
for (unsigned int c=0; c<n_vars; c++)
{
-
-#ifdef LIBMESH_USE_COMPLEX_NUMBERS
-
- // in case of complex data, write _three_ data sets
- // for each component
-
- // this is the real part
- out_stream << "r_" << (*solution_names)[c] << " 1\n";
-
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << (*v)[n*n_vars + c].real() << " ";
-
- out_stream << "\n\n";
-
- // this is the imaginary part
- out_stream << "i_" << (*solution_names)[c] << " 1\n";
-
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << (*v)[n*n_vars + c].imag() << " ";
-
- out_stream << "\n\n";
-
- // this is the magnitude
- out_stream << "a_" << (*solution_names)[c] << " 1\n";
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << std::abs((*v)[n*n_vars + c]) << " ";
-
- out_stream << "\n\n";
-
-#else
-
out_stream << (*solution_names)[c] << " 1\n";
for (unsigned int n=0; n<mesh.n_nodes(); n++)
out_stream << (*v)[n*n_vars + c] << " ";
out_stream << "\n\n";
-
-#endif
}
}
@@ -1134,46 +1101,12 @@ void GMVIO::write_ascii_old_impl (const std::string&
fname,
for (unsigned int c=0; c<n_vars; c++)
{
-
-#ifdef LIBMESH_USE_COMPLEX_NUMBERS
-
- // in case of complex data, write _tree_ data sets
- // for each component
-
- // this is the real part
- out_stream << "r_" << (*solution_names)[c] << " 1\n";
-
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << (*v)[n*n_vars + c].real() << " ";
-
- out_stream << '\n' << '\n';
-
-
- // this is the imaginary part
- out_stream << "i_" << (*solution_names)[c] << " 1\n";
-
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << (*v)[n*n_vars + c].imag() << " ";
-
- out_stream << '\n' << '\n';
-
- // this is the magnitude
- out_stream << "a_" << (*solution_names)[c] << " 1\n";
- for (unsigned int n=0; n<mesh.n_nodes(); n++)
- out_stream << std::abs((*v)[n*n_vars + c]) << " ";
-
- out_stream << '\n' << '\n';
-
-#else
-
out_stream << (*solution_names)[c] << " 1\n";
for (unsigned int n=0; n<mesh.n_nodes(); n++)
out_stream << (*v)[n*n_vars + c] << " ";
out_stream << '\n' << '\n';
-
-#endif
}
}
diff --git a/src/systems/equation_systems.C b/src/systems/equation_systems.C
index 557ab2e..50edb59 100644
--- a/src/systems/equation_systems.C
+++ b/src/systems/equation_systems.C
@@ -522,6 +522,12 @@ void EquationSystems::build_variable_names
(std::vector<std::string>& var_names,
// Here, we're assuming the number of vector components is the same
// as the mesh dimension. Will break for mixed dimension meshes.
+#ifdef LIBMESH_USE_COMPLEX_NUMBERS
+ // If we have --enable-complex, then we triple nv because we want
+ // to write out the real, imaginary and absolute value for each variable
+ nv *= 3;
+#endif
+
var_names.resize( nv );
}
@@ -551,6 +557,9 @@ void EquationSystems::build_variable_names
(std::vector<std::string>& var_names,
// Filter on the type if requested
if (type == NULL || (type && *type == fe_type))
{
+
+#ifndef LIBMESH_USE_COMPLEX_NUMBERS
+ // Code path for writing out real-valued data
if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
{
switch(n_vec_dim)
@@ -574,7 +583,52 @@ void EquationSystems::build_variable_names
(std::vector<std::string>& var_names,
}
}
else
- var_names[var_num++] = var_name;
+ {
+ var_names[var_num++] = var_name;
+ }
+#else
+ // Code path for --enable-complex, since we need to write out 3
values per variable
+ if( FEInterface::field_type(fe_type) == TYPE_VECTOR )
+ {
+ switch(n_vec_dim)
+ {
+ case 0:
+ case 1:
+ var_names[var_num++] = var_name+"_r";
+ var_names[var_num++] = var_name+"_i";
+ var_names[var_num++] = var_name+"_a";
+ break;
+ case 2:
+ var_names[var_num++] = var_name+"_x_r";
+ var_names[var_num++] = var_name+"_x_i";
+ var_names[var_num++] = var_name+"_x_a";
+ var_names[var_num++] = var_name+"_y_r";
+ var_names[var_num++] = var_name+"_y_i";
+ var_names[var_num++] = var_name+"_y_a";
+ break;
+ case 3:
+ var_names[var_num++] = var_name+"_x_r";
+ var_names[var_num++] = var_name+"_x_i";
+ var_names[var_num++] = var_name+"_x_a";
+ var_names[var_num++] = var_name+"_y_r";
+ var_names[var_num++] = var_name+"_y_i";
+ var_names[var_num++] = var_name+"_y_a";
+ var_names[var_num++] = var_name+"_z_r";
+ var_names[var_num++] = var_name+"_z_i";
+ var_names[var_num++] = var_name+"_z_a";
+ break;
+ default:
+ libMesh::err << "Invalid dim in build_variable_names" <<
std::endl;
+ libmesh_error();
+ }
+ }
+ else
+ {
+ var_names[var_num++] = var_name+"_r";
+ var_names[var_num++] = var_name+"_i";
+ var_names[var_num++] = var_name+"_a";
+ }
+#endif
}
}
}
@@ -730,7 +784,14 @@ void EquationSystems::build_solution_vector
(std::vector<Number>& soln,
nv = n_scalar_vars + dim*n_vector_vars;
}
- soln.resize(nn*nv);
+#ifdef LIBMESH_USE_COMPLEX_NUMBERS
+ // If we're using --enable-complex, then we
+ // store real, imag and abs for each variable
+ soln.resize(3*nn*nv);
+#else
+ soln.resize(nn*nv);
+#endif
+
// Zero out the soln vector
std::fill (soln.begin(), soln.end(), libMesh::zero);
@@ -846,12 +907,29 @@ void EquationSystems::build_solution_vector
(std::vector<Number>& soln,
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
repeat_count[elem->node(n)]++;
+
+#ifndef LIBMESH_USE_COMPLEX_NUMBERS
+ // Set entries of soln in the real-valued case
for( unsigned int d=0; d < n_vec_dim; d++ )
{
// For vector-valued elements, all components are
in nodal_soln. For each
// node, the components are stored in order, i.e.
node_0 -> s0_x, s0_y, s0_z
soln[nv*(elem->node(n)) + (var+d + var_num)] +=
nodal_soln[n_vec_dim*n+d];
}
+#else
+ // Set entries of soln in the complex-valued case
+ for( unsigned int d=0; d < n_vec_dim; d++ )
+ {
+ // We triple index in order to leave room for the
real, imag and abs parts
+ unsigned int index = 3*(nv*(elem->node(n)) + var +
var_num);
+ Number value = nodal_soln[n];
+ soln[index] += value.real();
+ soln[index+1] += value.imag();
+ soln[index+2] += std::abs(value);
+ }
+#endif
+
+
}
}
} // end loop over elements
@@ -867,8 +945,20 @@ void EquationSystems::build_solution_vector
(std::vector<Number>& soln,
for (unsigned int n=0; n<nn; n++)
for( unsigned int d=0; d < n_vec_dim; d++ )
+ {
+#ifndef LIBMESH_USE_COMPLEX_NUMBERS
soln[nv*n + (var+d + var_num)] /=
static_cast<Real>(std::max (repeat_count[n], one));
+#else
+ Real repeat_count_for_node =
+ static_cast<Real>(std::max (repeat_count[n], one));
+
+ unsigned int index = 3*(nv*n + var + d + var_num);
+ soln[index] /= repeat_count_for_node;
+ soln[index+1] /= repeat_count_for_node;
+ soln[index+2] /= repeat_count_for_node;
+#endif
+ }
} // end loop on variables in this system
------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel