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/ChLinkNodeFrame.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;
int main(int argc, char* argv[]) {
std::cout << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << std::endl;
// Create a Chrono::Engine physical system
// Create a mesh, that is a container for groups
// of elements and their referenced nodes.
my_mesh->SetAutomaticGravity(false);
// Create a material, that must be assigned to each element,
// and set its parameters
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 (std::exception myerr) {
std::cerr << myerr.what() << std::endl;
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->SetFieldVal(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->SetFieldVal(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 ChVisualShapeTriangleMesh
// 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 ChVisualShapeTriangleMesh).
// Paint the colored mesh with temperature scale (NODE_FIELD_VALUE is the scalar field of the Poisson problem)
auto mvisualizemesh = chrono_types::make_shared<ChVisualShapeFEA>(my_mesh);
mvisualizemesh->SetFEMdataType(ChVisualShapeFEA::DataType::NODE_FIELD_VALUE); // 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
vis->AttachSystem(&sys);
vis->SetWindowSize(800, 600);
vis->SetWindowTitle("FEM electrostatics");
vis->Initialize();
vis->AddLogo();
vis->AddSkyBox();
vis->AddLight(ChVector3d(20, 20, 20), 90, ChColor(0.5f, 0.5f, 0.5f));
vis->AddLight(ChVector3d(-20, 20, -20), 90, ChColor(0.7f, 0.8f, 0.8f));
vis->AddCamera(ChVector3d(0., 0.2, -0.3));
// SIMULATION LOOP
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->GetNumNodes(); ++inode) {
if (auto mnode = std::dynamic_pointer_cast<ChNodeFEAxyzP>(my_mesh->GetNode(inode))) {
if (mnode->GetFieldVal() < 6.2) {
std::cout << "Node at y=" << mnode->GetPos().y << " has V=" << mnode->GetFieldVal() << std::endl;
}
}
}
*/
return 0;
}
Definition of a visual color.
Definition ChColor.h:30
bool DoStaticLinear()
Solve the position of static equilibrium (and the reactions).
Definition ChSystem.cpp:1790
virtual void SetSolver(std::shared_ptr< ChSolver > newsolver)
Attach a solver (derived from ChSolver) for use by this system.
Definition ChSystem.cpp:319
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition ChSystem.cpp:196
Class for a physical system in which contact is modeled using a smooth (penalty-based) method.
Definition ChSystemSMC.h:30
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, ChVector3d 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:206
Namespace for FEA classes.
Definition ChVisualShapeFEA.h:28
Namespace with classes for the Irrlicht module.
Definition ChApiIrr.h:47
std::shared_ptr< T > make_shared(Args &&... args)
Replacement for make_shared guaranteed to use operator new rather than placement new in order to avoi...
Definition ChTypes.h:66
Main namespace for the Chrono package.
Definition ChCamera.cpp:17
std::string GetChronoDataFile(const std::string &filename)
Get the full path to the specified filename, given relative to the Chrono data directory (thread safe...
Definition ChGlobal.cpp:37
ChVector3< double > ChVector3d
Alias for double-precision vectors.
Definition ChVector3.h:283