I am trying to implement the Newton-Raphson method using a single function pointer. The function must contain both the equation and its derivative. I am having difficulty passing through these two separate functions within the test function.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
double NR(double, double(*)(double, double*), double);
void test_function( double x, double * f, double * f_prime )
{
*f = (x-2) * (x-2);
*f_prime = 2*x - 4;
}
double NR( double x0, double (*test_function)(double x, double *f, double *f_prime), double precision )
{
int i;
while(!isnan(x0)){
i = x0;
x0 = (x0 - (test_function(x0, f, 0)/test_function(x0, 0, f_prime)));
if(!isnan(x0))
printf("%f\n",x0);
if ( i - x0 < 0 )
printf("NO ROOT FOUND");
return -1;
else if ( i - x0 > 0 && i - x0 < precision )
break;
}
}
int main(void)
{
double x0 = 300;
double precision = .0000001;
double root = NR( x0, test_function, precision);
printf("%f\n",root);
return 0;
}
Thank you
Update declaration of NR to take function pointer that takes 3 parameters as
double NR(double, double(*)(double, double*, double *), double);
instead of
double NR(double, double(*)(double, double*), double);
As you are passing 0 (or NULL) to either prime or f_prime, you can update test function as
void test_function( double x, double * f, double * f_prime )
{
if(f)
*f = (x-2) * (x-2);
if(f_prime)
*f_prime = 2*x - 4;
}
Also you need to update NR as below to define f and f_prime
double NR( double x0, double (*test_function)(double x, double *f, double *f_prime), double precision )
{
int i;
double f, f_prime;
...
//your code
...
//----------------------------v pass address -------------v
x0 = (x0 - (test_function(x0, &f, 0)/test_function(x0, 0, &f_prime)));
....
//your code
}
Related
I'm having an assignment to complete where I need to find the zero body bias threshold voltage,based on the value of Vsb. Though this problem is based on the solution of another exercise, I give to you below some screenshots of what I need to calculate:
Where the Vthreshold formula is:
So I want to implement this:
My problem is that I don't know how to insert the Vsb value to the final formula in a way so that it can affect the final value of the zero body bias.The code that I've written returns only the value of the zero body bias based on the vthreshold only
Here's the code that I've written so far:
#include <stdio.h>
#include <math.h>
double vFB (double fgs, double B);
double vT (double A, double C);
double vA (double D);
double vSP (double J);
double gamwt (double A, double F);
double roulis( double H, double L);
double thres_volt(double vFB, double vSP, double vT, double vA);
double zero_body_bias_threshold_voltage(double thresh_volt, double gamma, double roulis);
int main(){
double eps0 = 8.854E-14; //Dielectric constant, void, [F/cm]
double epsox = 3.9*eps0; //Oxide dielectric constant, [F/cm]
double epsSi = 11.2*eps0; //Si dielectric constant, [F/cm]
double q = 1.6E-19; // expressed in Coulomb
double ni = 1.45E10; // intrincic carrier concentration expressed in cm^-3
double Na = 1.0E15; // expressed in cm^-3
double Ndpoly = 1.0E19; // expressed in cm^-3
double xox = 100.0; //Oxide thickness,[A]
double DI = 2.0E12; // number of implanted ions/cm^2 expressed in cm^-2
double kTq = 0.026; // expressed in Volt
double Qf = q*1.0E11; //expressed in C/cm2
double Vsb;
double Cox = (epsox)/(xox*1.0E-8); //Oxide capacitance per unit area, [F/cm2]
double A = 1.0/Cox;
double G = ((Na*Ndpoly))/((ni*ni));
double fgs = -((kTq)*log(G));
double B = A*Qf;
double T = Na/ni;
double J = 2*kTq*log(T);
double K = 2*q*epsSi*Na*J;
double C = sqrt(K);
double W = (q*DI)*(1.0/(Cox));
double D = W;
double U = 2*q*epsSi*Na;
double F = sqrt(U);
double ginomeno1 = J + Vsb;
double tetragwniki_tou_ginomenou1 = sqrt(ginomeno1);
double H = tetragwniki_tou_ginomenou1;
double ginomeno2 = J;
double tetragwniki_tou_ginomenou2 = sqrt(ginomeno2);
double L = tetragwniki_tou_ginomenou2;
double v1 = vFB(fgs, B);
double v2 = vSP(J);
double v3 = vT(A,C);
double v4 = vA(W);
double v5 = gamwt(A,F);
double v6 = roulis(H,L);
double v7 = thres_volt(v1,v2,v3,v4);
double v8 = zero_body_bias_threshold_voltage (v7,v5,v6);
double FocmtofFoum = 1.0E11; //Conversion factor of F/cm to fF/um
double Coxnew = Cox*FocmtofFoum;
printf ("Cox = %e [F/cm2]\n",Cox);
printf ("Coxnew = %f [fF/um]\n",Coxnew);
printf ("VFB = %f [V]\n", v1);
printf ("Vsp = %f [V]\n", v2);
printf ("Vt =%f [V]\n", v3);
printf ("Va = %f [V]\n", v4);
printf ("gamma = %f [V ^1/2]\n", v5);
printf ("Give me a number for Vsb..");
scanf ("%f", &Vsb);
if (Vsb==0)
ginomeno1 = J;
printf ("V_body_bias = %f [V]\n", v8);
getch();
return 0;
}
double vFB (double fgs, double B)
{
return (fgs-B);
}
double vT (double A, double C){
return (A*C);
}
double vA (double D){
return (+D);
}
double vSP (double J)
{
return (+J);
}
double gamwt (double A, double F)
{
return (A*F);
}
double roulis( double H, double L)
{
return (H-L);
}
double thres_volt(double vFB, double vSP, double vT, double vA)
{
return (vFB+vSP+vT+vA);
}
double zero_body_bias_threshold_voltage(double thresh_volt, double gamwt, double roulis)
{
return (thresh_volt + gamwt*roulis);
}
I am trying to write a program to find the root of a third degree polynomial function using Sidi's method which is similar to Newton's Method and the Secant Method. The only difference is using the interpolated polynomial instead of the derivative of the function. I also have to test my code with 50 guesses, and I have tried writing the code but when I execute it nothing happens. This is my code
double f(double x)
{
return ((3*x*x*x)-(6*x*x)-(6*x)-5);//polynomial equation
}
double y(double z)
{
return ((17.8*z*z*z)-(34.5*z*z)+(199.7*z)+30);//interpolation equation
}
double dy (float z)
{
return ((53.4*z*z)-(69*z)+199.7);//derivative of interpolation equation
}
main()
{
double i;
int maxitr = 10;
int itr;
double a;
double b;
double maxdec = 0.000001;
for(i=1; i<= 50; i++){
printf("Input guess ");
scanf("%lf", i);
for(itr = 1; itr < maxitr; itr++){
a = f(i) / dy(i);
b = i - a;
if(fabs(a) < maxdec){
printf("root: %lf", b);
return 0;
}
i = b;
}
}
Hope this helps you. My program solves this equation f(x)=x^7-1000 = 0.You can add your equation by editing the void f(double x[],int x1,int x2) function. Also you add whatever else you want more.
#include<stdio.h>
#include<math.h>
void f(double x[],int x1,int x2);
int main()
{
double x[50];
int x1,x2;
printf("Enter x1:\n");
scanf("%d",&x1);
printf("Enter x2:\n");
scanf("%d",&x2);
printf("\nCalculating....\n");
f(x,x1,x2);
return 0;
}
void f(double x[],int x1,int x2)
{
// Assuming Equation is x^7 - 1000
// you can edit this code to keep your
// own equation
int i,prec=10000;
double a,b,num;
double denom,d1,d2;
x[0] = 0.00; //let's start with index 1 instead of 0
x[1] = x1;
x[2] = x2;
printf("x[2]:%f\n",x[2]);
for(i=3;i<=50;i++)
{
num = pow(x[i-1],7)-1000;
d1 = (pow(x[i-1],7)-1000) - (pow(x[i-2],7)-1000);
d2 = (x[i-1] - x[i-2]);
denom = d1/d2;
x[i] = x[i-1] - num/denom;
printf("x[%d]:%f\n",i,x[i]);
a= (long int)(x[i]*prec);
b= (long int)(x[i-1]*prec);
if(a == b)
{
break;
}
}
printf("x[%d]=%f and x[%d]=%f are apprx equal!\n",i-1,x[i-1],i,x[i]);
}
Where,
num is (x2)^7 - 1000
d1 is ((x2)^7 - 1000)-((x1)^7-1000)
d2 is x2-x1
denom is d1/d2
I have a 3D mesh defined by verteces and triangles. I have also normals of the mesh. I'd like to calculate the area of the mesh, assuming it's always closed. I found an interesting implementation of calculation of the 3D volume in this question, and I applied it in a C code to build a function called by R. This is the code:
double SignedVolumeOfTriangle(double p1X, double p1Y, double p1Z,
double p2X, double p2Y, double p2Z, double p3X, double p3Y, double p3Z) {
double v321 = p3X*p2Y*p1Z;
double v231 = p2X*p3Y*p1Z;
double v312 = p3X*p1Y*p2Z;
double v132 = p1X*p3Y*p2Z;
double v213 = p2X*p1Y*p3Z;
double v123 = p1X*p2Y*p3Z;
return (double)(1.0/6.0)*(-v321 + v231 + v312 - v132 - v213 + v123);
}
void MeshVolume(double *X, double *Y, double *Z, int *numT, int *V1, int *V2, int *V3, double *Volume) {
int n;
*Volume=0;
for (n=0; n<*numT; n++) {
*Volume = *Volume + SignedVolumeOfTriangle(X[V1[n]], Y[V1[n]], Z[V1[n]], X[V2[n]], Y[V2[n]], Z[V2[n]], X[V3[n]], Y[V3[n]], Z[V3[n]]);
}
*Volume = fabs(*Volume);
}
Neither in the question nor in the article linked I found the algorithm for calculating the Area of the mesh. Is there anybody can help me please?
You have a closed volume whose surface is made up by triangles. And all triangles contribute to the outer surface. right?
The surface of a triangle between points P, Q and R can be obtained by:
A = 0.5 * |PQ × PR|
= 0.5 * |PQ| * |PR| * sin(Ɵ)
where
PQ = Q - P
PR = R - P
and × denotes the cross product and Ɵ is the angle between the vectors. (The magnitude of the resulting vector of a cross product is the area of a parallelogramme between the two original vectors. Half of that is the area of a triangle.)
Sum the aeras of all triangles. There's no need to take the absolute value, because the area can only be zero or positive. So:
double AreaOfTriangle(double p1X, double p1Y, double p1Z,
double p2X, double p2Y, double p2Z,
double p3X, double p3Y, double p3Z)
{
double ax = p2x - p1x;
double ay = p2y - p1y;
double az = p2z - p1z;
double bx = p3x - p1x;
double by = p3y - p1y;
double bz = p3z - p1z;
double cx = ay*bz - az*by;
double cy = az*bx - ax*bz;
double cz = ax*by - ay*bx;
return 0.5 * sqrt(cx*cx + cy*cy + cz*cz);
}
void MeshSurface(double *X, double *Y, double *Z,
int *numT, int *V1, int *V2, int *V3, double *Area)
{
int n;
*Area = 0.0;
for (n=0; n<*numT; n++) {
*Area += AreaOfTriangle(X[V1[n]], Y[V1[n]], Z[V1[n]],
X[V2[n]], Y[V2[n]], Z[V2[n]],
X[V3[n]], Y[V3[n]], Z[V3[n]]);
}
}
I need to get the user to input a number into a program and then need to be able to use that number in many other parts functions in the program. Any way to do that?
Here is the code:
#include <stdio.h>
#include <math.h>
#define W 8.
#define H 4.
double ellipse(double);
typedef double (*DfD) (double);
double simpsons_int (DfD, double, double, int);
int main()
{
double len, w, h, volume;
printf("Please enter a length, width and height (in meters) of the an elliptical storage tank \n");
scanf("%lf %lf %lf", &len, &w, &h);
double a = h/2.*-1., r;
for (double depth=10; depth<=400; depth=depth+10)
{
r=a+(depth/100);
volume = len*simpsons_int(ellipse, a, r, 10000);
printf("depth is %.1f, volume is %f\n", depth, volume);
}
}
double ellipse(double y)
{
double x;
double A=W/2.;
double B=H/2.;
x=2*sqrt((1-(y*y)/(B*B))*(A*A));
return x;
}
double simpsons_int(DfD f, double y0, double y1, int n)
{
double y, sum, dy = (y1 - y0)/n;
sum = f(y1) + f(y0);
for(y = y0; y <= y1-dy; y += dy)
sum += 2.0 * f(y+dy) + 4.0 * f(y + dy/2);
return sum * dy / 6.0;
}
but I need H and W to be number that are input by the user not 8 and 4.
You can either pass it as argument of the function, or declare it as global variable. I'd rather use the first, depending on the application.
1) passing as parameter. Your function should be:
double ellipse(double y, double W, double H )
{
double x;
double A=W/2.;
double B=H/2.;
x=2*sqrt((1-(y*y)/(B*B))*(A*A));
return x;
}
And then you declare and scanf W and H within main()
2) Just declare W and H before main();
double W,H;
int main()
{
double len, w, h, volume;
printf("Please enter a length, width and height (in meters) of the an elliptical storage tank \n");
scanf("%lf %lf %lf", &len, &w, &h);
scanf("%lf %lf",&W,&H);
double a = h/2.*-1., r;
for (double depth=10; depth<=400; depth=depth+10)
{
r=a+(depth/100);
volume = len*simpsons_int(ellipse, a, r, 10000);
printf("depth is %.1f, volume is %f\n", depth, volume);
}
}
Preprocessor directives like #define must be known at compile-time. Think of them as constants: you can set them, but as soon as you run the program they're set in stone.
You should be using your variables to do this; you could possibly define w and h to be global variables, but better practice would be to pass them in as parameters to the ellipse function.
I'm new to C and I ran into some problems understanding a part of the function below.
Shortly, it integrates a numerical R -> R function with the rectangle method:
double numint(double (*f)(double), double x1, double x2, double dx)
{
double x, sum = 0;
for (x = x1; x < x2; x += dx)
sum += f(x) * dx;
return sum;
}
My question is:
1.) What does double (*f)(double) stand for? How do I call this part of the function? Is it a type not defined in the example, or is it usable by itself?
For example, exampledouble = numint( ?? , double1, double2, double3);
Thank you for your help!
f is a function pointer which requires a double as an argument and returns a double. So you have to pass in a function address using this prototype
double myfunc(double);
It is called here in this line:
sum += f(x) * dx;
Example:
double myfunc(double v)
{
return v*v;
}
int main(int argc, char *argv[])
{
double x1 = 1.0;
double x1 = 2.0;
double x3 = 5.0;
double val = numint(myfunc, x1, x2, x3)
return 0;
}
To add to the answer by Devolus, you call numint like this:
double parabola(double x) {
return x * x + 3 * x + 1;
}
int main() {
int ans = numint(parabola, 0, 3, 0.1);
// gets integral from 0 to 3 of x^2 + 3x + 1
// ...
}