Perform electrostatics analysis (demo_FEA_electrostatics.cpp)

Tutorial that teaches how to use the FEA module to compute the electrostatic solution for a volume (Poisson problem) given boundary conditions. The tetrahedral mesh is imported from an Abaqus file. There are two node sets (boundaries) where high voltage is applied. The rest of the volume is considered to be air.

// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Alessandro Tasora
// =============================================================================
//
// FEA electrostatics
//
// =============================================================================
#include "chrono/physics/ChSystemSMC.h"
#include "chrono/solver/ChIterativeSolverLS.h"
#include "chrono/fea/ChContinuumElectrostatics.h"
#include "chrono/fea/ChElementBar.h"
#include "chrono/fea/ChElementHexaCorot_20.h"
#include "chrono/fea/ChElementHexaCorot_8.h"
#include "chrono/fea/ChElementTetraCorot_10.h"
#include "chrono/fea/ChElementTetraCorot_4.h"
#include "chrono/fea/ChLinkPointFrame.h"
#include "chrono/fea/ChMesh.h"
#include "chrono/fea/ChMeshFileLoader.h"
#include "chrono/fea/ChNodeFEAxyzP.h"
#include "chrono/assets/ChVisualShapeFEA.h"
#include "chrono_irrlicht/ChVisualSystemIrrlicht.h"
// Remember to use the namespace 'chrono' because all classes
// of Chrono::Engine belong to this namespace and its children...
using namespace chrono;
using namespace chrono::fea;
using namespace chrono::irrlicht;
using namespace irr;
int main(int argc, char* argv[]) {
GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
// Create a Chrono::Engine physical system
// Create a mesh, that is a container for groups
// of elements and their referenced nodes.
auto my_mesh = chrono_types::make_shared<ChMesh>();
my_mesh->SetAutomaticGravity(false);
// Create a material, that must be assigned to each element,
// and set its parameters
auto mmaterial = chrono_types::make_shared<ChContinuumElectrostatics>();
mmaterial->SetPermittivity(1);
// mmaterial->SetRelativePermettivity(1000.01);
//
// Add some TETAHEDRONS:
//
// Load an Abaqus .INP tetrahedron mesh file from disk, defining a complicate tetrahedron mesh.
// This is much easier than creating all nodes and elements via C++ programming.
// Ex. you can generate these .INP files using Abaqus or exporting from SolidWorks simulation.
std::map<std::string, std::vector<std::shared_ptr<ChNodeFEAbase> > > node_sets;
try {
ChMeshFileLoader::FromAbaqusFile(my_mesh, GetChronoDataFile("fea/electrostatics.INP").c_str(), mmaterial,
node_sets);
} catch (const ChException &myerr) {
GetLog() << myerr.what();
return 1;
}
//
// Set some BOUNDARY CONDITIONS on nodes:
//
// Impose potential on all nodes of 1st nodeset (see *NSET section in .imp file)
auto nboundary = "IMPV1";
for (unsigned int inode = 0; inode < node_sets.at(nboundary).size(); ++inode) {
if (auto mnode = std::dynamic_pointer_cast<ChNodeFEAxyzP>(node_sets[nboundary][inode])) {
mnode->SetFixed(true);
mnode->SetP(0); // field: potential [V]
}
}
// Impose potential on all nodes of 2nd nodeset (see *NSET section in .imp file)
nboundary = "IMPV2";
for (unsigned int inode = 0; inode < node_sets.at(nboundary).size(); ++inode) {
if (auto mnode = std::dynamic_pointer_cast<ChNodeFEAxyzP>(node_sets[nboundary][inode])) {
mnode->SetFixed(true);
mnode->SetP(21); // field: potential [V]
}
}
// Remember to add the mesh to the system!
sys.Add(my_mesh);
// Visualization of the FEM mesh.
// This will automatically update a triangle mesh (a ChTriangleMeshShape
// asset that is internally managed) by setting proper
// coordinates and vertex colors as in the FEM elements.
// Such triangle mesh can be rendered by Irrlicht or POVray or whatever
// postprocessor that can handle a colored ChTriangleMeshShape).
// This will paint the colored mesh with temperature scale (NODE_P is the scalar field of the Poisson problem)
auto mvisualizemesh = chrono_types::make_shared<ChVisualShapeFEA>(my_mesh);
mvisualizemesh->SetFEMdataType(ChVisualShapeFEA::DataType::NODE_P); // plot V, potential field
mvisualizemesh->SetColorscaleMinMax(-0.1, 24);
my_mesh->AddVisualShapeFEA(mvisualizemesh);
// This will paint the wireframe
auto mvisualizemeshB = chrono_types::make_shared<ChVisualShapeFEA>(my_mesh);
mvisualizemeshB->SetFEMdataType(ChVisualShapeFEA::DataType::SURFACE);
mvisualizemeshB->SetColorscaleMinMax(-0.1, 24);
mvisualizemeshB->SetWireframe(true);
my_mesh->AddVisualShapeFEA(mvisualizemeshB);
// This will paint the E vector field as line vectors
auto mvisualizemeshC = chrono_types::make_shared<ChVisualShapeFEA>(my_mesh);
mvisualizemeshC->SetFEMdataType(ChVisualShapeFEA::DataType::NONE);
mvisualizemeshC->SetFEMglyphType(ChVisualShapeFEA::GlyphType::ELEM_VECT_DP);
mvisualizemeshC->SetSymbolsScale(0.00002);
mvisualizemeshC->SetDefaultSymbolsColor(ChColor(1.0f, 1.0f, 0.4f));
mvisualizemeshC->SetZbufferHide(false);
my_mesh->AddVisualShapeFEA(mvisualizemeshC);
// Create the Irrlicht visualization system
auto vis = chrono_types::make_shared<ChVisualSystemIrrlicht>();
vis->AttachSystem(&sys);
vis->SetWindowSize(800, 600);
vis->SetWindowTitle("FEM electrostatics");
vis->Initialize();
vis->AddLogo();
vis->AddSkyBox();
vis->AddLight(ChVector<>(20, 20, 20), 90, ChColor(0.5f, 0.5f, 0.5f));
vis->AddLight(ChVector<>(-20, 20, -20), 90, ChColor(0.7f, 0.8f, 0.8f));
vis->AddCamera(ChVector<>(0., 0.2, -0.3));
// SIMULATION LOOP
auto solver = chrono_types::make_shared<ChSolverMINRES>();
sys.SetSolver(solver);
solver->SetMaxIterations(300);
solver->SetTolerance(1e-20);
solver->EnableDiagonalPreconditioner(true);
solver->SetVerbose(true);
// In electrostatics, you have only a single linear (non transient) solution
while (vis->Run()) {
vis->BeginScene();
vis->Render();
vis->EndScene();
}
// Print some node potentials V..
for (unsigned int inode = 0; inode < my_mesh->GetNnodes(); ++inode) {
if (auto mnode = std::dynamic_pointer_cast<ChNodeFEAxyzP>(my_mesh->GetNode(inode))) {
if (mnode->GetP() < 6.2) {
// GetLog() << "Node at y=" << mnode->GetPos().y << " has V=" << mnode->GetP() << "\n";
}
}
}
return 0;
}
std::string GetChronoDataFile(const std::string &filename)
Obtain the complete path to the specified filename, given relative to the Chrono data directory (thre...
Definition: ChGlobal.cpp:95
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChSystem.cpp:179
void AddSkyBox(const std::string &texture_dir=GetChronoDataFile("skybox/"))
Add a sky box in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:299
void SetSolverForceTolerance(double tolerance)
Set a solver tolerance threshold at force level (default: not specified).
Definition: ChSystem.h:195
Class for exceptions for throw() catch() mechanism.
Definition: ChException.h:25
virtual void Initialize()
Initialize the visualization system.
Definition: ChVisualSystemIrrlicht.cpp:160
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
bool DoStaticLinear()
Solve the position of static equilibrium (and the reactions).
Definition: ChSystem.cpp:1569
bool Run()
Run the Irrlicht device.
Definition: ChVisualSystemIrrlicht.cpp:217
irr::scene::ILightSceneNode * AddLight(const ChVector<> &pos, double radius, ChColor color=ChColor(0.7f, 0.7f, 0.7f))
Add a point light to the scene.
Definition: ChVisualSystemIrrlicht.cpp:344
void AddCamera(const ChVector<> &pos, ChVector<> targ=VNULL)
Add a camera in an Irrlicht 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:268
virtual void BeginScene(bool backBuffer=true, bool zBuffer=true, ChColor color=ChColor(0, 0, 0))
Clean the canvas at the beginning of each animation frame.
Definition: ChVisualSystemIrrlicht.cpp:501
Namespace with classes for the Irrlicht module.
Definition: ChApiIrr.h:48
Definition of a visual color.
Definition: ChColor.h:26
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
Class for a physical system in which contact is modeled using a smooth (penalty-based) method.
Definition: ChSystemSMC.h:30
virtual void EndScene()
End the scene draw at the end of each animation frame.
Definition: ChVisualSystemIrrlicht.cpp:546
void SetWindowTitle(const std::string &win_title)
Set the windoiw title (default "").
Definition: ChVisualSystemIrrlicht.cpp:124
static void FromAbaqusFile(std::shared_ptr< ChMesh > mesh, const char *filename, std::shared_ptr< ChContinuumMaterial > my_material, std::map< std::string, std::vector< std::shared_ptr< ChNodeFEAbase > > > &node_sets, ChVector<> pos_transform=VNULL, ChMatrix33<> rot_transform=ChMatrix33<>(1), bool discard_unused_nodes=true)
Load tetrahedrons, if any, saved in a .inp file for Abaqus.
Definition: ChMeshFileLoader.cpp:196
virtual void AttachSystem(ChSystem *sys) override
Attach another Chrono system to the run-time visualization system.
Definition: ChVisualSystemIrrlicht.cpp:144
virtual void SetSolver(std::shared_ptr< ChSolver > newsolver)
Attach a solver (derived from ChSolver) for use by this system.
Definition: ChSystem.cpp:335
virtual void Render()
Draw all 3D shapes and GUI elements at the current frame.
Definition: ChVisualSystemIrrlicht.cpp:556
Main namespace for the Chrono package.
Definition: ChBarrelShape.cpp:17
void AddLogo(const std::string &logo_filename=GetChronoDataFile("logo_chronoengine_alpha.png"))
Add a logo in a 3D scene.
Definition: ChVisualSystemIrrlicht.cpp:260
Namespace for FEA classes.
Definition: ChVisualShapeFEA.h:25
void SetWindowSize(unsigned int width, unsigned int height)
Set the window size (default 640x480).
Definition: ChVisualSystemIrrlicht.cpp:120