From: Derek G. <fri...@gm...> - 2012-05-14 18:37:53
|
Around line 1100 in unstructured_mesh.C in UnstructuredMesh::contract() it calls renumber_nodes_and_elements() This is a bad idea. We've initialized our meshes by skipping renumbering... but then calling eq->reinit() causes all of the nodes / elems to then be renumbered. Any ideas for what to do here? Should we make a separate function to remove the NULLs out of the element / node vectors but keep the numbering the same? Should we just not renumber if we skipped renumbering when we initialized the mesh? Derek |
From: Derek G. <fri...@gm...> - 2012-05-14 19:07:47
|
Also, on a related note, it looks like in equation_systems.C around line 194 sets "mesh_changed = true"... no matter what. So calling eq->reinit() will cause a mesh.contract() _no matter what_... even if you haven't modified the mesh. Meaning that just calling eq->reinit() you will get your nodes and elements renumbered! It looks like this is in there because of backwards compatibility... Derek On Mon, May 14, 2012 at 12:37 PM, Derek Gaston <fri...@gm...> wrote: > Around line 1100 in unstructured_mesh.C in UnstructuredMesh::contract() it > calls renumber_nodes_and_elements() > > This is a bad idea. > > We've initialized our meshes by skipping renumbering... but then calling > eq->reinit() causes all of the nodes / elems to then be renumbered. > > Any ideas for what to do here? Should we make a separate function to > remove the NULLs out of the element / node vectors but keep the numbering > the same? > > Should we just not renumber if we skipped renumbering when we initialized > the mesh? > > Derek > |
From: Derek G. <fri...@gm...> - 2012-05-14 20:29:08
|
Ok - one more thing on this.... a question actually: Why do we need to "contract()" for SerialMesh? Shouldn't it be ok to have holes in the element / node numbering? Right now we kind of have weird behavior where nodes will be changing numbers all the time as we adapt the mesh (even if a node isn't destroyed and recreated it can be renumbered through contract() ). That seems like weird behavior that is kind of anti-user. For instance, what if you want to track the value of a variable at a node that is created through refinement? You probably can't do that with our current system because that node number will be changing all the danged time.... right? Derek On Mon, May 14, 2012 at 1:07 PM, Derek Gaston <fri...@gm...> wrote: > Also, on a related note, it looks like in equation_systems.C around line > 194 sets "mesh_changed = true"... no matter what. > > So calling eq->reinit() will cause a mesh.contract() _no matter what_... > even if you haven't modified the mesh. Meaning that just calling > eq->reinit() you will get your nodes and elements renumbered! > > It looks like this is in there because of backwards compatibility... > > Derek > > > On Mon, May 14, 2012 at 12:37 PM, Derek Gaston <fri...@gm...> wrote: > >> Around line 1100 in unstructured_mesh.C in UnstructuredMesh::contract() >> it calls renumber_nodes_and_elements() >> >> This is a bad idea. >> >> We've initialized our meshes by skipping renumbering... but then calling >> eq->reinit() causes all of the nodes / elems to then be renumbered. >> >> Any ideas for what to do here? Should we make a separate function to >> remove the NULLs out of the element / node vectors but keep the numbering >> the same? >> >> Should we just not renumber if we skipped renumbering when we initialized >> the mesh? >> >> Derek >> > > |
From: Roy S. <roy...@ic...> - 2012-05-16 20:18:50
|
On Mon, 14 May 2012, Derek Gaston wrote: > Ok - one more thing on this.... a question actually: > Why do we need to "contract()" for SerialMesh? Shouldn't it be ok > to have holes in the element / node numbering? Hmmm... originally it was absolutely not okay. For starters, we had a ton of code that assumed (mesh.max_elem_id() == mesh.n_elem()), and in fact our code had no choice, since "MeshBase::max_elem_id()" didn't even exist yet. On the other hand, max_elem_id() *does* exist now, we're already using it in places that want arrays indexed over all elements like the ErrorEstimator subclasses, and in the long run we don't really want arrays indexed over all elements anywhere anyway. On the gripping hand: if we have a numbering full of holes, what is SerialMesh::add_elem() supposed to do? It would currently ignore them and append to the end, leaking memory until contract() is called. If instead we tried to fill holes in in one at a time, that would be more expensive in CPU than just letting a contract() bring everything together at once. Even in ParallelMesh, where we expect the local numberings to have holes, we renumber local elements contiguously to keep the hole count down, letting us use a partially contiguous data structure to keep asymptotic complexity down. Wait a minute (we're four digressions in - anyone still following my derailed train of thought?) - I never actually updated the mapvector implementation to make use of mostly-contiguous storage. It would still be nice to keep the option open, though. > Right now we kind of have weird behavior where nodes will be > changing numbers all the time as we adapt the mesh (even if a node > isn't destroyed and recreated it can be renumbered through > contract() ). That seems like weird behavior that is kind of > anti-user. For instance, what if you want to track the value of a > variable at a node that is created through refinement? You probably > can't do that with our current system because that node number will > be changing all the danged time.... right? Right, but how would this be improved if we did try to avoid renumbering? Unless we effectively don't allow coarsening, any node created through refinement could still be destroyed in a subsequent coarsening and then recreated with a different number later. Even if we did come up with a way to track vanishing and reappearing nodes, nodes are an artifact of the discretization - caring about a coefficient at node N is like caring about the float at memory address 0xC0DE. Track the value by Point location rather than by Node index and you get a sane result even if the node gets coarsened away, even if you switch from a Lagrange to a non-nodal basis set, etc. ... I write the above paragraph hesitantly, since I suspect that "track the value at a node" is a hypothetical that's been oversimplified for benefit of discussion and that your actual node-tracking needs aren't so heedlessly dismissable. IIRC you've often been the first person to chime in with "add auxilliary nodal or element-wise data to a separate ExplicitSystem" when people have asked about node-indexed data in the past, so trying to imagine what problem has you falling back on fixed indices is frightening. Feel free to surprise me with "of course, tracking by Point fixes everything, thanks!" rather than "here's a more complicated case where your ideas totally fail", though. ;-) > Also, on a related note, it looks like in equation_systems.C > around line 194 sets "mesh_changed = true"... no matter what. So > calling eq->reinit() will cause a mesh.contract() _no matter > what_... even if you haven't modified the mesh. > It looks like this is in there because of backwards compatibility... Correct. And it's been in there for quite a while, and we haven't even fixed the example codes which contain examples of the API usage requiring the backwards compatibility. The idea (from Ben IIRC) was that we could often cut down on max memory requirements in an AMR run by doing a refine-and-coarsen as a two-step process: coarsen first, free up some memory after the projections are done, then refine second. To make this work, we added coarsen and refinement steps within eq->reinit(). The trouble is that all our user code was already manually calling refine_and_coarsen_elements(), disabling any memory savings and also making it impossible for eq->reinit() to examine the MeshRefinement method return values to tell whether or not the mesh had been changed. We ought to fix this situation. Maybe add a bool "mesh_already_changed" argument to reinit(), defaulting to true for backwards compatibility, but allowing users to pass in false if they have an unchanged mesh and/or if they want to do the two-pass AMR? Just my first idea, anyone have a better one? > Meaning that just calling eq->reinit() you will get your nodes and > elements renumbered! True. We never really expect anyone to call reinit() except after changing the mesh, though, do we? I suppose maybe if your mesh is staying fixed but your stencil is changing you might be calling it to reinitialize ImplicitSystem matrices? --- Roy |
From: Derek G. <fri...@gm...> - 2012-05-16 20:45:06
|
On May 16, 2012, at 2:18 PM, Roy Stogner wrote: > True. We never really expect anyone to call reinit() except after > changing the mesh, though, do we? I suppose maybe if your mesh is > staying fixed but your stencil is changing you might be calling it to > reinitialize ImplicitSystem matrices? This is essentially what we are doing… but it's an "implicit" stencil that happens between "contact" surfaces (I say "contact" because it might not actually be contact… just two disparate surfaces that need to communicate). So when we are calling reinit() our mesh numbering is changing out from under us… flubbing up everything we've done for "contact". Now that I've thought about this for a few days (and based on your reply) here's what I'm thinking: Why don't we _only_ renumber nodes and elements that are "beyond" the initial mesh. What I mean by that is this: a: Read mesh containing elements 4,3,1,2 (out of order on purpose) b: Refine some to create 5,6,7… leave 4,3,1,2 alone so we have this "ordering": 4,3,1,2,5,6,7 c: Coarsen later to remove 6 so now we have 4,3,1,2,5,_,7 d: Contract ONLY elements beyond the initial mesh so we would get 4,3,1,2,5,6 (where 7 has now become 6) This should be pretty trivial to do by keeping track of the max elem # and max node # for the mesh we've read in… and only reordering / contracting elements/nodes from those numbers on. That way, our original mesh continues to have the same ordering. This works perfectly because we can't coarsen beyond our initial mesh in libMesh… so we won't ever get holes there…. > Even if we did come up with a way to track vanishing and reappearing > nodes, nodes are an artifact of the discretization - caring about a > coefficient at node N is like caring about the float at memory address > 0xC0DE. Track the value by Point location rather than by Node index > and you get a sane result even if the node gets coarsened away, even > if you switch from a Lagrange to a non-nodal basis set, etc. Yes, yes. That will fly in my ivory tower and yours… but there are realities involved here as well. MOOSE does currently allow users to track values at nodes given by node id. It's something our users wanted and needed… and in some cases it makes sense. For instance, how do you track by x,y,z position when you have a MOVING mesh? But ultimately, it's just a convenience thing. Note that when users are tracking by node id it has to be a node _in the initial mesh_…. so my scheme outlined above would be sufficient. As you correctly guessed I was giving the "track value at new node" case as a hypothetical ;-) We could try to band-aid reinit()… but I really think for our users they REALLY want the input numbering to _not_ change for the initial mesh… no matter what (even when using Adaptivity). What do you think about my proposal? Derek |
From: Roy S. <roy...@ic...> - 2012-05-16 22:15:31
|
On Wed, 16 May 2012, Derek Gaston wrote: > Why don't we _only_ renumber nodes and elements that are "beyond" > the initial mesh. What I mean by that is this: > > a: Read mesh containing elements 4,3,1,2 (out of order on purpose) > b: Refine some to create 5,6,7… leave 4,3,1,2 alone so we have this "ordering": 4,3,1,2,5,6,7 > c: Coarsen later to remove 6 so now we have 4,3,1,2,5,_,7 > d: Contract ONLY elements beyond the initial mesh so we would get 4,3,1,2,5,6 (where 7 has now become 6) Hmm... this is what already happens for SerialMesh, isn't it? It ought to be doable for ParallelMesh too. My first concern there is what happens when we're doing mesh generation rather than reading a pre-numbered mesh from file. For ParallelMesh creation of new nodes we start with them being as *interleaved* as possible, with each processor p responsible for handling the set ids which (mod n_procs+1) == p (with the n_procs+1 case reserved for unpartitioned nodes and elements). I'd hate to leave a mesh stuck with an initial numbering that was grossly interleaved and sparse. Maybe leave the existing renumbering routine in there, to be called for those cases, but add a new routine in that doesn't touch the first Ne0,Nn0 nodes and elements? > This should be pretty trivial to do by keeping track of the max elem > # and max node # for the mesh we've read in… and only reordering / > contracting elements/nodes from those numbers on. That way, our > original mesh continues to have the same ordering. This works > perfectly because we can't coarsen beyond our initial mesh in > libMesh… so we won't ever get holes there…. But then my second concern: we're capable of deleting (and ought to be capable of adding) level 0 elements on the fly, it's just that the library code never does so; it's the sort of thing that a user in a variable domain problem would do by hand - picture an ablation problem which combines mesh movement in the outermost cell layer with cell deletion as the boundary passes that layer. I'd hate to offer a "guarantee" that some numbers would go unchanged only to have to give a few pages of fine print explaining under what conditions they'd change. I suppose it wouldn't be the first situation requiring care by libMesh users, though. Add "topologically unchanging initial meshes" to "Lagrange elements", "unrefined meshes", "non-adaptively-refined meshes", "serialized meshes", etc. on the list of "stuff that makes it too easy to write code that will break when your discretization requirements get more interesting. > and in some cases it makes sense. For instance, how do you track by > x,y,z position when you have a MOVING mesh? Reference configuration position. But yeah, I can see how that could be a pain in the neck - throw in mesh tearing and I'd even want an (fixed-element-id, point-in-master-element-space) identifier pair myself. > What do you think about my proposal? I don't have time to implement it myself, but as long as we still end up doing initial renumbering on meshes which don't get their numbering from a file, I do like the idea. --- Roy |
From: Derek G. <fri...@gm...> - 2012-05-17 13:43:20
|
On May 16, 2012, at 4:15 PM, Roy Stogner wrote: > On Wed, 16 May 2012, Derek Gaston wrote: > >> Why don't we _only_ renumber nodes and elements that are "beyond" >> the initial mesh. What I mean by that is this: >> >> a: Read mesh containing elements 4,3,1,2 (out of order on purpose) >> b: Refine some to create 5,6,7… leave 4,3,1,2 alone so we have this "ordering": 4,3,1,2,5,6,7 >> c: Coarsen later to remove 6 so now we have 4,3,1,2,5,_,7 >> d: Contract ONLY elements beyond the initial mesh so we would get 4,3,1,2,5,6 (where 7 has now become 6) > > Hmm... this is what already happens for SerialMesh, isn't it? It > ought to be doable for ParallelMesh too. No! This isn't what happens for SerialMesh! The problem we're having is _with_ serial mesh. Go look at renumber_nodes_and_elements() around line 405 in unstructured_mesh.C… it very clearly renumbers _all_ nodes and elements. I actually don't care what happens to ParallelMesh right now. Our users know that there are certain restrictions when moving to ParallelMesh… but if they have a problem that needs it they are willing to take the trade off. > My first concern there is what happens when we're doing mesh > generation rather than reading a pre-numbered mesh from file. For > ParallelMesh creation of new nodes we start with them being as > *interleaved* as possible, with each processor p responsible for > handling the set ids which (mod n_procs+1) == p (with the n_procs+1 > case reserved for unpartitioned nodes and elements). I'd hate to > leave a mesh stuck with an initial numbering that was grossly > interleaved and sparse. > > Maybe leave the existing renumbering routine in there, to be called > for those cases, but add a new routine in that doesn't touch the first > Ne0,Nn0 nodes and elements? The idea is to store off the fact that we didn't want to renumber when we initialized…. and only then do the renumbering beyond the initial mesh. To be clear, this behavior would only happen when you do prepare_for_use(true)... > But then my second concern: we're capable of deleting (and ought to be > capable of adding) level 0 elements on the fly, it's just that the > library code never does so; it's the sort of thing that a user in a > variable domain problem would do by hand - picture an ablation problem > which combines mesh movement in the outermost cell layer with cell > deletion as the boundary passes that layer. I'd hate to offer a > "guarantee" that some numbers would go unchanged only to have to give > a few pages of fine print explaining under what conditions they'd > change. > > I suppose it wouldn't be the first situation requiring care by libMesh > users, though. Add "topologically unchanging initial meshes" to > "Lagrange elements", "unrefined meshes", "non-adaptively-refined > meshes", "serialized meshes", etc. on the list of "stuff that makes it > too easy to write code that will break when your discretization > requirements get more interesting. Yep - if you're changing the topology…. all bets are off. >> What do you think about my proposal? > > I don't have time to implement it myself, but as long as we still end > up doing initial renumbering on meshes which don't get their numbering > from a file, I do like the idea. Ok - I'm with you on this…. but I think it will be user selectable. i.e.... if you pass in "true" to prepare_for_use() there won't be any renumbering of the initial mesh _ever_ (With SerialMesh… ParallelMesh can do what it needs to). It is a "use at your own risk" kind of feature… The whole issue is that we have an API now where you can tell libMesh _not_ to renumber…. but then it will anyway the next time reinit() is called! That's inconsistent…. Derek |
From: Kirk, B. (JSC-EG311) <ben...@na...> - 2012-05-17 14:06:07
|
> Ok - I'm with you on thisŠ. but I think it will be user selectable. i.e.... > if you pass in "true" to prepare_for_use() there won't be any renumbering of > the initial mesh _ever_ (With SerialMeshŠ ParallelMesh can do what it needs > to). It is a "use at your own risk" kind of featureŠ > > The whole issue is that we have an API now where you can tell libMesh _not_ to > renumberŠ. but then it will anyway the next time reinit() is called! That's > inconsistentŠ. True. Sorry for my silence on this issue - I was on I-35 from MN to TX for way too long and am now just trying to catch up. Still clearly working on getting familiar with this thread, but want to interject a possible hiccup... How far do we need to go with supporing and maintaining an arbitrary initial numbering? I ask because it is perfectly conceivable that an input mesh might have only three nodes, numbered 100, 200, 300, and that means something to the user. Now if we go and refine that now things could and certainly (probably!) would break eventually. So do we only support arbitrary initial numbers so long as they are 0-based and contiguous? As for this proposal: > We could try to band-aid reinit()Š but I really think for our users they > REALLY want the input numbering to _not_ change for the initial meshŠ no > matter what (even when using Adaptivity). I'd like to propose an alternate course of action that doesn't have as much potential to constrain the data structures on the libMesh side... What about something along the lines of a Node::Identifier class that returns some strongly typed and less arbitrary way of identifying a node? This could be extended to elements too obviously... The thing that comes to mind is actually encapsulating the node address. Currently this is much more stable than the node number. In the serial mesh we take great pains to only allocate nodes and elements once, whereas as you notice we'll gleefully thrash the IDs at will. So if we went along these lines then perhaps a callback would be needed when a mesh is read to store the Node::Identifiers based on user-requested *original* node numbers, but then we'd be free to do whatever to them. Thoughts? -Ben |
From: Derek G. <fri...@gm...> - 2012-05-17 14:10:38
|
On May 17, 2012, at 8:05 AM, Kirk, Benjamin (JSC-EG311) wrote: > So if we went along these lines then perhaps a callback would be needed when > a mesh is read to store the Node::Identifiers based on user-requested > *original* node numbers, but then we'd be free to do whatever to them. I like it. So you are saying we can basically store an arbitrary "number" on each node / element that won't change as long as that node lives? In the case of reading in a mesh, we can store the original node number? This sounds good to me. Only downside is that we'd be adding memory overhead to nodes / elements. But I'm never one to quibble over bytes… Derek |
From: Kirk, B. (JSC-EG311) <ben...@na...> - 2012-05-17 14:23:28
|
>> So if we went along these lines then perhaps a callback would be needed when >> a mesh is read to store the Node::Identifiers based on user-requested >> *original* node numbers, but then we'd be free to do whatever to them. > > I like it. > > So you are saying we can basically store an arbitrary "number" on each node / > element that won't change as long as that node lives? In the case of reading > in a mesh, we can store the original node number? Not necessarily - it may return only constant-type objects to the user. One idea is that it would just return the address of the node wrapped in an object that clarifies the intent. So in that case there is no more memory required in the underlying mesh than currently required. There would need to be something added to the MeshInput base class (likely) that allows the user to request some node IDs though, so that before we prepare_for_use and contract and all that we acquire Node::Identifiers, but that should be easy. -Ben |
From: Roy S. <roy...@ic...> - 2012-05-17 14:34:40
|
On Thu, 17 May 2012, Kirk, Benjamin (JSC-EG311) wrote: > Not necessarily - it may return only constant-type objects to the user. One > idea is that it would just return the address of the node wrapped in an > object that clarifies the intent. So in that case there is no more memory > required in the underlying mesh than currently required. This is nice memory wise (and unlike Derek, I do shudder at the idea of adding more bytes-per-node), but then there's no way to safely pass nodes from one processor to another without losing that identification. Static ids are much preferable to that. --- Roy |
From: Kirk, B. (JSC-EG311) <ben...@na...> - 2012-05-17 14:41:34
|
>> Not necessarily - it may return only constant-type objects to the user. One >> idea is that it would just return the address of the node wrapped in an >> object that clarifies the intent. So in that case there is no more memory >> required in the underlying mesh than currently required. > > This is nice memory wise (and unlike Derek, I do shudder at the idea > of adding more bytes-per-node), but then there's no way to safely pass > nodes from one processor to another without losing that > identification. Static ids are much preferable to that. Oh absolutely - more state would need to be handled when shipping objects around. I'm not too worried about that though - I'll try to think of a fix for that. -Ben |
From: Derek G. <fri...@gm...> - 2012-05-17 14:43:28
|
On May 17, 2012, at 8:41 AM, Kirk, Benjamin (JSC-EG311) wrote: > Oh absolutely - more state would need to be handled when shipping objects > around. I'm not too worried about that though - I'll try to think of a fix > for that. I guess this would be true only for ParallelMesh… because with SerialMesh you should be able to generate the same IDs on every processor…. Derek |
From: Roy S. <roy...@ic...> - 2012-05-17 14:47:06
|
On Thu, 17 May 2012, Kirk, Benjamin (JSC-EG311) wrote: > Oh absolutely - more state would need to be handled when shipping objects > around. I'm not too worried about that though - I'll try to think of a fix > for that. Shouldn't the fix just be "state = object->id()"? If we're maintaining initial ids on level 0 objects (as Derek has convinced me is a good idea), and if people aren't imagining they can keep a simple state corresponding to ephemeral more-refined objects (other than an Elem,master-elem-Point ordered pair), then I don't see where we need more metadata. --- Roy |
From: Roy S. <roy...@ic...> - 2012-05-17 14:37:47
|
On Thu, 17 May 2012, Kirk, Benjamin (JSC-EG311) wrote: > How far do we need to go with supporing and maintaining an arbitrary initial > numbering? I ask because it is perfectly conceivable that an input mesh > might have only three nodes, numbered 100, 200, 300, and that means > something to the user. Now if we go and refine that now things could and > certainly (probably!) would break eventually. So do we only support > arbitrary initial numbers so long as they are 0-based and contiguous? Here's the trick: rather than Derek's "find initial n_elem, only renumber above that", we do "check elem->level() when renumbering, only renumber above 0". Then we can support crazy initial numberings (with the caveat that SerialMesh memory usage becomes O(max_elem_id)...), and we even get static ids after element deletion! --- Roy |
From: Roy S. <roy...@ic...> - 2012-05-17 14:42:59
|
On Thu, 17 May 2012, Derek Gaston wrote: > On May 16, 2012, at 4:15 PM, Roy Stogner wrote: > >> On Wed, 16 May 2012, Derek Gaston wrote: >> >>> Why don't we _only_ renumber nodes and elements that are "beyond" >>> the initial mesh. What I mean by that is this: >>> >>> a: Read mesh containing elements 4,3,1,2 (out of order on purpose) >>> b: Refine some to create 5,6,7… leave 4,3,1,2 alone so we have this "ordering": 4,3,1,2,5,6,7 >>> c: Coarsen later to remove 6 so now we have 4,3,1,2,5,_,7 >>> d: Contract ONLY elements beyond the initial mesh so we would get 4,3,1,2,5,6 (where 7 has now become 6) >> >> Hmm... this is what already happens for SerialMesh, isn't it? It >> ought to be doable for ParallelMesh too. > > No! This isn't what happens for SerialMesh! The problem we're > having is _with_ serial mesh. Go look at > renumber_nodes_and_elements() around line 405 in > unstructured_mesh.C… it very clearly renumbers _all_ nodes and > elements. I'm just skimming code here, so if you're seeing different behavior then I must be wrong, but: SerialMesh::renumber_nodes_and_elements() "renumbers" all elements, true, but as long as they start out in proper order (_elements[i]->id() == i) they should stay the same up until the first hole is reached, which shouldn't happen until after all the level 0 elements have been passed. Perhaps the trouble is that for file-based numberings our MeshInput classes *aren't* starting us with (_elements[i]->id() == i)? --- Roy |
From: Derek G. <fri...@gm...> - 2012-05-17 14:48:56
|
On May 17, 2012, at 8:42 AM, Roy Stogner wrote: > SerialMesh::renumber_nodes_and_elements() "renumbers" all elements, > true, but as long as they start out in proper order > (_elements[i]->id() == i) they should stay the same up until the first > hole is reached, which shouldn't happen until after all the level 0 > elements have been passed. Perhaps the trouble is that for file-based > numberings our MeshInput classes *aren't* starting us with > (_elements[i]->id() == i)? You're right about Elements, Roy… I hadn't notice that. But for nodes that's not the case (and that's where we're seeing problems). The issue happens when the node numbering for an element in a read in mesh doesn't match the libMesh ordering for nodes on that element. Look just below where it's setting the elem ids… Derek |
From: Roy S. <roy...@ic...> - 2012-05-17 15:28:17
|
On Thu, 17 May 2012, Derek Gaston wrote: > You're right about Elements, Roy… I hadn't notice that. But for > nodes that's not the case (and that's where we're seeing problems). > > The issue happens when the node numbering for an element in a read > in mesh doesn't match the libMesh ordering for nodes on that > element. Look just below where it's setting the elem ids… Ha! I saw the behavior for elements and just assumed it would be using the same behavior for nodes. Would it fix things for you (at least as a first pass) if it *was* using the same behavior for nodes? Take the node renumbering out of the elements loop, add a nodes loop which does the same renumbering-without-reordering? --- Roy |
From: Derek G. <fri...@gm...> - 2012-05-17 16:34:36
|
Yep - I think that would do it! Derek On May 17, 2012, at 9:28 AM, Roy Stogner wrote: > > On Thu, 17 May 2012, Derek Gaston wrote: > >> You're right about Elements, Roy… I hadn't notice that. But for >> nodes that's not the case (and that's where we're seeing problems). >> >> The issue happens when the node numbering for an element in a read >> in mesh doesn't match the libMesh ordering for nodes on that >> element. Look just below where it's setting the elem ids… > > Ha! I saw the behavior for elements and just assumed it would be > using the same behavior for nodes. > > Would it fix things for you (at least as a first pass) if it *was* > using the same behavior for nodes? Take the node renumbering out of > the elements loop, add a nodes loop which does the same > renumbering-without-reordering? > --- > Roy |
From: Roy S. <roy...@ic...> - 2012-05-24 18:36:52
|
On Thu, 24 May 2012, Derek Gaston wrote: > HOWEVER: This is now a 2nLog(n) algorithm... where n is the number > of nodes in your mesh. Replace std::set with LIBMESH_BEST_UNORDERED_SET and (as long as configure found a gnu or tr1 or c++11 hash table container) we ought to be back to O(n). Since you're not actually trying to iterate through connected_nodes in order, just testing for set inclusion later, there's no need to preserve ordering. The hash tables probably take up more memory, but I don't think the difference will be too bad - might want to benchmark (both RAM and CPU usage) to be sure. --- Roy |
From: Derek G. <fri...@gm...> - 2012-06-05 15:51:48
|
I tried LIBMESH_BEST_UNORDERED_SET... and I got this: error: ‘std::tr1’ has not been declared So apparently, that configure test isn't doing the right thing on my Mac. I guess we must not be using this anywhere else in the code... Derek On Thu, May 24, 2012 at 12:36 PM, Roy Stogner <roy...@ic...>wrote: > > On Thu, 24 May 2012, Derek Gaston wrote: > > HOWEVER: This is now a 2nLog(n) algorithm... where n is the number >> of nodes in your mesh. >> > > Replace std::set with LIBMESH_BEST_UNORDERED_SET and (as long as > configure found a gnu or tr1 or c++11 hash table container) we ought > to be back to O(n). Since you're not actually trying to iterate > through connected_nodes in order, just testing for set inclusion > later, there's no need to preserve ordering. The hash tables probably > take up more memory, but I don't think the difference will be > too bad - might want to benchmark (both RAM and CPU usage) to be sure. > --- > Roy > |
From: Kirk, B. (JSC-EG311) <ben...@na...> - 2012-06-05 15:54:45
|
> I tried LIBMESH_BEST_UNORDERED_SET... and I got this: > > error: Œstd::tr1¹ has not been declared > > So apparently, that configure test isn't doing the right thing on my Mac. I > guess we must not be using this anywhere else in the code... That's curious - can you send me your config.log directly to avoid the attachment filter? It should be very similar to the BEST_UNORDERED_MAP which we do use... -Ben |
From: Kirk, B. (JSC-EG311) <ben...@na...> - 2012-06-05 16:06:10
|
>> I tried LIBMESH_BEST_UNORDERED_SET... and I got this: >> >> error: Œstd::tr1¹ has not been declared >> >> So apparently, that configure test isn't doing the right thing on my Mac. I >> guess we must not be using this anywhere else in the code... > > That's curious - can you send me your config.log directly to avoid the > attachment filter? > > It should be very similar to the BEST_UNORDERED_MAP which we do use... Oh, did you also add a #include LIBMESH_INCLUDE_UNORDERED_SET header entry? -Ben |
From: Derek G. <fri...@gm...> - 2012-06-05 16:25:49
|
Whoops! Didn't know that was necessary - it works now... Derek On Tue, Jun 5, 2012 at 10:05 AM, Kirk, Benjamin (JSC-EG311) < ben...@na...> wrote: > >> I tried LIBMESH_BEST_UNORDERED_SET... and I got this: > >> > >> error: Œstd::tr1¹ has not been declared > >> > >> So apparently, that configure test isn't doing the right thing on my > Mac. I > >> guess we must not be using this anywhere else in the code... > > > > That's curious - can you send me your config.log directly to avoid the > > attachment filter? > > > > It should be very similar to the BEST_UNORDERED_MAP which we do use... > > Oh, did you also add a > > #include LIBMESH_INCLUDE_UNORDERED_SET > > header entry? > > -Ben > > |
From: Roy S. <roy...@ic...> - 2012-06-05 16:50:34
|
On this topic: I wonder, should we start defaulting to C++11 via libmesh_CXXFLAGS on newer gcc versions, to make sure we get a good unordered_map and unordered_set? They're getting stricter and stricter about standards compliance, and IIRC the latest gcc/libstdc++ (in default, C++03 mode) is now complaining about "deprecated" headers whenever we pull in hash_map or hash_set. --- Roy |