Using ParameterHandler to read in a vector of variable length?

80 views
Skip to first unread message

Ross Kynch

unread,
Jul 17, 2015, 7:56:21 AM7/17/15
to dea...@googlegroups.com
Hi all,

Apologies if this is covered in the documentation but I've gone through every tutorial code which is listed under input parameter handling and I can't find very much on the use of lists.

I'd like to use ParameterHandler to read in a vector of some length, but that length that might change depending on my problem (it'll be a list of material_id's contained in the mesh file - I want to group them into different regions). Is there a way to read this in without having to declare the length as part of the parameter file?

i.e. I want something like prm.declare_entry("vector", "1, 2, 3", Patterns::List(Patterns::Integer()),  "some info");

and then I'd like to initialise a storage vector of the correct length, and then copy the values over to it. Is it possible to access the length of the "vector" list once it's been read in?

Thanks

Ross

Timo Heister

unread,
Jul 17, 2015, 10:25:19 AM7/17/15
to dea...@googlegroups.com
I would declare the parameter as a string, use
Utilities::split_string_list(prm.get("vector")), and then convert the
entries of the std::vector<std::string> to whatever number format you
want.
> --
> 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.
> For more options, visit https://groups.google.com/d/optout.



--
Timo Heister
http://www.math.clemson.edu/~heister/

Guido Kanschat

unread,
Jul 18, 2015, 11:16:26 AM7/18/15
to dea...@googlegroups.com
Dear Ross,

reading the documentation, Patterns::List should allow you to do this. But I cannot find the appropriate "get_list()" in ParameterHandler. Do you know how to access a list that was declared with Patterns::List?

--
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.
For more options, visit https://groups.google.com/d/optout.



--
Prof. Dr. Guido Kanschat
Interdisziplinäres Zentrum für Wissenschaftliches Rechnen
Universität Heidelberg
Im Neuenheimer Feld 368, 69120 Heidelberg

Timo Heister

unread,
Jul 18, 2015, 1:48:21 PM7/18/15
to dea...@googlegroups.com
Guido,

I think the only way to do this is to get() and then split the string
manually (like I described). We only have get(), get_int(),
get_double(), and get_bool(). Adding something like get_list() is a
cool idea but would require looking up the Pattern to find out things
like separator.
Timo Heister
http://www.math.clemson.edu/~heister/

Ross Kynch

unread,
Jul 18, 2015, 4:26:41 PM7/18/15
to dea...@googlegroups.com
Hi Both,

Yes, I was only able to do it using get() and then splitting. I wrote a small function which counted the number of occurences of the specified delimiter and returned the count+1, although I'm fairly sure the split list you described does something very similar (and more).

Maybe it'd be worth adding something to the patterns class along the lines of get_list_length(...) and get_list(...)

R

Wolfgang Bangerth

unread,
Jul 19, 2015, 7:40:49 PM7/19/15
to dea...@googlegroups.com
On 07/18/2015 12:47 PM, Timo Heister wrote:
> I think the only way to do this is to get() and then split the string
> manually (like I described). We only have get(), get_int(),
> get_double(), and get_bool(). Adding something like get_list() is a
> cool idea but would require looking up the Pattern to find out things
> like separator.

Correct. The same issue would of course exist for all of the other Patterns
classes: it's not just about the return type, but possibly other information
as well that ParameterHandler doesn't know but the Pattern does (list
separators are just one example). This is why there is only get(), and the
specializations get_bool(), get_int() and get_double().

One could argue that the fact that we have these latter three is a mistake and
that ParameterHandler should only have get() and then let the user convert
things. I think they're useful, but if I had to write it again today I
probably wouldn't include them any more.

That said, I've occasionally thought that something like this would be nice:


class PatternBase {
public:
// have a function that returns a parameter's value to a type
// that's unclear here, but that derived classes specify
virtual boost::any convert_parameter_value (const std::string &) = 0;
};


template <typename PatternClass>
typename PatternClass::ReturnType
ParameterHandler::get (const std::string &param_name) const {
{
// look up the value, let the stored pattern convert to a
// type that matches the pattern, return it as a generic
// type so we can use the virtual function, then here
// any_cast it back to what the user wants
//
// the any_cast will fail if the template argument does
// not match the pattern you gave when the parameter was
// declared
return boost::any_cast<typename PatternClass::ReturnType>
(...look up pattern for param_name...
->convert_parameter_value (this->get (param_name)));
};


Then we could have this:

class Patterns::Integer {
public:
typedef ReturnType int;
virtual boost::any convert_parameter_value (const std::string &s)
{ return boost::lexical_cast<int>(s); }
};

and call
int i = prm.get<Patterns::Integer> ("integer_parameter");
which would do the same as we currently do with
int i = prm.get_int ("integer_parameter");


The problem is that individual patterns can only statically declare the type
of their values, i.e., Patterns::List would need to declare it as
typedef std::list<std::string> ReturnType;
or
typedef std::vector<std::string> ReturnType;
regardless whether you are using it in a context where you expect the user to
pass in a list of integers, a list of doubles, or a list of strings. In other
words, the conversion of the *inner* type does not happen; on the other hand,
one would not have to repeat the separator for the list at both the place
where the parameter is declared and the place where it is retrieved from
ParaneterHandler.

If people think that this facility would nevertheless be useful, then I'd be
happy to code this up in final form.

Best
W.

--
------------------------------------------------------------------------
Wolfgang Bangerth email: bang...@math.tamu.edu
www: http://www.math.tamu.edu/~bangerth/

Reply all
Reply to author
Forward
0 new messages