Indicator Chart maximum and minimum price MQL5 - indicator

I am trying to get the values of the indicator windows, The Highest Y-axis and the lowest Y-Axis.
Here is the code that I have tried:
#include <MovingAverages.mqh>
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots 3
#property indicator_type1 DRAW_LINE
#property indicator_color1 Yellow//LightSeaGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_type2 DRAW_LINE
#property indicator_color2 Lime//YellowGreen
#property indicator_style2 STYLE_SOLID//STYLE_DOT
#property indicator_width2 1
#property indicator_type3 DRAW_LINE
#property indicator_color3 Red//Wheat
#property indicator_style3 STYLE_SOLID//STYLE_DOT
#property indicator_width3 1
#property indicator_label1 "ADX"
#property indicator_label2 "+DI"
#property indicator_label3 "-DI"
//--- input parameters
input int InpPeriodADX=14; // Period
//---- buffers
double ExtADXBuffer[];
double ExtPDIBuffer[];
double ExtNDIBuffer[];
double ExtPDBuffer[];
double ExtNDBuffer[];
double ExtTmpBuffer[];
//--- global variables
int ExtADXPeriod;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input parameters
if(InpPeriodADX>=100 || InpPeriodADX<=0)
{
ExtADXPeriod=14;
printf("Incorrect value for input variable Period_ADX=%d. Indicator will use value=%d for calculations.",InpPeriodADX,ExtADXPeriod);
}
else ExtADXPeriod=InpPeriodADX;
//---- indicator buffers
SetIndexBuffer(0,ExtADXBuffer);
SetIndexBuffer(1,ExtPDIBuffer);
SetIndexBuffer(2,ExtNDIBuffer);
SetIndexBuffer(3,ExtPDBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,ExtNDBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(5,ExtTmpBuffer,INDICATOR_CALCULATIONS);
//--- indicator digits
IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- set draw begin
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtADXPeriod<<1);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtADXPeriod);
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtADXPeriod);
//--- indicator short name
string short_name="ADX("+string(ExtADXPeriod)+")";
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
//--- change 1-st index label
PlotIndexSetString(0,PLOT_LABEL,short_name);
//---- end of initialization function
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//--- checking for bars count
if(rates_total<ExtADXPeriod)
return(0);
//--- detect start position
int start;
if(prev_calculated>1) start=prev_calculated-1;
else
{
start=1;
ExtPDIBuffer[0]=0.0;
ExtNDIBuffer[0]=0.0;
ExtADXBuffer[0]=0.0;
}
//--- main cycle
for(int i=start;i<rates_total && !IsStopped();i++)
{
//--- get some data
double Hi =high[i];
double prevHi=high[i-1];
double Lo =low[i];
double prevLo=low[i-1];
double prevCl=close[i-1];
//--- fill main positive and main negative buffers
double dTmpP=Hi-prevHi;
double dTmpN=prevLo-Lo;
if(dTmpP<0.0) dTmpP=0.0;
if(dTmpN<0.0) dTmpN=0.0;
if(dTmpP>dTmpN) dTmpN=0.0;
else
{
if(dTmpP<dTmpN) dTmpP=0.0;
else
{
dTmpP=0.0;
dTmpN=0.0;
}
}
//--- define TR
double tr=MathMax(MathMax(MathAbs(Hi-Lo),MathAbs(Hi-prevCl)),MathAbs(Lo-prevCl));
//---
if(tr!=0.0)
{
ExtPDBuffer[i]=100.0*dTmpP/tr;
ExtNDBuffer[i]=100.0*dTmpN/tr;
}
else
{
ExtPDBuffer[i]=0.0;
ExtNDBuffer[i]=0.0;
}
//--- fill smoothed positive and negative buffers
ExtPDIBuffer[i]=ExponentialMA(i,ExtADXPeriod,ExtPDIBuffer[i-1],ExtPDBuffer);
ExtNDIBuffer[i]=ExponentialMA(i,ExtADXPeriod,ExtNDIBuffer[i-1],ExtNDBuffer);
//--- fill ADXTmp buffer
double dTmp=ExtPDIBuffer[i]+ExtNDIBuffer[i];
if(dTmp!=0.0)
dTmp=100.0*MathAbs((ExtPDIBuffer[i]-ExtNDIBuffer[i])/dTmp);
else
dTmp=0.0;
ExtTmpBuffer[i]=dTmp;
//--- fill smoothed ADX buffer
ExtADXBuffer[i]=ExponentialMA(i,ExtADXPeriod,ExtADXBuffer[i-1],ExtTmpBuffer);
Print(ChartGetDouble(0,CHART_PRICE_MAX,1));
Print(ChartGetDouble(0,CHART_PRICE_MIN,1));
}
//---- OnCalculate done. Return new prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+
The Print()-s for a indicator window:
Print( ChartGetDouble( 0, CHART_PRICE_MAX, 1 ) );
Print( ChartGetDouble( 0, CHART_PRICE_MIN, 1 ) );
give output as 0 (zero).
If I just print the CHART_PRICE_MAX, I get 109 as output.
Kindly, help me.

A general principle
Do nothing except OnCalculate(){...} processing "inside" Custom Indicator type-of-MQL5 code.
Print()-ing is not a good idea there. Many other functions are explicitly forbidden to get used in this type-of-MQL5 code, due to ultimate scheduling issues ( the MT4/5 platform architecture ).
If in a need to "read" { min, MAX }-values, use Script / ExpertAdvisor type of code, or some non-Print()-ing trick, if indeed in a need to remain inside the CustomIndicator.

Related

How to pass value from one function to another in C?

Here I have two functions and I call Both of them in my MAIN function. The first function gives me a value of "wage" and I want to use the value of "wage" in my 2nd function. But this doesn't work. Also, I will be using my variable in another function later in my code. Is there any way to call my values efficiently?
Here is the main function call:
#include <stdio.h>
#include <string.h>
int main()
{
categoryA();
workingInfo();
}
1st function that has value of "wage" :
void categoryA()
{
printf("\n\nCategory A: Administrative Worker[1]\n\t Data Entry Operator[2]\n\t Data Entry Clerk[3]\n\t Betting Clerk[4]\n");
int position;
float wage;
float overWage;
char positionName[100];
printf("Choose Your Job Title : ");
scanf("%d",&position);
if(position == 1)
{
wage = 12.5;
overWage= wage*1.15;
strcpy(positionName, "Administrative Worker");
}
else if (position == 2)
{
wage = 13;
overWage= wage*1.15;
strcpy(positionName,"Data Entry Operator");
}
else if (position == 3)
{
wage = 13.2;
overWage= wage*1.15;
strcpy(positionName, "Data Entry Clerk");
}
else
{
wage = 13.5;
overWage= wage*1.15;
strcpy(positionName,"Betting Clerk");
}
printf("wage in the category function : %.2f\n",wage);
}
2nd function where I want to use "wage" :
void workingInfo(float wage)
{
printf("wage in the working info %.2f\n",wage);
}
Change the function so that it returns a float, i.e.
float categoryA()
{
... your current code ...
return wage; // Return the value of wage
}
and use it like:
int main()
{
float f = categoryA(); // Save the returned value (i.e. wage) in
// a variable with the name f
workingInfo(f); // Use f
....
someOtherFunc(f); // Use f again
}
or the more compact version:
int main()
{
workingInfo(categoryA()); // The returned value isn't saved in
// a variable but passed directly to
// the workingInfo function
}
Once categoryA() has returned, its wage variable is gone, as well as out of scope. There's no way it can be accessed.
Rather, I suggest you return wage; at the end of categoryA(), then pass the result in to workingInfo().
You'll need to change the signature of categoryA():
float categoryA()
And change the call to something like:
float wage = categoryA();
workingInfo(wage);
... or...
workingInfo(categoryA());
The simplest way you can do it by making wage as global variable, then also you will be able to use it with in multiple functions too and you can also use it as pointer too if you are comfortable with pointers.

Calling local Julia package from C

The Julia documentation shows examples of how to call Base Julia functions from C (e.g. sqrt), which I've been successful in replicating. What I'm really interested in doing is calling locally developed Julia modules and it's not at all clear from the documentation how one would call non-Base functions. There are some discussion threads on the issue from a few years ago, but the APIs appear to have changed in the meantime. Any pointers would be appreciated.
The reason why jl_eval_string("using SomeModule") returns NULL is simply because using SomeModule returns nothing.
You can use functions from other modules by first importing the module, and then retrieving function objects from that Julia module into C. For example, let's use the package GR and its plot function. We can get the plot function with
jl_eval_string("using GR") // this returns nothing
jl_module_t* GR = (jl_module_t *)jl_eval_string("GR") // this returns the module
/* get `plot` function */
jl_function_t *plot = jl_get_function(GR, "plot");
Here we passed GR module as the first argument to jl_get_function. We can, knowing the fact that things will be loaded into the module Main and plot is exported from GR, use the following snippet instead to do the same. Note that jl_main_module holds a pointer to the module Main.
jl_eval_string("using GR")
/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "plot");
We can also use plots qualified name.
/* get `plot` function */
jl_function_t *plot = jl_get_function(jl_main_module, "GR.plot");
That said, here is the complete example plotting an array of values using GR. The example uses the first style to get the function GR.plot.
#include <julia.h>
JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.
#include <stdio.h>
int main(int argc, char *argv[])
{
/* required: setup the Julia context */
jl_init();
/* create a 1D array of length 100 */
double length = 100;
double *existingArray = (double*)malloc(sizeof(double)*length);
/* create a *thin wrapper* around our C array */
jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
/* fill in values */
double *xData = (double*)jl_array_data(x);
for (int i = 0; i < length; i++)
xData[i] = i * i;
/* import `Plots` into `Main` module with `using`*/
jl_eval_string("using GR");
jl_module_t* GR = (jl_module_t *)jl_eval_string("GR");;
/* get `plot` function */
jl_function_t *plot = jl_get_function(GR, "plot");
/* create the plot */
jl_value_t* p = jl_call1(plot, (jl_value_t*)x);
/* display the plot */
jl_function_t *disp = jl_get_function(jl_base_module, "display");
jl_call1(disp, p);
getchar();
/* exit */
jl_atexit_hook(0);
return 0;
}
Including a Julia module from a local file and use it in C
I do not know what is exactly meant by a local Julia package, but, you can include your files and then import the modules in those files to do the same. Here is an example module.
# Hello.jl
module Hello
export foo!
foo!(x) = (x .*= 2) # multiply entries of x by 2 inplace
end
To include this file you need to use jl_eval_string("Base.include(Main, \"Hello.jl\")");. For some reason, embedded Julia cannot access include directly. You need to use Base.include(Main, "/path/to/file") instead.
jl_eval_string("Base.include(Main, \"Hello.jl\")");
jl_eval_string("using Main.Hello"); // or just '.Hello'
jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello"); // or just .Hello
Here is the complete example in C.
#include <julia.h>
JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.
#include <stdio.h>
int main(int argc, char *argv[])
{
/* required: setup the Julia context */
jl_init();
/* create a 1D array of length 100 */
double length = 100;
double *existingArray = (double*)malloc(sizeof(double)*length);
/* create a *thin wrapper* around our C array */
jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
JL_GC_PUSH1(&x);
/* fill in values */
double *xData = (double*)jl_array_data(x);
for (int i = 0; i < length; i++)
xData[i] = i * i;
/* import `Hello` module from file Hello.jl */
jl_eval_string("Base.include(Main, \"Hello.jl\")");
jl_eval_string("using Main.Hello");
jl_module_t* Hello = (jl_module_t *)jl_eval_string("Main.Hello");
/* get `foo!` function */
jl_function_t *foo = jl_get_function(Hello, "foo!");
/* call the function */
jl_call1(foo, (jl_value_t*)x);
/* print new values of x */
for (int i = 0; i < length; i++)
printf("%.1f ", xData[i]);
printf("\n");
JL_GC_POP();
getchar();
/* exit */
jl_atexit_hook(0);
return 0;
}

While loop not working with bool statements in C (beginner!)

I'm learning the basics right now and am making a simple game using a basic graphics library provided by my uni.
There is a projectile thrown (the path of which is drawn)
an obstacle (a wall) - which the projectile can't pass through so must go over
and a target (must also appear solid so line stops being drawn when it is hit)
Right now my projectile is being thrown right through the wall
The issue is with the while loop
Any conditions I add (after (y_displacement < FLOOR_HEIGHT)) have had no effect
(This projectile on its own stops drawing when y_displacement => FLOOR_HEIGHT (Y-Axis is inverted), but any addition of bool statements or attempts at using bool (after #including too) to stop the projectile line being drawn don't make any changes.
TRIED BOOL FOR WALL (doesn't change anything):
bool hit_wall = false;
while ((y_displacement < FLOOR_HEIGHT) && (hit_wall == false))
{
time = (x_displacement - X_HAND) / x_velocity; //speed = distance/time
y_displacement = (Y_HAND - y_velocity * time) - (GRAVITY * pow(time, 2)/2);
GFX_DrawLineTo(x_displacement, y_displacement, 3);
x_displacement += 1;
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
}
}
If I can manage to sort this out then I should be able to do the same for my target..
Is there something wrong with what I'm doing?
BACKGROUND:
The full function is this:
void throwBall(int(x_position), int(y_position))
{
GFX_SetColour(YELLOW);
int x_mouse;
int y_mouse;
int x_distance;
int y_distance;
double angle;
float initial_velocity;
float x_velocity;
float y_velocity;
float time;
GFX_MoveTo(X_HAND, Y_HAND);
GFX_GetMouseCoordinates(&x_mouse, &y_mouse);
x_distance = x_mouse - X_HAND;
y_distance = y_mouse - Y_HAND;
angle = getAngle(x_distance, y_distance);
initial_velocity = sqrt(pow(x_distance, 2) + pow(y_distance, 2));
//these have been divided by 5 as the magnitude was too large for the window
y_velocity = (initial_velocity * sin (angle) - GRAVITY * time)/(X_MAX/256);
x_velocity = (initial_velocity * cos (angle))/(X_MAX/256);
float y_displacement;
float x_displacement;
x_displacement = X_HAND;
y_displacement = Y_HAND;
bool hit_wall = false;
while ((y_displacement < FLOOR_HEIGHT) && (hit_wall == false))
{
time = (x_displacement - X_HAND) / x_velocity; //speed = distance/time
y_displacement = (Y_HAND - y_velocity * time) - (GRAVITY * pow(time, 2)/2);
GFX_DrawLineTo(x_displacement, y_displacement, 3);
x_displacement += 1;
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
}
}
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
you use flaot values, and due to some reasons (values are aprroximatelly) you almost never get in this if.
you should use >, >=, < , <= poerators, but it also will not help you in 100% of cases.
best choice will be to use epsilon (Observational error, Neighbourhood)
like
float eps = 0,0000001f;
if ( abs(x_displacement - (X_MAX/2.5) ) < eps
&& y_displacement > ( (Y_MAX/2) - eps ) )
{
hit_wall = true;
}
expanding on previous answers regarding floating point equivalence and round off error, another way to do it is multiply your float or double value by some factor of 10 to move the decimal point to the right, then cast it to an int or long it. Then you can do a boolean comparison which will be on integers which will work reliably. I mention this because it can sometimes be easier to code and also read easier than doing the epilson method (which you would also have to do an absolute value on) described in the other answer .
The big thing to recognize is the factor of 10 by which you multiply with or set epsilon to.
Do not go crazy and multiply by something like 1e9 or set epsilon = 1e-9 when you don't need to because that can re-introduce the same problem.
For example if your variables for distance are in meters then you need to recognize you do not need resolution greater than ???. Let's use 1/100 of a millimeter as an example... as far as you are concerned 1.230012345mm == 1.230456789mm. So then multiply by 1e5 then cast to int or do epsilon=1e-5;. Same principle applies for units of inches, you typically do not need resolution greater than 0.0001" for anything so multiply by 1e4 or epsilon = 1e-4.
/* example */
# define D2I 1e2 /* dbl to int factor, 0.01mm resolution */
double x_displacement; /* units of millimeters for this example*/
double y_displacement; /* units of millimeters for this example*/
/* whatever previous calculations result in...
x_displacement having value of 3.00000249687738566
y_displacement having value of 120.00000085639820699
out past 6 or so decimal places a float or double will have arbitrary numbers, so don't multiply by some huge 1e12 number
*/
if ( ( (int)(x_displacement * D2I) == (int)((X_MAX / 2.5) * D2I ) ) &&
( (int)(y_displacement * D2I ) > (int)((Y_MAX / 2 ) * D2I ) )
)
{
hit_wall = true;
}

Cannot get MT4 indicator to work using prebuilt library

I'm using the code from this article https://www.mql5.com/en/articles/159 to calculate when a new bar opens but it's not displaying the historical data for the indicator.
I have modified the TimeCurrent() to iTime( _Symbol, _Period, shift ) so as to try to handle this, but it's not working.
Could you tell me what I'm doing wrong please?
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 RoyalBlue
#include <Lib_CisNewBar.mqh>
CisNewBar current_chart;
//---- input parameters
extern int Length=18; // Bollinger Bands Period
extern int Deviation=2; // Deviation was 2
extern double MoneyRisk=1.00; // Offset Factor
extern int Signal=1; // Display signals mode: 1-Signals & Stops; 0-only Stops; 2-only Signals;
extern int Line=1; // Display line mode: 0-no,1-yes
extern int Nbars=1000;
//---- indicator buffers
double TrendBuffer[];
extern bool SoundON=true;
bool TurnedUp = false;
bool TurnedDown = false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name;
//---- indicator line
SetIndexBuffer(0,TrendBuffer);
SetIndexStyle(0,DRAW_LINE,0,1);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
short_name="Example ("+Length+","+Deviation+")";
IndicatorShortName(short_name);
SetIndexLabel(0,"Trend Value");
//----
SetIndexDrawBegin(0,Length);
//----
return(INIT_SUCCEEDED);
}
void deinit()
{
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int shift;
for (shift=Nbars;shift>=0;shift--)
{
TrendBuffer[shift]=0;
}
for (shift=Nbars-Length-1;shift>=0;shift--)
{
int period_seconds=PeriodSeconds(_Period);
datetime new_time=iTime(_Symbol,_Period,shift)/period_seconds*period_seconds;
if(current_chart.isNewBar(new_time))
{
Print("time[shift] = "+TimeToString(time[shift]));
if( Close[shift] > Close[shift+1] )
TrendBuffer[shift]=1;
else if(Close[shift] < Close[shift+1] )
TrendBuffer[shift]=-1;
else
TrendBuffer[shift]=0;
}
}
return(0);
}
Thanks.
a) The "new"-MQL4.56789 has another syntax
For Custom Indicator, the "new"-MQL4.56789 source shall rather read
void OnInit(){ ... }andvoid OnDeinit( const int anMT4_Reason2callDeinit ){ ... }
b) The datetime
Your code defines a variable new_time, typed as a datetime
The datetime type is intended for storing the date and time as the number of seconds elapsed since January 01, 1970.
and
Values range from 1 January, 1970 to 31 December, 3000
So, in case of your new_time assignment, the proper iTime() value is divided by an amount of PeriodSeconds() and right next it is re-multiplied by the exact same value, which should not change the value of the iTime() result.
Such operation, while having no theoretical impact on result, might in practice of a code-execution introduce a risk of a numerical inaccuracy, range overflow/underflow and a theoretical notice about a resolution of an 8-byte class storage is not helping to go past the upper bound limit, stated in the documentation as Dec-31, 3000.
In similar cases unpredicatable results and even MT4 unhandled exceptions and MQL4-code terminations are to be expected.
What worse one may expect for a production grade software? So, avoid, avoid and avoid any such risk.
There is no direct positive value for such a Custom Indicator calculation step.
c) TimeCurrent() / PeriodSeconds() side-effect of rounding
While iTime() is always divisible by it's "own" time-frame PeriodSeconds(), TimeCurrent() is not.
Thus one may read the original ( assumed ) construct of
TimeCurrent() / PeriodSeconds() // .DIV is subject to rounding to int
* PeriodSeconds(); // before the forthcoming .MUL
"hacks" the need to align a [last known server time, time of the last quote receipt for one of the symbols selected in the "Market Watch" window] to one's "own" time-frame value of a start-of-current bar time.
d) The article is from 11 October 2010 (!) - be very carefull in MQL4
Current MQL4 code-execution engine is Build 890 ( 25 Sep 2015 ), so your cited source was using an MQL5 language syntax some 5 years old (!!), which namely in MQL4-domain means _be_very_carefull_
In the meantime string-s ceased to be string-s,
many GUI functions have several calling protocols in parallel,
andcountless man*years of DLL/API-code-base dev/maint were lost due to similar moving sands.
So -5- years gap is a warning per-se.
One never enters the same river twice
The recent state of "new"-MQL4.56789 allows a clean approach:
in case your motivation is just to be able to detect on-demand a situation a new bar has started, the Build-890/1174 compiler allows for a cleaner approach:
bool aNewBarEVENT( const string anFxSYMBOL, // _Symbol,
const int aTimeFRAME // PERIOD_M6
)
{ static int pBars = EMPTY; // previous
int oBars = iBars( anFxSYMBOL, aTimeFRAME ); // observed
if ( pBars == oBars ) return( False ); // .NACK
pBars = oBars, return( True ); // .UPD + .ACK
}

Garbage storage, programming in C

I'm new programing in C. I have a main code with 781 lines that is out of control because garbage value is stored in vectors. A short part of the main code is shown below where it calls a subroutine called diff_conv_intermedia1.
diff_conv_intermedia1(&factorteta,&N,ID,DIFF,X1_intermedia,Y1_intermedia,X1C_intermedia,Y1C_intermedia,CU1_intermedia,CV1_intermedia,AW1_intermedia,AE1_intermedia,AS1_intermedia,AN1_intermedia,AP1_intermedia,Q1_intermedia,FXI1,FYI1,FI_intermedia1,1,2,1,1);
int q,w;
for(q=1;q<(*factorteta_Ptr)*2+1;q++)
{
for(w=1;w<(*N_Ptr)+1;w++)
{
printf("%lf\n",AP1_intermedia[q][w]);
}
}
So the subroutine shown below. When I print the results inside the subroutine, everything is OK, but when I print the results outside the subroutine, in the main code, garbage is stored in the vectors as AP1_intermedia. I don't know what could be wrong. I repeat the same procedure with other subroutines and I don't have any errors.
int diff_conv_intermedia1(int *factorteta_Ptr,
int *N_Ptr,
int ID,
double DIFF,
double X[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Y[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double XC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double YC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double CU[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double CV[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AW[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AE[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AS[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AN[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Q[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FX[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FY[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FI[(*factorteta_Ptr)*2+1][*N_Ptr+1],
int WBC,int EBC,int SBC,int NBC)
{
int i,j;
double value,* valuePtr;
double AED, AWD, AND, ASD;
double AEC, AWC, ANC, ASC;
valuePtr = &value;
// Diffusive coefficients
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
for(j=1;j<*N_Ptr+1;j++)
{
AWD = -DIFF*(Y[i][j-1]-Y[i-1][j-1])/(XC[i][j]-XC[i][j-1]);
AED = -DIFF*(Y[i][j]-Y[i-1][j])/(XC[i][j+1]-XC[i][j]);
AND = -DIFF*(X[i][j]-X[i][j-1])/(YC[i+1][j]-YC[i][j]);
ASD = -DIFF*(X[i-1][j]-X[i-1][j-1])/(YC[i][j]-YC[i-1][j]);
// Convection term
if(ID==2)
{
max1_or_min2(CU[i][j-1],1,&value);
AWC=-*valuePtr;
max1_or_min2(CU[i][j],2,&value);
AEC=*valuePtr;
max1_or_min2(CV[i-1][j],1,&value);
ASC=-*valuePtr;
max1_or_min2(CV[i][j],2,&value);
ANC=*valuePtr;
}
if(ID==1)
{
AWC =-CU[i][j-1]*(1.0-FX[i][j-1]);
AEC =CU[i][j]*FX[i][j];
ASC =-CV[i-1][j]*(1.0-FY[i-1][j]);
ANC =CV[i][j]*FY[i][j];
}
// Set Coefficients matrix
AW[i][j] = AWD+AWC;
AE[i][j] = AED+AEC;
AS[i][j] = ASD+ASC;
AN[i][j] = AND+ANC;
AP[i][j] = -(AE[i][j]+AW[i][j]+AN[i][j]+AS[i][j]);
Q[i][j] = 0.0;
}
}
// West Boundary - Inlet B.C
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
if(WBC==1) Q[i][1] = Q[i][1]-AW[i][1]*FI[i][0];
if(WBC==2) AP[i][1] = AP[i][1] + AW[i][1];
AW[i][1] = 0.0;
// East Boundary - (1)Dirichlet (2)ZERP-GRAD Outflow B.C
if(EBC==1) Q[i][*N_Ptr] = Q[i][*N_Ptr] - AE[i][*N_Ptr]*FI[i][*N_Ptr+1];
if(EBC==2) AP[i][*N_Ptr] = AP[i][*N_Ptr] + AE[i][*N_Ptr];
AE[i][*N_Ptr] = 0.0;
}
// South Boundary - (1)Dirichlet (2)ZERO-GRAD
for(j=1;j<*N_Ptr+1;j++)
{
if(SBC==1) Q[1][j] = Q[1][j] - AS[1][j]*FI[0][j];
if(SBC==2) AP[1][j] = AP[1][j] + AS[1][j];
AS[1][j] = 0.0;
// North Boundary - (1)Dirichlet (2)ZERO-GRAD
if(NBC==1) Q[(*factorteta_Ptr)*2][j] = Q[(*factorteta_Ptr)*2][j] - AN[(*factorteta_Ptr)*2][j]*FI[(*factorteta_Ptr)*2+1][j];
if(NBC==2) AP[(*factorteta_Ptr)*2][j] = AP[(*factorteta_Ptr)*2][j] + AN[(*factorteta_Ptr)*2][j];
AN[(*factorteta_Ptr)*2][j] = 0.0;
}
// Print
int l,k;
for(l=1;l<(*factorteta_Ptr)*2+1;l++)
{
for(k=1;k<*N_Ptr+1;k++)
{
printf("%lf %lf %lf %lf\n",AP[l][k],AS[l][k],AN[l][k],FI[l][k]);
}
}
return 0;
}
If anybody wants I can send all code, but have many extensions.
In your function declaration:
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1]
I don't quite think this is doing what you think it is doing. While I haven't seen something like this myself before, I believe that this is telling the compiler to create a variable length 2D array for you based on the other given parameters. Then, you fill in these values in your function. But, because you don't return this value nor do you declare it as pass by reference, it is thrown away when you return, thus the work is lost and you have garbage in your array in main(). Better form would be to create this array in main(), then pass it in by reference something like double *AP[][], or return this array upon exit, or hack things up even worse than this function and just make it a global so that you can see it anywhere.

Resources