Topic: Material models in SM and TM module

SM module:

I want to add virtual functions:
giveRealStressVector_3d
giveRealStressVector_PlaneStrain - Default implementation, calls 3d version
giveRealStressVector_PlaneStress - Default implementation, calls 3d version iteratively
giveRealStressVector_1d - Default implementation, calls 3d version iteratively
where most material models would just overload giveRealStressVector_3d.
The big change would then be that the IP values would then always be stored in their full form.
This way, all 4 modes would be available for all materials. It's simpler to deal with material status when it is always stored in full 3d form.
Some material models might only be applicable to 1D cases, in which case they would overload it and give error messages accordingly.



TM module:
Mix of heat and heat+mass transfer problems. The material models are essentially completely different objects alltogether. The material models are only superficially compatible.
I think it should be a base class under for just heat+mass transfer problems, and another for just heat/mass.

2

Re: Material models in SM and TM module

I am fine with proposed family of methods giveRealStressVector*.
However, I think, that storing stress and strains in their full form is wasting of space. The extreme case is 1D, but here it is not too restrictive, as we probably do not expect that someone is going to compute a huge 1D structure, but in case of plane stress, this could consume too much of memory. The number of integration points is (or can easily be) bigger than number of nodes, and for each IP we will allocate twice the memory needed. And I really think that in this case we have to care about the memory.

I suggest to use existing abstractions for stress and strain vectors: stressVector and strainVector, that store the values in reduced form together with materialMode and naturally hide all implementation details inside. And as they are derived from FloatArray, many existing routines can be readily reused.

Re: Material models in SM and TM module

First, this would just be the default behavior. If a material model overloads the functions, there wouldn't really be a way to determine wether or not it stored full or reduced vectors. However, i still insist that the interface, setIPValue + getIPValue, should always just return the full vector, as the common denominator.
The elastic models would do this.

But in general, just because the we're solving for something less than full 3D (plane stress, plane strain, 1d) doesn't mean we always can get away with storing the internal variables in the equally reduced state. So it might not even be an option (as most material models doesn't even support plane stress right now).

Your comment on memory consumption is not at all correct;
Even in the extreme case of plane stress, and in a model that can reduce all the internal variables, you still wouldn't get to twice the memory consumption. The overhead from other internal variables, e.g. pointers, sizes, so, a quick estimate for the possible worst case scenario:
One GaussPoint in plane stress, containing one material status for an elastic material, will take up (meassured in sizeof(doubles)):
12 + statusDict = 19 + IntegrationPointStatus = 20 + StructuralMaterialStatus
A FloatArray takes up 3 + size of the array, so we end up with total size
44 + 4*length_of_array
So, for the reduced plane stress, you'd use 56*sizeof(double) for each GaussPoint, and for the full form you'd use 68*sizeof(double), so the memory consumption for a GaussPoint increases by a factor ~1.2 times more. That's a memory consumption I'd be willing to pay for the simplified logic, even for elastic models.

Storing them inside StressVector and StrainVector classes you still need to convert manually and do all that logic everywhere inside the material routines, or overload the access functions "at(...)", which will kill the performance they inherit from FloatArray (can't use any of them BLAS functions anymore, can't inline).

4

Re: Material models in SM and TM module

For me even 10% saving would be a reason for an additional logic...

Re: Material models in SM and TM module

Before I say anything more, I need to point out that if the material models overload giveRealStressVector_*** they can do whatever they want internally. Returning full vectors in giveIPValue doesn't mean you actually store full vectors.

As for the memory consumption, I disagree. Correctness is paramount, so making it as easy for material models as possible should be prioritized. A 20% theoretical worst possible case scenario, probably 10% in more realistic extreme cases, and perhaps ~1% in common cases.

For example, RCM2Material, one of the materials which supposedly supports PlaneStress. It takes the reduces strain vector and expands it, filling it up with zeros. Fine for plane strain, but it's incorrect for PlaneStress.
Or maybe how PlasticMaterial calls "giveStressDependentPartOfStrainVector" for the reduce strain, is that really correct for both PlaneStress and PlaneStrain?
I really think these two models are broken here, as direct result of trying to work with reduced components. Supporting especially plane stress directly in arbitrary material models is very very hard to get right, just storing the same reduced components for all vectors is not correct at all.

-------------------------------------------

But none of that actually matters for these default implementations.
I didn't add full form of vectors as an additional discussion point. I simply can't do a default implementation of giveRealStressVector_Planestress/PlaneStrain/1d without the 3d version storing the full vectors since it would be calling the 3D function (i.e. it must run giveRealStressVector_3d as if it was called directly). It certainly wouldn't work to just zero out component 3, 7, 8 or the strain, just like the stress and expect correct results.
Should the internal damage/plasticity-variable be zeroed in the same components as the strain? Most likely not, so reducing any components requires detailed knowledge about the material models.
Can't make any of those assumptions on internal variables in the default implementations (since they would always be wrong).
Even specialized implementations for specific material models, it would be hard to keep track of what components you can reduce. So hard it's not worth it, rather you risk breaking stuff.

Re: Material models in SM and TM module

Isn't it always possible  to compute the dependent variables (epsilon_33 for plane stress) from the basic variables(epsilon_11, epsilon_22 and epsilon_12 for plane stress), like for isotropic elasticity eps_33 = -nu/(1-nu)(eps_11 + eps_22) ? Then it would be possible to do default implementation even with vectors stored in the reduced form.

Re: Material models in SM and TM module

Then you are making assumptions about the material model. The default implementations should work for arbitrary models.

Re: Material models in SM and TM module

However in plane stress case you will have to call giveRealStress_3d iteratively to find  e_33 and fulfill the condition that the sig_33 =0 , so I don't exactly understand how storing of the stress and the strain in the full form might help. To obtain the vector in the full form function giveFullVectorForm() can be used  and  eps_33 = -nu/(1-nu)(eps_11 + eps_22) could be just an initial guess.

Re: Material models in SM and TM module

With anything but linear isotropic elasticity "eps_33 = -nu/(1-nu)(eps_11 + eps_22)" is not true. It would be like throwing away the previous FE solution and start iterating the next time-step from a linear elastic response. Awful convergence speed.

Luckily, no material models work like that. We always store the old converged values of internal variables + the temporary variables (which, when convergence is reached, replaces the old values). Material models will continue from the old, converged values of stress, strain, and other internal variables.
So if you modify the converged values, trying to reduce and restore them with estimates, you will break the material routine and just get garbage results.

One could do; delta_eps_33 = -nu/(1-nu)(delta_eps_11 + delta_eps_22), with the initial guess: eps_33_temp = eps_33_old_converged + delta_eps_33  (if "nu" is defined for the material model).
But we can never throw away the converged result, because when we call "MaterialStatus::updateYourself" it must be there .

Throwing away any temp values means recalculating them at the converged state again.. which is computationally expensive (this is the reason why we store the temp values in the first place).

Re: Material models in SM and TM module

For plasticity one could do  eps_33 = -nu/(1-nu)(eps_11 + eps_22) with elastic part of strain (under the condition of isotropic elasticity), so one possibility would be to implement something like computeOutOfPlaneStrain for models which should work under plane stress condition and doesn't overload giveRealStressVector_PlaneStress. Another possibility is to store the out of plane strain in the status, but I still don't see the reason why to store the full form.

Re: Material models in SM and TM module

Recomputing anything is, of course, an unacceptable solution.
This discussion is no different saying, "why store the temp stress in normal strain controlled analysis, clearly we can recompute the stress afterwards?"
We could, but we definitely aren't going to. For plane stress, we start dropping part of the strain and another part of the stress, but in the end it's the same thing. Just with mixed control and a lot more convoluted.

The function "computeOutOfPlaneStrain" would not something simple to implement, and one would no longer have the main advantage of all this, i.e: Implement 3D version, get PlaneStrain-, PlaneStress-, and 1D-support automatically.

Re: Material models in SM and TM module

I've started adding

    virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep);
    virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep);
    virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep);
    virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep);

where there are default implementations for all but the 3d code.
Linear elastic materials were really simple to adapt, but other materials are written in the exact opposite way (i.e. the 3D, PlaneStress, PlainStrain, 1D distinction is made as late as possible).

Most materials still overload the general giveRealStressVector(...)-function, but this should be changed so that they can take advantage of the default implementation for PlaneStress.

For new material routines, i encourage everyone to follow the function prototypes above (i.e. ignoring the material mode in the GaussPoint), and for the existing materials, try to convert those who already exist:
I think the current list of materials which still overload giveRealStressVector is
CompoDamageMat, ConcreteDPM, DustMaterial, MisesMat, MPlasticMaterial, PlasticMaterial,  RCM2Material, RheoChainMaterial, IsotropicDamageMaterial

Re: Material models in SM and TM module

As a prerequisite for implementing this default behavior in all the material models, it turns out is it necessary to modify how giveIPValue works.

Disclaimer: This has nothing to do with whether or not a reduced vector is stored in the material status. ( though it would be much much easier to implement this if it did)

It turns out that we must return the full vectors in the "giveIPValue" function. This is a good idea anyway, because we then no longer need the function "giveIntVarCompFullIndx" either (and giveIPValSize is almost redundant), but most importantly, it would allow us to fix a very serious bug:
Currently, when we export with e.g. VTKXML we get a zero value for the out-of-plane components for the *strain* in plane-stress simulations. The same applies to plastic strains etc. The strain component might not produce any work, but it is vitally important to output correctly anyway.
So, having giveIPValue return the full vectors is a must for more reasons than these default implementations.
It also turns out that all the code that uses giveIPValue also becomes simpler when it can just assume the full vectors (which is always a plus).



I'm working my way through it right now and there are a lot of inconsistencies in the giveIPValue+friends functions.
Vectors and tensors and sizes are used widly inconsistently, even within a material model (in ways that can't possible have worked with VTKXML export). I'm trying to correct as much as possible as I go through.
I leave @todo comments as I go where material models should fill in correct values when they expand their reduced vectors.

As I can't read up on the theory for every such material, so I'm just padding the vectors out with zeros (as before), but other developers should fix it (if they possess the theory knowledge for the specific material model). I'll be fixing the linear elastic materials at least.

There is a lot of code, and things weren't really always correct to begin with, so there is bound to be a bug or two left.

Re: Material models in SM and TM module

So, the conversion to have giveIPValue is turning out great.
1. Material models can actually export the correct values
2. Should be much simpler to properly have default implementations for plane stress now.
3 No need for giveIntVarCompFullIndx
4. No need for giveIPValueSize (it was used in the recovery models, but I've removed that need)
So much less duplicated information sent around.
Quite often, the sizes and indices given in these functions didn't match upp, but now it should be unconditionally compatible.
Plenty of simplifications follow from this, mostly by not having to overload the functions for returning the sizes and indices (in every single material and element).

Let me know ASAP if anyone is having problems after this big push.

Re: Material models in SM and TM module

After some more investigation i see that we should do the same thing for all the ****Layer and fiber material modes, since they are also only combinations of stress/strain control.
I will (after my vacation) add default implementations for these modes as well.

However, with the actual integrated quantaties; 3dBeam, 2dPlate etc. these belong n the crosssection, since, of course, they use cross-section data.

This makes it easier to ensure that when you use, say, a fiberedcross-section, you actually get the fibers. Currently, if you used a 3dbeam, you would get the fibers added, and if you used 2dbeam, you would get it without fibers (no warning, no errors). This is very misleading. I'd rather have it print an error message, so that you either 1. Implement the lacking features, 2. Change the cross-section you use to just a simplecrosssection.

Re: Material models in SM and TM module

I've also added the corresponding default implementations for: 2dBeamLayer, PlateLayer, Fiber.
These, and PlaneStress, 1dMat, are all calling "giveRealStressVector_3d" iteratively until they reach convergence.

Some materials support more than just 3DMat, and, unfortunately, they are typically not easily converted (without detailed knowledge of the theory), as they rely on checking "gp->giveMaterialMode()" in various ways and evaluating something other than what have been directly requested (e.g. giveRealStressVector_3d should always give the 3d mode, regardless of what the gauss point is actually doing).
This means that these materials are locked out of supporting some or all of the material modes: planestrain, planestress, 1d, beamlayer, platelayer, fiber.


I even don't think the gauss point should even know what material mode it has. It should be based upon what function is directly called.
Using virtual functions is more convenient, clear what should be computed, and it allows for default implementations like these.
A common function + enum + switch-case should be a last resort, if ever used.

Re: Material models in SM and TM module

A few more comments on material models (I'm trying to reduce the amount of fragmentation I see in the different components):

TrPlaneStrRot is an elements which introduced _PlaneStressRot. This introduces a penalty term associated with the drilling stiffness, which is set to the shear modulus in the linear elastic models.
I don't think this is a great idea. This penalty term isn't really part of the material model.
I would rather it be a simple membrane with a completely separate term is added by the stiffness matrix.
I use this approach with the Quad1MindlinShell3d element that I implemented. It would allow the membrane to be some nonlinear material as well, instead of being limited to linear elastic models. It would also allow for layered support and such.

Edit: I was thinking a bit more about this, and I suppose it would make sense (at least very practical) to add the penalty term for the drilling dofs as a parameter to the cross-section, and treat this similarly as we do with plates and beams.


StructuralMaterial should only be normal continuum models.
Things like cohesive zone models should use a separate base class for material models, instead of trying to force it through the same interface "giveRealStressVector". There is no advantage to using a common interface, and it forces StructuralMaterialStatus to keep try and deal with odd things like _1dInterface, even though it has nothing to do with stresses and strains.
I'm not sure what the lattice models are, but I think the same applies there. The GradDp models are however usually some extension of a normal continuum model (at least that's what the code looks like), so I guess these should as some extension.


The cross-sections should all overload "giveIPValue" and do everything related to beam and shell moments/forces.
The pipeline is already there, CrossSection::giveIPValue, but it is not properly overloaded by the existing cross-sections. I'm undecided on what i think about expanding the moments/forces to "full" form for beams and plates. It would probably be a good idea that would make post-processing easier.


MaterialStatus::printOutputAt has problems. It expands the stresses and strains (which might sometimes be generalized stresses and strains) and pads them out with zeroes.
I would rather we didn't expand at all if we are going to pad them out with values which we know are definitely false. So simply not expanding them is a possible option. It would give smaller files, and you would have, at least the most important part of the output still there so that one can check correctness in the tests suite.

The other option, to properly expand the output, would need to go through the same pipeline as giveIPValue, e.g. it should go
Element->CrossSection->Material
through some function like
"printOutputFromPointAt(FILE *file, GaussPoint *gp, TimeStep *tStep);"
where the material model should use giveIPValue to obtain the full form of the stress, strain and other internal variables for exporting.
This would be quite a lot of work to implement.