From: KIRK, B. (JSC-E. (NASA) <ben...@na...> - 2005-05-09 16:07:44
|
I think autoheader would break, but we can handle that manually. We would need to create the include files manually and use the standard autoconf @REPLACE@ syntax to create foo.h from foo.h.in -Ben -----Original Message----- From: lib...@li... [mailto:lib...@li...] On Behalf Of John Peterson Sent: Monday, May 09, 2005 9:25 AM To: lib...@li... Subject: [Libmesh-devel] libmesh_config.h Hi, It occurs to me that the libmesh_config.h file is a huge bottleneck for compilation. For example, if I have a working copy of LibMesh and do ./configure --disable-triangle (or any other contributed package) this effectively changes the libmesh_config.h file and forces a recompile of every source that includes that header (which is a lot). Some additional granularity should help here (at the cost of some complexity.) One basic break-down I can think of is to use the current directory structure to define multiple libmesh_foo_config.h files. For example libmesh_mesh_config.h libmesh_fe_config.h libmesh_contrib_config.h You can apparently have multiple AC_CONFIG_FILES commands, but I'm not sure about AC_CONFIG_HEADER. Anyway if a ton of files change in the near future, that's what it is :) -John ------------------------------------------------------- This SF.Net email is sponsored by: NEC IT Guy Games. Get your fingers limbered up and give it your best shot. 4 great events, 4 opportunities to win big! Highest score wins.NEC IT Guy Games. Play to win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20 _______________________________________________ Libmesh-devel mailing list Lib...@li... https://lists.sourceforge.net/lists/listinfo/libmesh-devel |
From: KIRK, B. (JSC-E. (NASA) <ben...@na...> - 2005-05-09 16:34:08
|
I see your point. I was thinking about using -DDIM=3 at compile time, for example, but then there are no clear dependencies to force a rebuild, so that isn't really an option. Before you get too carried away remember that rerunning ./configure will (I think) recreate *all* the header files, even if the values inside don't change. So, from a make point of view, the timestamp on the file will have changed and therefore everything will need to be rebuilt. At a higher level, if we are going to compartmentalize the build stuff further we might also think about building more libraries. For example, there are a lot of tiny applications I build to do single purpose stuff that don't need any of the linear solver stuff, so separate libraries would make sense. This certainly complicates things, though. Did you make any headway on figuring out why we can't move the _nodes and _elements in to the Mesh class? -Ben -----Original Message----- From: John Peterson [mailto:pet...@cf...] Sent: Monday, May 09, 2005 11:25 AM To: KIRK, BENJAMIN (JSC-EG) (NASA); lib...@li... Subject: RE: [Libmesh-devel] libmesh_config.h KIRK, BENJAMIN (JSC-EG) (NASA) writes: > I think autoheader would break, but we can handle that manually. We would > need to create the include files manually and use the standard autoconf > @REPLACE@ syntax to create foo.h from foo.h.in Yes, this is the approach I just settled on. However I think the include dependencies issues run even deeper. The main problem is that when the library first started we used (lib)mesh_common.h as a catch-all header file for common includes. This approach works well for small libraries, but I think it is starting to break down a bit for us. In particular, libmesh_common.h includes libmesh_config.h, so even if I were to break-up libmesh_config.h somehow, a lot of files still include libmesh_common.h and therefore will still have the same problem. My main plan of attack is to first separate libmesh_common.h a little. For example, if you just need to know the value of "DIM", you don't really want to #include <iostream> to do that. Also, the here()/error()/untested() macros are really useful, but they now depend on HAVE_MPI, libMesh::processor_id() and <iostream>. That's a bit heavy to be included by default in libmesh_common.h and they probably warrant their own libmesh_macros.h header file. -J |
From: Roy S. <roy...@ic...> - 2005-05-09 16:42:12
|
On Mon, 9 May 2005, KIRK, BENJAMIN (JSC-EG) (NASA) wrote: > I see your point. I was thinking about using -DDIM=3 at compile > time, for example, but then there are no clear dependencies to force > a rebuild, so that isn't really an option. This is roughly what deal.II does - the trick is to create object files compiled with different values of DIM. Each object depends on the same source file, and the final library depends on whichever sets of object files support the dimensionality you need. > Did you make any headway on figuring out why we can't move the > _nodes and _elements in to the Mesh class? If he hasn't, it's my fault. I asked John to hold off on that until after I had committed my changes to active(), to avoid a conflict. --- Roy |
From: John P. <pet...@cf...> - 2005-05-09 16:45:02
|
KIRK, BENJAMIN (JSC-EG) (NASA) writes: > I see your point. I was thinking about using -DDIM=3 at compile time, for > example, but then there are no clear dependencies to force a rebuild, so > that isn't really an option. > > Before you get too carried away remember that rerunning ./configure will (I > think) recreate *all* the header files, even if the values inside don't > change. So, from a make point of view, the timestamp on the file will have > changed and therefore everything will need to be rebuilt. Really? I thought it might be smart enough not to touch a file if your configuration options did not modify anything from the previous compile. OK, I just tested it by configuring, making, and then configuring and trying to make again. configure reports "include/base/libmesh_config.h is unchanged" and make reports "make: Nothing to be done for `all'." So I think we are in business...? > At a higher level, if we are going to compartmentalize the build stuff > further we might also think about building more libraries. For example, > there are a lot of tiny applications I build to do single purpose stuff that > don't need any of the linear solver stuff, so separate libraries would make > sense. This certainly complicates things, though. > > Did you make any headway on figuring out why we can't move the _nodes and > _elements in to the Mesh class? Not quite yet. The biggest issue I have come across so far is that all the specialized iterator return functions (like active_elements_begin() and friends) will move to the Mesh class as well since 1.) Their behavior depends on the method of storing nodes/elements and 2.) They shouldn't be in an abstract base class as virtual functions you are forced to implement for every derived type (or make into inline error()'s) Though the inline error might be a nice stop-gap measure, I don't think it's really good programming practice... So...any function that currently takes a reference to MeshBase and uses iterators will now have take a reference to a Mesh instead. This change will affect many areas of the code. I plan to work on this today. -J |
From: Roy S. <roy...@ic...> - 2005-05-09 17:16:38
|
On Mon, 9 May 2005, John Peterson wrote: > Not quite yet. The biggest issue I have come across so far is that > all the specialized iterator return functions (like active_elements_begin() > and friends) will move to the Mesh class as well since > > 1.) Their behavior depends on the method of storing nodes/elements and > 2.) They shouldn't be in an abstract base class as virtual functions you > are forced to implement for every derived type (or make into > inline error()'s) I don't think I agree. The element iterator functionality exists conceptually in every mesh (even if the active/inactive distinction might be a bit redundant for some), so the only reason I see not to have an abstract base class for the iterators (which would enable abstract definitions of their associated Mesh* functions) is efficiency. And I don't think that's a compelling reason. For meshtype-specific code, it should be possible to instantiate specific iterators - that avoids the virtual function call penalty and just wastes 4 bytes per iterator on a vtable pointer. For meshtype-independent code (i.e. user code until we get some really good System classes working), it sounds horrible for "it++" be virtual, but the cost should be negligable compared to all the per-element calculations that are typically done, and making meshtype-independent code inefficient is probably better than making it impossible. > Though the inline error might be a nice stop-gap measure, I don't > think it's really good programming practice... Not for a library, definitely. The closest things to runtime errors that a C++ library should have are well-documented exceptions, and I'd rather not go there. --- Roy |
From: John P. <pet...@cf...> - 2005-05-09 17:33:02
|
Roy Stogner writes: > On Mon, 9 May 2005, John Peterson wrote: > > > Not quite yet. The biggest issue I have come across so far is that > > all the specialized iterator return functions (like active_elements_begin() > > and friends) will move to the Mesh class as well since > > > > 1.) Their behavior depends on the method of storing nodes/elements and > > 2.) They shouldn't be in an abstract base class as virtual functions you > > are forced to implement for every derived type (or make into > > inline error()'s) > > I don't think I agree. The element iterator functionality exists > conceptually in every mesh (even if the active/inactive distinction > might be a bit redundant for some), so the only reason I see not to > have an abstract base class for the iterators (which would enable > abstract definitions of their associated Mesh* functions) is > efficiency. There will still be an abstract "iterator" type defined for all meshes. It is certainly possible to make MeshBase::elements_begin() pure virtual and redefine the functionality in the derived Mesh class. However there are about 20 of these functions right now, and making them all pure virtual would require that anyone deriving a new concrete Mesh class individually implement each and every one -- probably a pain in the future ass. Of course, the creator of the new Mesh class is free to have them all be error()s if he wants. -John |
From: Roy S. <roy...@ic...> - 2005-05-09 18:08:33
|
On Mon, 9 May 2005, John Peterson wrote: > MeshBase::elements_begin() pure virtual > > and redefine the functionality in the derived Mesh class. > However there are about 20 of these functions right now, and making > them all pure virtual would require that anyone deriving a new > concrete Mesh class individually implement each and every one -- > probably a pain in the future ass. Of course, the creator of the > new Mesh class is free to have them all be error()s if he wants. We need to make elements_begin() and elements_end() pure virtual, and for some of the rest there are no sane "default" values, but implementing several will be easy. active_whatever() and level_whatever() should return whatever() for non-hierarchic meshes, for example. --- Roy |
From: KIRK, B. (JSC-E. (NASA) <ben...@na...> - 2005-05-09 17:02:33
|
Good. I didn't realize that configure checked the config.log, so that alleviates that fear. I guess the -DDIM was a bad example. In general, I think DIM could always be 3, but the option is there in case someone knows they only really want to work with 2D meshes and need some space savings. This could also be done with templates, but I really don't see the point. It wouldn't take much convincing for me to always assume DIM=3. If we could rely on shared libraries there is potentially a more elegant approach to this mess... We could use dlopen()/dlclose() to load required dependencies on demand. Then, from a build point of view, you would always compile your Triangle wrapper class. The constructor/destructor for the class then calls dlopen()/dlclose(), respectively, to load the required libraries at runtime. Then, the support is essentially always there. However, you'll get a run-time error if you try to use a feature and the libraries aren't there. Problem is, I still can't figure out how to build shared libs on AIX. All the other platforms seem good. Anyway, enough rambling. -Ben -----Original Message----- From: John Peterson [mailto:pet...@cf...] Sent: Monday, May 09, 2005 11:45 AM To: KIRK, BENJAMIN (JSC-EG) (NASA) Cc: 'John Peterson'; lib...@li... Subject: RE: [Libmesh-devel] libmesh_config.h KIRK, BENJAMIN (JSC-EG) (NASA) writes: > I see your point. I was thinking about using -DDIM=3 at compile time, for > example, but then there are no clear dependencies to force a rebuild, so > that isn't really an option. > > Before you get too carried away remember that rerunning ./configure will (I > think) recreate *all* the header files, even if the values inside don't > change. So, from a make point of view, the timestamp on the file will have > changed and therefore everything will need to be rebuilt. Really? I thought it might be smart enough not to touch a file if your configuration options did not modify anything from the previous compile. OK, I just tested it by configuring, making, and then configuring and trying to make again. configure reports "include/base/libmesh_config.h is unchanged" and make reports "make: Nothing to be done for `all'." So I think we are in business...? > At a higher level, if we are going to compartmentalize the build stuff > further we might also think about building more libraries. For example, > there are a lot of tiny applications I build to do single purpose stuff that > don't need any of the linear solver stuff, so separate libraries would make > sense. This certainly complicates things, though. > > Did you make any headway on figuring out why we can't move the _nodes and > _elements in to the Mesh class? Not quite yet. The biggest issue I have come across so far is that all the specialized iterator return functions (like active_elements_begin() and friends) will move to the Mesh class as well since 1.) Their behavior depends on the method of storing nodes/elements and 2.) They shouldn't be in an abstract base class as virtual functions you are forced to implement for every derived type (or make into inline error()'s) Though the inline error might be a nice stop-gap measure, I don't think it's really good programming practice... So...any function that currently takes a reference to MeshBase and uses iterators will now have take a reference to a Mesh instead. This change will affect many areas of the code. I plan to work on this today. -J |
From: KIRK, B. (JSC-E. (NASA) <ben...@na...> - 2005-05-09 17:31:30
|
Honestly, I'm not at all concerned about the virtual function overhead in this case... What we are talking about is making MeshBase::active_elements_begin() etc... virtual, right? Remember, all that does is return an iterator, it does not say anything about the virtual functions inside that iterator. For example, the way we usually do stuff is like: MeshBase::element_iterator it = mesh.elements_begin(); MeshBase::element_iterator end = mesh.elements_end(); for (; it != end; ++it) ... Then there are only two virtual function calls, and provided you have more than one element there is no way the virtual function overhead will hurt. Now, you *might* notice it if instead you write for (it != mesh.elements_end(); ++it) ... but probably not except for the case of totally trivial loops. Other than that, reimplementing these in a derived class should be easy. For example, consider a fixed cartesian mesh that does not support any refinement (I know, quite boring). Then active_elements_begin() simply returns this->elements_begin(), and not_active_elements_begin() returns this->elements_end()... -Ben -----Original Message----- From: lib...@li... [mailto:lib...@li...] On Behalf Of Roy Stogner Sent: Monday, May 09, 2005 12:17 PM To: John Peterson Cc: lib...@li... Subject: RE: [Libmesh-devel] libmesh_config.h On Mon, 9 May 2005, John Peterson wrote: > Not quite yet. The biggest issue I have come across so far is that > all the specialized iterator return functions (like > active_elements_begin() and friends) will move to the Mesh class as > well since > > 1.) Their behavior depends on the method of storing nodes/elements and > 2.) They shouldn't be in an abstract base class as virtual functions you > are forced to implement for every derived type (or make into > inline error()'s) I don't think I agree. The element iterator functionality exists conceptually in every mesh (even if the active/inactive distinction might be a bit redundant for some), so the only reason I see not to have an abstract base class for the iterators (which would enable abstract definitions of their associated Mesh* functions) is efficiency. And I don't think that's a compelling reason. For meshtype-specific code, it should be possible to instantiate specific iterators - that avoids the virtual function call penalty and just wastes 4 bytes per iterator on a vtable pointer. For meshtype-independent code (i.e. user code until we get some really good System classes working), it sounds horrible for "it++" be virtual, but the cost should be negligable compared to all the per-element calculations that are typically done, and making meshtype-independent code inefficient is probably better than making it impossible. > Though the inline error might be a nice stop-gap measure, I don't > think it's really good programming practice... Not for a library, definitely. The closest things to runtime errors that a C++ library should have are well-documented exceptions, and I'd rather not go there. --- Roy ------------------------------------------------------- This SF.Net email is sponsored by: NEC IT Guy Games. Get your fingers limbered up and give it your best shot. 4 great events, 4 opportunities to win big! Highest score wins.NEC IT Guy Games. Play to win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20 _______________________________________________ Libmesh-devel mailing list Lib...@li... https://lists.sourceforge.net/lists/listinfo/libmesh-devel |
From: John P. <pet...@cf...> - 2005-05-09 17:41:34
|
KIRK, BENJAMIN (JSC-EG) (NASA) writes: > Honestly, I'm not at all concerned about the virtual function overhead in > this case... What we are talking about is making > MeshBase::active_elements_begin() etc... virtual, right? Remember, all that > does is return an iterator, it does not say anything about the virtual > functions inside that iterator. Actually **pure** virtual. When MeshBase no longer has std::vectors of Elem and Node, there is no possible meaning for active_elements_begin() and thus it becomes pure virtual or inline error() (which is not ideal cuz you still have to return something or you will get compiler warnings). So the question for me was not the performance of virtual/not but the programmer overhead required to re-implement about 20-something pure virtual functions in future derived Mesh classes. I have no problem with making the iterators pure virtual as long as you don't have a problem redefining **all 20** of them every time we subclass MeshBase in the future. -J |
From: John P. <pet...@cf...> - 2005-05-09 17:53:29
|
Another argument **for** making the foo_elements_begin() functions pure virtual in the base class is that all the n_active_elem, n_elem_of_type, etc. functions all fall through with no changes to derived classes. Actually that is pretty sweet. I'm thinking go with pure virtual and just deal with re-implementing all the functions or returning errors in derived Mesh classes. -J |
From: Roy S. <roy...@ic...> - 2005-05-09 18:02:18
|
On Mon, 9 May 2005, KIRK, BENJAMIN (JSC-EG) (NASA) wrote: > Honestly, I'm not at all concerned about the virtual function overhead in > this case... What we are talking about is making > MeshBase::active_elements_begin() etc... virtual, right? Remember, all that > does is return an iterator, it does not say anything about the virtual > functions inside that iterator. Here's the problem: what kind of iterator? The iterator might be something that thinks "it++" means "point to the next Elem* in our vector" or it might be something that thinks "it++" means "Change the cartesian coordinates of the Elem I store", or it might be something that creates refined elements on the fly, etc. etc. In short, we can't return a concrete iterator from *_begin(), we have to return an abstract iterator whose most basic function, iteration, is virtual. Now, I still think doing so is worth the price, but that's something to keep in mind. --- Roy |
From: KIRK, B. (JSC-E. (NASA) <ben...@na...> - 2005-05-09 18:00:51
|
I'll look and see how often some of those obscure ones are used... Certainly the active_type_elements was introduced solely for Xdr and could probably be defined in another file in an anonymous namespace... I'm sure there are others like this. On a somewhat related note, would it be possible to chain templated functions together to create your_favorite_element_iterator? Here is what I have in mind: typedef Iterator::Active< Iterator::Local < Iterator::Type (_elements_begin, HEX27) > > active_local_hex27_element_iterator; ? Kinda like the systems work. Seems like (perhaps) a workable alternative. We certainly should not aim to support every_possible_element_iterator()... -Ben -----Original Message----- From: lib...@li... [mailto:lib...@li...] On Behalf Of John Peterson Sent: Monday, May 09, 2005 12:33 PM To: Roy Stogner Cc: John Peterson; lib...@li... Subject: RE: [Libmesh-devel] libmesh_config.h Roy Stogner writes: > On Mon, 9 May 2005, John Peterson wrote: > > > Not quite yet. The biggest issue I have come across so far is that > > all the specialized iterator return functions (like active_elements_begin() > > and friends) will move to the Mesh class as well since > > > > 1.) Their behavior depends on the method of storing nodes/elements and > > 2.) They shouldn't be in an abstract base class as virtual functions you > > are forced to implement for every derived type (or make into > > inline error()'s) > > I don't think I agree. The element iterator functionality exists > conceptually in every mesh (even if the active/inactive distinction > might be a bit redundant for some), so the only reason I see not to > have an abstract base class for the iterators (which would enable > abstract definitions of their associated Mesh* functions) is > efficiency. There will still be an abstract "iterator" type defined for all meshes. It is certainly possible to make MeshBase::elements_begin() pure virtual and redefine the functionality in the derived Mesh class. However there are about 20 of these functions right now, and making them all pure virtual would require that anyone deriving a new concrete Mesh class individually implement each and every one -- probably a pain in the future ass. Of course, the creator of the new Mesh class is free to have them all be error()s if he wants. -John ------------------------------------------------------- This SF.Net email is sponsored by: NEC IT Guy Games. Get your fingers limbered up and give it your best shot. 4 great events, 4 opportunities to win big! Highest score wins.NEC IT Guy Games. Play to win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20 _______________________________________________ Libmesh-devel mailing list Lib...@li... https://lists.sourceforge.net/lists/listinfo/libmesh-devel |
From: John P. <pet...@cf...> - 2005-05-09 18:07:07
|
KIRK, BENJAMIN (JSC-EG) (NASA) writes: > I'll look and see how often some of those obscure ones are used... > Certainly the active_type_elements was introduced solely for Xdr and could > probably be defined in another file in an anonymous namespace... I'm sure > there are others like this. > > On a somewhat related note, would it be possible to chain templated > functions together to create your_favorite_element_iterator? Here is what I > have in mind: > > typedef Iterator::Active< Iterator::Local < Iterator::Type (_elements_begin, > HEX27) > > > active_local_hex27_element_iterator; > > ? > > Kinda like the systems work. I don't know, it might be. I will have to think about it. Right now they are constructed before-hand cuz that's the only way I could think of to do it. OTOH they are pretty flexible so it might be possible to change. > Seems like (perhaps) a workable alternative. We certainly should not aim to > support every_possible_element_iterator()... I agree. At the very least that is a good long-term goal, but for the time being, I think getting _elements and _nodes out of the base class should be the top concern. Re-engineering the iterators, if possible, could come later. -J |
From: John P. <pet...@cf...> - 2005-05-09 18:55:14
|
Other things to think about in the future: If we eventually implement a StructuredMesh class which doesn't store nodes or elements, it won't be feasible to return references as in const Node& node = mesh.node(0); Also it will be unsafe to return naked pointers, so I think we will probably have to go to AutoPtr<Node> node for the interface instead That's an unfortunate overhead when you are actually storing elements and nodes. -John |
From: John P. <pet...@cf...> - 2005-05-09 16:26:09
|
KIRK, BENJAMIN (JSC-EG) (NASA) writes: > I think autoheader would break, but we can handle that manually. We would > need to create the include files manually and use the standard autoconf > @REPLACE@ syntax to create foo.h from foo.h.in Yes, this is the approach I just settled on. However I think the include dependencies issues run even deeper. The main problem is that when the library first started we used (lib)mesh_common.h as a catch-all header file for common includes. This approach works well for small libraries, but I think it is starting to break down a bit for us. In particular, libmesh_common.h includes libmesh_config.h, so even if I were to break-up libmesh_config.h somehow, a lot of files still include libmesh_common.h and therefore will still have the same problem. My main plan of attack is to first separate libmesh_common.h a little. For example, if you just need to know the value of "DIM", you don't really want to #include <iostream> to do that. Also, the here()/error()/untested() macros are really useful, but they now depend on HAVE_MPI, libMesh::processor_id() and <iostream>. That's a bit heavy to be included by default in libmesh_common.h and they probably warrant their own libmesh_macros.h header file. -J |