Access to body material properties

Asked by Przemek

Hi,

I have a problem with the access to some properties which are assigned to a particle (sphere). Could you help me to solve the problem? Here are segments of code.

From .hpp file:

class CpmMat : public FrictMat {
public:
 shared_ptr<State> newAssocState() const override { return shared_ptr<State>(new CpmState); }
 bool stateTypeOk(State* s) const override { return (bool)dynamic_cast<CpmState*>(s); }

 // clang-format off
 YADE_CLASS_BASE_DOC_ATTRS_CTOR(CpmMat,FrictMat,"Concrete material, for use with other Cpm classes. \n\n.. note::\n\n\t:yref:`Density<Material::density>` is initialized to 4800 kgm⁻³automatically, which gives approximate 2800 kgm⁻³ on 0.5 density packing.\n\nConcrete Particle Model (CPM)\n\n\n:yref:`CpmMat` is particle material, :yref:`Ip2_CpmMat_CpmMat_CpmPhys` averages two particles' materials, creating :yref:`CpmPhys`, which is then used in interaction resultion by :yref:`Law2_ScGeom_CpmPhys_Cpm`. :yref:`CpmState` is associated to :yref:`CpmMat` and keeps state defined on particles rather than interactions (such as number of completely damaged interactions).\n\nThe model is contained in externally defined macro CPM_MATERIAL_MODEL, which features damage in tension, plasticity in shear and compression and rate-dependence. For commercial reasons, rate-dependence and compression-plasticity is not present in reduced version of the model, used when CPM_MATERIAL_MODEL is not defined. The full model will be described in detail in my (Václav Šmilauer) thesis along with calibration procedures (rigidity, poisson's ratio, compressive/tensile strength ratio, fracture energy, behavior under confinement, rate-dependent behavior).\n\nEven the public model is useful enough to run simulation on concrete samples, such as :ysrc:`uniaxial tension-compression test<examples/concrete/uniax.py>`.",
  ((Real,sigOld,0.,,"normal stress from previous iteration [Pa]"))
  ((Real,tauOld,0.,,"shear stress from previous iteration [Pa]"))
  ((Real,Sy_0,NaN,,"initial yield strength [Pa]"))
  ((Real,oldSy,0.,,"yield point form previous iteration [Pa]"))
  ((Real,cumStr,0.,,"cummulative plastic strain [-]"))
  ((Real,H,0.,,"hardening parameter [Pa]"))
  ((Real,density,2700.,,"density [kg/m3]"))
  ((Real,CP1,0.,,"heat capacity constant"))
  ((Real,CP2,0.,,"heat capacity constant"))
  ((Real,CP3,0.,,"heat capacity constant"))
        ((Real,K1,0.,,"thermal conductivity constant"))
        ((Real,K2,0.,,"thermal conductivity constant"))
        ((Real,K3,0.,,"thermal conductivity constant"))
        ((Real,K4,0.,,"thermal conductivity constant")),
  createIndex();

And from .cpp file:

FOREACH(shared_ptr<Body> B, *scene2->bodies)
 {
     CpmPhys* mat = dynamic_cast<CpmPhys*>(B->material.get());
     const Real& CP1(mat->CP1);
     const Real& CP2(B->material.CP2);
     const Real& CP3(B->material.CP3);
     const Real& K1(B->material.K1);
     const Real& K2(B->material.K2);
     const Real& K3(B->material.K3);
     const Real& K4(B->material.K4);

  if (!B) continue;
  const Body::id_t& id = B->getId();
  // add damaged contacts that have already been deleted
  CpmState* state = dynamic_cast<CpmState*>(B->state.get());
  if (!state) continue;
  state->stress = bodyStats[id].stress;
  Sphere* sphere = dynamic_cast<Sphere*>(B->shape.get()); // from that ok???
  if (!sphere) continue;
  Real& r = sphere->radius;
  state->stress = bodyStats[id].stress / (4 / 3. * Mathr::PI * r * r * r / .62) * .5;
  //state->oldTemp = state->temp; // przypisanie wartosci temperatury
  state->Cp = CP1 + CP2 * state->temp + CP3 * pow(state->temp,2);
  state->k = K1 + K2 * state->temp + K3 * pow(state->temp, 2) + K4 * pow(state->temp, 3);
 }

And here is the example message form terminal:

/home/przemek/DEMlab/trunk/pkg/dem/ConcretePM.cpp:492:33: error: ‘class boost::shared_ptr<yade::Material>’ has no member named ‘K2’
  492 | const Real& K2(B->material.K2);

Have you any suggestions?

BR
Przemek

Question information

Language:
English Edit question
Status:
Answered
For:
Yade Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Przemek (przemekn) said :
#1

I modified my code and I removed showed lines from .cpp file. I add them to a NewtonIntegrator.cpp file

State* state = b->state.get();
  //Material* mat = b->material.get();
  const Body::id_t& id = b->getId();
  Vector3r f = Vector3r::Zero();
  Vector3r m = Vector3r::Zero();
  state->oldTemp = state->temp;
  b->material->CP1
  state->Cp = CP1 + scene->CP2 * state->oldTemp + scene->CP3 * pow(state->oldTemp,2);
  state->k = K1 + K2 * state->oldTemp + K3 * pow(state->oldTemp, 2) + K4 * pow(state->oldTemp, 3);

But I still have a problem how to get the constants CP1, CP2, etc. to compute the heat capacity...

BR
Przemek

Revision history for this message
Jan Stránský (honzik) said :
#2

Hi,

body->material is "by default" an abstract base Material instance [1]. It has no CP1, CP2, ..., K1, ...
If you want to access those properties defined on derived classes, you have to cast the instance.
(You have something already in your code).

WhateverMat* mat = dynamic_cast<WhateverMat*>(B->material.get());

A robust code should count with the possibility, that B->material is not WhateverMat, but some else material, like:

WhateverMat* mat = dynamic_cast<WhateverMat*>(B->material.get());
if (mat) { // if true, mat is WhateverMat. If false, mat is NOT WhateverMat
   // do something with WhateverMat
} else {
   // do something for the case it is not WhateverMat (different code, error, ...)
}

a note:
CpmPhys* mat = dynamic_cast<CpmPhys*>(B->material.get());
also being valid code, casting B->material (a Material) to CpmPhys (IPhys) will always result into null pointer.

Cheers
Jan

Revision history for this message
Przemek (przemekn) said :
#3

Hi Jan,

thank you for reply. I modified code:

State* state = b->state.get();
  CpmMat* mat = dynamic_cast<CpmMat*>(b->material.get());
  const Body::id_t& id = b->getId();
  Vector3r f = Vector3r::Zero();
  Vector3r m = Vector3r::Zero();
  state->oldTemp = state->temp;
  state->Cp = mat->CP1 + mat->CP2 * state->oldTemp + mat->CP3 * pow(state->oldTemp,2);
  state->k = mat->K1 + mat->K2 * state->oldTemp + mat->K3 * pow(state->oldTemp, 2) + mat->K4 * pow(state->oldTemp, 3);

But now I get those messages:

/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp: In member function ‘virtual void yade::NewtonIntegrator::action()’:
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:3: error: ‘CpmPhys’ was not declared in this scope; did you mean ‘IPhys’?
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^~~~~~~
      | IPhys
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:12: error: ‘mat’ was not declared in this scope; did you mean ‘math’?
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^~~
      | math
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:31: error: ‘CpmPhys’ does not name a type; did you mean ‘IPhys’?
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^~~~~~~
      | IPhys
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:38: error: expected ‘>’ before ‘*’ token
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:38: error: expected ‘(’ before ‘*’ token
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^
      | (
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:39: error: expected primary-expression before ‘>’ token
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^
/home/przemek/DEMlab/trunk/pkg/dem/NewtonIntegrator.cpp:181:59: error: expected ‘)’ before ‘;’ token
  181 | CpmPhys* mat = dynamic_cast<CpmPhys*>(b->material.get());
      | ^
      | )
make[2]: *** [CMakeFiles/dem.dir/build.make:583: CMakeFiles/dem.dir/pkg/dem/NewtonIntegrator.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:247: CMakeFiles/dem.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

How to declare the CpmMat in NewtonIntegrator?

BR
Przemek

Revision history for this message
Przemek (przemekn) said :
#4

Hi,

I solved the problem. Thanks!

BR
Przemek

Revision history for this message
Jan Stránský (honzik) said :
#5

probably you included Cpm into NewtonIntegrator source files.
If yes, using these specific classes in NewtonIntegrator seems like antipattern..
If you have it for your own purposes, it is OK.
If you want to publish the code, please consider some "more natural" refactoring.
Cheers
Jan

Revision history for this message
Przemek (przemekn) said :
#6

Hi,

yes, I included it. What do you mean by "more natural" refactoring?
Recently I'll use this code in my thesis, but I also want to share it with others.

BR
Przemek

Revision history for this message
Jan Stránský (honzik) said :
#7

Disclaimer: I have no knowledge of your requirements, so some of the below comments might be false or even stupid.
So please for further discussion, describe "by words" your aim, its consequences etc.

From the code segments, it seems you want some temperature/heat quantity updates.

Does the heat stuff belong to NewtonIntegrator at all?
Does the values / their change influences the integration (which the integrator is for)?
If not (which I assume for the rest of this text), probably a separate engine (e.g. HeatQuantitiesUpdater) would be a better place for such code.
If it is only applicable for CpmMat, maybe something like CpmStateHeatUpdater should be created.

Also, it seems you are changing Cpm stuff significantly.
If it is the case, consider creating a new material/phys/law, either derived from Cpm or "copied" from Cpm, but derived from FrictMat. Something like CpmHeatMat or other more suitable name.
Or maybe adding these general heat-specific quantities "higher" (Material? FrictMat?)?
Usually there are a few material instances in the simulation, so a few more attributes is no issue (contrary to state, shape etc., exclusively individual for each body).

NewtonIntegrator is a "general" class.
As such, it should not include specific material class (this is the main antipattern). You include CpmMat. Why not FrictMat or ViscElMat?
If, in the future, somebody creates a new material, will it be necessary to include it to the NewtonIntegrator files?
Currently, NewtonIntegrator even does not use the (most base) Material class at all, it only depends on (the most base) State class.

A note to the OP. Inside the CpmMat, you have stuff like "stress from previous iteration", "yield point form previous iteration", "cummulative plastic strain". These all does not belong to material (imagine there is just one material for entire simulation), these "state" quantities are meant to be put to State or IPhys (contrary to one-per-simulation material, there is separate State for each body and separate IPhys for each interaction).

As said:
For your own "one purpose" implementation, do whatever gives you desired results in desired time, no matter the code is "not clean".
For public code, which should be maintainable in long-term scale, the code should be "clean" - commented, documented, the class structure and their interplay (i.e. includes) should be logical, etc. etc.

Also there are different levels of this.
The code should be "brilliant" for classes like NewtonIntegrator and core stuff, because everybody uses them.
If you create "leaf" material (plus state, phys, law, etc.), like Cpm, you do not need to be so strict, as not everybody uses it and it is (should be!) included nowhere or on very limited amount of places. E.g. Cpm in ConcretePM files is self-contained. It is only included in VTKRecorder, because VTKRecorder provides extra "cpm recorder", not usual for most materials.

Cheers
Jan

Revision history for this message
Przemek (przemekn) said :
#8

Yes, I'm developing a thermal model in Yade. Regarding the integration, I want to sum all of the temperature increments which are derived from the interactions between spheres. Because I began my journey with Yade I used NewtonIntegrator to do this.
I want to write my thesis as soon as possible, so maybe I do "the cleaning" after that :)
Thank you for your comments. Can we stay in touch?

BR
Przemek

Revision history for this message
Jan Stránský (honzik) said :
#9

> Regarding the integration, I want to sum all of the temperature increments which are derived from the interactions between spheres. Because I began my journey with Yade I used NewtonIntegrator to do this.

Does your new computation directly influences the integration - position and velocity update?
If no, then (in the case of "clean" code) NewtonIntegrator is a bad place for such code.

Seems like even PyRunner could do the computation.
If yes, but you need the C++ efficiency (compared to pure python), then a dedicated engine is IMO a good solution (for the "clean code case").

> I want to write my thesis as soon as possible, so maybe I do "the cleaning" after that :)

very reasonable approach :-)

> Can we stay in touch?

sure

Cheers
Jan

Revision history for this message
Przemek (przemekn) said :
#10

-> Does your new computation directly influences the integration - position and velocity update?
If no, then (in the case of "clean" code) NewtonIntegrator is a bad place for such code.

It is a good question because it doesn't affect those values yet. But in the future, I want to add the thermal expansion effect, so it could change the particle position due to the change of radius.

Thanks for help :)

BR
Przemek

Revision history for this message
Jan Stránský (honzik) said :
#11

Of course a change of particles changes somehow the **result** of the integration, but not the integration itself.
E.g. change of size changes intertia tensor, but once changes in the state, the integration depends only on the state (from the explicit integration approach point of view).
Therefore it really makes sense to create a separate engine and put it somewhere to the simulation flow.

Like interactions influences the "change of particle position", but they are evaluated prior to NewtonIntegrator in separate engine (InteractionLoop).

Cheers
Jan

Revision history for this message
Przemek (przemekn) said :
#12

Hi,

sorry for my late reply but I was on holiday :)

Ye, you have absolutely right. I will make this separate engine but maybe after the defense of my thesis :)

Thanks for your help and explanations!

BR
Przemek

Can you help with this problem?

Provide an answer of your own, or ask Przemek for more information if necessary.

To post a message you must log in.