Reading a Tensor from parameter file

91 views
Skip to first unread message

Paras Kumar

unread,
Apr 14, 2020, 11:12:39 AM4/14/20
to deal.II User Group
Dear deal.II community,

I am trying to read a second order tensor from a .prm file using the ParameterHandler functionalities. The tensor (for dim=3) is set in .prm file as

  set macro def grad = 1.2|0.0|0.0|0.0|1.1|0.0|0.0|0.0|1.4

and is currently read as a string using
parameterHandler.declare_entry(
         
"macro def grad",
         
"1.0|1.0|1.0|1.0",
          dealii
::Patterns::Anything(),
         
"Macroscopic deformation gradient for homogenization");

auto temp = parameterHandler.get("macro def grad");
std
::vector<std::string> defGradComps;
boost
::algorithm::split(defGradComps,
                        temp
,
                       boost
::algorithm::is_any_of("|"));
Assert(defGradComps.size() == dim * dim,
       dealii
::ExcDimensionMismatch(defGradComps.size(),
                                                dim
* dim));
           
for (mncfrac::utilities::UnsignedIntType i = 0; i < dim; ++i)
             
for (mncfrac::utilities::UnsignedIntType j = 0; j < dim; ++j)
               
this->problemSpecificParameters_.macroDefGrad_[i][j] =
                  std
::stod(defGradComps[i * dim + j]);


I am curious to know, if there is a smarter way (avoiding this manual copying by looping over the tensor entries) to do so using some other type of dealii::Patterns object or some other way.

Thanks in advance and best regards,
Paras Kumar

Ahmad Shahba

unread,
Apr 14, 2020, 11:39:06 AM4/14/20
to dea...@googlegroups.com
I don't know if it is the optimal way but I would use the following approach
  1. Read tensor components as Patterns::List
  2. Use  get  method of ParameterHandler to read all tensor  components as one string into a string variable
  3. Use  split_string_list   in the Utilities namespace to split the string into individual components (still all components are strings)
  4. Convert  string-type components into doubles using  string_to_double in the Utilities namespace
  5. Use  Tensor (const Tensor< rank_, dim, OtherNumber > &initializer) to construct the tensor

--
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see https://groups.google.com/d/forum/dealii?hl=en
---
You received this message because you are subscribed to the Google Groups "deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dealii+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dealii/595804dd-818f-4fd6-86ba-f4e3d7d378a6%40googlegroups.com.

Paras Kumar

unread,
Apr 15, 2020, 3:54:57 AM4/15/20
to deal.II User Group
Ahmad,


On Tuesday, April 14, 2020 at 5:39:06 PM UTC+2, Ahmad Shahba wrote:
I don't know if it is the optimal way but I would use the following approach
  1. Read tensor components as Patterns::List
  2. Use  get  method of ParameterHandler to read all tensor  components as one string into a string variable
  3. Use  split_string_list   in the Utilities namespace to split the string into individual components (still all components are strings)
  4. Convert  string-type components into doubles using  string_to_double in the Utilities namespace
  5. Use  Tensor (const Tensor< rank_, dim, OtherNumber > &initializer) to construct the tensor
Could you please elaborate on pointa 1 and 5, or share a code snippet which explains the process.

Best,
Paras

Ahmad Shahba

unread,
Apr 15, 2020, 8:53:55 AM4/15/20
to deal.II User Group
Here is the code that does what I explained. I just switched up step 5 with a much simpler approach. Note that you can simply make this into a function/class template so that you could read general tensors, not just 3x3 tensors. I leave that to you :-)

#include <deal.II/base/tensor.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/utilities.h>
#include <string>
#include <iostream>
#include <sstream>

using namespace dealii;

int main() {


   
// Let's read this tensor from an istringstream. You may read it from istream in your
    // application
    std::istringstream is("set Tensor3x3 = 11, 12, 13, 21, 22, 23, 31, 32, 33");


    // Now let's set up the ParameterHandler object. Since you are reading 3x3 tensor, you are
    // dealing with 9 components and the default value should also have 9 components (here 9
    // zeros) in it
    ParameterHandler prm;

    using Patterns::List;
    using Patterns::Double;
    prm.declare_entry("Tensor3x3",
                      "0,0,0,0,0,0,0,0,0",
                      List(Double(), 9, 9),
                      "Tensor components");


    // Let's read it in now
    prm.parse_input(is);
    const std::string tensorString = prm.get("Tensor3x3");

    // Now let's split the string into individual components
    const std::vector<std::string> tensorComponentsString =
           
Utilities::split_string_list(tensorString);

    // Now go over each component, convert it into double and put it in the tensor
    Tensor<2, 3> tensor;
    unsigned int counter = 0;
    for (unsigned ii = 0; ii < tensor.dimension; ++ii) {
       
for (unsigned jj = 0; jj < tensor.dimension; ++jj) {
            tensor
[ii][jj] = Utilities::string_to_double(tensorComponentsString[counter++]);
        }
   
}


   
// Let's check if we read the tensor correctly
    for (unsigned ii = 0; ii < tensor.dimension; ++ii) {
       
for (unsigned jj = 0; jj < tensor.dimension; ++jj) {
           
std::cout << "component [" << ii << ", " << jj << " ] = "
                      << tensor[ii][jj] << std::endl;
        }
   
}


}




Ahmad Shahba

unread,
Apr 15, 2020, 8:57:07 AM4/15/20
to deal.II User Group
Ooops! The background was too dark :-)

Enter code here...

Luca Heltai

unread,
Apr 15, 2020, 12:01:53 PM4/15/20
to dea...@googlegroups.com
Currently, this is also the simplest way:

Tensor<rank, dim> tens;
prm.add_parameter("Tensor", tens);

Take a look at the documentation of the add parameter method.

Patterns::Tools::to_string(tens);

And 

Patterns::Tools::to_value 

Are also available to simplify what you want to achieve. 

Alternatively: Patterns::Tools::Convert offers ways to construct default Patterns for many types, including Tensors. 

Best,
Luca

Il giorno 15 apr 2020, alle ore 14:57, Ahmad Shahba <ah.s...@gmail.com> ha scritto:


--
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see https://groups.google.com/d/forum/dealii?hl=en
---
You received this message because you are subscribed to the Google Groups "deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dealii+un...@googlegroups.com.

Paras Kumar

unread,
Aug 4, 2020, 12:15:47 PM8/4/20
to deal.II User Group
Hi,

Could you please provide an MWE to describe how the Patterns::Convert::to_value() function would work in this case.

Is it must to use prm.add_parameter()  to be able to do so? I usually use prm.declare_entry() and prm.get().

Best regards,
Paras

luca.heltai

unread,
Aug 5, 2020, 5:49:51 AM8/5/20
to Deal.II Users
> Could you please provide an MWE to describe how the Patterns::Convert::to_value() function would work in this case.

In the dealii/tests/parameter_handler/patterns_05.cc

there are many examples that show how to use these.

> Is it must to use prm.add_parameter() to be able to do so?
> I usually use prm.declare_entry() and prm.get().


No. It is more convenient, but not necessary:

Tensor<rank, dim> tensor;

using C = Patterns::Tools::Convert<Tensor<rank, dim>>;

prm.declare_entry(“My tensor”, C::to_string(tensor), *C::to_pattern(), “Documentation”);

...

tensor = C::to_value(prm.get(“My tensor”));


Best,
Luca.

Paras Kumar

unread,
Aug 5, 2020, 11:09:26 AM8/5/20
to deal.II User Group
Dear Luca,

Thank you. This really shortens the code. Is it also possible to set the delimiter to a user desired value, say "|" instead of ",". Also, where exactly is the procedure for conversion from string to deali::Tensor or some other type say std::vector<double> defined? I could not find it in the source code.

Best regards,
Paras

Luca Heltai

unread,
Aug 5, 2020, 11:30:17 AM8/5/20
to dea...@googlegroups.com

Thank you. This really shortens the code. Is it also possible to set the delimiter to a user desired value, say "|" instead of ",".

All functions of the Convert class take a unique pointer to a pattern. You can specify your own pattern, and use that in the conversion. The code is all in

deal.II/base/patterns_tools.h

After the Class declarations, you’ll find the implementations for the basic classes of deal.II, including vector, map, pairs and tuples of them. 

Best,
Luca 

Also, where exactly is the procedure for conversion from string to deali::Tensor or some other type say std::vector<double> defined? I could not find it in the source code.

Best regards,
Paras

On Tuesday, August 4, 2020 at 6:15:47 PM UTC+2, Paras Kumar wrote:
Hi,

Could you please provide an MWE to describe how the Patterns::Convert::to_value() function would work in this case.

Is it must to use prm.add_parameter()  to be able to do so? I usually use prm.declare_entry() and prm.get().

Best regards,
Paras

On Wednesday, April 15, 2020 at 6:01:53 PM UTC+2, Luca Heltai wrote:
Currently, this is also the simplest way:

Tensor<rank, dim> tens;
prm.add_parameter("Tensor", tens);

Take a look at the documentation of the add parameter method.

Patterns::Tools::to_string(tens);

And 

Patterns::Tools::to_value 

Are also available to simplify what you want to achieve. 

Alternatively: Patterns::Tools::Convert offers ways to construct default Patterns for many types, including Tensors. 

Best,
Luca

 

--
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see https://groups.google.com/d/forum/dealii?hl=en
---
You received this message because you are subscribed to the Google Groups "deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dealii+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages