NEW: cylindrical multigrid FDTD
this is a new multi grid approach for the cylindrical FDTD. The FDTD domain will be split in two regions in radial direction. The "inner" region will have half as many disc-lines in alpha direction and therefore allow for a much larger timestep which increases the simulation speed. Todo: - currently only a homogeneous disc is allowed in alpha direction - some extensions have to be tested and prepared for this approach (e.g. pml) - speed enhancement and more efficient memory usage - lots and lots of testing...
This commit is contained in:
parent
a52cd4711a
commit
bd4794ecc4
250
FDTD/engine_cylindermultigrid.cpp
Normal file
250
FDTD/engine_cylindermultigrid.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "engine_cylindermultigrid.h"
|
||||
#include "operator_cylindermultigrid.h"
|
||||
#include "engine_ext_cylindermultigrid.h"
|
||||
|
||||
Engine_CylinderMultiGrid* Engine_CylinderMultiGrid::New(const Operator_CylinderMultiGrid* op, unsigned int numThreads)
|
||||
{
|
||||
cout << "Create FDTD engine (cylindrical multi grid mesh using sse compression + multithreading)" << endl;
|
||||
Engine_CylinderMultiGrid* e = new Engine_CylinderMultiGrid(op);
|
||||
e->setNumThreads( numThreads );
|
||||
e->Init();
|
||||
return e;
|
||||
}
|
||||
|
||||
Engine_CylinderMultiGrid::Engine_CylinderMultiGrid(const Operator_CylinderMultiGrid* op) : Engine_Multithread(op)
|
||||
{
|
||||
Op_CMG = op;
|
||||
|
||||
m_WaitOnBase = new boost::barrier(2);
|
||||
m_WaitOnChild = new boost::barrier(2);
|
||||
m_WaitOnSync = new boost::barrier(2);
|
||||
|
||||
Engine* eng = op->GetInnerOperator()->CreateEngine();
|
||||
m_InnerEngine = dynamic_cast<Engine_Multithread*>(eng);
|
||||
|
||||
m_Eng_Ext_MG = new Engine_Ext_CylinderMultiGrid(NULL,true);
|
||||
m_Eng_Ext_MG->SetBarrier(m_WaitOnBase, m_WaitOnChild, m_WaitOnSync);
|
||||
m_Eng_Ext_MG->SetEngine(this);
|
||||
m_InnerEng_Ext_MG = new Engine_Ext_CylinderMultiGrid(NULL,false);
|
||||
m_InnerEng_Ext_MG->SetBarrier(m_WaitOnBase, m_WaitOnChild, m_WaitOnSync);
|
||||
|
||||
m_InnerEngine->m_Eng_exts.push_back(m_InnerEng_Ext_MG);
|
||||
}
|
||||
|
||||
Engine_CylinderMultiGrid::~Engine_CylinderMultiGrid()
|
||||
{
|
||||
m_Thread_NumTS = 0;
|
||||
m_startBarrier->wait();
|
||||
|
||||
m_IteratorThread_Group.join_all();
|
||||
|
||||
delete m_InnerEngine;
|
||||
m_InnerEngine = NULL;
|
||||
|
||||
delete m_WaitOnBase;
|
||||
m_WaitOnBase = NULL;
|
||||
delete m_WaitOnChild;
|
||||
m_WaitOnChild = NULL;
|
||||
delete m_WaitOnSync;
|
||||
m_WaitOnSync = NULL;
|
||||
|
||||
delete m_startBarrier;
|
||||
m_startBarrier = NULL;
|
||||
delete m_stopBarrier;
|
||||
m_stopBarrier = NULL;
|
||||
|
||||
}
|
||||
|
||||
void Engine_CylinderMultiGrid::Init()
|
||||
{
|
||||
Engine_Multithread::Init();
|
||||
|
||||
m_Eng_exts.push_back(m_Eng_Ext_MG);
|
||||
|
||||
m_startBarrier = new boost::barrier(3); //both engines + organizer
|
||||
m_stopBarrier = new boost::barrier(3); //both engines + organizer
|
||||
|
||||
boost::thread *t = NULL;
|
||||
|
||||
t = new boost::thread( Engine_CylinderMultiGrid_Thread(this,m_startBarrier,m_stopBarrier,&m_Thread_NumTS) );
|
||||
m_IteratorThread_Group.add_thread( t );
|
||||
|
||||
t = new boost::thread( Engine_CylinderMultiGrid_Thread(m_InnerEngine,m_startBarrier,m_stopBarrier,&m_Thread_NumTS) );
|
||||
m_IteratorThread_Group.add_thread( t );
|
||||
}
|
||||
|
||||
bool Engine_CylinderMultiGrid::IterateTS(unsigned int iterTS)
|
||||
{
|
||||
m_Thread_NumTS = iterTS;
|
||||
|
||||
m_startBarrier->wait(); //start base and child iterations
|
||||
|
||||
m_stopBarrier->wait(); //tell base and child to wait for another start event...
|
||||
|
||||
//interpolate child data to base mesh...
|
||||
for (unsigned int n=0;n<Op_CMG->m_Split_Pos-1;++n)
|
||||
InterpolVoltChild2Base(n);
|
||||
for (unsigned int n=0;n<Op_CMG->m_Split_Pos-2;++n)
|
||||
InterpolCurrChild2Base(n);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine_CylinderMultiGrid::InitExtensions()
|
||||
{
|
||||
m_InnerEngine->InitExtensions();
|
||||
Engine_Multithread::InitExtensions();
|
||||
}
|
||||
|
||||
void Engine_CylinderMultiGrid::InterpolVoltChild2Base(unsigned int rzPlane)
|
||||
{
|
||||
//interpolate voltages from child engine to the base engine...
|
||||
unsigned int pos[3];
|
||||
unsigned int pos1_rz1, pos1_rz2;
|
||||
unsigned int pos1_a1, pos1_a2;
|
||||
pos[0] = rzPlane;
|
||||
bool isOdd, isEven;
|
||||
f4vector half, one_eighth, three_eighth;
|
||||
for (int n=0;n<4;++n)
|
||||
{
|
||||
half.f[n]=0.5;
|
||||
one_eighth.f[n] = 1.0/8.0;
|
||||
three_eighth.f[n] = 3.0/8.0;
|
||||
}
|
||||
for (pos[1]=0; pos[1]<numLines[1]; ++pos[1])
|
||||
{
|
||||
isOdd = (pos[1]%2);
|
||||
isEven = !isOdd * (pos[1]>0);
|
||||
|
||||
pos1_rz1 = pos[1]/2;
|
||||
pos1_rz2 = pos[1]/2 + isOdd;
|
||||
|
||||
pos1_rz1 += pos[1]==1;
|
||||
pos1_rz2 -= pos[1]==(numLines[1]-2);
|
||||
|
||||
pos1_a1 = pos[1]/2;
|
||||
pos1_a2 = pos[1]/2 + isOdd - isEven;
|
||||
pos1_a2 += pos[1]==(numLines[1]-1);
|
||||
pos1_a2 -= pos[1]==(numLines[1]-2);
|
||||
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
{
|
||||
//r - direction
|
||||
f4_volt[0][pos[0]][pos[1]][pos[2]].v = half.v * ( m_InnerEngine->f4_volt[0][pos[0]][pos1_rz1][pos[2]].v + m_InnerEngine->f4_volt[0][pos[0]][pos1_rz2][pos[2]].v);
|
||||
|
||||
//z - direction
|
||||
f4_volt[2][pos[0]][pos[1]][pos[2]].v = half.v * ( m_InnerEngine->f4_volt[2][pos[0]][pos1_rz1][pos[2]].v + m_InnerEngine->f4_volt[2][pos[0]][pos1_rz2][pos[2]].v);
|
||||
|
||||
//alpha - direction
|
||||
f4_volt[1][pos[0]][pos[1]][pos[2]].v = three_eighth.v * m_InnerEngine->f4_volt[1][pos[0]][pos1_a1][pos[2]].v;
|
||||
f4_volt[1][pos[0]][pos[1]][pos[2]].v += one_eighth.v * m_InnerEngine->f4_volt[1][pos[0]][pos1_a2][pos[2]].v;
|
||||
}
|
||||
}
|
||||
|
||||
//r,z - interpolation correction...
|
||||
pos[1]=1;
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
{
|
||||
f4_volt[0][pos[0]][pos[1]][pos[2]].v += half.v * (m_InnerEngine->f4_volt[0][pos[0]][1][pos[2]].v - m_InnerEngine->f4_volt[0][pos[0]][2][pos[2]].v);
|
||||
f4_volt[2][pos[0]][pos[1]][pos[2]].v += half.v * (m_InnerEngine->f4_volt[2][pos[0]][1][pos[2]].v - m_InnerEngine->f4_volt[2][pos[0]][2][pos[2]].v);
|
||||
}
|
||||
pos[1]=numLines[1]-2;
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
{
|
||||
f4_volt[0][pos[0]][pos[1]][pos[2]].v += half.v * (m_InnerEngine->f4_volt[0][pos[0]][pos[1]/2][pos[2]].v - m_InnerEngine->f4_volt[0][pos[0]][pos[1]/2-1][pos[2]].v);
|
||||
f4_volt[2][pos[0]][pos[1]][pos[2]].v += half.v * (m_InnerEngine->f4_volt[2][pos[0]][pos[1]/2][pos[2]].v - m_InnerEngine->f4_volt[2][pos[0]][pos[1]/2-1][pos[2]].v);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_CylinderMultiGrid::InterpolCurrChild2Base(unsigned int rzPlane)
|
||||
{
|
||||
//interpolate voltages from child engine to the base engine...
|
||||
unsigned int pos[3];
|
||||
unsigned int pos1_rz1, pos1_rz2;
|
||||
unsigned int pos1_a1, pos1_a2;
|
||||
pos[0] = rzPlane;
|
||||
bool isOdd, isEven;
|
||||
f4vector quarter, one_fourth, three_fourth;
|
||||
for (int n=0;n<4;++n)
|
||||
{
|
||||
quarter.f[n]=0.25;
|
||||
one_fourth.f[n] = 1.0/4.0;
|
||||
three_fourth.f[n] = 3.0/4.0;
|
||||
}
|
||||
for (pos[1]=0; pos[1]<numLines[1]; ++pos[1])
|
||||
{
|
||||
isOdd = (pos[1]%2);
|
||||
isEven = !isOdd * (pos[1]>0);
|
||||
|
||||
pos1_a1 = pos[1]/2;
|
||||
pos1_a2 = pos[1]/2 + isOdd;
|
||||
|
||||
pos1_a1 += pos[1]==1;
|
||||
pos1_a2 -= pos[1]==(numLines[1]-2);
|
||||
|
||||
pos1_rz1 = pos[1]/2;
|
||||
pos1_rz2 = pos[1]/2 + isOdd - isEven;
|
||||
pos1_rz2 += pos[1]==(numLines[1]-1);
|
||||
pos1_rz2 -= pos[1]==(numLines[1]-2);
|
||||
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
{
|
||||
//r - direction
|
||||
f4_curr[0][pos[0]][pos[1]][pos[2]].v = three_fourth.v * m_InnerEngine->f4_curr[0][pos[0]][pos1_rz1][pos[2]].v;
|
||||
f4_curr[0][pos[0]][pos[1]][pos[2]].v += one_fourth.v * m_InnerEngine->f4_curr[0][pos[0]][pos1_rz2][pos[2]].v;
|
||||
|
||||
//z - direction
|
||||
f4_curr[2][pos[0]][pos[1]][pos[2]].v = three_fourth.v * m_InnerEngine->f4_curr[2][pos[0]][pos1_rz1][pos[2]].v;
|
||||
f4_curr[2][pos[0]][pos[1]][pos[2]].v += one_fourth.v * m_InnerEngine->f4_curr[2][pos[0]][pos1_rz2][pos[2]].v;
|
||||
|
||||
//alpha - direction
|
||||
f4_curr[1][pos[0]][pos[1]][pos[2]].v = quarter.v * (m_InnerEngine->f4_curr[1][pos[0]][pos1_a1][pos[2]].v + m_InnerEngine->f4_curr[1][pos[0]][pos1_a2][pos[2]].v);
|
||||
}
|
||||
|
||||
}
|
||||
//alpha - interpolation correction...
|
||||
pos[1]=1;
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
f4_curr[1][pos[0]][pos[1]][pos[2]].v += quarter.v * (m_InnerEngine->f4_curr[1][pos[0]][1][pos[2]].v - m_InnerEngine->f4_curr[1][pos[0]][2][pos[2]].v);
|
||||
pos[1]=numLines[1]-2;
|
||||
for (pos[2]=0; pos[2]<numVectors; ++pos[2])
|
||||
f4_curr[1][pos[0]][pos[1]][pos[2]].v += quarter.v * (m_InnerEngine->f4_curr[1][pos[0]][pos[1]/2][pos[2]].v - m_InnerEngine->f4_curr[1][pos[0]][pos[1]/2-1][pos[2]].v);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
Engine_CylinderMultiGrid_Thread::Engine_CylinderMultiGrid_Thread( Engine_Multithread* engine, boost::barrier *start, boost::barrier *stop, volatile unsigned int* numTS)
|
||||
{
|
||||
m_startBarrier = start;
|
||||
m_stopBarrier = stop;
|
||||
m_Eng=engine;
|
||||
m_numTS = numTS;
|
||||
}
|
||||
|
||||
void Engine_CylinderMultiGrid_Thread::operator()()
|
||||
{
|
||||
m_startBarrier->wait(); //wait for Base engine to start the iterations...
|
||||
|
||||
while(*m_numTS>0) //m_numTS==0 request to terminate this thread...
|
||||
{
|
||||
m_Eng->Engine_Multithread::IterateTS(*m_numTS);
|
||||
m_stopBarrier->wait(); //sync all workers after iterations are performed
|
||||
m_startBarrier->wait(); //wait for Base engine to start the iterations again ...
|
||||
}
|
||||
}
|
82
FDTD/engine_cylindermultigrid.h
Normal file
82
FDTD/engine_cylindermultigrid.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_CYLINDERMULTIGRID_H
|
||||
#define ENGINE_CYLINDERMULTIGRID_H
|
||||
|
||||
#include "engine_multithread.h"
|
||||
|
||||
class Operator_CylinderMultiGrid;
|
||||
class Engine_CylinderMultiGrid_Thread;
|
||||
class Engine_Ext_CylinderMultiGrid;
|
||||
|
||||
class Engine_CylinderMultiGrid : public Engine_Multithread
|
||||
{
|
||||
friend class Engine_Ext_CylinderMultiGrid;
|
||||
public:
|
||||
Engine_CylinderMultiGrid();
|
||||
|
||||
static Engine_CylinderMultiGrid* New(const Operator_CylinderMultiGrid* op, unsigned int numThreads = 0);
|
||||
virtual ~Engine_CylinderMultiGrid();
|
||||
|
||||
virtual void InterpolVoltChild2Base(unsigned int rzPlane);
|
||||
virtual void InterpolCurrChild2Base(unsigned int rzPlane);
|
||||
|
||||
virtual void Init();
|
||||
|
||||
//! Iterate \a iterTS number of timesteps
|
||||
virtual bool IterateTS(unsigned int iterTS);
|
||||
|
||||
virtual void InitExtensions();
|
||||
|
||||
protected:
|
||||
Engine_CylinderMultiGrid(const Operator_CylinderMultiGrid* op);
|
||||
const Operator_CylinderMultiGrid* Op_CMG;
|
||||
|
||||
Engine_Multithread* m_InnerEngine;
|
||||
|
||||
volatile unsigned int m_Thread_NumTS;
|
||||
boost::thread_group m_IteratorThread_Group;
|
||||
boost::barrier *m_startBarrier;
|
||||
boost::barrier *m_stopBarrier;
|
||||
Engine_CylinderMultiGrid_Thread* m_IteratorThread;
|
||||
Engine_CylinderMultiGrid_Thread* m_InnerIteratorThread;
|
||||
|
||||
//extension barrier
|
||||
boost::barrier *m_WaitOnBase;
|
||||
boost::barrier *m_WaitOnChild;
|
||||
boost::barrier *m_WaitOnSync;
|
||||
|
||||
Engine_Ext_CylinderMultiGrid* m_Eng_Ext_MG;
|
||||
Engine_Ext_CylinderMultiGrid* m_InnerEng_Ext_MG;
|
||||
};
|
||||
|
||||
|
||||
class Engine_CylinderMultiGrid_Thread
|
||||
{
|
||||
public:
|
||||
Engine_CylinderMultiGrid_Thread( Engine_Multithread* engine, boost::barrier *start, boost::barrier *stop, volatile unsigned int* numTS);
|
||||
void operator()();
|
||||
|
||||
protected:
|
||||
Engine_Multithread *m_Eng;
|
||||
boost::barrier *m_startBarrier;
|
||||
boost::barrier *m_stopBarrier;
|
||||
volatile unsigned int *m_numTS;
|
||||
};
|
||||
|
||||
#endif // ENGINE_CYLINDERMULTIGRID_H
|
158
FDTD/engine_ext_cylindermultigrid.cpp
Normal file
158
FDTD/engine_ext_cylindermultigrid.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "engine.h"
|
||||
#include "engine_ext_cylindermultigrid.h"
|
||||
#include "engine_cylindermultigrid.h"
|
||||
|
||||
Engine_Ext_CylinderMultiGrid::Engine_Ext_CylinderMultiGrid(Operator_Extension* op_ext, bool isBase) : Engine_Extension(op_ext)
|
||||
{
|
||||
m_IsBase = isBase;
|
||||
m_Eng_MG = NULL;
|
||||
}
|
||||
|
||||
Engine_Ext_CylinderMultiGrid::~Engine_Ext_CylinderMultiGrid()
|
||||
{
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::SetBarrier(boost::barrier* waitBase, boost::barrier* waitChild, boost::barrier* waitSync)
|
||||
{
|
||||
m_WaitOnBase = waitBase;
|
||||
m_WaitOnChild = waitChild;
|
||||
m_WaitOnSync = waitSync;
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::SetEngine(Engine* eng)
|
||||
{
|
||||
m_Eng_MG = dynamic_cast<Engine_CylinderMultiGrid*>(eng);
|
||||
if (m_Eng_MG==NULL)
|
||||
{
|
||||
cerr << "Engine_Ext_CylinderMultiGrid::SetEngine(): Error" << endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::DoPreVoltageUpdates()
|
||||
{
|
||||
//cerr << "Engine_Ext_CylinderMultiGrid::DoPreVoltageUpdates() for " << m_IsBase << endl;
|
||||
if (!m_IsBase)
|
||||
{
|
||||
//cerr << "child: volt wait on base " << endl;
|
||||
m_WaitOnBase->wait(); //wait on base to finisch current sync and/or to finisch voltage updates, than start child voltage updates
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::DoPostVoltageUpdates()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::Apply2Voltages()
|
||||
{
|
||||
if (m_IsBase)
|
||||
{
|
||||
m_WaitOnBase->wait(); //base voltage updates are done, tell child to start its voltage updates
|
||||
m_WaitOnChild->wait(); //wait for child to finisch its updates
|
||||
SyncVoltages(); //child is finisch, run sync and go to current updates next
|
||||
m_WaitOnSync->wait(); //sync is done... move on and tell child to move on...
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WaitOnChild->wait(); //child is finished voltage updates, will tell base to run sync
|
||||
m_WaitOnSync->wait(); //wait for base to finisch sync before going to wait for current updates
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::SyncVoltages()
|
||||
{
|
||||
if (m_Eng_MG==NULL)
|
||||
{
|
||||
cerr << "Engine_Ext_CylinderMultiGrid::SyncVoltages: Error engine is NULL" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int* numLines = m_Eng_MG->numLines;
|
||||
|
||||
Engine_Multithread* m_InnerEng = m_Eng_MG->m_InnerEngine;
|
||||
|
||||
//interpolate voltages from base engine to child engine...
|
||||
unsigned int pos[3];
|
||||
pos[0] = m_Eng_MG->Op_CMG->GetSplitPos()-1;
|
||||
unsigned int pos1_half = 0;
|
||||
f4vector v_null; v_null.f[0] = 0;v_null.f[1] = 0;v_null.f[2] = 0;v_null.f[3] = 0;
|
||||
for (pos[1]=0; pos[1]<numLines[1]-1; pos[1]+=2)
|
||||
{
|
||||
pos1_half = pos[1]/2;
|
||||
for (pos[2]=0; pos[2]<m_Eng_MG->numVectors; ++pos[2])
|
||||
{
|
||||
//r - direczion
|
||||
m_InnerEng->f4_volt[0][pos[0]][pos1_half][pos[2]].v = v_null.v;
|
||||
|
||||
//z - direction
|
||||
m_InnerEng->f4_volt[2][pos[0]][pos1_half][pos[2]].v = m_Eng_MG->f4_volt[2][pos[0]][pos[1]][pos[2]].v;
|
||||
|
||||
//alpha - direction
|
||||
m_InnerEng->f4_volt[1][pos[0]][pos1_half][pos[2]].v = m_Eng_MG->f4_volt[1][pos[0]][pos[1]][pos[2]].v;
|
||||
m_InnerEng->f4_volt[1][pos[0]][pos1_half][pos[2]].v += m_Eng_MG->f4_volt[1][pos[0]][pos[1]+1][pos[2]].v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::DoPreCurrentUpdates()
|
||||
{
|
||||
//cerr << "Engine_Ext_CylinderMultiGrid::DoPreCurrentUpdates() for " << m_IsBase << endl;
|
||||
if (!m_IsBase)
|
||||
{
|
||||
//cerr << "child: curr wait on base " << endl;
|
||||
m_WaitOnBase->wait(); //wait on base to finisch voltage sync and current updates, than start child current updates
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::DoPostCurrentUpdates()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::Apply2Current()
|
||||
{
|
||||
if (m_IsBase)
|
||||
{
|
||||
//cerr << "Base: curr wait on base done, wait on sync" << endl;
|
||||
m_WaitOnBase->wait(); //base current updates are done, tell child to start its current updates
|
||||
m_WaitOnChild->wait(); //wait for child to finisch its updates
|
||||
SyncCurrents(); //child is finisch, run sync and go to voltage updates next
|
||||
m_WaitOnSync->wait(); //sync is done... move on and tell child to move on...
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WaitOnChild->wait(); //child is finished current updates, will tell base to run sync...
|
||||
m_WaitOnSync->wait(); //wait for base to finisch sync before going to wait for next voltage updates
|
||||
//cerr << "Child: curr done, wait on sync" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine_Ext_CylinderMultiGrid::SyncCurrents()
|
||||
{
|
||||
if (m_Eng_MG==NULL)
|
||||
{
|
||||
cerr << "Engine_Ext_CylinderMultiGrid::SyncCurrents: Error engine is NULL" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_Eng_MG->InterpolCurrChild2Base(m_Eng_MG->Op_CMG->GetSplitPos()-2);
|
||||
return;
|
||||
}
|
58
FDTD/engine_ext_cylindermultigrid.h
Normal file
58
FDTD/engine_ext_cylindermultigrid.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_EXT_CYLINDERMULTIGRID_H
|
||||
#define ENGINE_EXT_CYLINDERMULTIGRID_H
|
||||
|
||||
#include "engine_cylindermultigrid.h"
|
||||
#include "engine_extension.h"
|
||||
#include "operator_cylindermultigrid.h"
|
||||
|
||||
class Operator_Ext_CylinderMultiGrid;
|
||||
|
||||
class Engine_Ext_CylinderMultiGrid : public Engine_Extension
|
||||
{
|
||||
public:
|
||||
Engine_Ext_CylinderMultiGrid(Operator_Extension* op_ext, bool isBase);
|
||||
virtual ~Engine_Ext_CylinderMultiGrid();
|
||||
|
||||
void SetBarrier(boost::barrier* waitBase, boost::barrier* waitChild, boost::barrier* waitSync);
|
||||
|
||||
virtual void DoPreVoltageUpdates();
|
||||
virtual void DoPostVoltageUpdates();
|
||||
virtual void Apply2Voltages();
|
||||
|
||||
virtual void DoPreCurrentUpdates();
|
||||
virtual void DoPostCurrentUpdates();
|
||||
virtual void Apply2Current();
|
||||
|
||||
virtual void SetEngine(Engine* eng);
|
||||
|
||||
protected:
|
||||
void SyncVoltages();
|
||||
void SyncCurrents();
|
||||
|
||||
Engine_CylinderMultiGrid* m_Eng_MG;
|
||||
|
||||
boost::barrier *m_WaitOnBase;
|
||||
boost::barrier *m_WaitOnChild;
|
||||
boost::barrier *m_WaitOnSync;
|
||||
|
||||
bool m_IsBase;
|
||||
};
|
||||
|
||||
#endif // ENGINE_EXT_CYLINDERMULTIGRID_H
|
@ -78,6 +78,7 @@ class Engine_Multithread : public Engine_SSE_Compressed
|
||||
{
|
||||
friend class NS_Engine_Multithread::thread;
|
||||
friend class NS_Engine_Multithread::thread_e_excitation;
|
||||
friend class Engine_CylinderMultiGrid;
|
||||
public:
|
||||
static Engine_Multithread* New(const Operator_Multithread* op, unsigned int numThreads = 0);
|
||||
virtual ~Engine_Multithread();
|
||||
|
@ -52,6 +52,7 @@ protected:
|
||||
|
||||
unsigned int numVectors;
|
||||
|
||||
public: //public access to the sse arrays for efficient extensions access... use careful...
|
||||
f4vector**** f4_volt;
|
||||
f4vector**** f4_curr;
|
||||
};
|
||||
|
@ -467,7 +467,6 @@ bool Operator::SetGeometryCSX(ContinuousStructure* geo)
|
||||
{
|
||||
if (geo==NULL) return false;
|
||||
|
||||
Reset();
|
||||
CSX = geo;
|
||||
|
||||
CSRectGrid* grid=CSX->GetGrid();
|
||||
@ -584,7 +583,8 @@ int Operator::CalcECOperator()
|
||||
bool PEC[6]={1,1,1,1,1,1};
|
||||
//exception for pml boundaries
|
||||
for (int n=0;n<6;++n)
|
||||
PEC[n] = m_BC[n]!=3;
|
||||
if ((m_BC[n]==3) || (m_BC[n]==-1))
|
||||
PEC[n] = false;
|
||||
ApplyElectricBC(PEC);
|
||||
|
||||
InitExcitation();
|
||||
@ -620,8 +620,8 @@ void Operator::ApplyElectricBC(bool* dirs)
|
||||
GetVI(nPP,pos[0],pos[1],pos[2]) *= (FDTD_FLOAT)!dirs[2*n];
|
||||
|
||||
pos[n]=numLines[n]-1;
|
||||
GetVV(n,pos[0],pos[1],pos[2]) = 0; // these are outside the FDTD-domain as defined by the main disc
|
||||
GetVI(n,pos[0],pos[1],pos[2]) = 0; // these are outside the FDTD-domain as defined by the main disc
|
||||
GetVV(n,pos[0],pos[1],pos[2]) *= (FDTD_FLOAT)!dirs[2*n+1]; // these are outside the FDTD-domain as defined by the main disc
|
||||
GetVI(n,pos[0],pos[1],pos[2]) *= (FDTD_FLOAT)!dirs[2*n+1]; // these are outside the FDTD-domain as defined by the main disc
|
||||
|
||||
GetVV(nP,pos[0],pos[1],pos[2]) *= (FDTD_FLOAT)!dirs[2*n+1];
|
||||
GetVI(nP,pos[0],pos[1],pos[2]) *= (FDTD_FLOAT)!dirs[2*n+1];
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
//! Set a forced timestep to use by the operator
|
||||
virtual void SetTimestep(double ts) {dT = ts;}
|
||||
double GetTimestep() const {return dT;};
|
||||
double GetNumberCells() const;
|
||||
virtual double GetNumberCells() const;
|
||||
|
||||
//! Returns the number of lines as needed for post-processing etc. (for the engine, use GetOriginalNumLines())
|
||||
virtual unsigned int GetNumberOfLines(int ny) const {return numLines[ny];}
|
||||
|
@ -27,6 +27,7 @@ all special cases e.g. a closed alpha mesh or an included r=0 case is treated by
|
||||
*/
|
||||
class Operator_Cylinder : public Operator_Multithread
|
||||
{
|
||||
friend class Operator_CylinderMultiGrid;
|
||||
public:
|
||||
static Operator_Cylinder* New(unsigned int numThreads = 0);
|
||||
virtual ~Operator_Cylinder();
|
||||
|
189
FDTD/operator_cylindermultigrid.cpp
Normal file
189
FDTD/operator_cylindermultigrid.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY{} without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "operator_cylindermultigrid.h"
|
||||
#include "engine_cylindermultigrid.h"
|
||||
#include "operator_ext_cylinder.h"
|
||||
|
||||
Operator_CylinderMultiGrid::Operator_CylinderMultiGrid(vector<double> Split_Radii) : Operator_Cylinder()
|
||||
{
|
||||
m_Split_Rad = Split_Radii.back();
|
||||
Split_Radii.pop_back();
|
||||
}
|
||||
|
||||
Operator_CylinderMultiGrid::~Operator_CylinderMultiGrid()
|
||||
{
|
||||
}
|
||||
|
||||
Operator_CylinderMultiGrid* Operator_CylinderMultiGrid::New(vector<double> Split_Radii, unsigned int numThreads)
|
||||
{
|
||||
cout << "Create cylindrical multi grid FDTD operator " << endl;
|
||||
Operator_CylinderMultiGrid* op = new Operator_CylinderMultiGrid(Split_Radii);
|
||||
op->setNumThreads(numThreads);
|
||||
op->Init();
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
Engine* Operator_CylinderMultiGrid::CreateEngine() const
|
||||
{
|
||||
Engine_CylinderMultiGrid* eng = Engine_CylinderMultiGrid::New(this,m_numThreads);
|
||||
return eng;
|
||||
}
|
||||
|
||||
double Operator_CylinderMultiGrid::GetNumberCells() const
|
||||
{
|
||||
if (numLines)
|
||||
return (numLines[0]-m_Split_Pos)*(numLines[1])*(numLines[2]) + m_InnerOp->GetNumberCells();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Operator_CylinderMultiGrid::SetGeometryCSX(ContinuousStructure* geo)
|
||||
{
|
||||
if (Operator_Cylinder::SetGeometryCSX(geo)==false)
|
||||
return false;
|
||||
|
||||
if (numLines[1]%2 != 1)
|
||||
{
|
||||
cerr << "Operator_CylinderMultiGrid::SetGeometryCSX: Error, number of line in alpha direction must be odd... found: " << numLines[1] << endl;
|
||||
}
|
||||
|
||||
m_Split_Pos = 0;
|
||||
for (unsigned int n=0;n<numLines[0];++n)
|
||||
{
|
||||
if (m_Split_Rad < discLines[0][n])
|
||||
{
|
||||
m_Split_Pos = n;
|
||||
cout << "Operator_CylinderMultiGrid::SetGeometryCSX: Found mesh split position @" << m_Split_Pos << endl;
|
||||
m_Split_Rad = discLines[0][n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((m_Split_Pos<4) || (m_Split_Pos>numLines[0]-4))
|
||||
{
|
||||
cerr << "Operator_CylinderMultiGrid::SetGeometryCSX: Error, split invalid..." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
CSRectGrid* grid = geo->GetGrid();
|
||||
|
||||
grid->ClearLines(0);
|
||||
grid->ClearLines(1);
|
||||
for (unsigned int n=0; n<m_Split_Pos ;++n)
|
||||
grid->AddDiscLine(0,discLines[0][n]);
|
||||
for (unsigned int n=0; n<numLines[1]; n+=2)
|
||||
grid->AddDiscLine(1,discLines[1][n]);
|
||||
|
||||
if (m_InnerOp->SetGeometryCSX(CSX)==false)
|
||||
return false;
|
||||
|
||||
//restore grid to original mesh
|
||||
grid->ClearLines(0);
|
||||
grid->ClearLines(1);
|
||||
for (unsigned int n=0; n<numLines[0]; ++n)
|
||||
grid->AddDiscLine(0,discLines[0][n]);
|
||||
for (unsigned int n=0; n<numLines[1]; ++n)
|
||||
grid->AddDiscLine(1,discLines[1][n]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::Init()
|
||||
{
|
||||
Operator_Cylinder::Init();
|
||||
m_InnerOp = Operator_Cylinder::New(m_numThreads);
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::CalcStartStopLines(unsigned int &numThreads, vector<unsigned int> &start, vector<unsigned int> &stop) const
|
||||
{
|
||||
if (numLines[0]<numThreads) //in case more threads requested as lines in r-direction, reduce number of worker threads
|
||||
numThreads = numLines[0];
|
||||
|
||||
unsigned int linesPerThread = round((float)(numLines[0] - m_Split_Pos + 1) / (float)numThreads);
|
||||
if ((numThreads-1) * linesPerThread >= (numLines[0] - m_Split_Pos + 1))
|
||||
--numThreads;
|
||||
|
||||
start.resize(numThreads);
|
||||
stop.resize(numThreads);
|
||||
|
||||
for (unsigned int n=0; n<numThreads; n++)
|
||||
{
|
||||
start.at(n) = n * linesPerThread + m_Split_Pos - 1;
|
||||
stop.at(n) = (n+1) * linesPerThread - 1 + m_Split_Pos - 1;
|
||||
if (n == numThreads-1) // last thread
|
||||
stop.at(n) = numLines[0]-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Operator_CylinderMultiGrid::CalcECOperator()
|
||||
{
|
||||
if (dT)
|
||||
m_InnerOp->SetTimestep(dT);
|
||||
|
||||
//calc inner child first
|
||||
m_InnerOp->CalcECOperator();
|
||||
|
||||
dT = m_InnerOp->GetTimestep();
|
||||
|
||||
return Operator_Cylinder::CalcECOperator();
|
||||
}
|
||||
|
||||
bool Operator_CylinderMultiGrid::SetupExcitation(TiXmlElement* Excite, unsigned int maxTS)
|
||||
{
|
||||
if (!m_InnerOp->Exc->setupExcitation(Excite,maxTS))
|
||||
return false;
|
||||
return Exc->setupExcitation(Excite,maxTS);
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::Reset()
|
||||
{
|
||||
Operator_Cylinder::Reset();
|
||||
m_InnerOp->Reset();
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::SetBoundaryCondition(int* BCs)
|
||||
{
|
||||
Operator_Cylinder::SetBoundaryCondition(BCs);
|
||||
BCs[1] = 0; //always PEC in +r-direction
|
||||
m_InnerOp->SetBoundaryCondition(BCs);
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::AddExtension(Operator_Extension* op_ext)
|
||||
{
|
||||
if (dynamic_cast<Operator_Ext_Cylinder*>(op_ext))
|
||||
{
|
||||
Operator_Cylinder::AddExtension(op_ext);
|
||||
return;
|
||||
}
|
||||
Operator_Extension* child_Ext = op_ext->Clone(m_InnerOp);
|
||||
if (child_Ext==NULL)
|
||||
{
|
||||
cerr << "Operator_CylinderMultiGrid::AddExtension: Warning, extension: " << op_ext->GetExtensionName() << " can not be cloned for the child operator. Skipping Extension... " << endl;
|
||||
return;
|
||||
}
|
||||
Operator_Cylinder::AddExtension(op_ext);
|
||||
//give the copy to child
|
||||
m_InnerOp->AddExtension(child_Ext);
|
||||
}
|
||||
|
||||
void Operator_CylinderMultiGrid::ShowStat() const
|
||||
{
|
||||
m_InnerOp->ShowStat();
|
||||
m_InnerOp->ShowExtStat();
|
||||
Operator_Cylinder::ShowStat();
|
||||
}
|
70
FDTD/operator_cylindermultigrid.h
Normal file
70
FDTD/operator_cylindermultigrid.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPERATOR_CYLINDERMULTIGRID_H
|
||||
#define OPERATOR_CYLINDERMULTIGRID_H
|
||||
|
||||
#include "operator_cylinder.h"
|
||||
|
||||
//! This is a cylindrical FDTD operator using a simple multi-grid approach.
|
||||
/*!
|
||||
This cylindrical multi-grid operator itself is not calculating any real operator, instead it is hosting two separate "child" operators of type "Operator_Cylinder".
|
||||
This operator class (or the corresponding engine) will perform the interpolation and connection between these two child-operator/engines.
|
||||
One of the child operators itself may be another multi-grid operator to allow for a cascaded multi-grid approach.
|
||||
*/
|
||||
class Operator_CylinderMultiGrid : public Operator_Cylinder
|
||||
{
|
||||
friend class Engine_CylinderMultiGrid;
|
||||
public:
|
||||
static Operator_CylinderMultiGrid* New(vector<double> Split_Radii, unsigned int numThreads = 0);
|
||||
virtual ~Operator_CylinderMultiGrid();
|
||||
|
||||
virtual double GetNumberCells() const;
|
||||
|
||||
virtual Engine* CreateEngine() const;
|
||||
|
||||
virtual bool SetGeometryCSX(ContinuousStructure* geo);
|
||||
|
||||
virtual unsigned int GetSplitPos() const {return m_Split_Pos;}
|
||||
|
||||
virtual int CalcECOperator();
|
||||
|
||||
virtual bool SetupExcitation(TiXmlElement* Excite, unsigned int maxTS);
|
||||
|
||||
virtual void SetBoundaryCondition(int* BCs);
|
||||
|
||||
virtual void AddExtension(Operator_Extension* op_ext);
|
||||
|
||||
Operator_Cylinder* GetInnerOperator() const {return m_InnerOp;}
|
||||
|
||||
virtual void ShowStat() const;
|
||||
|
||||
protected:
|
||||
Operator_CylinderMultiGrid(vector<double> Split_Radii);
|
||||
virtual void Init();
|
||||
// virtual void InitOperator();
|
||||
virtual void Reset();
|
||||
|
||||
double m_Split_Rad;
|
||||
unsigned int m_Split_Pos;
|
||||
|
||||
Operator_Cylinder* m_InnerOp;
|
||||
|
||||
virtual void CalcStartStopLines(unsigned int &numThreads, vector<unsigned int> &start, vector<unsigned int> &stop) const;
|
||||
};
|
||||
|
||||
#endif // OPERATOR_CYLINDERMULTIGRID_H
|
@ -76,6 +76,9 @@ void Operator_Multithread::Reset()
|
||||
|
||||
void Operator_Multithread::CalcStartStopLines(unsigned int &numThreads, vector<unsigned int> &start, vector<unsigned int> &stop) const
|
||||
{
|
||||
if (numLines[0]<numThreads) //in case more threads requested as lines in x-direction, reduce number of worker threads
|
||||
numThreads = numLines[0];
|
||||
|
||||
unsigned int linesPerThread = round((float)numLines[0] / (float)numThreads);
|
||||
if ((numThreads-1) * linesPerThread >= numLines[0])
|
||||
--numThreads;
|
||||
|
10
openEMS.pro
10
openEMS.pro
@ -81,7 +81,10 @@ SOURCES += main.cpp \
|
||||
FDTD/engine_ext_lorentzmaterial.cpp \
|
||||
FDTD/operator_ext_pml_sf.cpp \
|
||||
FDTD/engine_ext_pml_sf.cpp \
|
||||
FDTD/processmodematch.cpp
|
||||
FDTD/processmodematch.cpp \
|
||||
FDTD/operator_cylindermultigrid.cpp \
|
||||
FDTD/engine_cylindermultigrid.cpp \
|
||||
FDTD/engine_ext_cylindermultigrid.cpp
|
||||
HEADERS += tools/ErrorMsg.h \
|
||||
tools/AdrOp.h \
|
||||
tools/constants.h \
|
||||
@ -119,7 +122,10 @@ HEADERS += tools/ErrorMsg.h \
|
||||
FDTD/engine_ext_lorentzmaterial.h \
|
||||
FDTD/operator_ext_pml_sf.h \
|
||||
FDTD/engine_ext_pml_sf.h \
|
||||
FDTD/processmodematch.h
|
||||
FDTD/processmodematch.h \
|
||||
FDTD/operator_cylindermultigrid.h \
|
||||
FDTD/engine_cylindermultigrid.h \
|
||||
FDTD/engine_ext_cylindermultigrid.h
|
||||
QMAKE_CXXFLAGS_RELEASE = -O3 \
|
||||
-g \
|
||||
-march=native
|
||||
|
12
openems.cpp
12
openems.cpp
@ -19,6 +19,7 @@
|
||||
#include <iomanip>
|
||||
#include "tools/array_ops.h"
|
||||
#include "FDTD/operator_cylinder.h"
|
||||
#include "FDTD/operator_cylindermultigrid.h"
|
||||
#include "FDTD/engine_multithread.h"
|
||||
#include "FDTD/operator_multithread.h"
|
||||
#include "FDTD/operator_ext_mur_abc.h"
|
||||
@ -293,7 +294,6 @@ int openEMS::SetupFDTD(const char* file)
|
||||
double maxTime=0;
|
||||
FDTD_Opts->QueryDoubleAttribute("MaxTime",&maxTime);
|
||||
|
||||
|
||||
TiXmlElement* BC = FDTD_Opts->FirstChildElement("BoundaryCond");
|
||||
if (BC==NULL)
|
||||
{
|
||||
@ -319,7 +319,15 @@ int openEMS::SetupFDTD(const char* file)
|
||||
//*************** setup operator ************//
|
||||
if (CylinderCoords)
|
||||
{
|
||||
FDTD_Op = Operator_Cylinder::New(m_engine_numThreads);
|
||||
const char* radii = FDTD_Opts->Attribute("MultiGrid");
|
||||
if (radii)
|
||||
{
|
||||
string rad(radii);
|
||||
FDTD_Op = Operator_CylinderMultiGrid::New(SplitString2Double(rad,','),m_engine_numThreads);
|
||||
}
|
||||
else
|
||||
FDTD_Op = Operator_Cylinder::New(m_engine_numThreads);
|
||||
CSX.SetCoordInputType(1); //tell CSX to use cylinder-coords
|
||||
}
|
||||
else if (m_engine == EngineType_SSE)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user