Ok!
After some carefull consideration and application of general knowledge
about FEA software I've come up with a solution
In case someone else faces the same task I post part of my code below. Hope
it'll be helpfull
* // Create two FEM meshes: one for nodes that will be removed in modal
reduction, // the other for the nodes that will remain after modal
reduction. mesh_internal = chrono_types::make_shared<ChMesh>();
AddInternal(mesh_internal); // NOTE: MESH FOR INTERNAL NODES: USE
assembly->AddInternal() mesh_boundary =
chrono_types::make_shared<ChMesh>(); Add(mesh_boundary); // NOTE: MESH
FOR BOUNDARY NODES: USE assembly->Add()
mesh_internal->SetAutomaticGravity(false);
mesh_boundary->SetAutomaticGravity(false); std::shared_ptr<ChMesh>
mesh_loaded = chrono_types::make_shared<ChMesh>(); try{
ChMeshFileLoader::FromTetGenFile(mesh_loaded, ///< destination
mesh pathToNodesFile.c_str(),
///< name of the .node file
pathToEleFile.c_str(), ///< name of the .ele file
mmaterial, ///< material for the
created tetahedrons VNULL,
///< optional displacement of imported mesh
ChMatrix33<>(1) ///< optional
rotation/scaling of imported mesh ); } catch
(ChException myerr) { GetLog() << myerr.what(); throw
myerr; } mesh_internal->SetAutomaticGravity(false);
mesh_boundary->SetAutomaticGravity(false); //------------TODO:
internal and boundary nodes selection---------------------
std::cout<<"mesh_internal->GetNnodes() ==
"<<mesh_internal->GetNnodes()<<std::endl;
interfaceNodesIds.clear(); aggregatedNodesIds.clear();
interfaceNodesToAdd.clear(); interfaceNames.clear();
interfacePoints.clear();
if(!parse_interface_points_file(pathToInterfacePointsFile,
interfaceNames,
interfaceNodesIds,
aggregatedNodesIds)) { std::cout<<"Unable to parse
interface point file '"<<pathToInterfacePointsFile<<"'"<<std::endl;
std::string msg = "Unable to parse interface point file
'"+pathToInterfacePointsFile+"'"; throw new file_format(msg);
} if(!interfaceNodesIds.empty()) { //first
form internal and boundary meshes std::vector<int>
move2boundary; // total list of nodes to be made boundary
for(int i=0;i<interfaceNodesIds.size();++i) {
if(interfaceNodesIds[i]<0) // the point is being created not selected from
the mesh { ChVector<double>
newNodePos(0,0,0); // set it to the average of the aggregatedNodes
for(int j=0;j<aggregatedNodesIds[i].size();++j)
{
if(std::find(move2boundary.begin(),move2boundary.end(),aggregatedNodesIds[i][j])
== move2boundary.end()){
move2boundary.push_back(aggregatedNodesIds[i][j]);
} newNodePos +=
std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(aggregatedNodesIds[i][j]))->GetX0();
} newNodePos /=
aggregatedNodesIds[i].size();
std::shared_ptr<ChNodeFEAxyzrot> interfNodePnt =
chrono_types::make_shared<ChNodeFEAxyzrot>();
interfNodePnt->SetMass(0);
interfNodePnt->SetPos(newNodePos);
mesh_boundary->AddNode(interfNodePnt);
interfacePoints.push_back(interfNodePnt); for(int
j=0;j<aggregatedNodesIds[i].size();++j) {
auto my_root = chrono_types::make_shared<ChLinkPointFrame>();
my_root->Initialize(std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(aggregatedNodesIds[i][j])),
interfNodePnt);
AddLink(my_root); } }
else if(interfaceNodesIds[i]>=0){
std::shared_ptr<ChNodeFEAxyz> interfNode =
std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(interfaceNodesIds[i]));
if(std::find(move2boundary.begin(),move2boundary.end(),interfaceNodesIds[i])
== move2boundary.end()){
move2boundary.push_back(interfaceNodesIds[i]); }
for(int j=0;j<aggregatedNodesIds[i].size();++j)
{
if(std::find(move2boundary.begin(),move2boundary.end(),aggregatedNodesIds[i][j])
== move2boundary.end()){
move2boundary.push_back(aggregatedNodesIds[i][j]);
} } std::shared_ptr<ChNodeFEAxyzrot>
interfNodePnt = chrono_types::make_shared<ChNodeFEAxyzrot>();
interfNodePnt->SetMass(0);
interfNodePnt->SetPos(interfNode->GetX0());
mesh_boundary->AddNode(interfNodePnt);
interfacePoints.push_back(interfNodePnt); //connect
interfNode to interface body (just like another aggregated node
auto my_root = chrono_types::make_shared<ChLinkPointFrame>();
my_root->Initialize(interfNode, interfNodePnt);
AddLink(my_root); for(int
j=0;j<aggregatedNodesIds[i].size();++j) {
std::shared_ptr<ChNodeFEAxyz> aggregatedNode =
(std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(aggregatedNodesIds[i][j])));
auto linkInternal2Boundary =
chrono_types::make_shared<ChLinkPointFrame>();
linkInternal2Boundary->Initialize(aggregatedNode, interfNodePnt);
AddLink(linkInternal2Boundary); }
} } int nNodes = mesh_loaded->GetNnodes();
for(int i=0; i<nNodes; ++i) {
if(std::find(move2boundary.begin(),move2boundary.end(),i) ==
move2boundary.end()) mesh_internal->AddNode(
std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(i)) );
else mesh_boundary->AddNode(
std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_loaded->GetNode(i)) );
} int nElements = mesh_loaded->GetNelements();
for(int i=0; i<nElements; ++i) {
mesh_internal->AddElement(mesh_loaded->GetElement(i)); }
} else { mesh_internal = mesh_loaded; // just
overrite it } //------------TODO: internal and boundary nodes
selection - end -------------- auto visualizeInternalA =
chrono_types::make_shared<ChVisualShapeFEA>(mesh_internal);
visualizeInternalA->SetFEMdataType(ChVisualShapeFEA::DataType::NODE_P);
visualizeInternalA->SetColorscaleMinMax(-600, 600);
visualizeInternalA->SetSmoothFaces(true);
visualizeInternalA->SetWireframe(true);
mesh_internal->AddVisualShapeFEA(visualizeInternalA); auto
visualizeInternalB =
chrono_types::make_shared<ChVisualShapeFEA>(mesh_internal);
visualizeInternalB->SetFEMglyphType(ChVisualShapeFEA::GlyphType::NODE_CSYS);
visualizeInternalB->SetFEMdataType(ChVisualShapeFEA::DataType::NONE);
visualizeInternalB->SetSymbolsThickness(0.2);
visualizeInternalB->SetSymbolsScale(0.1);
visualizeInternalB->SetZbufferHide(false);
mesh_internal->AddVisualShapeFEA(visualizeInternalB); auto
visualizeBoundaryB =
chrono_types::make_shared<ChVisualShapeFEA>(mesh_boundary);
visualizeBoundaryB->SetFEMglyphType(ChVisualShapeFEA::GlyphType::NODE_CSYS);
visualizeBoundaryB->SetFEMdataType(ChVisualShapeFEA::DataType::NONE);
visualizeBoundaryB->SetSymbolsThickness(0.4);
visualizeBoundaryB->SetSymbolsScale(4);
visualizeBoundaryB->SetZbufferHide(false);
mesh_boundary->AddVisualShapeFEA(visualizeBoundaryB);*
On Wednesday, December 13, 2023 at 5:58:15 PM UTC+3 Vic M wrote:
> Ok. Now I'm absolutely sure that the problem is with ChLink.... but have
> no clue on how to fix it.
> I've tried both AddInternalLink(my_root) and AddLink(my_root) with the
> same result:
> "SymShiftInvert: factorization failed with the given shift"
>
> If anyone knows where the problem lies It'd be very helpful
>
>
> On Tuesday, December 5, 2023 at 10:42:27 AM UTC+3 Vic M wrote:
>
>> Hi Dario,
>>
>> Thank you for fast response!
>> I'm sorry that I did give any details on the problem. I thought that it
>> was some stupid mistake of a newbie and a common solution is ready )
>> Since my first post I've done some experiments and got more understanding
>> of the problem.
>> First of all you are right "Panel" object has mistakes in its
>> implementation which I still do not know how to fix yet.
>>
>> I followed these three tutorials:
>>
>> https://github.com/projectchrono/chrono/blob/main/src/demos/modal/demo_MOD_assembly.cpp
>>
>> https://github.com/projectchrono/chrono/blob/main/src/demos/fea/demo_FEA_modal_assembly.cpp
>>
>> https://github.com/projectchrono/chrono/blob/main/src/demos/fea/demo_FEA_contacts_NSC.cpp
>>
>> From the last I've taken the loading of Tetgen mesh from my CAD model.
>> The other two - for assembly and modal reduction.
>>
>> Now to the core of my situation...
>> I need to put several "Panels" together to model their vibration. A
>> single panel contains up to 15k DoFs that is already too much for Spectra
>> and requires significant memory usage (that I've grasped experimentally but
>> not yet sure about it).
>> In order to put the panels together interface points (boundary points)
>> are needed. As described in the first link above the two types of mesh are
>> needed in the ChModalAssembly, so I did like this:
>>
>> mesh_internal = chrono_types::make_shared<ChMesh>(); AddInternal(
>> mesh_internal); // NOTE: MESH FOR INTERNAL NODES: USE
>> assembly->AddInternal()
>> mesh_boundary = chrono_types::make_shared<ChMesh>(); Add(mesh_boundary);
>> // NOTE: MESH FOR BOUNDARY NODES: USE assembly->Add()
>>
>> But then I loaded the positions and indices of vertices into the model
>> and found out that I can't easily connect ChNodeFEAxyz to ... anything
>> else (like bodies).
>> After removing all interface points the reduction goes smooth but my
>> panel is useless(
>> So I guess that the problem is in the constrains equations that are set
>> by ChLinkXXXXXXs. And I don't know yet how to add ChLinks correctly
>>
>> I put my code for adding interface points below, may be you could give me
>> a hint where I'm wrong?
>>
>> ```
>> if(!interfaceNodesIds.empty())
>> {
>> for(int i=0;i<interfaceNodesIds.size();++i)
>> {
>> if(interfaceNodesIds[i]<0) // the point is being created not
>> selected from the mesh
>> {
>> std::vector<std::shared_ptr<ChNodeFEAxyz>>
>> aggregatedNodes(aggregatedNodesIds[i].size());
>> ChVector<double> newNodePos(0,0,0); // set it to the
>> average of the aggregatedNodes
>>
>> for(int j=0;j<aggregatedNodesIds[i].size();++j)
>> {
>> aggregatedNodes[i] =
>> (std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_internal->GetNode(aggregatedNodesIds[i][j])));
>> newNodePos +=
>> std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_internal->GetNode(aggregatedNodesIds[i][j]))->GetX0();
>> }
>>
>> newNodePos /= aggregatedNodesIds[i].size(); //
>>
>> // std::shared_ptr<ChNodeFEAxyz> interfNode =
>> chrono_types::make_shared<ChNodeFEAxyz>(newNodePos);
>>
>> std::shared_ptr<ChBody> interfNodeBody =
>> chrono_types::make_shared<ChBody>();
>> interfNodeBody->SetMass(0.0001);
>>
>> interfNodeBody->SetInertia(ChMatrix33<double>::Identity()*0.00000001);
>> interfNodeBody->SetPos(newNodePos);
>> interfNodeBody->SetName(interfaceNames[i].c_str());
>> Add(interfNodeBody);
>>
>> //add body to the list of interface points for external
>> links attachment
>> interfacePoints.push_back(interfNodeBody);
>>
>>
>> //attach all the aggregated nodes to the interface body
>> (point)
>> for(int j=0;j<aggregatedNodes.size();++j)
>> {
>> mesh_boundary->AddNode(aggregatedNodes[i]);
>> auto my_root =
>> chrono_types::make_shared<ChLinkPointFrame>();
>> my_root->Initialize(aggregatedNodes[i],
>> interfNodeBody);
>> // AddInternalLink(my_root);
>> AddLink(my_root);
>> }
>> }
>> else if(interfaceNodesIds[i]>=0){
>> std::shared_ptr<ChNodeFEAxyz> interfNode =
>> std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_internal->GetNode(interfaceNodesIds[i]));
>> std::shared_ptr<ChBody> interfNodeBody =
>> chrono_types::make_shared<ChBody>();
>> interfNodeBody->SetMass(0.001);
>>
>> interfNodeBody->SetInertia(ChMatrix33<double>::Identity()*0.001);
>> interfNodeBody->SetPos(interfNode->GetX0());
>> interfNodeBody->SetName(interfaceNames[i].c_str());
>> Add(interfNodeBody);
>>
>> //add body to the list of interface points for external
>> links attachment
>> interfacePoints.push_back(interfNodeBody);
>>
>> std::vector<std::shared_ptr<ChNodeFEAxyz>>
>> aggregatedNodes(aggregatedNodesIds[i].size());
>>
>> for(int j=0;j<aggregatedNodesIds[i].size();++j)
>> {
>> aggregatedNodes[i] =
>> (std::dynamic_pointer_cast<ChNodeFEAxyz>(mesh_internal->GetNode(aggregatedNodesIds[i][j])));
>> }
>>
>>
>> // new interface point to be added to the system
>>
>> //attach the interface node to the interface body (point)
>> // mesh_boundary->AddNode(interfNode);
>> {
>> auto my_root =
>> chrono_types::make_shared<ChLinkPointFrame>();
>> my_root->Initialize(interfNode, interfNodeBody);
>> // AddLink(my_root);
>> AddInternalLink(my_root);
>>
>> }
>>
>> //attach all the aggregated nodes to the interface body
>> (point)
>> for(int j=0;j<aggregatedNodes.size();++j)
>> {
>> // mesh_boundary->AddNode(aggregatedNodes[i]);
>> auto my_root =
>> chrono_types::make_shared<ChLinkPointFrame>();
>> my_root->Initialize(aggregatedNodes[i],
>> interfNodeBody);
>> AddInternalLink(my_root);
>> // AddLink(my_root);
>> }
>> }
>> }
>> }
>> ```
>>
>>
>>
>>
>>
>>
>> On Monday, December 4, 2023 at 7:48:03 PM UTC+3 [email protected]
>> wrote:
>>
>>> Hi Victor,
>>> I'm not an expert on modal reduction, but in the meantime can you be
>>> more precise about the problem?
>>> For example:
>>>
>>> 1. you say "some of the input matrices are wrong". What "wrong"
>>> means to you? Are there missing coefficients? Is the size wrong? Does
>>> the
>>> stiffness matrix have different values to the one expected? Wa
>>> 2. are you sure that your "Pannel" object is correctly implemented?
>>> Does a normal dynamic simulation work?
>>> 3. is there any exception triggered and, if so, in which line? you
>>> say that you hit "some kind of problems". We are not really able to fix
>>> *"some
>>> kind"* of problems, but we may try to fix some *specific *problem.
>>> Is there any missing attachment in your post? How can we expect to give
>>> advices if we don't have neither your full code nor even a precise error
>>> output?
>>> 4. Did you split internal nodes from those at the boundaries? like
>>> this?
>>> auto mesh_internal = chrono_types::make_shared<ChMesh>();
>>> assembly->AddInternal(mesh_internal); // NOTE: MESH FOR
>>> INTERNAL NODES: USE assembly->AddInternal()
>>>
>>> auto mesh_boundary = chrono_types::make_shared<ChMesh>();
>>> assembly->Add(mesh_boundary); // NOTE: MESH FOR BOUNDARY NODES:
>>> USE assembly->Add()
>>> 5. which tutorial did you follow?
>>> 6. Did you try to give a look at this demo?
>>>
>>>
>>> https://github.com/projectchrono/chrono/blob/main/src/demos/modal/demo_MOD_assembly.cpp
>>>
>>> We are currently working in better modal reduction methods on a separate
>>> branch, but in the meanwhile it would be great if you provide better info
>>> about your problem.
>>>
>>> Dario
>>> Il giorno lunedì 4 dicembre 2023 alle 11:07:32 UTC+1 [email protected]
>>> ha scritto:
>>>
>>>> Debuging shows the problem in ConvertToMatrixForm() function. Seems
>>>> some of the input matrices are wrong... but which one and how to fix it
>>>> ????
>>>>
>>>> On Monday, December 4, 2023 at 12:55:56 PM UTC+3 Vic M wrote:
>>>>
>>>>> Hello everyone,
>>>>> I'm experiencing some kind of problem working with model reduction
>>>>> functionality in chrono.
>>>>> I'm using the ChModalAssembly for modeling and reduction (as
>>>>> repented in the tutorial)
>>>>> First I create the system
>>>>> ```
>>>>> ChSystemNSC sys; auto qr_solver = chrono_types::make_shared<
>>>>> ChSolverSparseQR>(); sys.SetSolver(qr_solver);
>>>>> ....
>>>>> ```
>>>>> Then creating my model object
>>>>> ```
>>>>> auto sp = chrono_types::make_shared<Pannel>();
>>>>> sys.Add(sp);
>>>>> ```
>>>>>
>>>>> The mesh is loaded from external TetGen file
>>>>> ```
>>>>> ChMeshFileLoader::FromTetGenFile(mesh_internal, ///< destination mesh
>>>>> pathToNodesFile.c_str(), ///< name of the .node file pathToEleFile.
>>>>> c_str(), ///< name of the .ele file mmaterial, ///< material for the
>>>>> created tetahedrons VNULL, ///< optional displacement of imported mesh
>>>>> ChMatrix33<>(1) ///< optional rotation/scaling of imported mesh );
>>>>> ```
>>>>> Then I do the reduction
>>>>> ```
>>>>> SetModalMode(true); SwitchModalReductionON( nModes, // The number of
>>>>> modes to retain from modal reduction, or a ChModalSolveUndamped with
>>>>> more settings ChModalDampingRayleigh(0.001, 0.005) // The damping
>>>>> model - Optional parameter: default is ChModalDampingNone(). );
>>>>> ```
>>>>>
>>>>> After the reduction the program crashes with SEGV at either
>>>>> ```
>>>>> ComputeModesDamped(10);
>>>>> ```
>>>>> or (if the above is commented out) at
>>>>>
>>>>> ```
>>>>> sys.DoStepDynamics(step_size);
>>>>> ```
>>>>> The model has 1302 nodes and 3441 elements
>>>>> It's very frustrating since I don't know where my mistake may be
>>>>>
>>>>> Thanks in advance for your help
>>>>>
>>>>> Regards,
>>>>> Victor
>>>>>
>>>>>
--
You received this message because you are subscribed to the Google Groups
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/projectchrono/4568f2da-ba5f-44e3-8da8-8c3434feb0f7n%40googlegroups.com.