nuto icon indicating copy to clipboard operation
nuto copied to clipboard

Weird interfaces in Structure

Open Psirus opened this issue 8 years ago • 7 comments
trafficstars

For example, the method

virtual void GetNodesTotal(std::vector<NodeBase*>& rNodes) = 0;

should just return (a reference to) a vector, instead of filling a predefined one. Same goes for GetElementsTotal, GetElementsByGroup, NodeGetElements, NodeGroupGetMembers, NodeGetCoordinates, NodeGetDisplacements,

Methods that also have these interfaces but imho should simply disappear are NodeGroupGetCoordinates, NodeGroupGetDisplacements, ElementTotalGetAverageStress, ElementGroupGetAverageStress, ElementTotalGetAverageStrain, ElementGroupGetAverageStrain.

Psirus avatar Jun 21 '17 17:06 Psirus

Regarding the first issue. The original reason for having these methods at all this was that not all structures (derived from StructureBase) are using the same container for storing nodes and elements (so returning a reference was not possible). e.g. the current structure uses a boost::ptr_map<int, NodeBase> mNodeMap; to store the nodes. Another structure (originally we had a grid based structure with a voxel based regular element/node pattern ) used only a regular vector to store the nodes (since e.g. at the element, no nodes have to be stored, just from the element number and the global dimensions, the corresponding nodes can be calculated). However, in the current setup (regarding the generality/modularity we are currently working on), I would go even further and ask the question, if it is really necessary to continue maintaining the StructureBase interface. If everything is moved into modular sub containers (assembler, constraints), I do not see a particular reason to continue having a Structure/StructureBase. Especially, since the grid approach has been recently removed and I don't see that we will implement this again in the future (besides, I believe that the savings in directly using the grid structure in the data storage are only marginal compared to the additional implementation effort).

Regarding the second issue : I don't see reason to use the mentioned routines.

joergfunger avatar Jun 22 '17 07:06 joergfunger

Yep, I was never much of a StructureBase enthusiast anyway, I just figured opening a "Remove StructureBase" issue would be considered quite bold. Even if we had a StructureGrid, in what cases would I need to use these polymorphically, i.e. have only access to the StructureBase ptr/reference? I can't think of one.

Given your comment, do you think it worthwhile to sort of merge StructureBase and unstructured/Structure into one Structure class, with some cleanup along the way?

Psirus avatar Jun 22 '17 07:06 Psirus

The general interface would be the time integration scheme (that just requires the current StructureBase interface). However, as already pointed out before, I think merging Structure and StructureBase is the way to go (along with modularizing the Structure by removing some functionality such as the assembler (currently implemented in the base as well) or the constraints (also in Base) into separate containers.

joergfunger avatar Jun 22 '17 07:06 joergfunger

Of course, time integration, the old spoilsport. I was thinking along the lines of "Hey TimeIntegration, here are some matrices and previous solutions, could you give me the next one?", which has been discussed before, so that time integration schemes could be used for different purposes besides integrating the structure. But that's another issue altogether.

Psirus avatar Jun 22 '17 08:06 Psirus

@Psirus I was about to write something similar when your comment flew in. Even though it is a bit off topic, I want to add some lines. A lot of code (update constraints, merge dof values, ...) is very specific to StructureBase, not to the time integration. This might be one of the reason, the time integration looks complex or incomprehensible to some ppl. It is enough to provide a residual and hessian for the trial state and a residual and a hessian for the iterations. (Maybe more...). For the case of integrating a StructureBase, this includes updating the constraints, merging the dof values and so on. But this is hidden in the residual/hessian functions and the time integration does not need to know the details.

TTitscher avatar Jun 22 '17 08:06 TTitscher

Shouldn't this StructureBase exactly be this interface for general timeintegration schemes, where I just provide a (vector) function (in our case the gradient) and it's time derivatives, and then I can integrate any arbitrary function that provides those to me?

joergfunger avatar Jun 22 '17 09:06 joergfunger

@pmueller2 recently implemented interfaces like this one to decouple our Structure from the time integration. IMO we all agreed on the beauty of this approach.

We can now think about, how uniform the Structure interface has to be. It now provides methods like BuildGradient() that return a combined gradient of all PDEs or materials. We could think ob splitting that to something like

gradient  = AssembleVector(strucutureWithPde1);
gradient += AssembleVector(structureWithPde2);
...

or somehow translated into PDE

template <int TDim>
class CustomWrapperInMyMainFile
{
private:
  Group<Cell<MomentumBalance<TDim>>> mCellsLinear;
  Group<Cell<MomentumBalanceCycleJump<TDim>>> mCellsDamage;
  Matrix mInverseMass;

public:
BlockVector Rhs()
{
  gradient  = Assemble(mCellsLinear, MomentumBalance<2>>::Gradient());
  gradient += Assemble(mCellsDamage, MomentumBalanceCycleJump<2>::GradientElastic());
  return mInverseMass * gradient; // or whatever...
}

void Jump(int n)
{
  for (auto& cell : mCellsDamage)
    for (MomentumBalanceCycleJump<TDim>& integrand : cell.Integrands())
      integrand.CycleJump(n);
}
// ...
};

// later...
CustomWrapperInMyMainFile problem;
for (auto t : timeSteps)
{
  problem.Jump(42);
  solution = RungeKutta::DoStep(solution, t, problem.Rhs);
}

So we could completely remove the polymorphism here. The big difference to the template concept, we discussed before, is that we not even need a IntegrandTimeDependent. So instead of manually writing operations, we now write the interface for time integration / newton methods.

Again to point this out: This requires (apart from a collection of predefined defaults) the manual definition of those interfaces. Do we want that?

TTitscher avatar Nov 10 '17 13:11 TTitscher