"Embedded software often runs on processors with limited computation power, thus optimizing the code becomes a necessity. In this article we will explore the following optimization techniques for C and C++ code developed for Real-time and Embedded Systems."

http://www.eventhelix.com/realtimemantra/basics/optimizingcandcppcode.htm

Robert

]]>\begin{align} \nabla\cdot\mathbf{v}=0 \end{align}

or

(2)\begin{align} \nabla\cdot\left(\frac{k}{\mu}\nabla p\right)=0 \end{align}

and the resulting divergence, as computed with the FV scheme (Stephan's generic and my old one) must be numerically zero (this is the case for triangular meshes, see below). Now, I only get this for a homogeneous permeability field and quadrilateral finite elements, as shown in this image:

If I include a low-permeability region in the centre such that flow is around it, then the divergence becomes immediately non-zero.

Has somebody noticed this and/or a good explanation? We only realised this problem when Christine's Newton iterator got stuck trying to resolve these local source/sink terms that arise from the divergence.

]]>Reason is that in geothermal reservoir stimulation models such things have been used and we wondered if we could include them as well.

]]>The error is:

main: Enter name of 'Triangle' input file set: tetraMesh.1

MeshInterface::CheckTriangleOutput: '.ele' file contains no element attributes…

MeshInterface::CheckTriangleOutput 'tetraMesh.1' Input fileset apparently contains:

99013 nodes, 296148 segments=faces, 197136 triangles.

MeshInterface::ReadNodeDataFile: file 'tetraMesh.1.node' read successfully…

MeshInterface::ReadElementDataFile: file 'tetraMesh.1.ele' read successfully…

MeshInterface::ReadNeighborDataFile: file 'tetraMesh.1.neigh' read successfully…

csp5: ../CSP5.0/source_code/interfaces/CSP_TRIANGLE_Interface.cpp:936: void csp::TRIANGLE_Interface::FlagBoundaryNodesAccordingTo(csp::stl_index, csp::int32, const std::vector<unsigned int, std::allocator<unsigned int> >&, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, int> > >&): Assertion ‘bit != bflags.end()’ failed.

Aborted

Is there a guideline on how to create a proper triangle-mesh?

Thanks,

Matthias

I stripped down the code to the following stand-along test:

stl_index DIM(2); IsoparametricLinearLineElement elm(DIM,1); Element<csp_float,2> e(&elm); Node<csp_float,2> n0, n1; n0.x(0.0); n0.y(0.0); n1.x(1.0); n1.y(1.0); e.ConnectTo( 0, n0 ); e.ConnectTo( 1, n1 ); csp_float l = e.Volume(); csp_float p[2], v[2]; p[0] = 0.0; p[1] = 1.0; v[0] = v[1] = 0.0; DenseMatrix<csp_float,DM_MIN> DN, XY; e.CoordinateMatrix(XY); XY.Out(); for ( stl_index i=0; i<e.IntegrationPoints(); i++ ) { e.dN_AtIntegrationPoint( DN, i, 1 ); for ( stl_index n=0; n<e.Nodes(); n++ ) for ( stl_index j=0; j<DIM; j++ ) v[j] += p[n] * DN(j,n); } cout << "\n\nFE Gradient X: " << v[0] << ", should be " << (p[1]-p[0])/(n1.x()-n0.x()); cout << "\n\nFE Gradient Y: " << v[1] << ", should be " << (p[1]-p[0])/(n1.y()-n0.y()); cout.flush();

This is a 1D line element with two points at (0,0) and (1,1). There is a pressure of 0 at node 0 and a pressure of 1 at node 1. The length of the element is correctly calculated as square root of 2 and the pressure gradient in X and Y direction must be 1 (with the length of the vector between point 0 and 1 is square root of 2). Now, this is not what using the interpolation function derivatives yield. They yield gradients of 0.5 in X and Y directions. If I use coordinates of the nodes and the pressures from the actual mesh, I can recomputed the gradients that the “real” CSMP gives me, which differ from what I would think are the right ones. It only works if the line element is oriented horizontally or vertically.

Now, aside from the gravity effects, this could be very worrying because it implies that all fluid velocities in 2D DFM models where the fractures are 1D line elements are potentially not correct.

Am I doing something entirely stupid or is there an issue with the 1D line elements in 2D space?

Cheers, Sebastian

]]>I just started using Qt Creator IDE and followed Sebastian's step-by-step explanation of how to compile CSMP with Qt (see section CSMP-basics). The guide seemed to me quite clear… still, there are a few ambiguities, which I hope you can help me resolve:

- Is there a certain order in which I have to compile the libraries (e.g., do I have to compile the main library or the support libraries before the others)?
- When opening the Qt project files, I noticed that for some folders, there is none (such as
`computer_science`or`generic_element_centered_finite_volumes`). Are they not needed in the CSMP library? - Also for
`distributed_examples`, there are no .pro files. I assume these examples are still not working and haven't been used by anyone lately!? - From the support libraries, only
`f2c`,`jpeg`and`meschach`have to be compiled - right!? 'Cause again, for the others there are no .pro files. - For many libraries, an error message saying "instantiated from here" is occurring - referring to a template class definition (e.g.,
`template class LinearDiffusionAlgorithm<csp_float,2>;`). But the libraries are being compiled anyhow. Can I just ignore those messages? - It says that I have to add the PATH to the file
`mingwm10.dll`to my system environment variables. But if I want to start an .exe by -for example- double-click, also the file`samg_dyn_noomp.dll`is required. Do I always have to copy it into the same folder as the .exe (as I used to do with CodeWarrior)? Or is there another work-around?

No major issues and probably very basic questions - but I thought that other users might come upon them as well… If so, the answers could be incorporated into Sebastian's how-to.

Cheers,

Gillian

TNode->GEM_to_MT( m_NodeHandle[in], m_NodeStatusCH[in], m_IterDone[in],

m_Vs[in], m_Ms[in], m_Gs[in], m_Hs[in], m_IC[in], m_pH[in], m_pe[in],

m_Eh[in], m_rMB[in], m_uIC[in], m_xDC[in], m_gam[in], m_xPH[in],

m_vPS[in], m_mPS[in], m_bPS[in], m_xPA[in] );

This example is for a simple transport code where the nodes are stored in an array and access to physical variables (such as m_pH) at the node is directly via the index [in] of that node. All these variables m_… reside in the mass transport part of the coupled code and function arguments of GEM_to_MT are references to these.

]]>I tried to compile and execute the tutorial2 project under WinXP64 OS.

The SAMG Solver gets into an infinite loop with the FV-Algorithm or chrashes with the Code Generation/Optimization Level 1 or above. It works fine in case the Optimization is switched off.

It seems as if it depends on the OS, because this error doesn't appear with WinXP(32).

Maybe some additional windows settings are necessary, does somebody have any idea?

Cheers,

Christine

There is a bug in the ANSYS bit that generates an output file for CSMP. It is probably triggered when you use a 3D mesh that has no boundary flags, i.e. no TOP, LEFT, etc (at least that is how I triggered it). If you read in such a mesh, you might end up having the following CSMP error:

` ``MeshManager::ParseBoundary Error: Boundary flag from vset could not be identified. Flag: -30`

The workaround that I've found is opening the mesh .dat file in a hex-editor and replacing all the -30 values in it (E2 FF FF FF in hexadecimal representation) with zeros.

Yan

]]>I have a question/problem concerning a very simple heat conduction test I performed with finite elements. I want to solve the basic heat conduction equation on a regular 1500m x 1000m grid consisting of 12 nodes and elements only. Unfortunately I added a few images to describe the problem but didn't know how to include it into this thread. So I would really appreciate if you could have a quick (or long) look at this document:

Thanks, Philipp

]]>assert( iFacet < e.ConnectedFiniteVolumeStencil()->Sectors());

which should obviously be

assert( iFacet < e.ConnectedFiniteVolumeStencil()->Facets());

I was wondering who of you has already (intensely) worked with groups and/or the interface visitor?

'Cause I recently encountered a few problems when using the 2D SuperGroup function

` ``void SuperGroup<fT,2U>::FormAndAddGroup( const char* groupname, const char* prop, fT min, fT max )`

and the Visitors subclass

` ``template<typename fT, stl_index dim> InterfaceVisitor<fT,dim>::InterfaceVisitor( const SuperGroup<fT,dim>& sg, const char* flux_variable, const char* region_discr_prop, fT inside_val, fT outside_val, SG_BOUNDARY bound, const char* group )`

I created a few groups (e.g., a group called 'model' that comprises my whole geometry) by using the function

` ``supergroup.FormAndAddGroup( "model", "permeability", 0., 1. );`

Though, it seems that the group boundaries could not be recognized correctly… I queried the number of boundary elements, boundary nodes and boundary constraint points by calling the following Group functions:

` ``cout << "\nGroup 'model' contains " << supergroup.ReferenceGroup( "model" ).Elements() << " elements" << endl; cout << supergroup.ReferenceGroup( "model" ).BoundaryElementMembers() << " boundary elements" << endl; cout << supergroup.ReferenceGroup( "model" ).BoundaryNodeMembers() << " boundary nodes" << endl; cout << supergroup.ReferenceGroup( "model" ).BoundaryConstraintPointMembers() << " boundary constraint points" << endl;`

My output was as follows:

*Group 'model' contains 10809 elements 0 boundary elements 447 boundary nodes 0 boundary constraint points*

Does anyone have an idea what went wrong here, i.e., why the boundary elements and boundary constraint points could not be detected, while the boundary nodes could?

To measure fluxes across a certain boundary (e.g., the model boundary 'TOP'), I created the following InterfaceVisitor:

` ``InterfaceVisitor<csp_float, 2> interface_top( ph_based_model, "pore velocity", "permeability", 1.0e-14, 1.0e-23, TOP ); supergroup.Accept( interface_top );`

While its functions

` ``interface_top.WriteInterfaceToVTK("interfaceTOP"); interface_top.PrintFaceNormals(); interface_top.InterfaceArea();`

did work without any problems, the functions

` ``cout << "TOP interface measured influx of " << interface_top.InFlux() << endl; cout << "TOP interface measured outflux of " << interface_top.OutFlux() << endl; cout << "...which results in a net flux of " << interface_top.InFluxMinusOutFlux() << endl;`

returned the following output:

*TOP interface measured influx of nan TOP interface measured outflux of 0 …which results in a net flux of nan*

This does not make sense, because values for 'pore velocity' are above zero at this stage!

Both of these applications seem to be part of the core functionality of CSMP++, and I therefore assume that they should be working properly. Though, I really don't know what I could have done wrong here…!

]]>- avoid that people are duplicating work by sharing new developments,
- help all of us to have an up-to-date version with fixed bugs (of which we discovered quite a number recently),
- allow you to retreive older versions, which comes in handy
*especially*if your code is still in an alpha-stable version - encourage others to be more disciplined with using the SVN as well.

Otherwise the entire idea of having a central CSMP repository is takend somewhat ad absurdum and the dange of having several CSMP branches (atMU Leoben, ETH, IC London, IPE) is increasing.

Thanks!

Sebastian

]]>Take a standard linear advection equation with a conserved variable

(1)\begin{align} \phi_t + \nabla\cdot\left(\phi \mathbf{u}\right)=q, \end{align}

where $\phi$ is the conserved variable $\mathbf{u}$ is the velocity, and $q$ is the source term. Standard finite volume discretisation yields on a control volume $V_i$ over time increment $\Delta t$

(2)\begin{align} \frac{\phi^{t+\Delta t}-\phi^t}{\Delta t}V_i =-\mathcal{F}+qV_i, \end{align}

where $\mathcal{F}$ is the usual upwind weighted finite volume discretisation of the flux term (in implicit or explicit manner). Now, obviously, this becomes

(3)\begin{align} \phi^{t+\Delta t}=\phi^{t} - \frac{\Delta t}{V_i}\mathcal{F}+\Delta t q. \end{align}

If you have a look at the function `ComposeSolution()` in `ExplicitNodeCenteredTransport` you will see the following

for ( stl_index nidx=0U; nidx<net.FiniteVolumes(); nidx++ ) { // reading the transported variable value fT solution = net.N(nidx)->Read( pmem, NodeCenteredFiniteVolumeTransport<fT,dim>::ad1_key.index ); // adding potential (volumetric) source or sink terms due to a divergence of the flow (+ dt sum_j^e 1/3 V_e q_j) if ( with_flux_balance_correction ) { if ( this->FLUX_BALANCE[nidx] != static_cast<fT>(0.) ) RESULT[nidx] += solution * -this->FLUX_BALANCE[nidx]; } // adding externally assigned source or sink terms RESULT[nidx] += solution * net.N(nidx)->Read( pmem, this->src_key.index ); // subtracting the flux time-interval product RESULT[nidx] = solution - (time_interval / this->FVPOREVOL[nidx]) * RESULT[nidx]; }

Here, `nidx` corresponds to the ID of a control volume, `RESULT` to $\mathcal{F}$, `solution` to $\phi^t$, `time_interval` to $\Delta t$, and `net.N(nidx)->Read( pmem, this->src_key.index );` to $q$. This implies that we are solving

\begin{align} \phi^{t+\Delta t}=\phi^t -\frac{\Delta t}{V_i}\mathcal{F}-\frac{\Delta t}{V_i}\phi^t q. \end{align}

This is obviously wrong for several reasons (source has the wrong sign, is multiplied with $\phi^t$ and divided by the control volume $V_i$.

The function `Compose2PhaseSolution()` in `TwoPhaseExplicitNodeCenteredFVTransport` does even worse:

// 2. Nodal fluid SOURCE/SINK terms const fT nodal_src = net.N(nidx)->Read( pmem, this->src_key.index ); // if there is a source term if ( nodal_src != static_cast<fT>(0.) ) { // alarm if source term exceeds second stability criterion, Guignot, p. 166 (first criterion does // not apply since the source term should be positive in certain situations) if ( (nodal_src / RESULT[nidx]) * time_interval < -2. ) { #ifndef NDEBUG cerr <<"\nTwoPhaseExplicitNodeCenteredFVTransport<fT,dim>::Compose2PhaseSolution: "; cerr <<" cell "<< nidx <<", source term: "<< nodal_src <<" violated stability criterion."; #endif // explicit solution for source term at delta t_max (Guignot, p. 166) RESULT[nidx] += nodal_src * (-2. * RESULT[nidx] / nodal_src); } // overshoot criterion else if ( (nodal_src * time_interval + RESULT[nidx]) > 1. ) { #ifndef NDEBUG cerr <<"\nTwoPhaseExplicitNodeCenteredFVTransport<"<< typeid(fT).name() <<","<< dim <<"m>::Compose2PhaseSolution: "; cerr <<" cell "<< nidx <<", source term: "<< nodal_src <<" violated stability criterion."; #endif // explicit solution for source term at delta t_max (Guignot, p. 166) RESULT[nidx] += nodal_src * ((1. - RESULT[nidx]) / nodal_src); } // explicit solution for source terms due to capillary flow O.K. else RESULT[nidx] += nodal_src * time_interval; } // 3. ACCUMULATION: subtracting the flux time-interval product RESULT[nidx] = net.N(nidx)->Read( pmem, this->ad1_key.index ) - (time_interval / this->FVPOREVOL[nidx]) * RESULT[nidx];

Here, we end up with the following equations, depending on which statement is reached in the `if else` condition:

\begin{align} \phi^{t+\Delta t}=\phi^t- \frac{\Delta t}{V_i}\mathcal{F}+2\frac{\Delta t}{V_i}\mathcal{F}. \end{align}

or

(6)\begin{align} \phi^{t+\Delta t}=\phi^t -\frac{\Delta t}{V_i}\mathcal{F}-\frac{\Delta t}{V_i}\left(1-\mathcal{F}\right). \end{align}

or

(7)\begin{align} \phi^{t+\Delta t}=\phi^t- \frac{\Delta t}{V_i}\mathcal{F}-\frac{\Delta t}{V_i}q\Delta t. \end{align}

Again, the source term has the wrong sign, is multiplied by $\Delta t/V_i$ or $\Delta t^2/V_i$ or does not appear at all (instead, $\mathcal{F}$ is used).

As far as we can see, source terms are not at all considered in the implicity finite volume schemes. A variable `"nodal source"` is read in but never used. As mentioned above, we will work on these to fix it and provide new files via the SVN. Have a look at our recent plea of making more use of the SVN

I am about to set up a 2D model of which I want to change the geometry throughout the simulation (i.e., use an initial geometry of which I am going to remove and/or add a certain area). I noticed that - using an **ICEM** geometry - one can remove and add regions via the *ModelTopology*.

As I am still working with **TRIANGLE** geometries: Does a similar functionality exist for geometries imported with the TRIANGLE Interface? Or would I have to switch to the ICEM Interface? Is there any other possibility to change/edit a TRIANGLE geometry?

I'd be glad about your recommondations and inspirations!

Cheers,

Gillian

If one uses a recent compiler, e.g. gcc4.4.1 for the following output, there are problems with the CSP_Point and VectorVariable classes. Here's my output:

g++ -m64 -O3 -ffast-math -funroll-all-loops -fpeel-loops -ftracer -funswitch-loops -ftree-vectorize -DSAMG_UNIX_LINUX -DSAMG_LCASE_USCORE -Wno-deprecated -Wno-reorder -Wno-unused -Wno-switch -frtti -fexceptions -DCSP_WITH_SAMG_SOLVER -DNDEBUG -c -I../computational_geometry -I../finite_elements -I./ -I../applied_math -I../interfaces -I../solver -I../pde_operators -I../../support_libraries/f2c -I../../support_libraries/jpeg -I../../support_libraries/utilities -I../parallel Algorithm.cpp

In file included from VectorVariable.h:7,

from CSP_MemoryManager.h:7,

from Algorithm.h:8,

from Algorithm.cpp:5:

VectorVariable1.h:71: error: declaration of csp::Point<fT, 1u> csp::VectorVariable<fT, 1u>::Point() const

CSP_Point.h:78: error: changes meaning of Point from class csp::Point<fT, 1u> In file included from VectorVariable.h:8,

from CSP_MemoryManager.h:7,

from Algorithm.h:8,

from Algorithm.cpp:5:

VectorVariable2.h:71: error: declaration of csp::Point<fT, 2u> csp::VectorVariable<fT, 2u>::Point() const

CSP_Point.h:132: error: changes meaning of Point from class csp::Point<fT, 2u> In file included from CSP_MemoryManager.h:7,

from Algorithm.h:8,

from Algorithm.cpp:5:

VectorVariable.h:85: error: declaration of csp::Point<fT, 3u> csp::VectorVariable<fT, 3u>::Point() const

CSP_Point.h:188: error: changes meaning of Point from class csp::Point<fT, 3u>

make: *** [Algorithm.o] Error 1

I couldn't really figure out what happens here. Any ideas?

(Stephan once mentioned that this is fixed in the release version but in the "release version" that I got last April, those two classes are exactly the same as the ones I tried to compile.)

In order to correct this in your code, you must add tuples instead of triplets for the line elements, in order to match the original surface element sides of the surface_neighbor_keys map. For each boundary substitute:

` ``for ( vector<stl_index>::const_iterator eit=mt.ElementsOfRegionBegin("BOTTOM"); eit!=mt.ElementsOfRegionEnd("BOTTOM"); eit++ ) { assert( *eit > 0U and *eit <= vset.Elements() ); assert( mt.fem_specs.LineElement( vset.ElementType(*eit) ) ); for ( stl_index i=0U; i<vset.PlistSize(*eit); i++ ) key.insert( vset.Plist( *eit, i ) ); ebottom.insert( make_pair( key, *eit ) ); for ( set<stl_index>::const_iterator sit=key.begin(); sit!=key.end(); sit++ ) nbottom.insert( (*sit) ); key.clear(); }`

by

` `` for ( vector<stl_index>::const_iterator eit=mt.ElementsOfRegionBegin("BOTTOM"); eit!=mt.ElementsOfRegionEnd("BOTTOM"); eit++ ) { assert( *eit > 0U and *eit <= vset.Elements() ); assert( mt.fem_specs.LineElement( vset.ElementType(*eit) ) ); key.insert( vset.Plist( *eit, 0 ) ); key.insert( vset.Plist( *eit, 1 ) ); ebottom.insert( make_pair( key, *eit ) ); for ( set<stl_index>::const_iterator sit=key.begin(); sit!=key.end(); sit++ ) nbottom.insert( (*sit) ); key.clear(); }`

In this case, there is no need to iterate as the element is a line, and the two corner nodes are always stored in 0 and 1. Alternative implementations of the same solution can also be used.

I hope this helps anyone using quadratic elements with Ansys.

APR

]]>Using

tstar = 647.27e0;

the function caclulates the following two values

trat = (t+273.15e0)/tstar; trat1 = 1.0e0/trat-1.0e0;

Now, if the external CSMP temperature, t, is exactly t = 374.12, then obviously one obtains

trat = 1.0e0; trat1 = 0.0e0

which causes the viscosity, n, to be not a number because it is computed as

for(i=0;i<6;++i){ for(j=0;j<5;++j){ n += (b[i][j]*pow(trat1,i)*pow(rhorat1,j)); } }

where now pow(trat1,i) = nan if trat1 = 0 and i = 0

Am I missing some vital physics here (we are close to the critical temperature of pure water but t = 374.12 is not equal to tcrit 373.976) or am I just unlucky having encountered this value?

]]>It worked for some variables but gave the wrong sign for some other calculations.

I.e.

Concatenate<csp_float,DIM,minus> diff_temperature( p_ref, "diff temperature","temperature","previous temperature" );

gives the wrong sign.

If I give the last argument a name which comes later in the alphabet it works.

i.e.

Concatenate<csp_float,DIM,minus> diff_temperature( p_ref, "diff temperature","temperature","x previous temperature" );

I am not quite sure why the operand_list of an interrelation is filled like this:

operand_list[ string(var) ] = op;

but could this be the problem?

Or did I use Concatenate incorrectly?

Thanks for help or clarifications,

Philipp

For two different systems (pure water vs. water with salt) I am using two different fluid property visitors (

Question:

The idea is to write a **factory method** that constructs either the pure-H2O visitor or the NaCl-H2O visitor, dependent on a bool. Does someone of you have experience with factories? Does a factory make sense in this case? And how do I pass the constructed visitor(s) to the aux-function (syntax-wise)? What are pitfalls in using factory method?

(BTW: What are differences and dis-/advantages of **abstract factory vs. factory method**?!? Coudn't find very useful statements on the internet…)

I'd appreciate your help!

Cheers, Gillian

a) a 2D model from ICEM

b) with (sub)Groups

c) and using a configurations- and regionsfile.

is set up?

Long:

I used the ICEM_Model2D class to import the mesh and it compiles, but crashes upon running. The last Output is

"ICEM_Model2D<> Info: No property data supplied…"

"SuperGroup<>::FormGroupsFrom: Forming Groups:

MY_GROUPNAME"

and that's it.

From looking at the FormGroupsFrom Method i see it discovered, that the vset has no scalar properties assigned although there is a phys var file, a region and a config file in the folder. So, what is missing? (the output comes from ICEM_Model2D.cpp line 86) if this does not give you a clue, an example main file would help me to find out. The "Geiger-Group" tutorial example 3 uses also uses the ICEM_Model2D, but it does not form a group…

Thanks! Ingo ]]>

What speaks against defining it in VectorVariable?

]]>when we are evaluating our enthalpy-based energy equation, we are neglecting two volume work terms (as everybody does in other codes as these terms are considered to be too small to be of relevance). This may however, lead to an artifact in the case of cold liquids that flow downward where they can become even cooler (which may explain things that we see in some simulations).

Background:

The energy equation is evaluated at the nodes in the FV step.

The first volume work term is d/dt (phi * p), which is an easy one because it can be evaluated directly at the nodes in the FV step.

The second one is (v_steam + v_liquid) * grad(p), which is an element property (v= Darcy velocities). I would need to extrapolate this to the nodes, and prefer to do this in a way that is as close to the concept of th FV step as possible.

Of course, a pragmatic choice to convert this to values at nodes would probably be SuperGroup's method ExtrapolateElementPropertyToNodeProperty and would probably be good enough.

Nevertheless, there the averaging is done by weighting with the element area, whereas my preferred choice would be something that does the weighting by the the FV facet areas to be "more consistent" with evaluation of the energy equation in the FV method.

Has anybody done that or is this available in the generic or triangular FV schemes?

]]>Sebastian

]]>thanks again for your participation in the workshop. We are currently updating the workshop site such that you can download the talks from the programme site and a list of all email addresses as well. Please send me your pictures such that we can also include a collection of them. Some talks are still missing, we will contact the people individually.

Sebastian

]]>